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>
This commit is contained in:
Neo
2026-04-20 06:32:07 +08:00
parent 79d3c2e97e
commit 2a7a5d68aa
157 changed files with 14304 additions and 3717 deletions

View File

@@ -42,6 +42,12 @@
| 23 | create_time | TIMESTAMPTZ | YES | | 创建时间 |
| 24 | member_discount_money | NUMERIC(18,2) | YES | | 会员折扣金额 |
| 25 | coupon_sale_id | BIGINT | YES | | 优惠券销售 ID |
| 26 | mt_settlement_price | NUMERIC(14,2) | YES | | 美团结算价(扣费后实际到手,元) |
| 27 | mt_gross_income | NUMERIC(14,2) | YES | | 美团总收入(售价,元) |
| 28 | mt_service_fee | NUMERIC(14,2) | YES | | 美团平台技术服务费(负数,元) |
| 29 | mt_marketing_fee | NUMERIC(14,2) | YES | | 商家营销费用(负数,元) |
| 30 | mt_other_adjust | NUMERIC(14,2) | YES | | 其他调整(元) |
| 31 | mt_import_time | TIMESTAMPTZ | YES | | 美团结算数据导入时间 |
## 使用说明

View File

@@ -60,7 +60,7 @@
## 分类映射(完整台桌清单)
### BILLIARD 🎱 中式/追分43台)
### BILLIARD 🎱 中式/追分44台)
| 区域 | 台桌 |
|------|------|
| A区 | A1-A1818台 |
@@ -68,6 +68,7 @@
| C区 | C1-C66台 |
| VIP包厢 | VIP1, VIP2, VIP3 |
| TV台 | TV |
| 美洲豹赛台 | 美洲豹赛台 |
### SNOOKER 斯诺克5台
| 区域 | 台桌 |
@@ -110,6 +111,7 @@
| 2026-03-07 | 新增 source_table_name 支持台桌级细分;废弃 BILLIARD_VIP |
| 2026-03-09 | 改为纯台桌级精确映射,删除所有 LIKE 和区域级映射 |
| 2026-03-20 | 新增 sort_order 字段,控制前端筛选器分类显示排序 |
| 2026-04-11 | 新增美洲豹赛台 → BILLIARDBILLIARD 总数 43→44 |
## 验证 SQL
@@ -133,12 +135,12 @@ ORDER BY source_area_name, source_table_name;
-- 4. 确认总记录数
SELECT COUNT(*) AS total FROM dws.cfg_area_category;
-- 期望: 7574 台桌 + 1 DEFAULT 兜底)
-- 期望: 7675 台桌 + 1 DEFAULT 兜底)
-- 5. 按分类汇总
SELECT category_code, COUNT(*) AS cnt
FROM dws.cfg_area_category
WHERE match_type = 'EXACT'
GROUP BY category_code ORDER BY category_code;
-- 期望: BILLIARD=43, KTV=7, MAHJONG=11, SNOOKER=5, SPECIAL=8
-- 期望: BILLIARD=44, KTV=7, MAHJONG=11, SNOOKER=5, SPECIAL=8
```

View File

@@ -12,7 +12,7 @@
| 唯一键 | (site_id, member_id, time_window, category_code) |
| 数据来源 | dwd_table_fee_log + dim_table + cfg_area_category |
| 更新频率 | 每日全量重建(按 site_id 删除后重新插入) |
| 说明 | 按时间窗口计算客户在四大项目的消费时长占比≥25% 分配标签。散客不参与。 |
| 说明 | 按每位客户最近 30 次消费计算四大项目时长占比≥25% 分配标签。散客不参与。 |
## 字段说明
@@ -36,12 +36,11 @@
## 时间窗口
客户看板使用 2 个时间窗口:
| 枚举值 | 说明 |
|--------|------|
| LAST_30_DAYS | 近30天含今天base_date-29天 ~ base_date |
| LAST_60_DAYS | 近60天含今天base_date-59天 ~ base_date |
| LAST_30_VISITS | 每位客户最近 30 次消费(开台记录),按 ledger_end_time 倒序 |
> 2026-04-11 改为按消费次数取数,不再按固定日期范围,避免长期未到店或来店频率不稳定的客户标签丢失。
## 索引
@@ -55,26 +54,29 @@
## 数据链路
```
dwd.dwd_table_fee_log (ledger_count, site_table_id)
dwd.dwd_table_fee_log (ledger_count, site_table_id, ledger_end_time)
→ ROW_NUMBER() OVER (PARTITION BY member_id ORDER BY ledger_end_time DESC)
→ 取最近 30 条记录LAST_N_VISITS=30
→ 按 (member_id, site_table_id) 聚合 ledger_count
→ JOIN dwd.dim_table (site_table_id → table_id, scd2_is_current=1)
→ get_area_category(area_name, table_name) -- 通过 cfg_area_category 映射
→ 只保留 BILLIARD/SNOOKER/MAHJONG/KTV
排除散客(member_id IS NULL 或 = 0
→ 按 (member_id, category_code) 汇总 ledger_count
按 (member_id, category_code) 汇总
→ 计算占比 percentage = duration_seconds / total_seconds
→ ≥0.25 标记 is_tagged=TRUE
→ 写入 dws.dws_member_project_tag
→ 写入 dws.dws_member_project_tagtime_window='LAST_30_VISITS'
```
### 关键规则
1. 数据链路走 `dim_table`(通过 `site_table_id` JOIN不直接用事实表的 `site_table_area_name`
2. 客户时长使用 `ledger_count`(计费时长),不使用 `income_seconds`(那是助教工作时长)
3. 散客member_id=0 或 NULL不参与标签计算
4. 只计算四大项目BILLIARD/SNOOKER/MAHJONG/KTV
5. 标签阈值 25%`TAG_THRESHOLD = 0.25`
6. 全量删除重建策略:按 `site_id` 删除后重新插入所有时间窗口
7. `COALESCE(is_delete, 0) = 0` 过滤已删除的台费记录
1. 按每位客户最近 30 次消费取数,不按固定日期范围,避免来店频率不稳定的客户标签丢失
2. 数据链路走 `dim_table`(通过 `site_table_id` JOIN不直接用事实表的 `site_table_area_name`
3. 客户时长使用 `ledger_count`(计费时长),不使用 `income_seconds`(那是助教工作时长)
4. 散客member_id=0 或 NULL不参与标签计算
5. 只计算四大项目BILLIARD/SNOOKER/MAHJONG/KTV
6. 标签阈值 25%`TAG_THRESHOLD = 0.25`
7. 全量删除重建策略:按 `site_id` 删除后重新插入
8. `COALESCE(is_delete, 0) = 0` 过滤已删除的台费记录
## ETL 任务
@@ -90,6 +92,7 @@ dwd.dwd_table_fee_log (ledger_count, site_table_id)
| 日期 | 变更 | 说明 |
|------|------|------|
| 2026-03-07 | 新建表 | 支持客户看板按项目类型筛选 |
| 2026-04-11 | 时间窗口改为消费次数 | LAST_30/60_DAYS → LAST_30_VISITS按最近30次消费取数 |
## 验证 SQL

View File

@@ -97,6 +97,12 @@ graph LR
| `DWD_LOAD_FROM_ODS` | `DwdLoadTask` | 核心装载:遍历 TABLE_MAP维度走 SCD2事实走增量 | [查看](dwd_tasks.md) |
| `DWD_QUALITY_CHECK` | `DwdQualityTask` | ODS 与 DWD 行数/金额核对,输出 JSON 报表 | [查看](dwd_tasks.md) |
### Core 层(统一维度)
| 任务代码 | Python 类 | 目标表 | 粒度 | 说明 |
|----------|-----------|--------|------|------|
| `CORE_DIM_SYNC` | `CoreDimSyncTask` | `core.dim_assistant/member/site/table` | 全量 | 将 DWD 当前版本scd2_is_current=1同步到 core 统一维度层TRUNCATE+INSERT 幂等 |
### DWS 层(数据服务)
#### 助教业绩域