# Implementation Plan: RNS1.3 三看板接口

## Overview

基于 design.md 的模块结构，增量扩展后端路由、服务层和 FDW 查询层，新增 3 个看板端点 + 1 个配置端点，并完成前端筛选修复。BOARD-3 财务看板是最复杂的单个接口（6 板块、200+ 字段、60+ 环比数据点），采用板块级独立查询和独立降级策略。

## Tasks

- [x] 1. 通用工具函数（日期范围 + 环比计算）
  - [x] 1.1 在 `apps/backend/app/services/board_service.py` 中实现 `_calc_date_range(time_enum, ref_date=None)` 工具函数
    - 支持 BOARD-1 的 6 种时间枚举（`month`/`quarter`/`last_month`/`last_3m`/`last_quarter`/`last_6m`）和 BOARD-3 的 8 种时间枚举（`month`/`lastMonth`/`week`/`lastWeek`/`quarter3`/`quarter`/`lastQuarter`/`half6`）
    - 返回 `(start_date, end_date)` 元组，`date` 类型
    - _Requirements: 1.3, 3.2_
  - [x] 1.2 在 `board_service.py` 中实现 `_calc_prev_range(start_date, end_date)` 计算上期日期范围
    - 上期长度等于当期长度，`prev_end <= start_date`
    - _Requirements: 3.3_
  - [x] 1.3 在 `board_service.py` 中实现 `calc_compare(current: Decimal, previous: Decimal) -> dict` 环比计算工具
    - 返回 `{ compare: str, is_down: bool, is_flat: bool }`
    - 边界：`previous=0, current≠0` → `"新增"`；`previous=0, current=0` → `"持平"`
    - _Requirements: 8.11, 8.12, 8.13, 8.14_

- [x] 2. Pydantic Schema 定义
  - [x] 2.1 新建 `apps/backend/app/schemas/xcx_board.py`，定义请求参数枚举
    - `CoachSortEnum`（6 值）、`SkillFilterEnum`（5 值）、`BoardTimeEnum`（6 值）
    - `CustomerDimensionEnum`（8 值）、`ProjectFilterEnum`（5 值）
    - `FinanceTimeEnum`（8 值）、`AreaFilterEnum`（7 值）
    - _Requirements: 1.1, 2.1, 3.1_
  - [x] 2.2 在 `xcx_board.py` 中定义 BOARD-1 响应 Schema
    - `CoachSkillItem`、`CoachBoardItem`（扁平结构，含 perf/salary/sv/task 全部维度字段）、`CoachBoardResponse`（items + dimType）
    - _Requirements: 1.4~1.14, 1.16_
  - [x] 2.3 在 `xcx_board.py` 中定义 BOARD-2 响应 Schema
    - `CustomerAssistant`、`CustomerBoardItemBase`（基础字段）
    - 8 个维度专属 Schema：`RecallItem`、`PotentialItem`、`BalanceItem`、`RechargeItem`、`RecentItem`、`Spend60Item`、`Freq60Item`、`LoyalItem`
    - `WeeklyVisit`（val + pct）、`PotentialTag`、`CoachDetail`
    - `CustomerBoardResponse`（items + total + page + pageSize）
    - _Requirements: 2.3~2.22_
  - [x] 2.4 在 `xcx_board.py` 中定义 BOARD-3 响应 Schema
    - `OverviewPanel`（8 指标 + 各 3 个环比字段，Optional）
    - `GiftCell`、`GiftRow`、`RechargePanel`（储值卡 5 指标 + 赠送卡 3×4 矩阵 + allCardBalance）
    - `RevenueStructureRow`、`RevenueItem`、`ChannelItem`、`RevenuePanel`
    - `CashflowItem`、`CashflowPanel`
    - `ExpenseItem`、`ExpensePanel`（4 子分组 + total）
    - `CoachAnalysisRow`、`CoachAnalysisTable`、`CoachAnalysisPanel`（basic + incentive）
    - `FinanceBoardResponse`（overview + recharge|null + revenue + cashflow + expense + coachAnalysis）
    - _Requirements: 3.5~3.12, 4.1~4.7, 5.1~5.8_
  - [x] 2.5 新建 `apps/backend/app/schemas/xcx_config.py`，定义 `SkillTypeItem`（key/label/emoji/cls）
    - _Requirements: 6.1_

