# 实现计划：数据流字段补全与前后端联调

## 概述

按"先排查确认 → 再 DDL 变更 → 再代码映射 → 再移除废弃表 → 再 DWS 汇总 → 再文档精化 → 最后联调"的顺序，分阶段推进。每个表的字段补全遵循"先确认再新增"原则。

执行依据：`export/SYSTEM/REPORTS/field_audit/field_review_for_user.md`（逐表逐字段排查结论）

## 任务

- [x] 1. 字段排查脚本与基础设施
  - [x] 1.1 编写字段排查脚本 `scripts/ops/field_audit.py`
    - 连接数据库，对每张目标表执行排查流程：查 DWD 现有列、查 FACT_MAPPINGS 现状、查 ODS 列、查自动映射
    - 输出排查记录表（markdown 格式），标注每个字段的排查结论和建议操作
    - 覆盖 11 张表的所有疑似缺失字段
    - _Requirements: 1.1-1.4, 2.1-2.3, 3.1-3.3, 4.1-4.3, 5.1-5.3, 6.1-6.4, 7.1-7.4, 8.1-8.4, 9.1-9.3, 10.1-10.5, 11.1-11.3_

  - [x] 1.2 执行排查脚本，生成排查报告
    - 运行脚本，审查输出结果
    - _Requirements: 1.1-1.4_

  - [x] 1.3 逐字段调查与推测，确认排查结论（由 Kiro 执行）
    - 结论文档：`export/SYSTEM/REPORTS/field_audit/field_review_for_user.md`
    - 脚本输出仅为线索，不能直接作为最终结论
    - 对脚本标记为"缺失"或"对不齐"的每个字段，Kiro 需逐一执行以下调查：
      - 查阅 FACT_MAPPINGS 源码，确认是否已以其他名称/表达式映射
      - 查阅 DWD DDL，确认是否已有同语义列（命名差异）
      - 查阅 ODS loader 代码，确认 ODS 列是否真实写入
      - 结合字段命名规律、上下文语义、业务逻辑进行推测
      - 必要时查询数据库实际数据（SELECT DISTINCT / 采样）辅助判断
    - 对每个字段标注最终决策：无需变更 / 仅补映射 / 新增列+映射 / 跳过（附理由）
    - 将调查过程和推测依据记录到排查报告中，确保可追溯
    - _Requirements: 1.1-1.4, 2.1-2.3, 3.1-3.3, 4.1-4.3, 5.1-5.3, 6.1-6.4, 7.1-7.4, 8.1-8.4, 9.1-9.3, 10.1-10.5, 11.1-11.3_

- [x] 2. Checkpoint - 排查结果确认
  - 此项已完成，最终文档为：`export/SYSTEM/REPORTS/field_audit/field_review_for_user.md` 

- [x] 3. 🔴 映射错误修复（高优先级）
  - 依据：`field_review_for_user.md` 映射错误修复章节

  - [x] 3.1 assistant_service_records — site_assistant_id 映射错误修正
    - 当前问题：DWD `dwd_assistant_service_log.site_assistant_id` 错误映射自 ODS `order_assistant_id`（订单级 ID），应映射自 ODS `site_assistant_id`（助教档案 ID）
    - 修正 FACT_MAPPINGS：将 DWD `site_assistant_id` 的 ODS 源从 `order_assistant_id` 改为 `site_assistant_id`
    - 新增 DWD 列 `order_assistant_id`（bigint）到 `dwd_assistant_service_log`，映射 ODS `order_assistant_id`
    - 编写迁移脚本
    - 需重新加载历史数据
    - _Requirements: 2.1, 2.2_

  - [x] 3.2 store_goods_sales_records — discount_price 列名误导修正
    - 当前问题：DWD `discount_price` 实际映射自 ODS `discount_money`（折扣金额），而非 ODS `discount_price`（折后单价）
    - 将 DWD 列名 `discount_price` 重命名为 `discount_money`
    - 新增 DWD 列 `discount_price`（numeric），映射 ODS `discount_price`（折后单价）
    - 编写迁移脚本
    - _Requirements: 4.1, 4.2_

  - [x] 3.3 store_goods_master — batch_stock_qty 和 provisional_total_cost 映射源修正
    - `batch_stock_qty` 的 FACT_MAPPINGS 从 `stock`（当前库存）改为 `batch_stock_quantity`（批次库存）
    - `provisional_total_cost` 的 FACT_MAPPINGS 从 `total_purchase_cost`（实际采购成本）改为 `provisional_total_cost`（暂估成本）
    - 需重新加载历史数据
    - _Requirements: 10.3_

