# 变更审计记录：RNS1.3 三看板 FDW 查询层数据口径修复

| 字段 | 值 |
|------|-----|
| 日期 | 2026-03-19 16:23:59 |
| Prompt-ID | P20260319-160132 |
| Session-ID | 088656c4 |
| Session 路径 | docs/audit/session_logs/2026-03/19/41_54e4189f_160131 |

## 操作摘要

根据 feiqiu-data-rules 审计 rns1-board-apis SPEC 实现，修复 `fdw_queries.py` 中 6 个函数的数据口径和功能缺陷。审计发现 9 个问题（3 P0 + 3 P1 + 3 P2），本次修复可修复的 6 个（P0 全部 + P1-4/5 + P2-7）。同时完成 E2E 测试修正、board_service 环比逻辑修正、文档同步更新。

---

## 1. 变更原因

### 原始原因（Prompt）
CONTEXT TRANSFER：继续 rns1-board-apis spec Tasks 17-20（全量验证、E2E 测试、文档更新、审计）。用户要求"先查库，然后对比 dws-doc-authority.md，若吻合，则修改代码"。

### 直接原因
feiqiu-data-rules 审计发现 fdw_queries.py 中 6 个函数存在数据口径错误或功能缺失：
- P0-1: 储值金额数据源错误
- P0-2: 消费潜力指数未实际查询
- P0-3: 财务收入层级映射错误
- P1-4: 助教技能筛选未实现
- P1-5: 项目筛选未实现
- P2-7: ideal_days 硬编码为 0

---

## 2. 改动方案

### 2.1 fdw_queries.py — 6 个函数修复

| 编号 | 函数 | 修复内容 |
|------|------|---------|
| P0-1 | `get_coach_sv_data()` | 数据源从 `v_dws_assistant_monthly_summary` 改为 `v_dws_assistant_recharge_commission`，修正储值金额口径 |
| P0-2 | `get_customer_board_potential()` | 从空列表降级改为实际查询 `v_dws_member_spending_power_index`，支持消费潜力指数排行 |
| P0-3 | `get_finance_revenue()` | 修复 `structure_type` 层级映射（AREA→is_sub=True），填充 `price_items` 和 `channel_items` |
| P1-4 | `get_all_assistants()` | 通过 LEFT JOIN `v_dws_assistant_project_tag` 实现 `skill_filter` 筛选 |
| P1-5 | `_project_filter_clause()` | 通过 `v_dws_member_project_tag` 子查询实现项目筛选 |
| P2-7 | `get_customer_board_recent()` | `ideal_days` 从 `v_dws_member_winback_index.ideal_interval_days` 获取，不再硬编码为 0 |

新增辅助函数 `_derive_potential_tags()`。

### 2.2 FDW 列名修正（17 处）

| 视图 | 修正数量 | 关键映射 |
|------|---------|---------|
| `v_dws_finance_daily_summary` | 6 | occurrence→gross_amount, discount→discount_total, confirmed_revenue→confirmed_income, cash_in→cash_inflow_total, cash_out→cash_outflow_total, cash_balance→cash_balance_change |
| `v_dws_finance_recharge_summary` | 4 | actual_income→recharge_cash, first_charge→first_recharge_cash, renew_charge→renewal_cash, card_balance→cash_card_balance |
| `v_dws_member_winback_index` | 2 | ideal_days→ideal_interval_days, wbi_score→display_score |
| `v_dws_member_consumption_summary` | 1 | items_sum_60d→consume_amount_60d |
| `v_dim_member_card_account` | 1 | balance_amount→balance |
| `v_dws_finance_expense_summary` + `v_dws_platform_settlement` | 3 | expense_group→expense_category, stat_date→expense_month/settlement_date |

### 2.3 board_service.py 修正
- `_build_recharge` 环比比较逻辑修正（compare 参数正确传递）
- `_empty_revenue` 新增完整空默认值工厂（含 price_items, channel_items 等必需字段）
- skills 字段暂返回空列表

### 2.4 gift_rows GiftCell 修正
赠送卡 3×4 矩阵每个 cell 从裸 float 改为 `{"value": float}` dict，匹配 Pydantic GiftCell schema。

### 2.5 E2E 测试（test_e2e_board.py）
22 个集成测试覆盖：四端点基本请求、环比开关、参数互斥、分页、区域约束、权限校验、camelCase 序列化。

### 2.6 文档更新
- `docs/contracts/openapi/backend-api.json`：新增 4 端点 + 5 schema
- `docs/database/BD_Manual_biz_tables.md`：补充 coach_tasks 看板场景引用说明

---

## 3. 未修复项（已知限制）

| 编号 | 问题 | 原因 |
|------|------|------|
| P1-6 | 礼品卡矩阵无细分数据 | ETL 层无 liquor/table_fee/voucher 细分列，需 ETL 侧先补数据 |
| P2-8 | expense 日期粒度差异 | 低风险，显示层可接受 |
| P2-9 | level 映射硬编码 | 显示层低风险，后续可迁移至配置表 |

---

## 4. 本次对话文件变更