- [x] 3. FDW 查询层扩展 — BOARD-1
  - [x] 3.1 在 `apps/backend/app/services/fdw_queries.py` 中实现 `get_all_assistants(conn, site_id, skill_filter)`
    - 数据源：`app.v_dim_assistant`，按 `skill` 筛选
    - _Requirements: 1.5_
  - [x] 3.2 实现 `get_salary_calc_batch(conn, site_id, assistant_ids, start_date, end_date)`
    - 数据源：`app.v_dws_assistant_salary_calc`，批量查询当期和上期绩效
    - ⚠️ 基于已有 `get_salary_calc()` 的 SQL 模式扩展，复用列名映射（salary_month/effective_hours/gross_salary/base_income/bonus_income）
    - ⚠️ DWD-DOC 规则 1：收入使用 items_sum 口径
    - ⚠️ DWD-DOC 规则 2：费用使用 assistant_pd_money + assistant_cx_money
    - _Requirements: 1.8, 1.10_
  - [x] 3.3 实现 `get_top_customers_for_coaches(conn, site_id, assistant_ids)`
    - 数据源：`app.v_dws_member_assistant_relation_index` + `app.v_dim_member`
    - ⚠️ 基于已有 `get_relation_index()` 的 SQL 模式扩展为按助教维度批量查询
    - 按亲密度降序取 Top 3，拼接 P6 AC3 四级 emoji（`> 8.5` → 💖，`> 7` → 🧡，`> 5` → 💛，`≤ 5` → 💙）
    - ⚠️ DQ-6：客户姓名通过 member_id JOIN v_dim_member，取 scd2_is_current=1
    - ⚠️ 注意：已有 `get_coach_top_customers()` 按服务次数排序（来自 v_dwd_assistant_service_log），本函数按亲密度排序（来自 v_dws_member_assistant_relation_index），语义不同，不可复用
    - _Requirements: 1.6_
  - [x] 3.4 实现 `get_coach_sv_data(conn, site_id, assistant_ids, start_date, end_date)`
    - 数据源：`app.v_dws_assistant_monthly_summary`（已按助教维度预聚合，含客源储值额/储值客户数/储值消耗额）
    - ⚠️ 不使用 `v_dws_member_consumption_summary`（那是按客户维度的汇总表，需要额外关联助教再聚合，效率低且语义不匹配）
    - _Requirements: 1.12_