- [x] 4. A 类表：新增 DWD 列 + FACT_MAPPINGS
  - 依据：`field_review_for_user.md` 各表"待新增/补映射字段"

  - [x] 4.1 assistant_accounts_master — 新增 4 个字段到 dim_assistant_ex
    - 新增列：`system_role_id`（bigint）、`job_num`（text）、`cx_unit_price`（numeric(18,2)）、`pd_unit_price`（numeric(18,2)）
    - 更新 `dwd.sql`，添加 FACT_MAPPINGS 条目
    - 编写迁移脚本
    - _Requirements: 1.1, 1.2, 1.3_

  - [x] 4.2 assistant_service_records — 新增 2 个字段到 dwd_assistant_service_log_ex
    - 新增列：`operator_id`（bigint）、`operator_name`（text）
    - 跳过 `siteprofile`（jsonb 嵌套列）
    - 更新 `dwd.sql`，添加 FACT_MAPPINGS 条目
    - 编写迁移脚本
    - _Requirements: 2.1, 2.2_

  - [x] 4.3 assistant_cancellation_records — 更新 FACT_MAPPINGS
    - 更新映射：ODS `assistanton` → DWD `dwd_assistant_trash_event.assistant_no`
    - 跳过 `siteprofile`（jsonb 嵌套列）
    - _Requirements: 3.1_

  - [x] 4.4 member_balance_changes — 新增 1 个字段到 dwd_member_balance_change_ex
    - 新增列：`relate_id`（bigint）— 关联业务单据 ID
    - 更新 `dwd.sql`，添加 FACT_MAPPINGS 条目
    - 编写迁移脚本
    - _Requirements: 5.1, 5.2_

  - [x] 4.5 site_tables_master — 新增 14 个字段到 dim_table_ex
    - 新增列：`create_time`（timestamptz）、`light_status`（integer）、`tablestatusname`（text）、`sitename`（text）、`appletQrCodeUrl`（text）、`audit_status`（integer）、`charge_free`（integer）、`delay_lights_time`（integer）、`is_rest_area`（integer）、`only_allow_groupon`（integer）、`order_delay_time`（integer）、`self_table`（integer）、`temporary_light_second`（integer）、`virtual_table`（integer）
    - 更新 `dwd.sql`，添加 FACT_MAPPINGS 条目
    - 编写迁移脚本
    - _Requirements: 9.1, 9.2_

  - [x] 4.6 tenant_goods_master — 无需变更（跳过）
    - `commoditycode` 与 `commodity_code` 100% 冗余（花括号包裹格式），已确认跳过
    - _Requirements: 11.1（已确认无需操作）_

  - [x] 4.7 编写 A 类表字段映射属性测试
    - **Property 1: FACT_MAPPINGS 字段映射正确性**
    - **Validates: Requirements 1.1, 1.2, 2.1, 3.1, 4.1, 5.1, 9.1**

- [x] 5. B 类表：仅补 FACT_MAPPINGS / 修正映射
  - 依据：`field_review_for_user.md` B 类表章节

  - [x] 5.1 recharge_settlements — 补充 5 个 FACT_MAPPINGS 条目
    - 仅补映射（DWD 列已存在，ODS/DWD 两侧数据全为 0，业务未启用）：
      - `plcouponsaleamount → pl_coupon_sale_amount`
      - `mervousalesamount → mervou_sales_amount`
      - `electricitymoney → electricity_money`
      - `realelectricitymoney → real_electricity_money`
      - `electricityadjustmoney → electricity_adjust_money`
    - 无需 DDL 变更，无需迁移脚本
    - _Requirements: 6.1, 6.2, 6.3_

  - [x] 5.2 编写 B 类表属性测试
    - **Property 2: FACT_MAPPINGS 引用完整性**
    - **Validates: Requirements 6.3**

- [x] 5.5. Checkpoint - 映射修复与 A/B 类表完成确认
  - 确保所有映射错误已修正、A/B 类表的 FACT_MAPPINGS、DDL、迁移脚本都已更新
  - Ask the user if questions arise.

