Files
Neo-ZQYY/docs/specs/board-finance-dws-area-refactor/tasks.md
Neo 2a7a5d68aa 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>
2026-04-20 06:32:07 +08:00

17 KiB
Raw Blame History

Implementation Plan: 财务看板 DWS 区域维度重构

Overview

将财务看板的优惠数据从全局 DWS 取数改为按区域日粒度预计算,分 4 个阶段实施:基础设施层(共享映射 + DDL→ ETL 层(两个新任务)→ 后端层(查询改造 + 缓存逻辑)→ 收尾联调、DDL 合并、文档、审计)。每个阶段末尾设检查点,确保增量验证。

Tasks

  • 1. 共享区域映射配置与属性测试

    • 1.1 创建 packages/shared/src/neozqyy_shared/area_mapping.py

      • 定义 AREA_LABEL_MAP 字典7 个具体区域 → 物理名称列表)
      • 定义 SPECIFIC_AREA_CODESALL_AREA_CODES 常量
      • 构建 _REVERSE_MAP 反向映射
      • 实现 resolve_area_code(area_name)get_area_labels(area_code) 函数
      • Requirements: 1.1, 1.2, 1.3, 1.5
    • 1.2 编写属性测试:区域映射 round-trip

      • Property 1: 区域映射 round-trip
      • 生成器:从 AREA_LABEL_MAP 所有值列表中随机选取 area_name
      • 验证:resolve_area_code(area_name) 返回正确 area_code,且 area_name in get_area_labels(result)
      • 验证: 需求 1.1, 1.5
    • 1.3 编写属性测试:未知区域名称返回 None

      • Property 2: 未知区域名称返回 None
      • 生成器:st.text() 生成随机字符串,过滤掉已知 area_name
      • 验证:resolve_area_code(unknown_name) 返回 None
      • 验证: 需求 1.4
    • 1.4 编写单元测试area_mapping 边界条件

      • 测试文件:tests/test_area_mapping_unit.py
      • 覆盖空字符串、None、大小写敏感、特殊字符、hall/all 的 get_area_labels 返回 None
      • Requirements: 1.4, 1.5
  • 2. DDL创建 dws_finance_area_daily 表与 RLS 视图

    • 2.1 编写 DDL 迁移脚本
      • 创建 dws.dws_finance_area_daily 表(含收入 5 字段、优惠 7 字段、confirmed_income、现金流 8 字段、卡消费 3 字段、充值 3 字段、order_count
      • 添加 UNIQUE 约束 (site_id, stat_date, area_code)
      • 创建 RLS 视图 v_dws_finance_area_dailyWHERE site_id = current_setting('app.current_site_id')::bigint
      • Requirements: 2.1, 2.2, 2.3, 2.4, 2.5, 2.6
  • 3. 检查点 — 基础设施层验证

    • 确保 area_mapping 属性测试和单元测试通过:cd C:\Project\NeoZQYY && pytest tests/test_area_mapping_props.py tests/test_area_mapping_unit.py -v
    • 确保 DDL 迁移脚本语法正确
    • ask the user if questions arise.
  • 4. ETLDWS_FINANCE_AREA_DAILY 任务与属性测试

    • 4.1 创建 apps/etl/connectors/feiqiu/tasks/dws/finance_area_daily.py

      • 继承 FinanceBaseTask,实现 get_task_code/get_target_table/get_primary_keys
      • extract:从 dwd_settlement_head + dim_tablescd2_is_current=1)提取当天结算单(settle_type IN (1,3),按 BUSINESS_DAY_START_HOUR 切点),同时从 dws_finance_daily_summary 提取全局现金流/充值/卡消费
      • transform:使用 resolve_area_code 映射区域,按区域聚合收入和优惠字段,构建 9 行hallA~ktv + hall + all非 all 行现金流/卡消费/充值字段为 0
      • loaddelete-before-insertsite_id + stat_date 删除后插入 9 行,单事务)
      • discount_gift_card 使用赠送卡消费金额口径(与现有 ETL 一致)
      • Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 8.1, 8.2
    • 4.2 编写属性测试:日粒度行数学恒等式

      • Property 3: 日粒度行数学恒等式
      • 生成器:随机生成结算单列表(金额用 st.decimalsarea_name 从已知+未知混合)
      • 验证transform 输出的每行满足 gross_amount = 四项之和、discount_total = 六项之和、confirmed_income = gross - discount
      • 验证: 需求 2.1, 2.2, 2.3, 8.3
    • 4.3 编写属性测试:非 all 区域现金流为零

      • Property 4: 非 all 区域现金流/卡消费/充值为零
      • 生成器:随机结算单列表 + 全局现金流数据
      • 验证transform 输出中 area_code ≠ 'all' 的行,所有现金流/卡消费/充值字段 = 0
      • 验证: 需求 2.5
    • 4.4 编写属性测试ETL 输出完整性与聚合正确性

      • Property 5: ETL 输出完整性与聚合正确性
      • 生成器:随机结算单列表
      • 验证:输出恰好 9 行all 行收入/优惠 = hallAktv 之和hall 行 = hallAktv 之和
      • 验证: 需求 2.7, 2.8, 8.4
    • 4.5 编写属性测试ETL 幂等性

      • Property 6: ETL 幂等性delete-before-insert
      • 生成器:随机结算单列表
      • 验证:对同一输入运行两次 transform两次输出完全相同
      • 验证: 需求 3.4
    • 4.6 编写属性测试settle_type 过滤

      • Property 7: settle_type 过滤
      • 生成器:包含不同 settle_type 值的结算单列表
      • 验证:仅 settle_type IN (1, 3) 的记录影响输出金额
      • 验证: 需求 3.6
    • 4.7 编写单元测试ETL transform 边界条件

      • 测试文件:apps/etl/connectors/feiqiu/tests/unit/test_finance_area_daily.py
      • 覆盖discount_gift_card 口径验证、营业日切点边界、未知区域名称处理、空结算单输入
      • Requirements: 3.1, 3.2, 3.9
  • 5. DDL创建 dws_finance_board_cache 表与 RLS 视图

    • 5.1 编写 DDL 迁移脚本
      • 创建 dws.dws_finance_board_cacheoverview 8 项 + 日期范围 + 指纹 + 元数据)
      • 添加 UNIQUE 约束 (site_id, time_range, area_code)
      • 创建 RLS 视图 v_dws_finance_board_cache
      • Requirements: 4.1, 4.2, 4.3, 4.4
  • 6. ETLDWS_FINANCE_BOARD_CACHE 任务与属性测试

    • 6.1 创建 apps/etl/connectors/feiqiu/tasks/dws/finance_board_cache.py

      • 继承 BaseDwsTask
      • extract:遍历 5 个已完成周期 × 9 个区域 = 45 组合,从 dws_finance_area_daily 读取日粒度行
      • transform:实现 compute_fingerprintMD5与缓存表对比标记需重算的组合
      • load:对需重算的组合从日粒度表 SUM 后 upsert 到缓存表(ON CONFLICT DO UPDATE
      • Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7
    • 6.2 编写属性测试:数据指纹确定性与缓存失效

      • Property 8: 数据指纹确定性与缓存失效
      • 生成器:随机日粒度行列表
      • 验证:相同输入产生相同指纹;修改任意行的 gross_amount 或 discount_total 后指纹变化
      • 验证: 需求 5.2, 5.3, 5.4
    • 6.3 编写属性测试:当期周期不写入缓存

      • Property 9: 当期周期不写入缓存
      • 生成器:随机 time_range 从 {month, week, quarter}
      • 验证ETL 缓存任务不为当期 time_range 写入缓存记录
      • 验证: 需求 5.7
    • 6.4 编写单元测试:缓存任务边界条件

      • 测试文件:apps/etl/connectors/feiqiu/tests/unit/test_finance_board_cache.py
      • 覆盖指纹变化检测、空数据处理、upsert 幂等性
      • Requirements: 5.2, 5.3, 5.4
  • 7. 检查点 — ETL 层验证

    • 运行 ETL 属性测试:cd C:\Project\NeoZQYY && pytest tests/test_finance_area_daily_props.py tests/test_finance_board_cache_props.py -v
    • 运行 ETL 单元测试:cd apps/etl/connectors/feiqiu && pytest tests/unit/test_finance_area_daily.py tests/unit/test_finance_board_cache.py -v
    • 确保 Property 3-9 全部通过
    • ask the user if questions arise.
  • 8. 后端:改造 fdw_queries.py 查询函数与属性测试

    • 8.1 新增/改造 apps/backend/app/fdw_queries.py 中的查询函数

      • 新增 get_finance_overview_area(conn, site_id, start_date, end_date, area_code) — 从 v_dws_finance_area_daily 按 area_code 聚合 overview 8 项指标
      • 新增 get_finance_revenue_area(conn, site_id, start_date, end_date, area_code) — 从 v_dws_finance_area_daily 按 area_code 聚合 revenue 板块数据
      • 新增 get_finance_board_cache(conn, site_id, time_range, area_code) — 查询 v_dws_finance_board_cache 缓存
      • 新增 set_finance_board_cache(conn, site_id, time_range, area_code, data) — 写入/更新缓存
      • 使用 SET LOCAL app.current_site_id 保证 RLS 隔离
      • Requirements: 6.1, 6.2, 6.3, 6.5, 6.6
    • 8.2 编写属性测试:查询路由正确性

      • Property 10: 查询路由正确性
      • 生成器随机查询参数time_range、area_code+ mock 数据库返回
      • 验证:已完成周期+缓存存在→返回缓存缓存不存在→SUM+写缓存;当期→直接 SUM 不查缓存
      • 验证: 需求 6.1, 6.2, 6.3, 9.4
    • 8.3 编写属性测试:区域过滤行为

      • Property 11: 区域过滤行为
      • 生成器:随机 area_code ≠ 'all' + mock 数据
      • 验证recharge 返回 nullcashflow/expense/coach_analysis 使用全局数据
      • 验证: 需求 6.7, 6.8
    • 8.4 编写属性测试revenue 固定项数

      • Property 12: revenue 固定项数
      • 生成器:随机查询参数 + mock 数据
      • 验证discount_items 恰好 5 项channel_items 恰好 3 项
      • 验证: 需求 7.3, 7.4
    • 8.5 编写属性测试area≠all 时 overview 覆盖逻辑

      • Property 13: area≠all 时 overview 覆盖逻辑
      • 生成器:随机 area_code ≠ 'all' + mock revenue 数据
      • 验证overview.occurrence = revenue.total_occurrenceoverview.discount = revenue.discount_totaloverview.confirmed_revenue = revenue.confirmed_total
      • 验证: 需求 7.6
    • 8.6 编写单元测试fdw_queries 查询正确性

      • 测试文件:apps/backend/tests/unit/test_fdw_queries_area.py
      • 覆盖SQL 正确性、area_code 过滤、缓存命中/未命中、RLS 隔离
      • Requirements: 6.1, 6.2, 6.5, 6.6
  • 9. 后端:改造 board_service.py 缓存查询逻辑

    • 9.1 改造 apps/backend/app/board_service.pyget_finance_board 函数

      • 新增缓存查询逻辑:已完成周期先查 get_finance_board_cache,命中直接返回
      • 缓存未命中:从日粒度表 SUM 计算,写入缓存后返回
      • 当期周期:直接从日粒度表 SUM不查缓存
      • _build_overview 改为调用 get_finance_overview_area(传入 area_code
      • _build_revenue 改为调用 get_finance_revenue_area(传入 area_code
      • _build_cashflow 不变(始终用全局数据)
      • area≠all 时 overview 覆盖逻辑保留occurrence/discount/confirmedRevenue = revenue 对应值)
      • area≠all 时 recharge 返回 null
      • compare=1 时对上期执行同样缓存/日粒度逻辑
      • Requirements: 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 7.1, 7.2, 7.5, 7.6
    • 9.2 编写属性测试area=all 回归一致性

      • Property 14: area=all 回归一致性
      • 生成器:随机日期范围 + mock 新旧逻辑数据
      • 验证area=all 时新逻辑的 overview 8 项指标与旧逻辑完全一致
      • 验证: 需求 9.1
    • 9.3 编写单元测试board_service 改造

      • 测试文件:apps/backend/tests/unit/test_board_service_area.py
      • 覆盖:缓存命中/未命中路径、覆盖逻辑、环比计算、降级行为(无数据返回全零)
      • Requirements: 6.1, 6.2, 6.3, 7.6, 9.1
  • 10. 检查点 — 后端层验证

    • 运行后端属性测试:cd C:\Project\NeoZQYY && pytest tests/test_board_service_props.py -v
    • 运行后端单元测试:cd apps/backend && pytest tests/unit/test_fdw_queries_area.py tests/unit/test_board_service_area.py -v
    • 确保 Property 10-14 全部通过
    • ask the user if questions arise.
  • 11. 历史数据回填脚本

    • 11.1 编写回填脚本 scripts/ops/backfill_finance_area_daily.py
      • 对已有日期范围批量调用 FinanceAreaDailyTask.transform 逻辑
      • 支持指定 site_id 和日期范围参数
      • 回填完成后触发 DWS_FINANCE_BOARD_CACHE 重算所有已完成周期缓存
      • Requirements: 2.7, 3.4, 5.1
  • 12. 前后端联调与集成验证

    • 12.1 启动后端服务,使用测试库验证各端点完整请求-响应链路
      • 使用真实 FDW 连接验证 SQL 查询正确性
      • 验证 JSON 响应结构与 Schema 定义一致camelCase 序列化)
      • 验证数据隔离(SET LOCAL app.current_site_id)在真实请求中生效
      • Requirements: 7.1, 7.2, 9.1
    • 12.2 运行 144 组合全量验证脚本
      • 执行 scripts/ops/validate_board_finance.py8 time_range × 9 area_code × 2 compare
      • 确认 area=all 时所有板块数据与重构前完全一致(回归测试)
      • 确认 area≠all 时 discountRate 不出现 400%+ 异常值
      • 确认已完成周期第二次请求命中缓存
      • Requirements: 9.1, 9.2, 9.3, 9.4
    • 12.3 前端联调验证
      • 确认小程序财务看板页能正确调用 API 并渲染数据(前端零改动)
      • 验证空数据/降级场景下前端不崩溃
      • 如前端页面尚未开发,记录待联调清单供后续任务使用
      • Requirements: 7.1, 7.2
  • 13. 数据库变更审计与 DDL 合并

    • 13.1 审计本次实现中对数据库的所有改动
      • 检查新建表dws_finance_area_daily、dws_finance_board_cache、RLS 视图、FDW 映射变更
      • Requirements: 2.6, 4.1
    • 13.2 执行迁移脚本到测试库
      • 验证新表和索引已正确创建(使用 BD 手册中的验证 SQL
      • Requirements: 2.6, 4.1
    • 13.3 合并到主 DDL 基线文件
      • ETL 库 → docs/database/ddl/etl_feiqiu__dws.sql
      • FDW → db/fdw/ 对应文件
      • Requirements: 2.6, 4.1
    • 13.4 编写回滚脚本(逆序 DROP TABLE/VIEW
      • Requirements: 2.6, 4.1
  • 14. BD 手册更新

    • 14.1 创建 BD 手册
      • ETL 库 → apps/etl/connectors/feiqiu/docs/database/dws/main/BD_manual_dws_finance_area_daily.md
      • ETL 库 → apps/etl/connectors/feiqiu/docs/database/dws/main/BD_manual_dws_finance_board_cache.md
      • FDW → docs/database/BD_Manual_fdw_finance_area.md
      • 每份手册包含:字段明细、约束与索引、验证 SQL≥3 条)、兼容性影响、回滚策略
      • 记录变更原因、影响范围
      • Requirements: 2.1, 2.6, 4.1, 4.4
  • 15. 文档同步更新

    • 15.1 更新 ETL 任务文档
      • docs/etl_tasks/ 新增 DWS_FINANCE_AREA_DAILY 和 DWS_FINANCE_BOARD_CACHE 任务文档
      • Requirements: 3.7, 3.8, 5.5, 5.6
    • 15.2 更新后端 README
      • apps/backend/README.md 更新 board_service 和 fdw_queries 模块摘要
      • Requirements: 6.5, 6.6
    • 15.3 更新文档地图
      • docs/DOCUMENTATION-MAP.md 新增本次模块条目BD 手册、ETL 任务文档)
      • Requirements: 2.6, 4.1
  • 16. 变更审计收口

    • 16.1 触发审计子代理audit-writer执行完整审计流程
      • 确认 .kiro/state/.audit_state.jsonaudit_required 已标记
      • 审计子代理自动完成变更审计记录docs/audit/changes/、AI_CHANGELOG、CHANGE 标记注释
      • 高风险路径:tasks/ETLapps/backend/app/(后端)、packages/shared/(共享包)、db/(数据库)
      • Requirements: 全部
    • 16.2 验证审计产物完整性
      • 确认 docs/audit/changes/<YYYY-MM-DD>__board-finance-dws-area-refactor.md 已生成
      • 确认涉及的高风险文件均有 AI_CHANGELOG 条目
      • 确认逻辑变更处有 CHANGE 标记注释含日期、Prompt、直接原因
      • Requirements: 全部
    • 16.3 刷新审计一览表
      • 执行 python scripts/audit/gen_audit_dashboard.py
      • 确认新记录出现在 docs/audit/audit_dashboard.md
      • Requirements: 全部
  • 17. 最终检查点 — 全量验证

    • 运行 Monorepo 属性测试:cd C:\Project\NeoZQYY && pytest tests/ -v
    • 运行 ETL 单元测试:cd apps/etl/connectors/feiqiu && pytest tests/unit -v
    • 运行后端单元测试:cd apps/backend && pytest tests/ -v
    • 确保所有属性测试Property 1-14和单元测试全部通过
    • 确保 DDL 迁移已合并到主基线
    • 确保 BD 手册已同步更新
    • 确保后端 README、文档地图均已更新
    • 确保变更审计记录已生成、AI_CHANGELOG 已写入、审计一览表已刷新
    • ask the user if questions arise.

备注

  • 标记 * 的子任务为可选(属性测试/单元测试),可跳过以加速 MVP
  • 每个任务引用了具体的需求编号以确保可追溯性
  • 属性测试验证通用正确性属性Property 1-14单元测试验证具体边界条件
  • 检查点任务确保增量验证,避免问题累积
  • 本 spec 为跨系统类ETL + 后端 + DB + 共享包),收尾阶段覆盖步骤 1-6
  • 设计文档使用 Python所有实现和测试均使用 Python