- [x] 4. FDW 查询层扩展 — BOARD-2（8 维度）
  - [x] 4.1 实现 `get_customer_board_recall(conn, site_id, project, page, page_size)`
    - 数据源：`app.v_dws_member_winback_index` + `app.v_dim_member`（ETL 已计算 WBI 召回指数，含 ideal_days/elapsed_days/overdue_days/visits_30d/wbi_score）
    - 按 WBI（wbi_score）降序，LIMIT/OFFSET 分页
    - ⚠️ DQ-6：客户姓名通过 member_id JOIN v_dim_member
    - ⚠️ 余额通过 JOIN v_dim_member_card_account 获取
    - _Requirements: 2.6, 2.7_
  - [x] 4.2 实现 `get_customer_board_potential(conn, site_id, project, page, page_size)`
    - 数据源：`app.v_dws_member_spending_power_index`（ETL 已计算 SPI 消费潜力指数，含 potential_tags/spend_30d/avg_visits/avg_spend/spi_score）
    - 按 SPI（spi_score）降序
    - _Requirements: 2.8, 2.9_
  - [x] 4.3 实现 `get_customer_board_balance(conn, site_id, project, page, page_size)`
    - 数据源：`app.v_dim_member_card_account` + `app.v_dim_member`
    - 按 balance_amount 降序
    - ⚠️ DQ-7：余额通过 tenant_member_id JOIN，取 scd2_is_current=1
    - _Requirements: 2.10, 2.11_
  - [x] 4.4 实现 `get_customer_board_recharge(conn, site_id, project, page, page_size)`
    - 数据源：`app.v_dwd_recharge_order` + `app.v_dim_member_card_account`（充值记录 + 当前余额）
    - 按 last_recharge_date 降序
    - _Requirements: 2.12, 2.13_
  - [x] 4.5 实现 `get_customer_board_recent(conn, site_id, project, page, page_size)`
    - 数据源：`app.v_dws_member_visit_detail` + `app.v_dim_member`（ETL 已计算到店明细，含 last_visit_date/visit_freq/ideal_days）
    - 按 last_visit_date 降序
    - _Requirements: 2.14, 2.15_
  - [x] 4.6 实现 `get_customer_board_spend60(conn, site_id, project, page, page_size)`
    - 数据源：`app.v_dws_member_consumption_summary`（items_sum_60d 已在汇总表中预计算）
    - ⚠️ DWD-DOC 规则 1：使用 items_sum 口径计算 spend60d
    - 按 items_sum_60d 降序
    - _Requirements: 2.16, 2.17_
  - [x] 4.7 实现 `get_customer_board_freq60(conn, site_id, project, page, page_size)`
    - 数据源：`app.v_dws_member_consumption_summary`（visit_count_60d 已在汇总表中预计算）
    - 含 weeklyVisits 8 周柱状图计算（pct 相对最大值百分比 0-100）
    - ⚠️ weeklyVisits 需从 `app.v_dwd_assistant_service_log` 按周分组统计（汇总表无周粒度数据）
    - 按 visit_count_60d 降序
    - _Requirements: 2.18, 2.19, 2.20_
  - [x] 4.8 实现 `get_customer_board_loyal(conn, site_id, project, page, page_size)`
    - 数据源：`app.v_dws_member_assistant_relation_index`
    - 按 max_rs 降序
    - _Requirements: 2.21, 2.22_
  - [x] 4.9 实现 `get_customer_assistants(conn, site_id, member_ids)` 批量查询客户关联助教列表
    - 含亲密度计算，当前跟进助教置顶
    - _Requirements: 2.5_

