# 设计文档：ETL 全流程前后端联调（etl-fullstack-integration）

## 概述

本 Spec 是一个运维联调任务，不涉及新功能开发。目标是验证 `admin-web-console` Spec 产出的前后端代码在真实环境下的端到端正确性，同时收集性能数据。

核心流程：
1. 启动后端 + 前端服务
2. 通过 API 登录获取 JWT
3. 提交全流程 ETL 任务（api_full, full_window, force-full, 全选常用任务, 自定义窗口 2025-11-01~当前时间, 30天切分, 全部门店）
4. 实时监控执行过程，捕获错误/警告
4. 执行完成后进行黑盒数据一致性测试（全链路检查器 `scripts/ops/etl_consistency_check.py` + FlowRunner 内置 `ConsistencyChecker`）
5. 生成综合报告（含性能数据和黑盒测试结果）

## 架构

```
联调脚本 (scripts/ops/)
    │
    ├── 1. 启动服务
    │   ├── uvicorn app.main:app (后端 :8000)
    │   └── pnpm dev (前端 :5173)
    │
    ├── 2. API 调用链
    │   ├── POST /api/auth/login → JWT
    │   ├── GET /api/tasks/registry → 任务列表
    │   ├── GET /api/tasks/sync-check → 同步检查
    │   ├── POST /api/tasks/validate → CLI 预览
    │   └── POST /api/execution/run → 触发执行
    │
    ├── 3. 监控循环
    │   ├── GET /api/execution/queue → 状态轮询
    │   ├── GET /api/execution/{id}/logs → 日志获取
    │   └── 错误/警告检测
    │
    ├── 4. 黑盒数据一致性测试
    │   ├── 全链路检查器（scripts/ops/etl_consistency_check.py）
    │   │   ├── API JSON vs ODS：字段完整性 + 值采样比对
    │   │   ├── ODS vs DWD：行数 + 字段映射 + 值比对（含 EX 表合并）
    │   │   ├── DWD vs DWS：聚合表行数 + 数值列健全性检查
    │   │   └── 白名单机制：ETL_META_COLS / SCD2_COLS / 空字符串≡None
    │   ├── FlowRunner 内置检查（quality/consistency_checker.py，自动执行）
    │   └── etl-data-consistency Hook（可选手动触发）
    │
    └── 5. 报告生成
        └── 输出到 SYSTEM_LOG_ROOT
```

## 任务参数

根据用户需求，联调任务的具体参数：

```python
INTEGRATION_TASK_CONFIG = {
    "flow": "api_full",                    # 全流程：API → ODS → DWD → DWS → INDEX
    "processing_mode": "full_window",      # 全窗口处理
    "window_mode": "custom",               # 自定义时间范围
    "window_start": "2025-11-01 00:00",
    "window_end": "",                      # 补充当前时间
    "window_split": "day",                 # 按天切分
    "window_split_days": 30,               # 30天一个切片
    "force_full": True,                    # 强制全量
    "dry_run": False,
    "tasks": [                             # 全选 is_common=True 的任务
        # ODS 层（22 个）
        "ODS_ASSISTANT_ACCOUNT", "ODS_ASSISTANT_LEDGER", "ODS_ASSISTANT_ABOLISH",
        "ODS_SETTLEMENT_RECORDS", "ODS_TABLE_USE", "ODS_TABLE_FEE_DISCOUNT",
        "ODS_TABLES", "ODS_PAYMENT", "ODS_REFUND", "ODS_PLATFORM_COUPON",
        "ODS_MEMBER", "ODS_MEMBER_CARD", "ODS_MEMBER_BALANCE", "ODS_RECHARGE_SETTLE",
        "ODS_GROUP_PACKAGE", "ODS_GROUP_BUY_REDEMPTION",
        "ODS_INVENTORY_STOCK", "ODS_INVENTORY_CHANGE",
        "ODS_GOODS_CATEGORY", "ODS_STORE_GOODS", "ODS_STORE_GOODS_SALES", "ODS_TENANT_GOODS",
        # DWD 层（1 个常用）
        "DWD_LOAD_FROM_ODS",
        # DWS 层（15 个常用，排除 DWS_MAINTENANCE）
        "DWS_BUILD_ORDER_SUMMARY", "DWS_ASSISTANT_DAILY", "DWS_ASSISTANT_MONTHLY",
        "DWS_ASSISTANT_CUSTOMER", "DWS_ASSISTANT_SALARY", "DWS_ASSISTANT_FINANCE",
        "DWS_MEMBER_CONSUMPTION", "DWS_MEMBER_VISIT",
        "DWS_FINANCE_DAILY", "DWS_FINANCE_RECHARGE", "DWS_FINANCE_INCOME_STRUCTURE",
        "DWS_FINANCE_DISCOUNT_DETAIL",
        "DWS_GOODS_STOCK_DAILY", "DWS_GOODS_STOCK_WEEKLY", "DWS_GOODS_STOCK_MONTHLY",
        # INDEX 层（3 个常用，排除 DWS_ML_MANUAL_IMPORT）
        "DWS_WINBACK_INDEX", "DWS_NEWCONV_INDEX", "DWS_RELATION_INDEX",
    ],
    # store_id 由后端从 JWT 注入（默认管理员 site_id=1）
    # 注意：用户要求"全部门店"，但当前系统只有 site_id=1，后续多门店需逐个执行
}
```