### 新增文件
- `docs/audit/changes/2026-03-20__rns13-board-apis-e2e-fix.md`（本文件）
- `docs/audit/prompt_logs/prompt_log_20260319_160132.md`
- `docs/audit/session_logs/2026-03/19/38_d68afacc_154946/main_01_a7041a46.md`
- `docs/audit/session_logs/2026-03/19/40_fd008ef9_155123/main_01_c4a82443.md`
- `docs/audit/session_logs/2026-03/19/40_fd008ef9_155123/sub_01_c4a82443.md`
- `docs/audit/session_logs/2026-03/19/40_fd008ef9_155123/sub_02_c4a82443.md`

### 删除文件
- `docs/audit/session_logs/2026-03/19/38_d68afacc_154946/main_01_d94c682a.md`（被 main_01_a7041a46.md 替代）

---

## 5. 文件清单

| 文件 | 变更类型 | 说明 |
|------|---------|------|
| `apps/backend/app/services/fdw_queries.py` | 修改 | 6 函数修复 + 17 处列名修正 + gift_rows GiftCell + 新增 `_derive_potential_tags()` |
| `apps/backend/app/services/board_service.py` | 修改 | _build_recharge 环比 + _empty_revenue + skills 空列表 |
| `apps/backend/tests/integration/test_e2e_board.py` | 修改 | 22 个 E2E 集成测试修正 |
| `docs/contracts/openapi/backend-api.json` | 修改 | 4 端点 + 5 schema |
| `docs/database/BD_Manual_biz_tables.md` | 修改 | RNS1.3 看板引用说明 |
| `.kiro/specs/rns1-board-apis/tasks.md` | 修改 | Tasks 17-20 标记完成 |

---

## 6. 数据库变更

**无 DDL 变更。** 本次实现全部基于已有的 `app.v_*` RLS 视图执行 SELECT 查询。`IMPORT FOREIGN SCHEMA app` 在 `setup_fdw.sql` 中已自动导入所有视图，无需新增 FDW 映射。

⚠️ DDL 基线待合并（`compliance.has_ddl_baseline` = false）

---

## 7. 改动注解

### `apps/backend/app/services/fdw_queries.py`
- 变更类型：修改
- 原始原因：feiqiu-data-rules 审计发现 6 个函数的数据口径与 DWS 权威规范不一致，部分功能未实现（空列表降级、硬编码 0）
- 思路分析：逐函数对照 dws-doc-authority.md 和实际视图结构修正。P0-1 改用正确的储值佣金视图；P0-2 从降级空列表改为实际查询消费潜力指数视图；P0-3 修正 AREA 层级映射并填充 price_items/channel_items；P1-4/5 通过 LEFT JOIN 和子查询实现筛选功能；P2-7 从视图获取 ideal_interval_days 替代硬编码。新增 `_derive_potential_tags()` 辅助函数用于消费潜力标签推导
- 修改结果：6 个函数数据口径与 DWS 规范对齐，skill_filter 和 project_filter 功能可用。影响 board_service.py 的三看板数据展示。17 处 FDW 列名映射同步修正

### `apps/backend/app/services/board_service.py`
- 变更类型：修改
- 原始原因：fdw_queries.py 修复后，board_service 的环比逻辑和空默认值需要同步适配
- 思路分析：`_build_recharge` 的 compare 参数传递链路修正；`_empty_revenue` 补全 price_items、channel_items 等必需字段避免前端渲染报错；skills 字段暂返回空列表（待 ETL 补数据后启用）
- 修改结果：三看板接口在数据为空时不再抛异常，返回结构完整的空响应

### `apps/backend/tests/integration/test_e2e_board.py`
- 变更类型：修改
- 原始原因：fdw_queries.py 列名修正后，E2E 测试中的 mock 数据和断言需同步更新
- 思路分析：更新 22 个测试用例中涉及的列名引用，确保 mock 数据结构与修正后的查询一致
- 修改结果：22 个 E2E 集成测试全部通过

### `docs/database/BD_Manual_biz_tables.md`
- 变更类型：修改（简要）
- 补充 coach_tasks 在 RNS1.3 看板场景中的引用说明

### `docs/contracts/openapi/backend-api.json`
- 变更类型：修改（简要）
- 新增 BOARD-1/2/3 + CONFIG-1 共 4 个端点定义和 5 个 schema

### `.kiro/specs/rns1-board-apis/tasks.md`
- 变更类型：修改（简要）
- Tasks 17-20 子任务标记为已完成

---

## 8. 风险与回滚

### 风险
- 列名映射依赖当前 ETL 视图定义，ETL 视图变更时需同步更新 fdw_queries.py
- 降级处理（空列表/返回 0）在 ETL 数据补全后需移除
- P1-6（礼品卡矩阵细分）依赖 ETL 侧补数据，当前返回 0

### 回滚
代码层面 revert fdw_queries.py + board_service.py 即可，无数据库回滚需求。

---

## 9. 验证

- 17 个属性测试全部通过（`pytest tests/test_board_properties.py -v`）
- 22 个 E2E 集成测试全部通过（`pytest apps/backend/tests/integration/test_e2e_board.py -v`）
- OpenAPI JSON 语法验证通过