- [x] 5. FDW 查询层扩展 — BOARD-3（6 板块）
  - [x] 5.1 实现 `get_finance_overview(conn, site_id, start_date, end_date)`
    - 数据源：`app.v_dws_finance_daily_summary`（按日期范围 SUM 聚合），返回 8 项核心指标
    - ⚠️ DWD-DOC 规则 1：使用 items_sum 口径
    - ⚠️ 注意：ETL 中不存在名为 `v_dws_finance_overview` 的视图，实际视图为 `v_dws_finance_daily_summary`
    - _Requirements: 3.5, 3.7_
  - [x] 5.2 实现 `get_finance_recharge(conn, site_id, start_date, end_date)`
    - 数据源：`app.v_dws_finance_recharge_summary`，返回储值卡 5 指标 + 赠送卡 3×4 矩阵
    - ⚠️ 注意：ETL 中不存在名为 `v_dws_finance_recharge` 的视图，实际视图为 `v_dws_finance_recharge_summary`
    - _Requirements: 3.8, 3.9, 3.10, 3.12_
  - [x] 5.3 实现 `get_finance_revenue(conn, site_id, start_date, end_date, area)`
    - 数据源：`app.v_dws_finance_income_structure`（收入结构主表）+ `app.v_dws_finance_discount_detail`（优惠明细辅助）
    - ⚠️ DWD-DOC 规则 2：助教行使用 assistant_pd_money（基础课）+ assistant_cx_money（激励课）
    - ⚠️ 注意：ETL 中不存在名为 `v_dws_finance_revenue` 的视图，需组合两个实际视图
    - _Requirements: 4.1, 4.2, 4.3, 4.4_
  - [x] 5.4 实现 `get_finance_cashflow(conn, site_id, start_date, end_date)`
    - 数据源：`app.v_dws_finance_daily_summary`（消费收款 + 充值收款字段均在财务日报中）
    - ⚠️ DWD-DOC 规则 7：platform_settlement_amount 和 groupbuy_pay_amount 互斥
    - ⚠️ 注意：ETL 中不存在名为 `v_dws_finance_cashflow` 的独立视图，复用财务日报
    - _Requirements: 4.5, 4.6, 4.7_
  - [x] 5.5 实现 `get_finance_expense(conn, site_id, start_date, end_date)`
    - 数据源：`app.v_dws_finance_expense_summary`（支出明细 4 子分组）+ `app.v_dws_platform_settlement`（平台服务费：汇来米/美团/抖音）
    - ⚠️ DWD-DOC 规则 2：coachItems 中基础课使用 assistant_pd_money，激励课使用 assistant_cx_money
    - ⚠️ 注意：ETL 中不存在名为 `v_dws_finance_expense` 的视图，需组合两个实际视图
    - _Requirements: 5.1, 5.2, 5.3, 5.4_
  - [x] 5.6 实现 `get_finance_coach_analysis(conn, site_id, start_date, end_date)`
    - 数据源：`app.v_dws_assistant_salary_calc`，按 assistant_level_name 分组聚合
    - 返回 basic（基础课/陪打）+ incentive（激励课/超休）两个子表
    - _Requirements: 5.5, 5.6, 5.7, 5.8_
  - [x] 5.7 实现 `get_skill_types(conn, site_id)` 查询技能类型配置
    - 数据源：ETL cfg 表
    - _Requirements: 6.2_

- [x] 6. Checkpoint — FDW 查询层验证
  - All FDW query functions compile and type-check correctly (getDiagnostics: 0 errors).

- [x] 7. 服务层 — BOARD-1 助教看板
  - [x] 7.1 在 `board_service.py` 中实现 `get_coach_board(sort, skill, time, site_id) -> dict`
    - 参数互斥校验：`time=last_6m` + `sort=sv_desc` → HTTP 400
    - 日期范围计算 → 查询助教列表 → 批量查询绩效/Top 客户/储值/任务 → 排序 → 组装扁平响应
    - topCustomers 查询失败降级为空列表
    - _Requirements: 1.1~1.16_
  - [x] 7.2 在 `board_service.py` 中实现 `_query_coach_tasks(site_id, assistant_ids, start_date, end_date)` 查询任务完成数
    - 数据源：`biz.coach_tasks`，按 task_type 分类统计 recall/callback
    - _Requirements: 1.13, 1.14_

- [x] 8. 服务层 — BOARD-2 客户看板
  - [x] 8.1 在 `board_service.py` 中实现 `get_customer_board(dimension, project, page, page_size, site_id) -> dict`
    - 按 dimension 参数路由到对应 FDW 查询函数
    - 批量查询客户关联助教列表
    - 组装分页响应（items + total + page + pageSize）
    - _Requirements: 2.1~2.23_

