Files
Neo-ZQYY/.kiro/specs/gift-card-breakdown/tasks.md

148 lines
8.1 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.
# Implementation Plan: 赠送卡矩阵细分数据 (gift-card-breakdown)
## Overview
贯穿全栈数据链路的改动DDL 新增 6 字段 → ETL 拆分填充 → RLS 视图 + FDW 同步 → 后端 SQL + 接口返回 → 小程序替换 mock。消费行因上游 API 限制,细分列保持 0。
## Tasks
- [x] 1. DDL 迁移与基线同步
- [x] 1.1 创建 DDL 迁移脚本 `db/etl_feiqiu/migrations/2026-xx-xx_add_gift_breakdown_fields.sql`
- ALTER TABLE 新增 6 个 NUMERIC(14,2) 字段NOT NULL DEFAULT 0
- 使用 `ADD COLUMN IF NOT EXISTS` 保证幂等
- _Requirements: 1.1, 1.2_
- [x] 1.2 同步 DDL 基线文件 `docs/database/ddl/etl_feiqiu__dws.sql`
-`dws_finance_recharge_summary` 表定义中追加 6 个新字段
- _Requirements: 1.1_
- [x] 2. ETL 赠送卡余额拆分
- [x] 2.1 修改 `_extract_card_balances()` 按 card_type_id 分组返回细分余额
- 文件:`apps/etl/connectors/feiqiu/tasks/dws/finance_recharge_task.py`
- 新增 `GIFT_TYPE_FIELD_MAP` 常量映射 card_type_id → 字段名
- 返回值新增 `gift_liquor_balance``gift_table_fee_balance``gift_voucher_balance`
- 保留原有 `gift_balance` 字段(向后兼容)
- 某种卡类型无记录时对应字段返回 0
- _Requirements: 2.1, 2.2, 2.3_
- [x] 2.2 编写属性测试ETL 余额提取 round-trip
- **Property 3: ETL 余额提取 round-trip**
- 生成随机 `dim_member_card_account` 记录mock DB验证各类型余额等于对应 card_type_id 的 balance 之和
- 当某种卡类型无记录时,对应余额为 0
- **Validates: Requirements 2.1, 2.2, 2.3, 10.1**
- [ ] 3. ETL 赠送卡新增充值拆分
- [x] 3.1 新增 `_extract_gift_recharge_breakdown()` 方法
- 文件:`apps/etl/connectors/feiqiu/tasks/dws/finance_recharge_task.py`
- SQL`dwd_recharge_order JOIN dim_member_card_account``tenant_member_card_id``tenant_member_id`)按 card_type_id 分组
- 新增 `GIFT_RECHARGE_FIELD_MAP` 常量映射
- 返回 `{gift_liquor_recharge, gift_table_fee_recharge, gift_voucher_recharge}`,缺失卡类型默认 0
- _Requirements: 3.1, 3.2, 3.3_
- [-] 3.2 编写属性测试ETL 新增提取 round-trip
- **Property 4: ETL 新增提取 round-trip**
- 生成随机 `dwd_recharge_order` + `dim_member_card_account` 记录mock DB验证各类型新增等于对应 card_type_id 的 point_amount 之和
- 当某种卡类型无充值记录时,对应新增为 0
- **Validates: Requirements 3.1, 3.2, 3.3, 10.2**
- [ ] 4. ETL transform 合并细分字段
- [~] 4.1 修改 `extract()` 调用新方法并传递结果
- 文件:`apps/etl/connectors/feiqiu/tasks/dws/finance_recharge_task.py`
- 在 extract 返回值中新增 `gift_recharge_breakdown` key
- _Requirements: 4.1_
- [~] 4.2 修改 `transform()` 将 6 个新字段写入 record dict
- 使用 `self.safe_decimal()` 处理值,缺失 key 时填充 0
- 沿用现有 delete-before-insert 幂等策略
- _Requirements: 4.1, 4.2, 4.3_
- [~] 4.3 编写属性测试transform 正确合并细分字段
- **Property 5: transform 正确合并细分字段**
- 生成随机 `card_balances` dict 和 `gift_recharge_breakdown` dict验证 record 包含 6 个字段且值正确
- 输入 dict 缺少某个 key 时,对应字段为 0
- **Validates: Requirements 4.1, 4.2**
- [ ] 5. Checkpoint — ETL 层验证
- Ensure all tests pass, ask the user if questions arise.
- [ ] 6. 数据库视图层同步
- [~] 6.1 RLS 视图重建 `app.v_dws_finance_recharge_summary`
- 创建迁移脚本 `db/zqyy_app/migrations/`
- `CREATE OR REPLACE VIEW` 包含全部 6 个新字段
- 保持 `site_id` 行级安全过滤策略不变
- _Requirements: 5.1, 5.2, 5.3_
- [~] 6.2 FDW 外部表同步
- 创建/更新幂等脚本(先 DROP 再 `IMPORT FOREIGN SCHEMA`
- 支持重复执行不报错
- _Requirements: 6.1, 6.2_
- [ ] 7. 后端接口修改
- [~] 7.1 修改 `fdw_queries.get_finance_recharge()` SQL 查询
- 文件:`apps/backend/app/services/fdw_queries.py`
- SQL 新增 6 个字段的 SUM 聚合
- _Requirements: 7.1_
- [~] 7.2 修改 `gift_rows` 构建逻辑
- 余额行:`liquor`/`table_fee`/`voucher` 填充对应细分余额
- 新增行:`liquor`/`table_fee`/`voucher` 填充对应细分新增,`total` 使用三个细分之和
- 消费行:`liquor`/`table_fee`/`voucher` 保持 0`total` 返回消费总额
- _Requirements: 7.2, 7.3, 7.4, 8.1, 8.2_
- [~] 7.3 修改 `_empty_recharge_data()` 空默认值同步
- 确保新增 6 个字段在空数据结构中默认为 0
- _Requirements: 7.5_
- [~] 7.4 编写属性测试:余额恒等式
- **Property 1: 余额恒等式**
- 生成随机三种余额,验证 `gift_card_balance = gift_liquor_balance + gift_table_fee_balance + gift_voucher_balance`
- **Validates: Requirements 1.3, 10.3**
- [~] 7.5 编写属性测试:新增恒等式
- **Property 2: 新增恒等式**
- 生成随机三种新增,验证 `recharge_gift = gift_liquor_recharge + gift_table_fee_recharge + gift_voucher_recharge`
- **Validates: Requirements 1.4**
- [~] 7.6 编写属性测试:后端接口返回正确细分数据
- **Property 6: 后端接口返回正确的细分数据**
- 生成随机 DWS 行mock FDW 查询,验证 gift_rows 余额行和新增行的细分值等于对应字段 SUM
- **Validates: Requirements 7.2, 7.3**
- [~] 7.7 编写属性测试:消费行细分列始终为 0
- **Property 7: 消费行细分列始终为 0**
- 验证 gift_rows 消费行的 `liquor.value``table_fee.value``voucher.value` 始终为 0
- **Validates: Requirements 7.4, 8.1, 8.2**
- [~] 7.8 编写属性测试:环比计算对新字段正确适配
- **Property 8: 环比计算对新字段正确适配**
- 生成随机当期/上期数据,验证 `compare=1` 时 gift_rows 每个 cell 的 compare 等于 `calc_compare(当期值, 上期值)`
- **Validates: Requirements 7.6**
- [ ] 8. Checkpoint — 后端层验证
- Ensure all tests pass, ask the user if questions arise.
- [ ] 9. 小程序联调
- [~] 9.1 替换 `board-finance.ts` 中 mock 数据为真实 API 调用
- 文件:`apps/miniprogram/miniprogram/pages/board-finance/board-finance.ts`
- 移除 `giftRows` 硬编码 mock 数据
- 使用 Finance_Board_API 返回的真实数据
- 字段映射:`liquor→wine``table_fee→table``voucher→coupon`,在数据转换层处理
- API 返回错误或超时时展示加载失败提示,不显示 mock 数据
- _Requirements: 9.1, 9.2, 9.3, 9.4_
- [ ] 10. 数据一致性验证
- [~] 10.1 创建验证 SQL 脚本
- 验证余额恒等式:`gift_card_balance = 三种余额之和`
- 验证新增恒等式:`recharge_gift = 三种新增之和`
- 验证 DWS 与 DWD 源数据一致DWS 各类型余额 = DWD `dim_member_card_account` 对应 card_type_id 的 balance 之和
- 脚本放置在 `scripts/ops/` 或迁移目录
- _Requirements: 10.1, 10.2, 10.3_
- [ ] 11. BD 手册更新
- [~] 11.1 更新 `BD_manual_dws_finance_recharge_summary.md`
- 文件:`apps/etl/connectors/feiqiu/docs/database/DWS/main/BD_manual_dws_finance_recharge_summary.md`
- 新增 6 个字段的说明(字段名、类型、含义、数据来源)
- 更新恒等式约束说明
- 更新数据流向描述
- _Requirements: 1.1, 1.3, 1.4_
- [ ] 12. Final checkpoint — 全链路验证
- Ensure all tests pass, ask the user if questions arise.
## Notes
- Tasks marked with `*` are optional and can be skipped for faster MVP
- 设计文档使用 PythonETL、SQLDDL/查询、TypeScript小程序任务中代码示例沿用对应语言
- 消费行因上游飞球 API 限制(`dwd_settlement_head.gift_card_amount` 仅提供总额),细分列保持 0
- 属性测试使用 `hypothesis` 库,测试文件统一放置在 `tests/test_gift_card_breakdown_properties.py`
- 单元测试放置在各模块的 `tests/` 目录下
- 所有 DDL 迁移脚本使用 `IF NOT EXISTS` 保证幂等
- card_type_id 硬编码沿用现有 `GIFT_CARD_TYPE_IDS` 常量