Files
Neo-ZQYY/docs/_overview/04c-feedback/P2-4-course-system-deep-research.md
Neo 509cf43284 chore(docs): Wave 0 调研产出 + P0/P1/P2 反馈调研
建立项目级标杆文档 docs/_overview/ 作为产品全景索引,
解决"PRD 零碎、文档膨胀、跨子系统调研无入口"的问题。

主要内容:
- 00-index 总索引 + 维护协议 + 与 CLAUDE.md 关系
- 01-product-overview 产品全景脑图(6 角色 / 6 子系统 / 数据流 /
  7 业务概念 / 8+1 AI 矩阵 / 22 术语)
- 02a-miniprogram-page-matrix 小程序 21 页业务指纹
- 02b-adminweb-page-matrix admin-web 19 路由业务指纹
- 03-test-spec 测试规范 (L1-L5 分层 + 走查模板 + 75-95 case 估算)
- 04-doc-conflicts 39 条冲突索引(P0×8 / P1×13 / P2×13 + 5 子项)
- 04a/b/c-conflicts-*-detail 业务故事卡(7 字段:关联/逻辑/影响/选项/判定)
- 05-orphan-pages-cleanup admin-web 6 孤儿页面处置(1 归档 + 4 保留)
- WAVES-MASTER-PLAN.md 全 Wave 主计划(0-5,共 22-32 工作日)
- WAVE-1-KICKOFF.md Wave 1 实施 kickoff
- GLOBAL-DECISION-DASHBOARD.md 全局决策仪表板

反馈调研产物:
- 04a-feedback/ P0 两轮反馈(8+8 项决策 + D-1/2/3 + F-1/2 子代理产出)
- 04b-feedback/ P1 两轮反馈(13+1+5 项 + E-1/2/3/4 + G-1/2 子代理产出)
- 04c-feedback/ P2 反馈(13 项 + 5 子项 + H-1/2/3 子代理产出)
- NEO-DECISIONS-LOG 累积决策记录

关键追加发现 8 处 D Bug(原蓝本 0):
- P0-3 看板沙箱接入(Wave 1 W1-T1)
- P0-5 致命 1 (4 处 fdw_etl 残留, 已修 commit 17f045a)
- P0-5 致命 2 (JWT aud 缺失, 已修 commit 17f045a)
- P0-6 clearAllTasks 守卫 (Wave 3)
- P0-8 DBViewer 黑名单漏 (已修 commit 17f045a)
- P1-3 task-detail 跳转传 task_id 而非 customer_id
- P2-7 board-finance 隐式 null
- 2 个独立 Bug (page_context.created_at + ClueCategory 字典)

参考: docs/_overview/00-index.md
2026-05-04 07:38:28 +08:00