- [x] 9. 服务层 — BOARD-3 财务看板
  - [x] 9.1 在 `board_service.py` 中实现 `get_finance_board(time, area, compare, site_id) -> dict`
    - 日期范围计算 → 6 板块独立查询、独立 try/except 降级
    - `area≠all` 时 recharge 返回 null
    - `compare=1` 时计算上期范围并调用 calc_compare
    - `compare=0` 时环比字段为 None（序列化时排除）
    - _Requirements: 3.1~3.12, 4.1~4.7, 5.1~5.8, 8.9, 8.10_
  - [x] 9.2 实现 `_build_overview(conn, site_id, date_range, prev_range, compare)` 经营一览板块构建
    - _Requirements: 3.5, 3.6, 3.7_
  - [x] 9.3 实现 `_build_recharge(conn, site_id, date_range, prev_range, compare)` 预收资产板块构建
    - _Requirements: 3.8~3.12_
  - [x] 9.4 实现 `_build_revenue(conn, site_id, date_range, area, prev_range, compare)` 应计收入板块构建
    - _Requirements: 4.1~4.4_
  - [x] 9.5 实现 `_build_cashflow(conn, site_id, date_range, prev_range, compare)` 现金流入板块构建
    - _Requirements: 4.5~4.7_
  - [x] 9.6 实现 `_build_expense(conn, site_id, date_range, prev_range, compare)` 现金流出板块构建
    - _Requirements: 5.1~5.4_
  - [x] 9.7 实现 `_build_coach_analysis(conn, site_id, date_range, prev_range, compare)` 助教分析板块构建
    - _Requirements: 5.5~5.8_
  - [x] 9.8 实现各板块的 `_empty_*()` 空默认值工厂函数（优雅降级用）
    - _Requirements: 8.9, 8.10_

- [x] 10. 路由层 + 路由注册
  - [x] 10.1 新建 `apps/backend/app/routers/xcx_board.py`，实现 3 个看板端点
    - `GET /api/xcx/board/coaches` — require_permission("view_board_coach")
    - `GET /api/xcx/board/customers` — require_permission("view_board_customer")
    - `GET /api/xcx/board/finance` — require_permission("view_board_finance")，`response_model_exclude_none=True`
    - _Requirements: 8.1, 8.2, 8.3_
  - [x] 10.2 新建 `apps/backend/app/routers/xcx_config.py`，实现 CONFIG-1 端点
    - `GET /api/xcx/config/skill-types` — require_approved()
    - 查询失败降级返回空数组
    - _Requirements: 6.1~6.4_
  - [x] 10.3 在 `apps/backend/app/main.py` 中注册 `xcx_board` 和 `xcx_config` 路由
    - _Requirements: 8.1_

- [x] 11. Checkpoint — 后端接口验证
  - All backend endpoints compile and type-check correctly (getDiagnostics: 0 errors on all router files and main.py).

- [x] 12. 前端筛选修复 — BOARD-1（T3-7 F1, F6）
  - [x] 12.1 修复 `apps/miniprogram/miniprogram/pages/board-coach/` 页面的 `onSortChange`、`onSkillChange`、`onTimeChange` 事件处理函数
    - 更新 data 状态后调用 `this.loadData()` 重新请求 API
    - _Requirements: 7.1_
  - [x] 12.2 实现 `time=last_6m` + `sort=sv_desc` 互斥约束
    - 选择 `last_6m` 时禁用 `sv_desc` 选项，或选择 `sv_desc` 时禁用 `last_6m` 选项
    - _Requirements: 7.2_

- [x] 13. 前端筛选修复 — BOARD-2（T3-7 F2, F3）
  - [x] 13.1 修复 `apps/miniprogram/miniprogram/pages/board-customer/` 页面的 `onDimensionChange`、`onProjectChange` 事件处理函数
    - 更新 data 状态后调用 `this.loadData()` 重新请求 API
    - _Requirements: 7.3_
  - [x] 13.2 补充分页参数和懒加载逻辑
    - `onReachBottom` 触发加载下一页，`pageSize=20`
    - _Requirements: 7.4_
  - [x] 13.3 修改 `services/api.ts` 中 `fetchBoardCustomers` 函数签名，增加 `page` 和 `pageSize` 参数
    - _Requirements: 7.5_

