feat: batch update - gift card breakdown spec, backend APIs, miniprogram pages, ETL finance recharge, docs & migrations

This commit is contained in:
Neo
2026-03-20 01:43:48 +08:00
parent 075caf067f
commit 79f9a0e1da
437 changed files with 118603 additions and 976 deletions

View File

@@ -0,0 +1,319 @@
# 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-28 维度)
- [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
- 按 WBIwbi_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
- 按 SPIspi_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-36 板块)
- [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 规则 7platform_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 规则 2coachItems 中基础课使用 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-1T3-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-2T3-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-3T3-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:\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`