Files
Neo-ZQYY/apps/backend/app/schemas/xcx_coaches.py
Neo 2a7a5d68aa feat: 2026-04-15~04-20 累积变更基线 — 多主线合流
主线 1: rns1-customer-coach-api + 04-miniapp-core-business 后端实施
  - 新增 GET /xcx/coaches/{id}/banner 轻量接口
  - performance/records 加 coach_id 参数 + view_board_coach 权限分流
  - coach/customer/performance/board/task 服务层重构
  - fdw_queries 结算单粒度聚合 + consumption_summary 视图统一
  - task_generator 回访宽限 72h + UPSERT 替代策略 + Step 5 保底清理
  - recall_detector settle_type=3 双重限制 + 门店级 resolved

主线 2: 小程序权限分流 + 新增 coach-service-records 管理者视角业绩明细页
  - perf-progress 共享模块去重 task-list/coach-detail 动画逻辑
  - isScattered 散客标记端到端
  - foodDetail/phoneFull/creator* 字段透传

主线 3: P19 指数回测框架 Phase 1+2
  - 3 个指数表 stat_date 日快照模式
  - 新增 DWS_INDEX_BACKFILL / DWS_TASK_SIMULATION 工具任务
  - task_engine 升级 HTTP 实时 + 推演回测双模式

主线 4: Core 维度层启用
  - 新增 CORE_DIM_SYNC 任务(DWD → core 4 维度表)
  - 修复 app 视图空查询问题

主线 5: member_project_tag 改为 LAST_30_VISITS 消费次数窗口

主线 6: 2 个迁移 SQL 已执行(stat_date + member_project_tag 新窗口)
  - schema 基线与 DDL 快照同步

主线 7: 开发机路径迁移 C:\NeoZQYY → C:\Project\NeoZQYY(约 95% 改动量)

附带: 新建运维脚本(churned_customer_report / simulate_historical_tasks /
      backfill_index_snapshots)+ tools/task-analysis/ 任务分析工具

合计 157 文件。未包含中间产物(tmp/ .playwright-mcp/ inspect-* excel/sheet 分析 txt)。
审计记录见下一个 commit。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 06:32:07 +08:00

163 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# AI_CHANGELOG
# - 2026-03-20 | Prompt: M4 emoji 注释修复 | heart_emoji 注释从旧 3 级(❤️/💛/🤍)
# 改为 P6 权威定义的 4 级(💖/🧡/💛/💙),与 compute_heart_icon() 实际逻辑对齐。
from __future__ import annotations
from app.schemas.base import CamelModel
class PerformanceMetrics(CamelModel):
"""绩效概览 -- 与任务页 PerformanceSummary 统一数据源monthly_summary 实时值)。"""
# 核心绩效字段(来自 build_performance_summary与任务页一致
total_hours: float = 0
total_income: float = 0
total_customers: int = 0
month_label: str = ""
tier_nodes: list[float] = []
basic_hours: float = 0
bonus_hours: float = 0
current_tier: int = 0
next_tier_hours: float = 0
tier_completed: bool = False
bonus_money: float = 0
income_trend: str = ""
income_trend_dir: str = "up"
prev_month: str = ""
current_tier_label: str = ""
# 助教详情页专属扩展字段
customer_balance: float = 0
tasks_completed: int = 0
# 兼容旧字段名(前端渐进适配)
monthly_hours: float = 0
monthly_salary: float = 0
class IncomeItem(CamelModel):
label: str
amount: str
color: str
class IncomeSection(CamelModel):
this_month: list[IncomeItem] = []
last_month: list[IncomeItem] = []
class CoachTaskItem(CamelModel):
type_label: str
type_class: str
customer_name: str
customer_id: int | None = None
note_count: int = 0
pinned: bool = False
notes: list[dict] | None = None
class AbandonedTask(CamelModel):
customer_name: str
reason: str
class TopCustomer(CamelModel):
id: int
name: str
initial: str
avatar_gradient: str
# CHANGE 2026-03-20 | M4 修复: emoji 注释与 P6 权威定义对齐4 级映射)
# intent: 注释应反映 compute_heart_icon() 的实际 4 级映射(💖🧡💛💙)
heart_emoji: str # 💖 / 🧡 / 💛 / 💙
score: str
score_color: str
service_count: int
# CHANGE 2026-03-29 | str → float后端返回原始数字前端 WXS 格式化(避免 NaN
balance: float
consume: float
is_scattered: bool = False # 散客标识,前端据此置灰名称
class CoachServiceRecord(CamelModel):
customer_id: int | None = None
customer_name: str
initial: str
avatar_gradient: str
type: str
type_class: str
table: str | None = None
duration: str
# CHANGE 2026-03-29 | str → float后端返回原始数字前端 WXS 格式化(避免 NaN
income: float
date: str
perf_hours: str | None = None
is_scattered: bool = False # 散客标识,前端据此置灰名称
class HistoryMonth(CamelModel):
month: str
estimated: bool
# CHANGE 2026-03-29 | str → int/float后端返回原始数字前端 WXS 格式化(避免 NaN
customers: int
hours: float
salary: float
callback_done: int
recall_done: int
class CoachNoteItem(CamelModel):
id: int
content: str
timestamp: str
score: int | None = None
customer_name: str
tag_label: str
created_at: str
class CoachTaskStats(CamelModel):
"""当月任务完成统计(回访/召回分类)。"""
callback: int = 0 # follow_up_visit 完成数
recall: int = 0 # high_priority_recall + priority_recall 完成数
class CoachBannerResponse(CamelModel):
"""助教 banner 轻量响应(仅 name / level / store_name用于 PERF-2 等只需 banner 的页面。"""
id: int
name: str
level: str = ""
store_name: str = ""
class CoachDetailResponse(CamelModel):
"""COACH-1 响应。"""
# 基础信息
id: int
name: str
avatar: str
level: str
# 门店名称:跟随被查看助教所在门店,供小程序 banner 展示
store_name: str = ""
skills: list[str] = []
work_years: float = 0
customer_count: int = 0
hire_date: str | None = None
# 绩效
performance: PerformanceMetrics
# 收入
income: IncomeSection
# 档位
tier_nodes: list[float] = []
# 当月任务完成统计
task_stats: CoachTaskStats = CoachTaskStats()
# 任务分组
visible_tasks: list[CoachTaskItem] = []
hidden_tasks: list[CoachTaskItem] = []
abandoned_tasks: list[AbandonedTask] = []
# TOP 客户
top_customers: list[TopCustomer] = []
# 近期服务记录
service_records: list[CoachServiceRecord] = []
# 历史月份
history_months: list[HistoryMonth] = []
# 备注
notes: list[CoachNoteItem] = []