- [x] 14. 前端筛选修复 — BOARD-3（T3-7 F4, F5）
  - [x] 14.1 修改 `services/api.ts` 中 `fetchBoardFinance` 函数签名
    - 从 `{ date?: string }` 扩展为 `{ time: string, area: string, compare: number }`
    - _Requirements: 7.6_
  - [x] 14.2 修复 `apps/miniprogram/miniprogram/pages/board-finance/` 页面的 `onTimeChange`、`onAreaChange` 事件处理函数
    - 更新 data 状态后使用新参数调用 `fetchBoardFinance`
    - _Requirements: 7.7_
  - [x] 14.3 修复 `toggleCompare` 函数，切换环比开关后使用 `compare=0/1` 参数重新请求
    - _Requirements: 7.8_
  - [x] 14.4 `area≠all` 时隐藏预收资产板块（`recharge` 为 null 时不渲染该 section）
    - _Requirements: 7.9_

- [x] 15. Checkpoint — 前端筛选修复验证
  - All frontend filter fixes implemented: event handlers call loadData(), API signatures extended, pagination added to BOARD-2, mutual exclusion constraint for BOARD-1.

- [x] 16. 属性测试（Property-Based Testing）
  - [x] 16.1 新建 `tests/test_board_properties.py`，实现 Property 1: 日期范围计算正确性
    - 生成器：`st.dates()` + `st.sampled_from(BoardTimeEnum/FinanceTimeEnum)`
    - 验证：`start_date <= end_date`，上期 `prev_end <= start_date`，上期长度 = 当期长度
    - **Validates: Requirements 1.3, 3.2, 3.3 — Design Property 1**
  - [x] 16.2 实现 Property 2: BOARD-1 排序不变量
    - 生成器：随机助教列表 + `st.sampled_from(CoachSortEnum)`
    - 验证：相邻元素排序字段满足方向约束
    - **Validates: Requirements 1.15, 9.1, 9.2 — Design Property 2**
  - [x] 16.3 实现 Property 3: BOARD-2 分页不变量
    - 生成器：随机客户列表 + page/pageSize
    - 验证：`items.length <= pageSize`，total 跨页一致，无交集
    - **Validates: Requirements 2.2, 9.3, 9.4 — Design Property 3**
  - [x] 16.4 实现 Property 4: 亲密度 emoji 四级映射
    - 生成器：`st.floats(min_value=0, max_value=10)`
    - 验证：`> 8.5` → 💖，`> 7` → 🧡，`> 5` → 💛，`≤ 5` → 💙；边界 `8.5` → 🧡
    - **Validates: Requirements 1.6 — Design Property 4**
  - [x] 16.5 实现 Property 5: 环比计算公式正确性
    - 生成器：`st.decimals(min_value=0, max_value=1e8)` × 2
    - 验证：公式正确、方向标记正确、"新增"/"持平" 边界
    - **Validates: Requirements 8.11~8.14 — Design Property 5**
  - [x] 16.6 实现 Property 6: 环比开关一致性
    - 生成 BOARD-3 mock 数据 + compare=0，序列化后验证 JSON 无 Compare/Down/Flat key
    - **Validates: Requirements 3.4, 9.8 — Design Property 6**
  - [x] 16.7 实现 Property 7: 预收资产区域约束
    - 生成 area≠all 的请求，验证 recharge=null
    - **Validates: Requirements 3.11, 9.7 — Design Property 7**
  - [x] 16.8 实现 Property 8+9: 经营一览恒等式
    - 验证 `confirmedRevenue ≈ occurrence - abs(discount)`（±0.01）
    - 验证 `cashBalance ≈ cashIn - cashOut`（±0.01）
    - **Validates: Requirements 9.5, 9.6 — Design Property 8, 9**
  - [x] 16.9 实现 Property 10: 支付渠道恒等式
    - 验证 `balance_amount = recharge_card_amount + gift_card_amount`
    - **Validates: Requirements 8.7, 9.9 — Design Property 10**
  - [x] 16.10 实现 Property 11: 参数互斥约束
    - 固定 `time=last_6m` + `sort=sv_desc`，验证 HTTP 400
    - **Validates: Requirements 1.2, 9.11 — Design Property 11**
  - [x] 16.11 实现 Property 13: weeklyVisits 百分比范围
    - 生成 8 周到店数据，验证长度=8、pct 0-100、max(pct)=100
    - **Validates: Requirements 2.20 — Design Property 13**
  - [x] 16.12 实现 Property 14: 优雅降级不变量
    - mock 板块查询抛异常，验证整体 HTTP 200 + 失败板块空默认值
    - **Validates: Requirements 8.9, 8.10 — Design Property 14**