## 监控策略

- 轮询间隔：30 秒
- 最长等待：30 分钟（无新日志输出时）
- 错误检测：日志行匹配 `ERROR`、`CRITICAL`、`Traceback`、`Exception`
- 警告检测：日志行匹配 `WARNING`、`WARN`
- 计时解析：从日志中提取时间戳，计算阶段耗时

## 黑盒数据一致性测试

### 两套检查工具的定位

| 工具 | 路径 | 触发方式 | 覆盖范围 | 适用场景 |
|------|------|---------|---------|---------|
| 全链路检查器 | `scripts/ops/etl_consistency_check.py` | 手动运行 / `etl-data-consistency` Hook | API→ODS→DWD→DWS 四层全链路 | 联调后独立全面验证（本 Spec 主要使用） |
| FlowRunner 内置检查 | `apps/etl/connectors/feiqiu/quality/consistency_checker.py` | FlowRunner 自动调用 `_run_post_consistency_check()` | API→ODS 字段 + ODS→DWD 映射/值 | ETL 执行后自动轻量检查 |

联调场景下，FlowRunner 在 ETL 执行完成后已自动运行内置检查并输出报告到 `ETL_REPORT_ROOT`。联调脚本额外运行全链路检查器，覆盖 DWD→DWS 聚合验证和更深入的值采样比对。

### etl-data-consistency Hook

`.kiro/hooks/etl-data-consistency.kiro.hook` 提供手动触发入口，执行 `scripts/ops/etl_consistency_check.py`。联调任务 5 也可通过此 Hook 替代手动运行脚本。

### 白名单机制

全链路检查器在值比对时使用三层白名单过滤，避免 ETL 框架自动填充的列和已知等价差异产生误报：

#### 1. ETL 元数据列白名单（`ETL_META_COLS`）

不参与 API↔ODS 值比对的列：

```python
ETL_META_COLS = {"source_file", "source_endpoint", "fetched_at", "payload", "content_hash"}
```

这些列由 ETL 框架在 ODS 落库时自动填充，API 源数据中不存在。

#### 2. SCD2 管理列白名单（`SCD2_COLS`）

不参与 ODS↔DWD 值比对的列：

```python
SCD2_COLS = {
    "valid_from", "valid_to", "is_current", "etl_loaded_at", "etl_batch_id",
    "scd2_start_time", "scd2_end_time", "scd2_is_current", "scd2_version",
}
```

这些列由 DWD 层 SCD2 逻辑自动维护，ODS 源数据中不存在。

#### 3. 空字符串 vs None 等价规则（`_values_differ()`）

API 返回空字符串 `""` 而数据库存储为 `None` 时，视为等价（不算差异），但标记为 `whitelist`：

```python
# API 空字符串 "" vs DB None → 白名单（等价但标记）
if api_val is not None and ods_val is None:
    if isinstance(api_val, str) and api_val.strip() == "":
        return False, "whitelist"
```

报告中白名单差异以折叠 `<details>` 块展示，不计入失败统计。

#### 4. FlowRunner 内置检查的白名单

`consistency_checker.py` 使用类似但略有不同的白名单：
- `ODS_META_COLUMNS`：与 `ETL_META_COLS` 相同，额外包含 `record_index`
- `KNOWN_NO_SOURCE`：按表配置的已知无源字段（如 `dwd.dim_member.update_time`），标记为已知无源而非报错

### 调用方式

联调脚本在 ETL 全流程执行完成后，运行全链路检查器：

```bash
cd C:\Project\NeoZQYY
uv run python scripts/ops/etl_consistency_check.py
```