- [x] 6. C 类表：新建 DWD 表与完整映射
  - 依据：`field_review_for_user.md` C 类表章节

  - [x] 6.1 goods_stock_summary — 修改 ODS 配置 + 新建 DWD 表
    - 步骤 1：修改 ODS 任务配置 `requires_window=True` + `time_fields=("startTime", "endTime")`
    - 步骤 2：重新采集历史数据（按时间窗口分批）
    - 步骤 3：编写 DDL 创建 `dwd.dwd_goods_stock_summary`（14 个字段）
    - 步骤 4：在 `TABLE_MAP` 中注册，在 `FACT_MAPPINGS` 中添加映射
    - 步骤 5：创建 DWD loader 和 task 代码
    - 编写迁移脚本
    - _Requirements: 7.1, 7.2, 7.3_

  - [x] 6.2 goods_stock_movements — 新建 DWD 表
    - 编写 DDL 创建 `dwd.dwd_goods_stock_movement`（19 个字段，事实表，按 createtime 增量加载）
    - 在 `TABLE_MAP` 中注册，在 `FACT_MAPPINGS` 中添加映射（驼峰 → 蛇形命名）
    - 创建 DWD loader 和 task 代码
    - 编写迁移脚本
    - _Requirements: 8.1, 8.2, 8.3_

  - [x] 6.3 编写 C 类表属性测试
    - **Property 3: TABLE_MAP 覆盖完整性**
    - **Validates: Requirements 7.2, 8.2**

- [x] 7. Checkpoint - 全部字段补全完成
  - 确保所有 11 张表的字段补全工作完成，所有测试通过，ask the user if questions arise.

- [x] 7.3. 彻底移除 settlement_ticket_details
  - [x] 7.3.1 移除 ETL 核心代码中的 settlement_ticket_details
    - 从 `tasks/ods/ods_tasks.py` 中移除：`OdsTaskSpec("ODS_SETTLEMENT_TICKET", ...)`、`OdsSettlementTicketTask` 类、`ENABLED_ODS_CODES` 中的条目、`ODS_TASK_CLASSES` 覆盖
    - 从 `tasks/verification/dwd_verifier.py` 中移除主键映射条目
    - 从 `tasks/verification/ods_verifier.py` 中移除相关注释和特殊处理
    - 从 `tasks/utility/manual_ingest_task.py` 中移除表映射和配置
    - 从 `utils/json_store.py` 中移除 `/order/getordersettleticketnew` 路径映射
    - _Requirements: 17.1, 17.3_

  - [x] 7.3.2 移除 DDL、种子数据和迁移脚本
    - 从 `db/etl_feiqiu/schemas/ods.sql` 和 `schema_ODS_doc.sql` 中移除建表语句和注释
    - 从 `db/etl_feiqiu/seeds/seed_ods_tasks.sql` 中移除 `ODS_SETTLEMENT_TICKET`
    - 编写迁移脚本：`DROP TABLE IF EXISTS ods.settlement_ticket_details`、`DROP INDEX`、`DELETE FROM meta.ods_task_registry`
    - _Requirements: 17.2, 17.4, 17.6_

  - [x] 7.3.3 移除分析脚本和工具中的引用
    - 从 `scripts/ops/` 下移除：`gen_full_dataflow_doc.py`、`gen_field_review_doc.py`、`gen_api_field_mapping.py`、`field_audit.py`、`export_dwd_field_review.py`、`dataflow_analyzer.py`、`check_ods_latest_indexes.py` 中的相关引用
    - 从 `scripts/check/check_ods_gaps.py` 中移除 `_check_settlement_tickets` 函数及调用
    - 从 `scripts/debug/debug_blackbox.py` 中移除跳过逻辑
    - _Requirements: 17.7_

  - [x] 7.3.4 移除文档和测试中的引用
    - 从 `docs/database/etl_feiqiu_schema_migration.md` 中移除索引条目
    - 从 `apps/etl/connectors/feiqiu/docs/etl_tasks/` 中移除任务表格条目
    - 从 `tests/unit/test_ods_tasks.py` 中移除 `test_ods_settlement_ticket_by_payment_relate_ids`
    - _Requirements: 17.5, 17.8_