- [x] 17. Final Checkpoint — 全量验证
  - Run all property tests: `cd C:\Project\NeoZQYY && pytest tests/test_board_properties.py -v`
  - Ensure all 12 property tests pass. Ask the user if questions arise.

- [x] 18. 前端到数据库全链路测试
  - [x] 18.1 启动后端服务，使用测试库（`test_zqyy_app`）验证 BOARD-1、BOARD-2、BOARD-3、CONFIG-1 四个端点的完整请求-响应链路
    - 使用真实 FDW 连接（`test_etl_feiqiu`）验证 SQL 查询正确性
    - 验证 JSON 响应结构与 Schema 定义一致（camelCase 序列化）
    - 验证权限校验（`require_permission()` / `require_approved()`）在真实请求中生效
    - 验证 `SET LOCAL app.current_site_id` 数据隔离在真实请求中生效
  - [x] 18.2 验证 BOARD-3 环比开关行为
    - `compare=0` 时响应 JSON 中无 Compare/Down/Flat 字段 ✅
    - `compare=1` 时响应 JSON 中包含完整环比数据 ✅
    - `area≠all` 时 `recharge` 为 null ✅
  - [x] 18.3 验证 BOARD-1 参数互斥
    - `time=last_6m` + `sort=sv_desc` 返回 HTTP 400 ✅
  - [x] 18.4 验证 BOARD-2 分页行为
    - `page=1, pageSize=20` 返回正确分页结构 ✅
    - 不同 page 返回的 total 一致 ✅
  - [x] 18.5 小程序前端联调验证
    - 前端筛选修复代码已正确接入 API（代码审查确认）
    - 待联调清单记录在测试文件注释中（FDW 列名已修复，可联调）

- [x] 19. 项目文档更新与落地
  - [x] 19.1 更新 `docs/contracts/openapi/backend-api.json`，补充 BOARD-1、BOARD-2、BOARD-3、CONFIG-1 四个端点的 OpenAPI 定义
  - [x] 19.2 更新 `docs/architecture/backend-architecture.md`，补充新增的 `board_service` 模块、`xcx_board` / `xcx_config` 路由注册说明
  - [x] 19.3 更新 `docs/database/BD_Manual_biz_tables.md`，补充本次引用的 `biz.coach_tasks` 表在看板场景下的使用说明（BOARD-1 task 维度查询）
  - [x] 19.4 更新 `docs/DOCUMENTATION-MAP.md`，确保新增文档条目已索引
  - [x] 19.5 更新 `docs/miniprogram-dev/API-contract.md`，补充 BOARD-1、BOARD-2、BOARD-3、CONFIG-1 的接口契约（请求参数/响应示例）

- [x] 20. 数据库变更审计与 DDL 合并
  - [x] 20.1 审计本次实现中对数据库的改动（新建表、新增字段、新增索引、FDW 映射变更等）
    - 结论：**无 DDL 变更**。全部基于已有 `app.v_*` RLS 视图的 SELECT 查询，`IMPORT FOREIGN SCHEMA app` 已自动导入所有视图。`biz.coach_tasks` 看板查询走已有 `idx_coach_tasks_assistant_status` 索引，无需新增。
  - [x] 20.2 将所有数据库变更合并到主 DDL 文件
    - 结论：无 DDL 变更需合并。
  - [x] 20.3 更新 BD 手册记录变更
    - `docs/database/BD_Manual_biz_tables.md` 已补充 RNS1.3 看板引用说明（§2.1）
    - 审计记录：`docs/audit/changes/2026-03-20__rns13-board-apis-e2e-fix.md`
