Files
Neo-ZQYY/docs/specs/02-etl-dws-miniapp-extensions/tasks.md
Neo 70324d8542 chore: 文档与 IDE 配置整理
- .kiro/specs/ → docs/specs/(41 个历史需求 spec 迁移,移除 .config.kiro)
- CLAUDE.md 三层拆分:根文件精简 + apps/backend/CLAUDE.md + .claude/commands/
- 新增 /spec-close、/pre-change 两个工作流命令
- DDL 基线刷新(从测试库重新导出 11 个文件,dws 35→38 表,biz 18→21 表)
- BD_Manual → BD_manual 命名统一(48 个文件)
- 修复 3 处文档与数据库不一致(auth.users.status 默认值、scheduled_tasks 字段、RLS 视图数)
- 新增 BD_manual_public_rbac_tables.md(public schema 8 张 RBAC/工作流表)
- 合并 biz.trigger_jobs 文档(10→12 字段,归档独立文档)
- docs/database/README.md 索引更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-06 00:02:37 +08:00

153 lines
8.8 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.
# 实现计划ETL DWS 层扩展 — 小程序数据支撑
## 概述
基于设计文档将实现拆分为DDL 建表/扩展 → 助教订单流水统计任务 → 会员消费汇总扩展 → 定档折算惩罚 → RLS 视图 + FDW 映射 → 影子跑数验证 六个阶段。所有数据库操作在测试库(`test_etl_feiqiu` / `test_zqyy_app`)中进行。
## 任务
- [x] 1. DDL 建表与字段扩展
- [x] 1.1 编写迁移脚本创建 `dws.dws_assistant_order_contribution`
- 新建 `db/etl_feiqiu/migrations/<日期>__create_dws_assistant_order_contribution.sql`
- 包含表定义、唯一索引 `idx_aoc_site_assistant_date`、查询索引 `idx_aoc_stat_date`
- 字段参照设计文档数据模型章节
- _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5_
- [x] 1.2 编写迁移脚本扩展 `dws_member_consumption_summary` 字段
- 新建 `db/etl_feiqiu/migrations/<日期>__alter_member_consumption_add_recharge_fields.sql`
- ALTER TABLE 添加 `recharge_count_30d/60d/90d``recharge_amount_30d/60d/90d``avg_ticket_amount`
- _Requirements: 3.1, 3.2_
- [x] 1.3 编写迁移脚本扩展 `dws_assistant_daily_detail` 字段
- 新建 `db/etl_feiqiu/migrations/<日期>__alter_assistant_daily_add_penalty_fields.sql`
- ALTER TABLE 添加 `penalty_minutes``penalty_reason``is_exempt``per_hour_contribution`
- _Requirements: 5.1, 5.2_
- [x] 1.4 在测试库 `test_etl_feiqiu` 执行全部迁移脚本
- 通过 `PG_DSN`(指向测试库)连接执行 SQL
- _Requirements: 1.5, 3.2, 5.2_
- [x] 1.5 运行 `gen_consolidated_ddl.py` 导出最新 DDL
- 执行 `python scripts/ops/gen_consolidated_ddl.py`
- 验证 `docs/database/ddl/etl_feiqiu__dws.sql` 已包含新表和扩展字段
- _Requirements: 1.6_
- [x] 2. 实现助教订单流水统计任务
- [x] 2.1 创建数据结构和 `AssistantOrderContributionTask` 骨架
- 新建 `apps/etl/connectors/feiqiu/tasks/dws/assistant_order_contribution_task.py`
- 定义 `TableUsage``AssistantService``OrderData` dataclass
- 定义 `AssistantOrderContributionTask` 类继承 `BaseDwsTask`
- 实现 `get_task_code``get_target_table``get_primary_keys`
- _Requirements: 1.1, 2.7_
- [x] 2.2 实现四项统计核心计算(纯函数)
- 实现 `compute_order_gross_revenue` 静态方法
- 实现 `compute_order_net_revenue` 静态方法
- 实现 `compute_time_weighted_revenue` 静态方法(含台费分摊、酒水均分逻辑)
- 实现 `compute_time_weighted_net_revenue` 静态方法
- 处理超休/打赏课特殊情况
- _Requirements: 2.2, 2.3, 2.4, 2.5, 2.6_
- [x] 2.3 编写属性测试:订单级统计不变量
- **Property 1: 订单级统计不变量 — gross/net 各助教相等**
- **Validates: Requirements 2.2, 2.3, 10.1, 10.2**
- [x] 2.4 编写属性测试:时效贡献流水之和约束
- **Property 2: 时效贡献流水之和 ≤ order_gross_revenue**
- **Validates: Requirements 2.4, 10.3**
- [x] 2.5 编写属性测试:时效净贡献减法关系
- **Property 3: time_weighted_net_revenue = time_weighted_revenue - commission**
- **Validates: Requirements 2.5, 10.4**
- [x] 2.6 实现 `extract` 方法
-`dwd_settlement_head``dwd_table_fee_log``dwd_assistant_service_log` 提取数据
-`order_settle_id` 聚合为 `OrderData` 结构
- _Requirements: 2.1_
- [x] 2.7 实现 `transform` 方法
- 遍历订单,调用四项统计计算函数
-`(assistant_id, stat_date)` 聚合日度统计
- _Requirements: 2.2, 2.3, 2.4, 2.5, 2.6_
- [x] 2.8 注册任务到 task_registry 并导出模块
-`tasks/dws/__init__.py` 中导出 `AssistantOrderContributionTask`
-`orchestration/task_registry.py` 中注册 `DWS_ASSISTANT_ORDER_CONTRIBUTION``layer="DWS"``depends_on=["DWD_LOAD_FROM_ODS"]`
- _Requirements: 2.7, 2.8_
- [x] 3. 检查点 — 确保助教订单流水统计测试通过
- 运行属性测试:`cd C:\NeoZQYY && pytest tests/test_dws_contribution_properties.py -v`
- 确保所有属性测试通过,如有问题请询问用户。
- [x] 4. 扩展会员消费汇总任务
- [x] 4.1 在 `MemberConsumptionTask` 中新增充值统计提取
- 新增 `_extract_recharge_stats` 方法,从 `dwd.dwd_recharge_order` 按 30/60/90 天窗口聚合
-`extract` 方法中调用并返回充值统计数据
- _Requirements: 4.1, 3.3_
- [x] 4.2 在 `MemberConsumptionTask.transform` 中填充新字段
- 合并充值统计到输出记录
- 计算 `avg_ticket_amount = total_consume_amount / MAX(total_visit_count, 1)`
- 处理无充值/无消费的边界情况
- _Requirements: 4.2, 4.3, 4.4, 3.4_
- [x] 4.3 编写属性测试:次均消费公式
- **Property 5: avg_ticket_amount = total_consume_amount / MAX(total_visit_count, 1)**
- **Validates: Requirements 3.4, 10.7**
- [x] 5. 实现定档折算惩罚检测与计算
- [x] 5.1 实现时间重叠检测逻辑
-`AssistantDailyTask` 中新增 `detect_overlap_violations` 静态方法
- 定义惩罚区域集合(大厅 A/B/C/S/TV + 麻将房 M1M7
-`(table_id, service_date)` 分组,检测时间段重叠且助教数 > 2
- _Requirements: 6.1_
- [x] 5.2 实现惩罚分钟数计算
-`AssistantDailyTask` 中新增 `compute_penalty_minutes` 静态方法
- 计算 `per_hour_contribution = 台费每小时单价 / 助教人数`
- 按分段公式计算 `penalty_minutes`
- 处理 `is_exempt = TRUE` 豁免逻辑
- _Requirements: 6.2, 6.3, 6.4, 6.5_
- [x] 5.3 集成惩罚逻辑到 `AssistantDailyTask.transform`
- 在现有聚合逻辑后调用重叠检测和惩罚计算
-`penalty_minutes``penalty_reason``is_exempt``per_hour_contribution` 填充到输出记录
- _Requirements: 6.6, 6.7_
- [x] 5.4 编写属性测试:惩罚分钟数分段公式
- **Property 4: 惩罚分钟数符合分段公式且在 [0, actual_minutes] 范围内**
- **Validates: Requirements 6.3, 6.4, 10.5, 10.6**
- [x] 5.5 编写属性测试:重叠检测正确性
- **Property 6: 3+ 助教时间重叠时应检测到违规**
- **Validates: Requirements 6.1**
- [x] 6. 检查点 — 确保惩罚计算和消费汇总测试通过
- 运行属性测试:`cd C:\NeoZQYY && pytest tests/test_dws_contribution_properties.py -v`
- 运行单元测试:`cd apps/etl/connectors/feiqiu && pytest tests/unit/ -k "contribution or penalty or consumption" -v`
- 确保所有测试通过,如有问题请询问用户。
- [x] 7. RLS 视图与 FDW 映射
- [x] 7.1 创建 `dws_assistant_order_contribution` 的 RLS 视图
- 在测试库 `test_etl_feiqiu``app` schema 中创建 `v_dws_assistant_order_contribution` 视图
- 使用 `current_setting('app.current_site_id')::bigint` 过滤
- 授予 `app_reader` 角色 SELECT 权限
- _Requirements: 7.1, 7.3_
- [x] 7.2 验证已有 RLS 视图自动包含新增字段
- 确认 `app.v_dws_member_consumption_summary``app.v_dws_assistant_daily_detail` 使用 `SELECT *`,新增字段自动包含
- _Requirements: 7.2_
- [x] 7.3 创建/更新 FDW 外部表映射
- 在测试库 `test_zqyy_app``fdw_etl` schema 中创建 `dws_assistant_order_contribution` 外部表
- 重建 `dws_member_consumption_summary``dws_assistant_daily_detail` 的 FDW 外部表以包含新字段
- FDW 映射通过 `app` schema RLS 视图访问
- _Requirements: 8.1, 8.2, 8.3_
- [x] 8. 影子跑数验证
- [x] 8.1 编写验证脚本
- 新建 `apps/etl/connectors/feiqiu/scripts/verify_dws_extensions.py`
- 验证四项统计:对照 PRD 示例数据验算,检查 gross/net 各助教相等
- 验证充值窗口:检查新增字段有值,充值金额与源数据一致
- 验证惩罚字段:检查符合条件的记录正确填充
- _Requirements: 9.1, 9.2, 9.3, 9.4_
- [x] 8.2 编写数据库手册文档
- 新建 `docs/database/BD_Manual_dws_assistant_order_contribution.md`
- 包含表结构、字段说明、索引、验证 SQL至少 3 条)、兼容性说明、回滚策略
- 更新 `docs/database/``dws_member_consumption_summary``dws_assistant_daily_detail` 的文档
- _Requirements: 1.1_
- [x] 9. 最终检查点 — 确保所有测试通过
- 运行属性测试:`cd C:\NeoZQYY && pytest tests/test_dws_contribution_properties.py -v`
- 运行单元测试:`cd apps/etl/connectors/feiqiu && pytest tests/unit/ -k "contribution or penalty or consumption" -v`
- 确保所有测试通过,如有问题请询问用户。
## 备注
- 标记 `*` 的子任务为可选(属性测试),可跳过以加速 MVP
- 每个任务引用具体需求编号以确保可追溯
- 所有数据库操作在测试库(`test_etl_feiqiu` / `test_zqyy_app`)中进行
- 检查点确保增量验证
- 属性测试验证全称正确性属性,单元测试验证具体示例和边界情况