- [x] 7.5. DWS 库存汇总（日/周/月）
  - 前置依赖：任务 6.1（goods_stock_summary DWD 表）完成、ODS 任务配置修改（`requires_window=True`）完成并重新采集数据

  - [x] 7.5.1 编写 DWS 库存汇总 DDL 与迁移脚本
    - 在 `db/etl_feiqiu/schemas/dws.sql` 中添加三张表的建表语句：`dws_goods_stock_daily_summary`、`dws_goods_stock_weekly_summary`、`dws_goods_stock_monthly_summary`
    - 编写迁移脚本 `db/etl_feiqiu/migrations/{date}__create_dws_goods_stock_summary.sql`
    - 主键：`(site_id, stat_date, site_goods_id)`
    - 字段：site_id, tenant_id, stat_date, site_goods_id, goods_name, goods_unit, goods_category_id, goods_category_second_id, category_name, range_start_stock, range_end_stock, range_in, range_out, range_sale, range_sale_money, range_inventory, current_stock, stat_period, created_at, updated_at
    - _Requirements: 12.5, 12.6, 12.8_

  - [x] 7.5.2 实现 DWS_GOODS_STOCK_DAILY 任务
    - 在 `apps/etl/connectors/feiqiu/tasks/dws/` 下创建 `goods_stock_daily_task.py`
    - 继承 `BaseDwsTask`，实现 `extract` / `transform` / `load` 三阶段
    - extract：从 `dwd.dwd_goods_stock_summary` 按时间范围查询
    - transform：按日粒度汇总，`stat_period='daily'`
    - load：upsert 写入 `dws.dws_goods_stock_daily_summary`
    - _Requirements: 12.2, 12.7_

  - [x] 7.5.3 实现 DWS_GOODS_STOCK_WEEKLY 任务
    - 创建 `goods_stock_weekly_task.py`，按 ISO 周分组，`stat_date` = 周一日期，`stat_period='weekly'`
    - _Requirements: 12.3, 12.7_

  - [x] 7.5.4 实现 DWS_GOODS_STOCK_MONTHLY 任务
    - 创建 `goods_stock_monthly_task.py`，按自然月分组，`stat_date` = 月首日期，`stat_period='monthly'`
    - _Requirements: 12.4, 12.7_

  - [x] 7.5.5 注册 DWS 库存汇总任务到任务调度
    - 在任务注册表中添加 `DWS_GOODS_STOCK_DAILY`、`DWS_GOODS_STOCK_WEEKLY`、`DWS_GOODS_STOCK_MONTHLY`
    - 确保任务依赖关系正确（依赖 DWD goods_stock_summary 加载完成）
    - _Requirements: 12.9_

  - [x] 7.5.6 编写 DWS 库存汇总属性测试
    - **Property 8: DWS 库存汇总粒度聚合正确性**
    - **Validates: Requirements 12.2, 12.3, 12.4, 12.5, 12.6**


- [x] 8. 文档精化
  - [x] 8.1 精化 A/B/C 类表涉及的 BD_Manual 文档
    - 逐个文档、逐项排查所有"待补充""待处理""未确定""未定义"等缺失内容
    - 将"金额字段""XX 相关""XXX 类"等粗略说明替换为精确的字段语义描述
    - 通过字段名称分析、上下文推测、遍历值/枚举值分析、代码取用情况分析确定字段含义
    - 确保每个字段说明包含：字段类型、业务含义、取值范围或枚举值、在代码中的使用位置
    - _Requirements: 13.1, 13.2, 13.3, 13.4_

  - [x] 8.2 更新 dataflow 分析报告中涉及表的字段说明
    - 同步更新 `docs/database/` 下对应的文档
    - _Requirements: 1.4, 2.3, 3.3, 4.3, 5.3, 6.4, 7.4, 8.4, 9.3, 10.5, 11.3_

- [x] 9. Checkpoint - 文档精化完成
  - 确保所有文档更新完毕，无遗留的"待补充"标记，ask the user if questions arise.

- [x] 10. Admin-Web 前后端联调
  - [x] 10.1 排查并修复后端 ETL 执行 API
    - 检查 `apps/backend/app/routers/` 中 ETL 执行相关路由
    - 确保参数解析正确：全部门店、api_full、仅校验修复且校验前从 API 获取、自定义范围 2025-11-01 至 2026-02-20、窗口切分 10 天、force-full、全选常用功能
    - 确保参数正确转换为 ETL CLI 命令
    - _Requirements: 14.1, 14.2_

  - [x] 10.2 排查并修复前端 TaskManager 页面
    - 检查 `apps/admin-web/src/pages/TaskManager.tsx` 中的参数配置表单
    - 确保所有参数选项可正确选择和提交
    - 确保任务执行状态实时展示（WebSocket 日志流）
    - _Requirements: 14.3_

  - [x] 10.3 实现 ETL 执行计时器模块
    - 在 `apps/etl/connectors/feiqiu/utils/` 中新增计时器工具
    - 记录每个步骤和分步骤的开始时间、结束时间、耗时（精确到毫秒）
    - 全部任务完成后输出计时结果文档
    - _Requirements: 15.1, 15.2, 15.3_

  - [x] 10.4 编写计时器属性测试
    - **Property 7: 计时器记录完整性**
    - **Validates: Requirements 15.2**

  - [x] 10.5 编写 ETL 参数解析属性测试
    - **Property 5: ETL 参数解析与 CLI 命令构建正确性**
    - **Validates: Requirements 14.1, 14.2**

