feat(analytics): A3 流失预警三分法——真流失/从未激活/待交接
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import Annotated, Any, Literal
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.analytics import health as health_svc
|
||||
@@ -36,3 +36,22 @@ async def analytics_overview(
|
||||
与 entities[].last_seen 为 ISO 字符串的双格式)。
|
||||
"""
|
||||
return await metrics_svc.overview(session, channel=channel, scope=scope)
|
||||
|
||||
|
||||
@router.get("/churn")
|
||||
async def churn_list(
|
||||
session: SessionDep,
|
||||
channel: ChannelParam = "wechat",
|
||||
type: Literal["real", "inactive", "handover"] = "real",
|
||||
tier: int = Query(30, ge=30, le=90),
|
||||
min_msgs: int = Query(5, ge=1, le=100),
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
) -> dict[str, Any]:
|
||||
"""A3 流失预警名单(三分法)。tier 只认 30/60/90。"""
|
||||
if tier not in (30, 60, 90):
|
||||
raise HTTPException(422, "tier must be 30/60/90")
|
||||
return await metrics_svc.churn(
|
||||
session, channel=channel, kind=type, tier=tier,
|
||||
min_msgs=min_msgs, page=page, page_size=page_size,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user