Files
Mutual_Fund/service/advisor/dashboard.py
T

70 lines
2.6 KiB
Python

"""驾驶舱聚合(首页数据与待办聚合,PRD §4.1)。
口径说明(E1 最小口径):总 AUM=名下客户「持有中」持仓市值之和;有效客户=signed;
流失率=closed/总客户;报告产出/发送=advisor_report 计数。回访完成率等精细口径 P2 后置。
"""
from __future__ import annotations
from sqlalchemy.ext.asyncio import AsyncSession
from common_const import (
CUSTOMER_REL_STATUS_CLOSED,
CUSTOMER_REL_STATUS_SIGNED,
REPORT_SEND_STATUS_DRAFT,
REPORT_SEND_STATUS_SENT,
TODO_STATUS_PENDING,
)
from model.sys_user import SysUser
from repositories.advisor_report import AdvisorReportRepo
from repositories.advisor_todo import AdvisorTodoRepo
from repositories.advisor_visit_record import AdvisorVisitRecordRepo
from repositories.customer_relation import CustomerRelationRepo
async def get_dashboard(db: AsyncSession, user: SysUser) -> dict:
relation_repo = CustomerRelationRepo(db)
todo_repo = AdvisorTodoRepo(db)
report_repo = AdvisorReportRepo(db)
visit_repo = AdvisorVisitRecordRepo(db)
pending = await todo_repo.count_by_advisor(advisor_id=user.id, status=TODO_STATUS_PENDING)
total = await relation_repo.count_customer_rows(advisor_id=user.id)
signed = await relation_repo.count_customer_rows(
advisor_id=user.id, status=CUSTOMER_REL_STATUS_SIGNED
)
closed = await relation_repo.count_customer_rows(
advisor_id=user.id, status=CUSTOMER_REL_STATUS_CLOSED
)
aum = await relation_repo.sum_holdings_value(user.id)
sent = await report_repo.count_by_advisor(
advisor_id=user.id, send_status=REPORT_SEND_STATUS_SENT
)
draft = await report_repo.count_by_advisor(
advisor_id=user.id, send_status=REPORT_SEND_STATUS_DRAFT
)
visits = await visit_repo.count_by_advisor(advisor_id=user.id)
# 客户分层:C1-C5 各档人数(未知等级归入 unknown)
levels = {k: 0 for k in ("C1", "C2", "C3", "C4", "C5")}
unknown = 0
for level, cnt in await relation_repo.risk_level_distribution(user.id):
if level in levels:
levels[level] = cnt
else:
unknown += cnt
return {
"todos": {"pending": pending},
"overview": {
"total_customers": total,
"signed_customers": signed,
"closed_customers": closed,
"churn_rate": round(closed / total, 4) if total else 0.0,
"total_aum": f"{aum:.2f}",
"reports_sent": sent,
"reports_draft": draft,
"visits_count": visits,
},
"customer_levels": {**levels, "unknown": unknown},
}