Files
Neo-ZQYY/scripts/ops/export_full_bug_report.py

216 lines
10 KiB
Python
Raw Permalink 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.
# -*- coding: utf-8 -*-
"""导出完整 BUG 修复报告BUG 1~11"""
from pathlib import Path
from dotenv import load_dotenv
load_dotenv(Path(__file__).resolve().parents[2] / ".env")
from _env_paths import get_output_path
out = get_output_path("SYSTEM_LOG_ROOT")
report = r"""# ETL 前后端联调 — BUG 修复全记录
> 日期: 2026-02-21
> 执行轮次: v1 ~ v8共 8 次)
> 任务配置: api_full, full_window, 2025-11-01 ~ 2026-02-20, 30天窗口切分, force_full, 19个任务
---
## 总览
| 指标 | v1 (首次) | v6 (中期最佳) | v8 (最终) |
|------|-----------|--------------|-----------|
| 耗时 | 590.7s | 29m26s | 1m24s |
| 成功任务 | 10/41 | 11/19 | 14/19 |
| 失败任务 | 31/41 | 8/19 | 5/19 |
| 累计修复 BUG | 0 | 7 | 11 |
最终 5 个失败均为 `InFailedSqlTransaction` 级联(根因是上游数据质量问题,非代码 BUG
---
## BUG 详情
### BUG 1 — DWS_ASSISTANT_DAILY SQL 字段引用错误
| 项目 | 内容 |
|------|------|
| 发现版本 | v1 |
| 验证版本 | v2 |
| 文件 | `apps/etl/connectors/feiqiu/tasks/dws/assistant_daily_task.py` |
| 错误现象 | `UndefinedColumn: column "xxx" does not exist`DWS_ASSISTANT_DAILY 及其下游 31 个任务全部失败 |
| 根因 | SQL 中引用了 DWD 表中不存在的列名4 处字段名与实际 DDL 不匹配) |
| 修复方式 | 修正 4 处列名引用,对齐 `dwd.dwd_table_fee_log` / `dwd.dwd_assistant_service_log` 的实际 DDL |
| 修复结果 | ✅ v2 中 DWS_ASSISTANT_DAILY 执行成功 |
### BUG 2 — DWS_ASSISTANT_MONTHLY GROUP BY 聚合错误
| 项目 | 内容 |
|------|------|
| 发现版本 | v2 |
| 验证版本 | v3 |
| 文件 | `apps/etl/connectors/feiqiu/tasks/dws/assistant_monthly_task.py` |
| 错误现象 | `UniqueViolation: duplicate key value violates unique constraint` |
| 根因 | GROUP BY 子句缺少必要的聚合列导致同一主键产生多行INSERT 时违反唯一约束 |
| 修复方式 | 将非 GROUP BY 列改用 `MAX()` 聚合函数包裹 |
| 修复结果 | ✅ v3 中 DWS_ASSISTANT_MONTHLY 执行成功(删除 9 行,插入 9 行) |
### BUG 3 — DWS_ASSISTANT_CUSTOMER 引用不存在的 site_id 列
| 项目 | 内容 |
|------|------|
| 发现版本 | v2 |
| 验证版本 | v3 |
| 文件 | `apps/etl/connectors/feiqiu/tasks/dws/assistant_customer_task.py` |
| 错误现象 | `UndefinedColumn: column dm.site_id does not exist` |
| 根因 | `dwd.dim_member` 表没有 `site_id` 列,实际字段为 `register_site_id` |
| 修复方式 | `dm.site_id` → `dm.register_site_id` |
| 修复结果 | ✅ v3 中 DWS_ASSISTANT_CUSTOMER 执行成功285 行) |
### BUG 4 — 多个 DWS 任务引用 dim_member/dim_member_card_account 的 site_id
| 项目 | 内容 |
|------|------|
| 发现版本 | v3 |
| 验证版本 | v4 |
| 文件 | `assistant_customer_task.py`、`member_consumption_task.py`、`finance_recharge_task.py`(共 4 处) |
| 错误现象 | 多个 DWS 任务因 `UndefinedColumn: site_id` 失败 |
| 根因 | 与 BUG 3 同源 — `dim_member` 和 `dim_member_card_account` 均无 `site_id`,需用 `register_site_id` |
| 修复方式 | 4 处 `site_id` → `register_site_id` |
| 修复结果 | ✅ v4 中相关任务执行成功 |
### BUG 5 — DWS_MEMBER_VISIT 引用不存在的 birthday 字段
| 项目 | 内容 |
|------|------|
| 发现版本 | v4 |
| 验证版本 | v6 |
| 文件 | `apps/etl/connectors/feiqiu/tasks/dws/member_visit_task.py` |
| 错误现象 | `UndefinedColumn: column dm.birthday does not exist` |
| 根因 | `dwd.dim_member` 表没有 `birthday` 字段(上游 API 不提供) |
| 修复方式 | 移除 `birthday` 相关的 SELECT/INSERT/GROUP BY 引用 |
| 修复结果 | ✅ v6 中 DWS_MEMBER_VISIT 执行成功v5 被 BUG 6 遮蔽) |
### BUG 6 — DWS_MEMBER_VISIT _extract_table_info() 字段名不匹配
| 项目 | 内容 |
|------|------|
| 发现版本 | v5 |
| 验证版本 | v6 |
| 文件 | `apps/etl/connectors/feiqiu/tasks/dws/member_visit_task.py` |
| 错误现象 | `UndefinedColumn` — `_extract_table_info()` 方法中引用了 DWD 表中不存在的列名 |
| 根因 | `_extract_table_info()` 中的字段名与 `dwd.dwd_table_fee_log` 实际 DDL 不一致 |
| 修复方式 | 修正 `_extract_table_info()` 中的列名映射 |
| 修复结果 | ✅ v6 中 DWS_MEMBER_VISIT 执行成功 |
### BUG 7 — DWS_FINANCE_INCOME_STRUCTURE JOIN 条件列名错误
| 项目 | 内容 |
|------|------|
| 发现版本 | 预防性修复v5 代码审查发现) |
| 验证版本 | v6 |
| 文件 | `apps/etl/connectors/feiqiu/tasks/dws/finance_income_task.py` |
| 错误现象 | JOIN 条件中 `dt.site_table_id` 不存在 |
| 根因 | `dwd.dwd_table_fee_log` 的台桌 ID 列名是 `table_id`,不是 `site_table_id` |
| 修复方式 | `dt.site_table_id` → `dt.table_id` |
| 修复结果 | ✅ v6 中未出现该错误(但被 BUG 8 级联遮蔽) |
### BUG 8 — DWS_FINANCE_DAILY / DWS_FINANCE_RECHARGE 字段名错误
| 项目 | 内容 |
|------|------|
| 发现版本 | v6 |
| 验证版本 | v8 |
| 文件 | `finance_base_task.py`、`finance_recharge_task.py` |
| 错误现象 | `UndefinedColumn: column "pay_money" does not exist`DWS_FINANCE_DAILY 失败并级联导致 7 个下游任务失败 |
| 根因 | `dwd.dwd_recharge_order` 的实际字段是 `pay_amount` / `point_amount`,代码中写的是 `pay_money` / `gift_money` |
| 修复方式 | `pay_money` → `pay_amount``gift_money` → `point_amount`2 个文件) |
| 修复结果 | ✅ v8 中 DWS_FINANCE_DAILY 和 DWS_FINANCE_RECHARGE 均执行成功v7 被 BUG 9 遮蔽) |
### BUG 9 — DWD_LOAD_FROM_ODS 缺少 _pick_snapshot_order_column 方法
| 项目 | 内容 |
|------|------|
| 发现版本 | v7 |
| 验证版本 | v8 |
| 文件 | `apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py` |
| 错误现象 | `AttributeError: 'DwdLoadTask' object has no attribute '_pick_snapshot_order_column'`,所有 dim 表 SCD2 装载全部失败 |
| 根因 | `_merge_dim_scd2` 方法调用了 `self._pick_snapshot_order_column()`,但该方法只存在于 `integrity_checker.py` 中作为模块级函数,`DwdLoadTask` 类中没有定义 |
| 修复方式 | 在 `DwdLoadTask` 类中添加 `_pick_snapshot_order_column` 静态方法(逻辑与 `integrity_checker.py` 中的同名函数一致) |
| 修复结果 | ✅ v8 中所有 15 个 dim 表 SCD2 装载成功dim_site, dim_table, dim_assistant, dim_member, dim_member_card_account, dim_tenant_goods, dim_store_goods, dim_goods_category, dim_groupbuy_package 及其 _ex 表) |
### BUG 10 — goods_stock 表 FACT_MAPPINGS 驼峰字段名导致 SQL 错误
| 项目 | 内容 |
|------|------|
| 发现版本 | v7 |
| 验证版本 | v8 |
| 文件 | `apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py` |
| 错误现象 | `UndefinedColumn: column "siteGoodsId" does not exist, perhaps you mean "sitegoodsid"` |
| 根因 | `FACT_MAPPINGS` 中 `dwd_goods_stock_summary` 和 `dwd_goods_stock_movement` 的源列使用了带引号的驼峰名(如 `"siteGoodsId"`),但 ODS 表中 PostgreSQL 存储的列名是全小写的 `sitegoodsid`ODS 入库时 `_int_col("sitegoodsid", "siteGoodsId")` 已将 JSON 驼峰键转为小写列名) |
| 修复方式 | 将 FACT_MAPPINGS 中 2 个表共 30+ 个字段的驼峰引用全部改为小写(如 `"siteGoodsId"` → `"sitegoodsid"` |
| 修复结果 | ✅ v8 中 `dwd_goods_stock_summary`716 条 INSERT和 `dwd_goods_stock_movement`14306 条 INSERT装载成功 |
### BUG 11 — flow_runner.py sum() 类型不安全
| 项目 | 内容 |
|------|------|
| 发现版本 | v7 |
| 验证版本 | v8 |
| 文件 | `apps/etl/connectors/feiqiu/orchestration/flow_runner.py` |
| 错误现象 | `TypeError: unsupported operand type(s) for +: 'int' and 'list'` |
| 根因 | 某些任务的 `counts.errors` 返回了 `list`(错误详情列表)而非 `int`(错误计数),`sum()` 无法将 `int` 与 `list` 相加 |
| 修复方式 | 添加 `_safe_int()` 辅助函数,将 `int`/`list`/`None` 统一转为 `int` 计数(`list` 取 `len()` |
| 修复结果 | ✅ v8 中不再出现 TypeErrorFlow 汇总正常完成 |
---
## 未修复的遗留问题
### 数据质量问题 — dim_assistant_ex / dim_member_card_account_ex 非法日期
| 项目 | 内容 |
|------|------|
| 发现版本 | v8 |
| 性质 | 上游数据质量问题,非代码 BUG |
| 错误现象 | `ValueError: year -1 is out of range` |
| 根因 | ODS 中某些记录的日期字段包含非法值year=-1Python `datetime` 无法解析 |
| 影响 | `dim_assistant_ex` 和 `dim_member_card_account_ex` 装载失败 → 事务进入 `InFailedSqlTransaction` → 级联导致 5 个 DWS 任务失败DWS_FINANCE_INCOME_STRUCTURE, DWS_FINANCE_DISCOUNT_DETAIL, DWS_WINBACK_INDEX, DWS_NEWCONV_INDEX, DWS_RELATION_INDEX |
| 建议 | 在 DWD 装载的日期类型转换中添加容错处理(捕获 ValueError将非法日期置为 NULL 或哨兵值) |
---
## 修复文件清单
| 文件 | 修复的 BUG |
|------|-----------|
| `apps/etl/connectors/feiqiu/tasks/dws/assistant_daily_task.py` | BUG 1 |
| `apps/etl/connectors/feiqiu/tasks/dws/assistant_monthly_task.py` | BUG 2 |
| `apps/etl/connectors/feiqiu/tasks/dws/assistant_customer_task.py` | BUG 3, 4 |
| `apps/etl/connectors/feiqiu/tasks/dws/member_consumption_task.py` | BUG 4 |
| `apps/etl/connectors/feiqiu/tasks/dws/member_visit_task.py` | BUG 5, 6 |
| `apps/etl/connectors/feiqiu/tasks/dws/finance_income_task.py` | BUG 7 |
| `apps/etl/connectors/feiqiu/tasks/dws/finance_base_task.py` | BUG 8 |
| `apps/etl/connectors/feiqiu/tasks/dws/finance_recharge_task.py` | BUG 4, 8 |
| `apps/etl/connectors/feiqiu/tasks/dwd/dwd_load_task.py` | BUG 9, 10 |
| `apps/etl/connectors/feiqiu/orchestration/flow_runner.py` | BUG 11 |
---
## 执行历史
| 版本 | execution_id | 耗时 | 成功 | 失败 | 修复验证 |
|------|-------------|------|------|------|---------|
| v1 | `dbf0c29a-...` | 590.7s | 10 | 31 | — |
| v2 | `e21e1935-...` | 150.4s | — | — | BUG 1 ✅ |
| v3 | `abc94b2d-...` | 681.2s | 9 | 22 | BUG 2,3 ✅ |
| v4 | `efd4f421-...` | 11m55s | 10 | 21 | BUG 4 ✅ |
| v5 | `fe87144a-...` | 11m37s | 10 | 21 | BUG 5 部署(被 BUG 6 遮蔽) |
| v6 | `d9443781-...` | 29m26s | 11 | 8 | BUG 5,6,7 ✅ |
| v7 | `0929ab3a-...` | 89.3s | — | 全部 | BUG 8 部署(被 BUG 9 遮蔽) |
| v8 | `f943bac6-...` | 1m24s | 14 | 5 | BUG 8,9,10,11 ✅ |
"""
(out / "2026-02-21__etl_full_bug_report.md").write_text(report, encoding="utf-8")
print(f"报告已导出: {out / '2026-02-21__etl_full_bug_report.md'}")