- [x] 11. 黑盒测试机制
  - [x] 11.1 实现数据一致性检查器
    - 在 `apps/etl/connectors/feiqiu/quality/` 中新增一致性检查模块
    - 实现 API 源数据 vs ODS 落库数据的字段完整性对比
    - 实现 ODS 数据 vs DWD 落库数据的映射正确性对比
    - 输出黑盒测试报告（每张表的检查结果、差异明细、通过/失败状态）
    - _Requirements: 16.1, 16.2, 16.3, 16.4_

  - [x] 11.2 编写数据一致性检查属性测试
    - **Property 6: 数据一致性检查正确性**
    - **Validates: Requirements 16.2, 16.3**

- [x] 12. 端到端联调验证
  - [x] 12.1 执行完整 ETL 流程并验证数据正确性
    - 将 `EtlTimer` 集成到 `orchestration/flow_runner.py` 的 `FlowRunner.run()` 方法中
    - 增量 ETL 和校验分支均包裹计时步骤（`INCREMENT_ETL`、`VERIFICATION`、`FETCH_BEFORE_VERIFY`）
    - `timer.finish(write_report=True)` 在 Flow 结束时自动输出计时报告到 `ETL_REPORT_ROOT`
    - 产出物：`export/ETL-Connectors/feiqiu/REPORTS/etl_timing_*.md`
    - _Requirements: 14.4, 15.3_

  - [x] 12.2 执行黑盒测试并生成报告
    - 将 `ConsistencyChecker` 集成到 `FlowRunner.run()` 的 `_run_post_consistency_check()` 方法中
    - ETL Flow 完成后自动运行一致性检查（API vs ODS + ODS vs DWD），输出报告到 `ETL_REPORT_ROOT`
    - 独立验证脚本 `scripts/ops/run_post_etl_reports.py` 确认报告生成正常
    - 实际执行结果：API vs ODS 22/22 通过，ODS vs DWD 38/42 通过
    - 产出物：`export/ETL-Connectors/feiqiu/REPORTS/consistency_report_*.md`
    - _Requirements: 16.1, 16.4_

  - [x] 12.3 前后端浏览器联调验证（2026-02-20）
    - 启动后端 `uvicorn app.main:app --reload`（localhost:8000）+ 前端 `pnpm dev`（localhost:5173）
    - 浏览器登录管理后台，进入"任务配置"页面
    - 配置：Flow=ods_dwd, 处理模式=仅增量, dry-run=✓, 本地JSON=✓, 回溯24h
    - 点击"直接执行"→ 自动跳转"任务管理 > 历史"tab
    - 验证结果：status=success, duration=22.5s, exit_code=0
    - CLI 命令正确构建：`python -m cli.main --flow ods_dwd --processing-mode increment_only --tasks DWD_LOAD_FROM_ODS --lookback-hours 24 --overlap-seconds 600 --dry-run --data-source offline --store-id 2790685415443269`
    - 执行日志实时推送到前端 Modal（WebSocket /ws/logs/{id}）✅
    - 计时报告自动生成：`etl_timing_20260220_073610.md`（2步骤，总耗时20.78s）✅
    - 一致性检查报告自动生成：`consistency_report_20260220_073610.md` ✅
    - _Requirements: 14.1, 14.2, 14.3, 14.4, 15.3, 16.4_

- [x] 13. Final checkpoint - 全部完成
  - 确保所有字段补全、文档精化、前后端联调、黑盒测试均已完成，ask the user if questions arise.

## 备注

- 标记 `*` 的任务为可选，可跳过以加速 MVP
- 每个任务引用具体需求编号以确保可追溯
- Checkpoint 确保增量验证
- 属性测试验证通用正确性属性，单元测试验证具体示例和边界情况
- 所有涉及 `loaders/`、`tasks/`、`db/` 的变更属于高风险路径，完成后需触发 `/audit`