脚本自动完成：
1. 从 `LOG_ROOT` 找到最近一次 ETL 日志，解析执行的任务列表
2. 从 `FETCH_ROOT` 读取 API JSON 落盘文件
3. 连接数据库（`PG_DSN`），逐表逐字段比对：
   - API JSON vs ODS：字段完整性 + 值采样比对（随机 5 条）
   - ODS vs DWD：行数 + 字段映射 + 值比对（含 EX 表合并）
   - DWD vs DWS：聚合表行数 + 数值列健全性（NULL 率、负值、min/max）
4. 输出 Markdown 报告到 `ETL_REPORT_ROOT`

### 检查内容

| 检查类型 | 对比对象 | 检查项 | 白名单处理 |
|---------|---------|--------|-----------|
| API vs ODS | API JSON 缓存 vs ODS 表 | 字段完整性 + 值采样比对（5 条记录） | `ETL_META_COLS` 排除；空字符串≡None |
| ODS vs DWD | ODS 表 vs DWD 表（含 EX 表） | 行数对比 + 字段映射 + 值比对 | `SCD2_COLS` 排除；空字符串≡None |
| DWD vs DWS | DWD 源表 vs DWS 聚合表 | 行数非空 + 数值列健全性（NULL 率、负值、min/max） | 无（DWS 为聚合结果，不做逐行值比对） |

### 报告格式

全链路检查器输出 Markdown 报告，包含：
1. ETL 执行概览（任务列表、成功/失败/跳过统计）
2. API↔ODS 数据一致性（逐表逐字段值比对，白名单差异折叠展示）
3. ODS↔DWD 数据一致性（行数对比 + 映射验证 + 值采样，含字段级统计）
4. DWD↔DWS 数据一致性（DWS 表概览 + 数值列健全性检查）
5. 异常汇总与建议

### 参考数据

`dataflow-field-completion` 的实际执行结果：API vs ODS 22/22 通过，ODS vs DWD 38/42 通过。本次联调执行 api_full 全流程后，预期结果应与此一致或更优（因为联调包含最新的字段补全）。

## 报告格式

报告输出为 Markdown 文件，路径：`{SYSTEM_LOG_ROOT}/{date}__etl_integration_report.md`

```markdown
# ETL 全流程联调报告

## 执行概要
- 任务参数：...
- 开始时间 / 结束时间 / 总时长
- 退出码 / 最终状态

## 性能报告
- 各窗口切片耗时对比表
- Top-5 耗时阶段
- 总体吞吐量估算

## 黑盒测试报告
- API vs ODS：X/Y 张表通过（白名单差异 N 处）
- ODS vs DWD：X/Y 张表通过（白名单差异 N 处）
- DWD vs DWS：X 张表有数据 / Y 张总计，异常指标 N 个
- 失败表清单及差异明细

## DEBUG 报告（如有）
- 错误摘要
- 警告摘要
- 相关日志片段
- 可能的原因分析
```

## 正确性属性

本 Spec 为运维联调任务，不涉及新功能代码开发，因此不定义形式化的属性测试。验证通过以下方式进行：
- 服务健康检查通过
- 任务提交成功并开始执行
- 执行完成后退出码和日志符合预期
- 黑盒数据一致性测试通过（全链路检查器覆盖 API→ODS→DWD→DWS 四层，白名单差异不计入失败）
- 报告文件成功生成（含性能报告和黑盒测试报告）

## 测试策略

本 Spec 本身就是一次集成测试。不额外编写单元测试或属性测试。验证标准：
- 后端 API 响应正确
- ETL CLI 子进程正常启动和执行
- 日志正确捕获和推送
- 黑盒数据一致性测试通过（全链路检查器 API→ODS→DWD→DWS + FlowRunner 内置检查）
- 报告文件正确生成到 ETL_REPORT_ROOT（全链路检查报告）和 SYSTEM_LOG_ROOT（联调综合报告）

### 黑盒测试验证标准

- API vs ODS：所有已采集的 ODS 表字段完整性和值采样检查通过（白名单差异不计入失败）
- ODS vs DWD：所有已配置映射的表行数和值比对检查通过（SCD2 列排除，白名单差异不计入失败）
- DWD vs DWS：所有 DWS 聚合表行数非空，数值列无异常（高 NULL 率、金额负值等）
- 全链路检查报告 `consistency_check_<timestamp>.md` 成功生成到 ETL_REPORT_ROOT
- 综合联调报告中包含黑盒测试结果摘要（含白名单差异统计）
