8.1 KiB
8.1 KiB
Implementation Plan: 赠送卡矩阵细分数据 (gift-card-breakdown)
Overview
贯穿全栈数据链路的改动:DDL 新增 6 字段 → ETL 拆分填充 → RLS 视图 + FDW 同步 → 后端 SQL + 接口返回 → 小程序替换 mock。消费行因上游 API 限制,细分列保持 0。
Tasks
-
1. DDL 迁移与基线同步
- 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
- 1.2 同步 DDL 基线文件
docs/database/ddl/etl_feiqiu__dws.sql- 在
dws_finance_recharge_summary表定义中追加 6 个新字段 - Requirements: 1.1
- 在
- 1.1 创建 DDL 迁移脚本
-
2. ETL 赠送卡余额拆分
- 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
- 文件:
- 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
- 2.1 修改
-
3. ETL 赠送卡新增充值拆分
- 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
- 3.1 新增
-
4. ETL transform 合并细分字段
- [~] 4.1 修改
extract()调用新方法并传递结果- 文件:
apps/etl/connectors/feiqiu/tasks/dws/finance_recharge_task.py - 在 extract 返回值中新增
gift_recharge_breakdownkey - 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_balancesdict 和gift_recharge_breakdowndict,验证 record 包含 6 个字段且值正确 - 输入 dict 缺少某个 key 时,对应字段为 0
- Validates: Requirements 4.1, 4.2
- [~] 4.1 修改
-
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
- 创建/更新幂等脚本(先 DROP 再
- [~] 6.1 RLS 视图重建
-
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
- [~] 7.1 修改
-
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
- 文件:
- [~] 9.1 替换
-
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
- 验证余额恒等式:
- [~] 10.1 创建验证 SQL 脚本
-
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
- 文件:
- [~] 11.1 更新
-
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 - 设计文档使用 Python(ETL)、SQL(DDL/查询)、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常量