主线 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>
155 lines
4.0 KiB
Python
155 lines
4.0 KiB
Python
# AI_CHANGELOG
|
|
# - 2026-03-20 | Prompt: M4 emoji 注释修复 | FavoriteCoach.emoji 注释从旧 2 级(💖/💛)
|
|
# 改为 P6 权威定义的 4 级(💖/🧡/💛/💙),与 compute_heart_icon() 实际逻辑对齐。
|
|
|
|
from __future__ import annotations
|
|
|
|
from app.schemas.base import CamelModel
|
|
|
|
|
|
class AiStrategy(CamelModel):
|
|
color: str
|
|
text: str
|
|
|
|
class AiInsight(CamelModel):
|
|
summary: str = ""
|
|
strategies: list[AiStrategy] = []
|
|
|
|
class MetricItem(CamelModel):
|
|
label: str
|
|
value: str
|
|
color: str | None = None
|
|
|
|
class CoachTask(CamelModel):
|
|
name: str
|
|
level: str # star / senior / middle / junior
|
|
level_color: str
|
|
heart_score: float = 0.0 # CHANGE 2026-03-29 | RSI 关系指数,用于爱心标识
|
|
task_type: str
|
|
task_color: str
|
|
bg_class: str
|
|
status: str
|
|
last_service: str | None = None
|
|
metrics: list[MetricItem] = []
|
|
|
|
class FavoriteCoach(CamelModel):
|
|
emoji: str
|
|
name: str
|
|
heart_score: float = 0.0
|
|
level: str = ""
|
|
relation_index: str
|
|
index_color: str
|
|
bg_class: str
|
|
stats: list[MetricItem] = []
|
|
|
|
class CoachServiceItem(CamelModel):
|
|
name: str
|
|
level: str
|
|
level_color: str
|
|
course_type: str # "基础课" / "激励课"
|
|
hours: str # "2.5h" 格式
|
|
perf_hours: float | None = None
|
|
fee: float
|
|
|
|
class ConsumptionRecord(CamelModel):
|
|
id: str
|
|
type: str # table / shop / recharge
|
|
date: str
|
|
table_name: str | None = None
|
|
start_time: str | None = None
|
|
end_time: str | None = None
|
|
duration: str | None = None
|
|
table_fee: float | None = None
|
|
table_orig_price: float | None = None
|
|
coaches: list[CoachServiceItem] = []
|
|
food_amount: float | None = None
|
|
food_orig_price: float | None = None
|
|
food_detail: str | None = None
|
|
total_amount: float
|
|
total_orig_price: float | None = None
|
|
pay_method: str | None = None
|
|
recharge_amount: float | None = None
|
|
|
|
class RetentionClue(CamelModel):
|
|
type: str
|
|
text: str
|
|
|
|
class CustomerNote(CamelModel):
|
|
id: int
|
|
tag_label: str
|
|
creator_name: str = ""
|
|
creator_role: str = ""
|
|
created_at: str
|
|
content: str
|
|
|
|
class CustomerDetailResponse(CamelModel):
|
|
"""CUST-1 响应。"""
|
|
# 基础信息
|
|
id: int
|
|
name: str
|
|
phone: str
|
|
phone_full: str
|
|
avatar: str
|
|
member_level: str
|
|
relation_index: str
|
|
tags: list[str] = []
|
|
# Banner 概览
|
|
balance: float | None = None
|
|
consumption_60d: float | None = None
|
|
ideal_interval: int | None = None
|
|
days_since_visit: int | None = None
|
|
# 扩展模块
|
|
ai_insight: AiInsight = AiInsight()
|
|
coach_tasks: list[CoachTask] = []
|
|
favorite_coaches: list[FavoriteCoach] = []
|
|
retention_clues: list[RetentionClue] = []
|
|
consumption_records: list[ConsumptionRecord] = []
|
|
notes: list[CustomerNote] = []
|
|
|
|
class ServiceRecordItem(CamelModel):
|
|
id: str
|
|
date: str
|
|
time_range: str | None = None
|
|
table: str | None = None
|
|
type: str
|
|
type_class: str
|
|
record_type: str | None = None # course / recharge
|
|
duration: float
|
|
duration_raw: float | None = None
|
|
income: float
|
|
is_estimate: bool = False
|
|
drinks: str | None = None
|
|
|
|
class CustomerRecordsResponse(CamelModel):
|
|
"""CUST-2 响应。"""
|
|
customer_name: str
|
|
customer_phone: str
|
|
customer_phone_full: str
|
|
relation_index: str
|
|
tables: list[dict] = []
|
|
total_service_count: int
|
|
month_count: int
|
|
month_hours: float
|
|
month_income: float = 0.0
|
|
records: list[ServiceRecordItem] = []
|
|
has_more: bool = False
|
|
|
|
|
|
class CustomerConsumptionRecordsResponse(CamelModel):
|
|
"""CUST-3 响应:客户消费记录(按月)。"""
|
|
# Banner
|
|
id: int
|
|
name: str
|
|
phone: str
|
|
phone_full: str
|
|
balance: float | None = None
|
|
consumption_60d: float | None = None
|
|
ideal_interval: int | None = None
|
|
days_since_visit: int | None = None
|
|
# 月度汇总
|
|
visit_count: int = 0
|
|
consume_total: float = 0.0
|
|
recharge_total: float = 0.0
|
|
# 消费记录
|
|
records: list[ConsumptionRecord] = []
|