279 lines
19 KiB
Markdown
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.
# P2-4 课程体系深度调研(第二轮)
> 日期:2026-05-04
> 触发:Neo 否决 H-1 调研结论(`P2-4-and-P2-7-research.md`):"课程的调研不对,不够深入,课程全部应该有 包厢课 麻将课 基础课 激励课 但应该分布在不同的表中"
> 范围:**重新调研课程体系**,把上游 SaaS 真实 skill、配置表、DWD 明细、DWS 派生列、ETL 代码、前端文案统一对齐
> 数据库:`test_etl_feiqiu`(只读 SELECT)
> 替代关系:**本文件取代 `P2-4-and-P2-7-research.md` 中的 P2-4 部分。P2-7 部分仍以原文件为准。**
---
## 一、Neo 提示的关键(逐字引用)
> "category_code 不是课程,是项目分类。课程的调研不对,不够深入,课程全部应该有 **包厢课 麻将课 基础课 激励课** 但应该分布在不同的表中。"
解读:
1. **课程 ≠ 场地分类(`category_code`)**:H-1 把 `cfg_area_category` 当成课程候选,这条路是错的(它在 `category_code` 列里映射的是 `BILLIARD/SNOOKER/MAHJONG/KTV` 等"项目分类",描述台桌而非课程)。
2. **课程至少 4 类**:基础课 / 包厢课 / 麻将课 / 激励课。
3. **分布在不同表中**:不是一张表的 4 行,是多张表的不同列、不同模块各自表达一部分。
---
## 二、表搜索全集(只读,2026-05-04)
### 2.1 schema 全表名搜索结果(命中 course/lesson/class/room/mahjong/incentive/bonus/skill)
| schema | table | 命中关键字 |
|--------|-------|-----------|
| dws | `cfg_skill_type` | skill |
| dws | `cfg_bonus_rules` | bonus |
| app | `v_cfg_bonus_rules` | bonus(RLS 视图) |
注意:**没有任何表名以 `cfg_course_*``dim_course_*``mahjong_*``incentive_*``lesson_*` 命名**。也就是说"课程"在 NeoZQYY 中**不是一个独立的实体**,而是依附在助教服务记录上的一个**类型属性**。
### 2.2 含课程相关字段的表(course/lesson/class_type/room_type/mahjong/bonus_type/incentive)
| 模块 | 表 | 字段 | 用途 |
|------|---|------|------|
| 配置 | `dws.cfg_skill_type` | `skill_id`, `skill_name`, `course_type_code`(BASE/BONUS/ROOM), `course_type_name` | skill_id → 课程类型映射 |
| 配置 | `dws.cfg_assistant_level_price` | `base_course_price`, `bonus_course_price` | 等级 × 课程类型定价 |
| DWS 明细 | `dws.dws_assistant_daily_detail` | `base_*``bonus_*``room_*`(共 12 列:count/seconds/hours/ledger_amount × 3 类型) | 助教日级三维拆分 |
| DWS 工资 | `dws.dws_assistant_salary_calc` | `base_hours``bonus_hours``room_hours``base_income``bonus_income``room_income` | 工资按 3 类计算 |
| DWS 财务 | `dws.dws_assistant_finance_analysis` | `revenue_base``revenue_bonus``revenue_room``room_service_count``room_service_hours` | 助教营收按 3 类拆分 |
| DWS 关系 | `dws.dws_member_assistant_intimacy` | `basic_session_count``incentive_session_count` | 会员-助教亲密度按 2 类拆分 |
| DWS 关系 | `dws.dws_member_assistant_relation_index` | `basic_session_count``incentive_session_count` | 关系指数按 2 类拆分 |
| DWS 区域 | `dws.dws_coach_area_hours` | `base_hours``bonus_hours``room_hours``*_service_count` | 助教区域工时按 3 类 |
| DWD 明细 | `dwd.dwd_assistant_service_log` | `skill_id`, `skill_name`(原始字符串) | 单笔服务原始 skill |
| ODS 上游 | `ods.assistant_service_records` | `skill_id`, `skillname`(飞球 SaaS 原始字段) | 来自飞球 API |
---
## 三、4 类课程的实际分布
> **核心结论**:NeoZQYY 中"课程"以三个不同抽象层、四个不同模块各自表达,不存在统一的课程表。
### 3.1 基础课(BASE) — 全链路一等公民
| 层 | 实例 |
|---|------|
| ODS | `assistant_service_records.skillname='基础课'`,9 095 条有效订单(2025-09-16 ~ 2026-04-23) |
| 配置 | `cfg_skill_type` 映射 `skill_id ∈ {2790683529513797(基础课), 2791903611396869(台球基础陪打)}``course_type_code='BASE'`(`course_type_name='基础课'`) |
| 代码 | `base_dws_task.py::CourseType.BASE` |
| DWS 列 | `dws_assistant_daily_detail.base_service_count/base_hours/base_seconds/base_ledger_amount`(已写入,2026 年 1-4 月有数据) |
| 工资 | `dws_assistant_salary_calc.base_hours / base_income`(按 `cfg_assistant_level_price.base_course_price` × 等级 计价,初/中/高/星 = 98/108/118/138 元) |
| 关系指数 | `dws_member_assistant_intimacy.basic_session_count`(注意:这里是 `basic` 不是 `base`,命名不一致) |
| 前端文案 | "基础课"(performance/coach-detail/task-list/customer-detail) |
| 别名 | "陪打"、"PD"、`assistant_pd_money` |
### 3.2 包厢课(ROOM) — 设计存在但**实际未生效**
| 层 | 实例 |
|---|------|
| ODS | `skillname='包厢课'`,**174 条有效订单**(2026-01-06 ~ 2026-04-26) |
| 配置 | `cfg_skill_type` 中"包厢课"(`skill_id=3039912271463941`)和"包厢服务"(`skill_id=2807440316432198`)**被映射为 `course_type_code='BASE'`**(注释说"包厢服务:归入基础课统计,统一按 138 元/小时计价";"包厢课:与'包厢服务'同类") |
| 代码 | `base_dws_task.py::CourseType.ROOM` 枚举存在;`get_course_type()``if code == 'ROOM': return CourseType.ROOM` 分支存在,**但永不命中**(因配置表无 ROOM 行) |
| DWS 列 | `dws_assistant_daily_detail.room_service_count/room_hours/room_seconds/room_ledger_amount` 列存在,**全 0**(2942 行均为 0) |
| 工资 | `dws_assistant_salary_calc.room_hours / room_income` 列存在,**全 0**(10 个月全 0) |
| 财务 | `dws_assistant_finance_analysis.revenue_room` SQL 中 `WHEN ... = 'ROOM'` 分支存在,**永不命中** |
| 现状 | 174 条飞球原始包厢课订单**实际被合并进 BASE**(因为 cfg_skill_type 把它们都标成 BASE) |
| 文档 | `CLAUDE.md` 写"包厢课统一 138 元/小时(`dws.salary.room_course_price`)";`assistant_finance_task.py:146` 注释写 ROOM 分类 |
**这是 H-1 漏掉的最关键发现**:**ROOM 是设计预留 + 死代码组合**,不是 H-1 说的"纯死代码可移除"。
174 条真实包厢订单存在,Neo 心目中"包厢课要独立"是合理需求,只是配置表没把它们标出来。
### 3.3 麻将课(MAHJONG) — **数据库与代码层完全空白**
| 层 | 实例 |
|---|------|
| ODS | `assistant_service_records.skillname` 中**没有"麻将课"**(只有"基础课"/"附加课"/"包厢课"/NULL 共 4 种) |
| 飞球上游 | 飞球 SaaS **没有"麻将"作为助教 skill** |
| 配置 | `cfg_skill_type` 没有 MAHJONG 行 |
| 代码 | `CourseType` 枚举**没有 MAHJONG**(只有 BASE/BONUS/ROOM) |
| DWS 列 | 没有 `mahjong_*` 列 |
| 文档 | 仅在 `cfg_area_category.category_code='MAHJONG'` 中出现(场地分类,**不是课程**) |
| 前端 | 没有"麻将课"文案 |
**结论**:"麻将课"在 NeoZQYY **完全不存在**。它是 Neo 在业务规划层提出的概念,**当前所有表、代码、配置、上游都没有对应的载体**。
可能的语义:店铺用麻将台桌时,助教提供的服务可能也叫"麻将课"。但飞球助教 skill 当前不区分这种,落到 ODS 时 `skillname` 仍是"基础课"。
### 3.4 激励课(INCENTIVE) — **实际就是 BONUS,有别名混乱**
| 层 | 实例 |
|---|------|
| ODS | `skillname='附加课'`,985 条有效订单 |
| 配置 | `cfg_skill_type` `skill_id ∈ {2790683529513798(附加课), 2807440316432197(台球超休服务)}``course_type_code='BONUS'`,`course_type_name='附加课'`,`description='附加课:超休/激励课,固定 190 元/小时'` |
| 代码 | `CourseType.BONUS`;`relation_index_task.py:268` `is_incentive = course_type == CourseType.BONUS` |
| DWS 列 | `bonus_service_count/bonus_hours/bonus_seconds/bonus_ledger_amount`(已写入,2 942 行中 574 行有 bonus) |
| 关系 | `incentive_session_count`(BD 手册写"附加课服务次数",但列名用 `incentive`) |
| 工资 | `bonus_income`(单价 190,`bonus_deduction_ratio` 35%~50%) |
| 前端文案 | **"激励课" / "超休" / "打赏课" 三种说法在前端都用** — `performance.ts``performance-records.ts` 中明确写 `'超休': 'incentive', '激励课': 'incentive', '打赏课': 'incentive'`(三个上游别名都映射到 `incentive` CSS 标签) |
| BD-DWD-DOC | 称为"助教激励课正价 / `assistant_cx_money`",规则 2 强制要求 `assistant_cx_money` 表示 BONUS |
| 别名总集 | "附加课"(配置/ODS) / "激励课"(前端文案/Neo 用语) / "超休"(用户口语) / "打赏课"(用户口语) / `BONUS`(代码枚举) / `cx`(SQL/费用字段) |
**结论**:"激励课"和"BONUS"和"附加课"和"超休"是**同一个东西**,只是叫法不一致。Neo 提的"激励课"不是新维度,只是更口语化的命名。
---
## 四、4 类是否真的"分布在不同表中"
回答 Neo 的核心判断:**部分正确,但分布的不是"4 类"而是"多种抽象组合"**。
| 类别 | 是否独立存在 | 在哪些表/列体现 |
|------|------------|----------------|
| 基础课(BASE) | 是,完整 | cfg_skill_type、dwd_assistant_service_log.skill_id、dws.*.base_*(daily/salary/finance/coach_area) + intimacy.basic_session_count |
| 激励课(BONUS) | 是,完整 | 同上替换为 bonus_*、intimacy.incentive_session_count |
| 包厢课(ROOM) | **半残**:DWD 有 174 条原始订单,DWS 列预留但全 0,代码 ROOM 分支永不命中 | dws.*.room_*(daily/salary/finance/coach_area)全 0;cfg_skill_type 把它们标成 BASE 而不是 ROOM |
| 麻将课(MAHJONG) | **不存在**:仅在台桌分类中有 MAHJONG 区(`cfg_area_category`),从未作为课程类型落库 | 没有任何相关列、配置、代码 |
所以"分布在不同表"只对前两类成立(基础课和激励课确实在 daily/salary/finance/intimacy/relation_index 多表多列各自展开)。
**包厢课是半成品,麻将课是空白**
---
## 五、与 H-1 调研对照(必须修正的错误)
H-1 报告(`P2-4-and-P2-7-research.md` 第 87-115 行)说:
| H-1 结论 | 实际情况 | 修正 |
|---------|---------|------|
| "cfg_skill_type 只有 2 行" | **6 行**(基础课/附加课各 3 个 skill_id 别名都已建好) | H-1 漏掉了 SKill_id 4/5/6(2026-03-24 通过 `add_missing_cfg_skill_type.sql` 补齐的"基础课/附加课/包厢课"原始 skill) |
| "ROOM 是死代码,所有 ROOM 分支永不命中" | 命中是真的不命中(配置无 ROOM 行),但**DWD 有 174 条真实包厢订单**正在被错误合并进 BASE | 不是"死代码可移除",而是"配置缺失导致包厢数据被吞" |
| "包厢课在 NeoZQYY 不需要" | Neo 明确要求"包厢课"独立 | 需要补齐(改 cfg_skill_type 把包厢类 skill 标成 ROOM) |
| 完全没提"麻将课" | Neo 提的 4 类之一 | 需在产品层决策"是否新增麻将课作为第 4 类" |
| 没区分"激励课 / 附加课 / 超休 / 打赏课"的别名问题 | 前端 4 套文案,后端 BONUS,配置"附加课",上游 SaaS"附加课/超休服务" | 应在"统一术语"层面收口 |
H-1 漏掉的 5 个关键点:
1. **174 条飞球包厢课订单已落 ODS / DWD,被错误归入 BASE**(因 cfg_skill_type 把它们标成 BASE)
2. **room_* 列在 4 张 DWS 表(daily/salary/finance/coach_area)同时预留,全 0**
3. **`assistant_finance_task.py:146` 写了 `WHEN ... = 'ROOM'` 的 SQL 分支**(永不命中,但代码意图清晰)
4. **关系指数模块用 `basic_session_count` / `incentive_session_count` 命名,不与 `base_*` / `bonus_*` 对齐**(同概念两套命名)
5. **前端文案 4 个别名("激励课"/"超休"/"打赏课"/"附加课")混用,没有统一术语表**
---
## 六、修正后的 P2-4 选项(给 Neo 决策)
### 选项 A:统一术语 + 启用 ROOM(最小改动,贴近现状)
1.`cfg_skill_type` 中"包厢课"和"包厢服务"两行的 `course_type_code``BASE` 改为 `ROOM`
2. 重跑 dws_assistant_daily_detail / salary_calc / finance_analysis / coach_area_hours,让 174 条订单进入 `room_*`
3. 决定 `room_course_price` 真实值(目前 CLAUDE.md 写 138 元/小时,但 cfg_assistant_level_price 没有 room_price 列 — 需要补字段或借用现有规则)
4. 统一前端"激励课"术语:performance.ts 已经做了别名映射,但其他页面要全检
5. **不引入麻将课**
适用场景:Neo 只是想看到包厢课独立,不想全面铺开。
代价:1 次 cfg_skill_type 数据修改 + 1 次回填 + 前端术语清理 + 价格字段补齐。
### 选项 B:课程类型完整化(4 类全开,新增 MAHJONG)
1. `cfg_skill_type.course_type_code` CHECK 约束扩展支持 `BASE/BONUS/ROOM/MAHJONG`
2. `dws_assistant_daily_detail` / `salary_calc` / `coach_area_hours` 增加 `mahjong_*` 列(count/seconds/hours/ledger_amount)
3. `cfg_assistant_level_price` 增加 `room_course_price``mahjong_course_price` 两列
4. 关系指数表增加 `room_session_count``mahjong_session_count`(以及把 `basic_session_count` 重命名为 `base_session_count` 对齐)
5. ETL 4 任务全部改写
6. 飞球上游目前没有"麻将课" skill 数据 — 需要店铺侧手动在飞球后台新建 skill,或在 NeoZQYY 侧用台桌区域(area_category=MAHJONG)反推
7. 前端 task-list / performance / coach-detail / customer-detail / board-coach 全部增加第 3、4 类展示
适用场景:Neo 真的要按 4 类做长期产品规划。
代价:大改动,4 张 DWS 表 schema + 5 个 ETL 任务 + 前端多页 + 飞球上游配合。
### 选项 C:三层澄清(暂不增数据列,先消除认知冲突)
1. **不动 schema**,只产出权威术语对照表归档 `docs/_overview/04c-glossary-courses.md`
2. 明确:"激励课 = 附加课 = 超休 = 打赏课 = BONUS"是同一概念
3. 明确:"包厢课"目前合并在 BASE,需要后续单独建模(选项 A)
4. 明确:"麻将课"目前不存在,需要后续业务决策(选项 B 或不做)
5. 把现有 `room_*` 列 + `CourseType.ROOM` 枚举 + `mahjong_*` 概念 全部标记为"预留,未启用"
6. 修正 BD 手册中"附加课"/"激励课"不一致的注释
适用场景:Neo 只是想确认"我提的 4 类系统当前实际分布",不一定要立刻改实现。
代价:零代码改动,只写文档。
---
## 七、给 Neo 的决策清单
| 编号 | 决策点 | 选项 | 影响范围 |
|-----|--------|------|---------|
| D1 | "包厢课"是否独立成第 3 类 | (a)合并 BASE 不变 (b)启用 ROOM(改 cfg_skill_type+回填) (c)不动 schema 只标记 | DWS 4 表回填 + 前端展示 |
| D2 | "麻将课"是否新增为第 4 类 | (a)不引入 (b)新增 MAHJONG(大改) | DWS 列新增 + 前端 + 飞球上游配合 |
| D3 | "激励课/附加课/超休/打赏课" 是否统一术语 | (a)前端统一为"激励课" (b)统一为"附加课" (c)保持现状 | 前端 5+ 页面 + BD 手册 + 后端 schema 注释 |
| D4 | `room_*` / `CourseType.ROOM` 当前状态 | (a)启用并回填 (b)删除并清理 (c)保留预留并文档化 | 4 张 DWS 表 + ETL 4 任务 + 后端服务 |
| D5 | 关系指数模块 `basic_session_count` vs DWS 通用 `base_*` 命名不一致 | (a)统一命名(改列名) (b)在文档说明同义 (c)保持现状 | 关系表迁移 + 后端 schema |
| D6 | `cfg_assistant_level_price.room_course_price` 缺失 | (a)增加列 (b)用单一常量 138 写死 (c)等 D1 决策后再处理 | cfg_assistant_level_price 表结构 |
---
## 八、命名一致性问题(派生发现)
| 概念 | DWS 主流命名 | 关系指数命名 | 前端 CSS | 后端字段 | 上游 |
|-----|------------|-------------|---------|---------|------|
| 基础课 | `base_*` | `basic_session_count` | `course-tag--base` | `assistant_pd_money`(PD) | "基础课"/"台球基础陪打" |
| 激励课 | `bonus_*` | `incentive_session_count` | `course-tag--incentive` | `assistant_cx_money`(CX) | "附加课"/"台球超休服务" |
| 包厢课 | `room_*`(全 0) | 无 | 无 | 无 | "包厢课"/"包厢服务" |
| 麻将课 | 无 | 无 | 无 | 无 | 无 |
5 套命名混用是高熵问题,长期容易踩坑。建议在 D3/D5 决策时一并收口。
---
## 九、实际 ODS / DWD 课程数据样本(2026-05-04 测试库,脱敏)
ODS 上游 `assistant_service_records` skillname 实际分布(有效订单,`is_trash=0 AND is_delete=0`):
| skillname | 订单数 | 首次日期 | 最近日期 |
|-----------|--------|----------|----------|
| 基础课 | 9 095 | 2025-09-16 | 2026-04-23 |
| (NULL) | 7 382 | 2025-07-21 | 2025-11-30 |
| 附加课 | 985 | 2025-09-18 | 2026-04-18 |
| 包厢课 | 174 | 2026-01-06 | 2026-04-26 |
注意:NULL 7 382 条主要在 2025-07~11 期间,2025-12 起 skillname 全部填充。说明飞球 SaaS 在 2025-12 之后才补全 skillname 字段 — 这是另一个数据质量问题。
cfg_skill_type 全量(6 行):
| id | skill_id | skill_name | course_type_code | description |
|---|----------|-----------|------------------|-------------|
| 1 | 2791903611396869 | 台球基础陪打 | BASE | 基础课:陪打服务,按助教等级计价 |
| 2 | 2807440316432197 | 台球超休服务 | BONUS | 附加课:超休/激励课,固定 190 元/小时 |
| 3 | 2807440316432198 | 包厢服务 | BASE | 包厢服务:归入基础课统计,统一按 138 元/小时计价 |
| 4 | 2790683529513797 | 基础课 | BASE | 基础课:飞球系统原始课程类型,与"台球基础陪打"同类 |
| 5 | 2790683529513798 | 附加课 | BONUS | 附加课:飞球系统原始课程类型,与"台球超休服务"同类 |
| 6 | 3039912271463941 | 包厢课 | BASE | 包厢课:飞球系统原始课程类型,与"包厢服务"同类 |
**注意**:第 3、6 行注释里写"包厢服务/包厢课"但 `course_type_code``BASE` — 这是**配置数据有意为之的合并**,不是 bug。
要让 ROOM 列生效,需要把它们改成 `ROOM` + 给 `cfg_assistant_level_price``room_course_price` 列(或使用现有的 BASE 价 + 一个 ROOM 专属规则)。
DWS `dws_assistant_daily_detail` 整体统计(2 942 行):
| 指标 | base | bonus | room |
|-----|------|-------|------|
| 非零行数 | 2 833 | 574 | **0** |
| 累计服务次数 | 5 237 | 645 | **0** |
| 累计金额 | 1 546 983.80 | 301 910.00 | **0.00** |
DWS `dws_assistant_salary_calc` 月度统计(10 个月):**room_hours / room_income 全部为 0.00**。
DWS `dws_member_assistant_intimacy` 整体统计(219 行):
| 指标 | 数值 |
|------|------|
| 总会话 | 698 |
| basic_session_count | 698 |
| incentive_session_count | **0** |
注意:亲密度模块的 incentive_session_count 也全 0。这与 daily_detail 的 bonus(574 行非零)不一致,值得在选项 A 决策后再深查 `relation_index_task.py` 的归类口径。
---
## 十、总结(给主流程)
1. **课程实际分布**:不是 H-1 说的"BASE+BONUS 两类",也不是 Neo 提的"4 类独立分布",而是 **"BASE + BONUS 完整,ROOM 半残空表,MAHJONG 空白"**。
2. **5 处分布载体**:`cfg_skill_type`(配置)、`cfg_assistant_level_price`(定价)、`dws_assistant_daily_detail/salary_calc/finance_analysis/coach_area_hours`(派生汇总)、`dws_member_assistant_intimacy/relation_index`(关系)、`dwd_assistant_service_log` + `ods.assistant_service_records`(原始)。
3. **关键 H-1 错误**:漏报 cfg_skill_type 实际 6 行(不是 2 行)、漏报 174 条真实包厢课订单被错误合并进 BASE、未提"激励课"4 套别名混用、未识别关系指数模块的命名错位。
4. **不存在统一课程表**:NeoZQYY 用"skill_id → course_type_code"映射 + DWS 派生列展开的方式表达课程,没有 `dim_course` / `cfg_course` 这种独立维度。
5. **决策清单 6 项**:D1(包厢课独立) / D2(麻将课新增) / D3(术语统一) / D4(ROOM 处置) / D5(关系指数命名) / D6(包厢定价字段)。