feat: 累积功能变更 — 聊天集成、租户管理、小程序更新、ETL 增强、迁移脚本
包含多个会话的累积代码变更: - backend: AI 聊天服务、触发器调度、认证增强、WebSocket、调度器最小间隔 - admin-web: ETL 状态页、任务管理、调度配置、登录优化 - miniprogram: 看板页面、聊天集成、UI 组件、导航更新 - etl: DWS 新任务(finance_area_daily/board_cache)、连接器增强 - tenant-admin: 项目初始化 - db: 19 个迁移脚本(etl_feiqiu 11 + zqyy_app 8) - packages/shared: 枚举和工具函数更新 - tools: 数据库工具、报表生成、健康检查 - docs: PRD/架构/部署/合约文档更新 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,7 @@ from decimal import Decimal
|
||||
|
||||
from app.services import fdw_queries
|
||||
from app.services.task_generator import compute_heart_icon
|
||||
from app.trace.decorators import trace_service
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -39,9 +40,10 @@ LEVEL_COLOR_MAP = {
|
||||
}
|
||||
|
||||
TASK_TYPE_MAP = {
|
||||
"follow_up_visit": {"label": "回访", "class": "tag-callback"},
|
||||
"high_priority_recall": {"label": "紧急召回", "class": "tag-recall"},
|
||||
"priority_recall": {"label": "优先召回", "class": "tag-recall"},
|
||||
"follow_up_visit": {"label": "客户回访", "class": "callback"},
|
||||
"high_priority_recall": {"label": "高优先召回", "class": "high-priority"},
|
||||
"priority_recall": {"label": "优先召回", "class": "priority"},
|
||||
"relationship_building": {"label": "关系构建", "class": "relationship"},
|
||||
}
|
||||
|
||||
# 头像渐变色池(循环使用)
|
||||
@@ -85,6 +87,7 @@ def _format_currency(amount: float) -> str:
|
||||
# ── 6.1 核心函数 ──────────────────────────────────────────
|
||||
|
||||
|
||||
@trace_service("获取助教详情", "Get coach detail")
|
||||
async def get_coach_detail(coach_id: int, site_id: int) -> dict:
|
||||
"""
|
||||
助教详情(COACH-1)。
|
||||
@@ -150,7 +153,13 @@ async def get_coach_detail(coach_id: int, site_id: int) -> dict:
|
||||
|
||||
performance = {
|
||||
"monthly_hours": salary_this.get("total_hours", 0.0),
|
||||
"monthly_salary": salary_this.get("total_income", 0.0),
|
||||
# CHANGE 2026-03-26 | 到手 = base_income + bonus_income + bonus_money + room_income(DWS 层已扣抽成)
|
||||
"monthly_salary": (
|
||||
salary_this.get("assistant_pd_money_total", 0.0)
|
||||
+ salary_this.get("assistant_cx_money_total", 0.0)
|
||||
+ salary_this.get("bonus_money", 0.0)
|
||||
+ salary_this.get("room_income", 0.0)
|
||||
),
|
||||
"customer_balance": customer_balance,
|
||||
"tasks_completed": tasks_completed,
|
||||
"perf_current": salary_this.get("total_hours", 0.0),
|
||||
@@ -287,22 +296,22 @@ def _build_income(
|
||||
{
|
||||
"label": "基础课时费",
|
||||
"amount": f"¥{salary.get('assistant_pd_money_total', 0.0):,.0f}",
|
||||
"color": "#42A5F5",
|
||||
"color": "primary",
|
||||
},
|
||||
{
|
||||
"label": "激励课时费",
|
||||
"amount": f"¥{salary.get('assistant_cx_money_total', 0.0):,.0f}",
|
||||
"color": "#FFA726",
|
||||
"color": "success",
|
||||
},
|
||||
{
|
||||
"label": "充值提成",
|
||||
"amount": f"¥{salary.get('bonus_money', 0.0):,.0f}",
|
||||
"color": "#66BB6A",
|
||||
"color": "warning",
|
||||
},
|
||||
{
|
||||
"label": "酒水提成",
|
||||
"amount": f"¥{salary.get('room_income', 0.0):,.0f}",
|
||||
"color": "#AB47BC",
|
||||
"color": "purple",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -385,17 +394,18 @@ def _build_top_customers(
|
||||
balance = cust.get("customer_balance", 0.0)
|
||||
consume = cust.get("total_consume", 0.0)
|
||||
|
||||
# CHANGE 2026-03-29 | coach-detail-500 修复 | relation_score → score,对齐 TopCustomer.score Schema
|
||||
result.append({
|
||||
"id": mid or 0,
|
||||
"name": name,
|
||||
"initial": _get_initial(name),
|
||||
"avatar_gradient": _get_avatar_gradient(i),
|
||||
"heart_emoji": heart_emoji,
|
||||
"relation_score": f"{score:.2f}",
|
||||
"score": f"{score:.2f}",
|
||||
"score_color": score_color,
|
||||
"service_count": cust.get("service_count", 0),
|
||||
"balance": _format_currency(balance),
|
||||
"consume": _format_currency(consume),
|
||||
"balance": float(balance) if balance else 0.0,
|
||||
"consume": float(consume) if consume else 0.0,
|
||||
})
|
||||
|
||||
return result
|
||||
@@ -440,9 +450,9 @@ def _build_service_records(
|
||||
"avatar_gradient": _get_avatar_gradient(i),
|
||||
"type": course_type or "课程",
|
||||
"type_class": type_class,
|
||||
"table": str(rec.get("table_id")) if rec.get("table_id") else None,
|
||||
"table": rec.get("table_name") or None,
|
||||
"duration": f"{hours:.1f}h",
|
||||
"income": _format_currency(income),
|
||||
"income": float(income),
|
||||
"date": date_str,
|
||||
"perf_hours": None,
|
||||
})
|
||||
@@ -594,11 +604,12 @@ def _build_notes(coach_id: int, site_id: int, conn) -> list[dict]:
|
||||
|
||||
result = []
|
||||
for r in rows:
|
||||
# CHANGE 2026-03-29 | coach-detail-500 修复 | ai_score → score,对齐 CoachNoteItem.score Schema
|
||||
result.append({
|
||||
"id": r[0],
|
||||
"content": r[1] or "",
|
||||
"timestamp": r[2].isoformat() if r[2] else "",
|
||||
"ai_score": r[3],
|
||||
"score": r[3],
|
||||
"customer_name": member_name_map.get(r[5], ""),
|
||||
"tag_label": r[4] or "",
|
||||
"created_at": r[2].isoformat() if r[2] else "",
|
||||
@@ -698,9 +709,9 @@ def _build_history_months(
|
||||
result.append({
|
||||
"month": month_label,
|
||||
"estimated": month_str == current_month_str,
|
||||
"customers": f"{customers}人",
|
||||
"hours": f"{hours:.1f}h",
|
||||
"salary": _format_currency(salary_amount),
|
||||
"customers": customers,
|
||||
"hours": float(hours),
|
||||
"salary": float(salary_amount),
|
||||
"callback_done": callback_done,
|
||||
"recall_done": recall_done,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user