# 需求文档 — RNS1.3:三看板接口 ## 简介 RNS1.3 是 NS1 小程序后端 API 补全项目的第四个子 spec,负责实现 3 个看板接口(BOARD-1 助教看板、BOARD-2 客户看板、BOARD-3 财务看板)、CONFIG-1 技能配置接口、以及前端看板筛选修复。看板是管理层视角的核心功能,其中 BOARD-3 财务看板是全项目最复杂的单个接口(6 个独立板块、200+ 字段、60+ 环比数据点)。 ### 依赖 - RNS1.0(基础设施与契约重写)必须先完成:全局响应包装中间件(`ResponseWrapperMiddleware`)、camelCase 转换(`CamelModel`)、重写后的 API 契约 - RNS1.1 / RNS1.2 可并行开发,无直接依赖 - 后端已有 `fdw_queries.py`(FDW 查询集中封装)、`task_manager.py`、`note_service.py` - 前端已有 13 个页面(P5.2 交付),当前使用 mock 数据 ### 来源文档 - `docs/prd/Neo_Specs/RNS1-split-plan.md` — 拆分计划主文档(RNS1.3 章节,T3-1 ~ T3-7) - `docs/miniprogram-dev/API-contract.md` — API 契约(BOARD-1/2/3、CONFIG-1 完整定义) - `docs/prd/Neo_Specs/NS1-xcx-backend-api.md` — 原始 spec(八¾ 看板筛选交叉矩阵为权威参考) - `docs/prd/Neo_Specs/miniprogram-storyboard-walkthrough-gaps.md` — 管理层视角走查报告(G1~G10 看板相关 Gap) - `docs/prd/Neo_Specs/storyboard-walkthrough-assistant-view.md` — 助教视角走查报告 - `docs/reports/DWD-DOC/` — 金额口径与字段语义权威标杆文档 ## 术语表 - **Backend**:FastAPI 后端应用,位于 `apps/backend/` - **Miniprogram**:微信小程序前端应用,位于 `apps/miniprogram/` - **BOARD_1_API**:助教看板接口 `GET /api/xcx/board/coaches`,返回助教排行列表(4 维度专属字段) - **BOARD_2_API**:客户看板接口 `GET /api/xcx/board/customers`,返回客户排行列表(8 维度专属字段) - **BOARD_3_API**:财务看板接口 `GET /api/xcx/board/finance`,返回 6 个板块的财务数据(overview/recharge/revenue/cashflow/expense/coachAnalysis) - **CONFIG_1_API**:技能类型列表接口 `GET /api/xcx/config/skill-types`,返回助教技能类型配置 - **FDW**:PostgreSQL Foreign Data Wrapper,后端通过直连 ETL 库查询 `app.v_*` RLS 视图 - **items_sum**:DWD-DOC 强制使用的消费金额口径,= `table_charge_money + goods_money + assistant_pd_money + assistant_cx_money + electricity_money` - **assistant_pd_money**:助教陪打费用(基础课),DWD-DOC 强制规则 2 要求的拆分字段 - **assistant_cx_money**:助教超休费用(激励课),DWD-DOC 强制规则 2 要求的拆分字段 - **v_dws_assistant_salary_calc**:ETL RLS 视图,提供助教绩效/档位/收入/工资数据 - **v_dws_assistant_monthly_summary**:ETL RLS 视图,提供助教月度汇总(客户数、储值额等) - **v_dim_assistant**:ETL RLS 视图,提供助教基本信息(姓名、技能、入职日期等) - **v_dim_member**:ETL RLS 视图,提供会员基本信息(nickname、mobile),通过 `member_id` 关联,取 `scd2_is_current=1` - **v_dim_member_card_account**:ETL RLS 视图,提供会员卡余额,通过 `tenant_member_id` 关联,取 `scd2_is_current=1` - **v_dws_member_assistant_relation_index**:ETL RLS 视图,提供会员与助教的关系指数 - **v_dws_member_consumption_summary**:ETL RLS 视图,提供会员消费汇总 - **v_dws_finance_daily_summary**:ETL RLS 视图,提供财务日报汇总数据(经营一览 8 指标 + 现金流入/流出),BOARD-3 overview/cashflow/expense 板块的主数据源 - **v_dws_finance_income_structure**:ETL RLS 视图,提供收入结构表 + 正价/优惠/渠道明细,BOARD-3 revenue 板块数据源 - **v_dws_finance_recharge_summary**:ETL RLS 视图,提供储值卡 + 赠送卡矩阵数据,BOARD-3 recharge 板块数据源 - **v_dws_finance_discount_detail**:ETL RLS 视图,提供优惠明细(大客户优惠/其他优惠拆分),BOARD-3 revenue 板块辅助数据源 - **v_dws_finance_expense_summary**:ETL RLS 视图,提供现金流出 4 子分组明细,BOARD-3 expense 板块数据源 - **v_dws_platform_settlement**:ETL RLS 视图,提供平台结算数据(汇来米/美团/抖音),BOARD-3 expense.platformItems 数据源 - **coach_tasks**:业务库 `biz.coach_tasks` 表,存储助教任务分配与状态 - **user_assistant_binding**:认证库 `auth.user_assistant_binding` 表,映射小程序用户与助教身份 - **dimType**:BOARD-1 中根据 `sort` 参数映射的维度类型(`perf`/`salary`/`sv`/`task`),决定卡片展示模板 - **环比**:月环比,与上一个相同时间周期对比(本月 vs 上月、本周 vs 上周等),返回百分比字符串 + 方向标记 - **GiftRow**:赠送卡 3×4 矩阵中的一行(新增/消费/余额),每行含 4 列(合计/酒水卡/台费卡/抵用券) - **RevenueStructureRow**:收入结构表中的一行(9 行含子行),含发生额、优惠、入账金额 - **CoachAnalysisTable**:助教分析子表(基础课或激励课),含汇总行 + 按等级分行(初级/中级/高级/星级) ## 需求 ### 需求 1:实现 BOARD-1 助教看板(T3-1) **用户故事:** 作为管理者,我希望在助教看板中按不同维度(定档业绩/工资/客源储值/任务完成)查看助教排行,并支持技能筛选和时间范围切换,以便评估和对比各助教的工作表现。 #### 验收标准 #### 1.1 请求参数与筛选 1. THE BOARD_1_API SHALL 接受 3 个查询参数:`sort`(排序维度,6 种枚举:`perf_desc`/`perf_asc`/`salary_desc`/`salary_asc`/`sv_desc`/`task_desc`)、`skill`(技能筛选,5 种枚举:`all`/`chinese`/`snooker`/`mahjong`/`karaoke`)、`time`(时间范围,6 种枚举:`month`/`quarter`/`last_month`/`last_3m`/`last_quarter`/`last_6m`) 2. IF `time=last_6m` 且 `sort=sv_desc`,THEN THE BOARD_1_API SHALL 返回 HTTP 400 `{ code: 400, message: "最近6个月不支持客源储值排序" }` 3. THE BOARD_1_API SHALL 根据 `time` 参数计算对应的日期范围(本月=当月1日~末日、上月=上月1日~末日、本季度=季度首日~末日、前3个月=不含本月的前3个月、上季度=上季度、最近6个月=不含本月的前6个月) #### 1.2 基础字段(所有维度共享) 4. THE BOARD_1_API SHALL 为每个助教 item 返回基础字段:`id`(助教 ID)、`name`(助教姓名)、`initial`(姓名首字)、`avatarGradient`(头像渐变色标识)、`level`(等级 key:`star`/`senior`/`middle`/`junior`)、`skills`(技能列表,`Array<{ text: string, cls: string }>`)、`topCustomers`(Top 客户列表,含亲密度 emoji 前缀,如 `['💖 王先生', '💛 李女士']`) 5. THE BOARD_1_API SHALL 从 `v_dim_assistant` 获取助教基本信息,从 `v_dws_assistant_salary_calc` 获取等级(`assistant_level_name`) 6. THE BOARD_1_API SHALL 从 `v_dws_member_assistant_relation_index` 按亲密度降序取 Top 3 客户,拼接亲密度 emoji(P6 AC3 四级映射:`rs_display > 8.5` → 💖,`> 7` → 🧡,`> 5` → 💛,`≤ 5` → 💙)+ 客户姓名作为 `topCustomers` #### 1.3 perf 维度专属字段 7. WHEN `sort` 为 `perf_desc` 或 `perf_asc` 时,THE BOARD_1_API SHALL 返回 perf 维度字段:`perfHours`(当期定档工时)、`perfHoursBefore`(上期定档工时,可选)、`perfGap`(距升档差距描述,如 `"距升档 13.8h"`,已达标时不返回)、`perfReached`(是否已达标) 8. THE BOARD_1_API SHALL 从 `v_dws_assistant_salary_calc` 查询当期和上期的定档工时数据,根据档位阈值计算 `perfGap` 和 `perfReached` #### 1.4 salary 维度专属字段 9. WHEN `sort` 为 `salary_desc` 或 `salary_asc` 时,THE BOARD_1_API SHALL 返回 salary 维度字段:`salary`(预估工资总额,元)、`salaryPerfHours`(定档工时)、`salaryPerfBefore`(上期定档工时,可选) 10. THE BOARD_1_API SHALL 使用 `items_sum` 口径计算 `salary` 字段(DWD-DOC 强制规则 1) #### 1.5 sv 维度专属字段 11. WHEN `sort` 为 `sv_desc` 时,THE BOARD_1_API SHALL 返回 sv 维度字段:`svAmount`(客源储值总额,元)、`svCustomerCount`(储值客户数)、`svConsume`(储值消耗额,元) 12. THE BOARD_1_API SHALL 从 `v_dws_assistant_monthly_summary` 获取助教月度储值汇总数据(客源储值额、储值客户数、储值消耗额),该视图已按助教维度预聚合 #### 1.6 task 维度专属字段 13. WHEN `sort` 为 `task_desc` 时,THE BOARD_1_API SHALL 返回 task 维度字段:`taskRecall`(召回任务完成数)、`taskCallback`(回访任务完成数) 14. THE BOARD_1_API SHALL 从 `biz.coach_tasks` 查询指定时间范围内 `status='completed'` 的任务,按 `task_type` 分类统计 #### 1.7 排序与返回策略 15. THE BOARD_1_API SHALL 根据 `sort` 参数对结果排序(`perf_desc` 按定档工时降序、`perf_asc` 按定档工时升序、`salary_desc` 按工资降序、`salary_asc` 按工资升序、`sv_desc` 按储值额降序、`task_desc` 按任务完成总数降序) 16. THE BOARD_1_API SHALL 始终返回所有维度的字段(扁平结构),前端根据当前 `sort` 选择性渲染对应卡片模板,切换维度时无需重新请求 ### 需求 2:实现 BOARD-2 客户看板(T3-2) **用户故事:** 作为管理者,我希望在客户看板中按 8 个维度(最应召回/最大消费潜力/最高余额/最近充值/最近到店/最高消费60天/最频繁60天/最专一60天)查看客户排行,每个维度展示不同的专属字段卡片和关联助教信息,以便从多角度评估客户价值和服务需求。 #### 验收标准 #### 2.1 请求参数与分页 1. THE BOARD_2_API SHALL 接受 4 个查询参数:`dimension`(维度,8 种枚举:`recall`/`potential`/`balance`/`recharge`/`recent`/`spend60`/`freq60`/`loyal`)、`project`(项目筛选,5 种枚举:`all`/`chinese`/`snooker`/`mahjong`/`karaoke`)、`page`(页码,默认 1)、`pageSize`(每页条数,默认 20,上限 100) 2. THE BOARD_2_API SHALL 返回分页结构:`items`(客户列表)、`total`(总数)、`page`(当前页)、`pageSize`(每页条数),支持前端 20 条懒加载 #### 2.2 基础字段(所有维度共享) 3. THE BOARD_2_API SHALL 为每个客户 item 返回基础字段:`id`(客户 member_id)、`name`(客户姓名)、`initial`(姓名首字)、`avatarCls`(头像样式类)、`assistants`(关联助教列表,`Array<{ name, cls, heartScore, badge?, badgeCls? }>`) 4. THE BOARD_2_API SHALL 通过 `member_id` LEFT JOIN `v_dim_member`(取 `scd2_is_current=1`)获取客户姓名(DQ-6) 5. THE BOARD_2_API SHALL 从 `biz.coach_tasks` + 亲密度计算获取 `assistants` 列表,按亲密度降序排列,当前跟进助教(`cls='assistant--assignee'`)置顶 #### 2.3 recall 维度专属字段 6. WHEN `dimension=recall` 时,THE BOARD_2_API SHALL 返回:`idealDays`(理想到店间隔天数)、`elapsedDays`(已过天数)、`overdueDays`(超期天数 = elapsedDays - idealDays)、`visits30d`(近30天到店次数)、`balance`(余额,格式化字符串)、`recallIndex`(召回指数) 7. THE BOARD_2_API SHALL 按 WBI(召回指数)降序排列 recall 维度结果 #### 2.4 potential 维度专属字段 8. WHEN `dimension=potential` 时,THE BOARD_2_API SHALL 返回:`potentialTags`(潜力标签列表,`Array<{ text, theme }>`)、`spend30d`(近30天消费)、`avgVisits`(月均到店)、`avgSpend`(次均消费) 9. THE BOARD_2_API SHALL 按 SPI(消费潜力指数)降序排列 potential 维度结果 #### 2.5 balance 维度专属字段 10. WHEN `dimension=balance` 时,THE BOARD_2_API SHALL 返回:`balance`(当前余额)、`lastVisit`(最近到店描述,如 `"3天前"`)、`monthlyConsume`(月均消耗)、`availableMonths`(可用月数,如 `"约0.8个月"`) 11. THE BOARD_2_API SHALL 按 `balance_amount` 降序排列 balance 维度结果 #### 2.6 recharge 维度专属字段 12. WHEN `dimension=recharge` 时,THE BOARD_2_API SHALL 返回:`lastRecharge`(最后充值日期)、`rechargeAmount`(充值金额)、`recharges60d`(近60天充值次数)、`currentBalance`(当前余额) 13. THE BOARD_2_API SHALL 按 `last_recharge_date` 降序排列 recharge 维度结果 #### 2.7 recent 维度专属字段 14. WHEN `dimension=recent` 时,THE BOARD_2_API SHALL 返回:`daysAgo`(距今天数)、`visitFreq`(到店频率,如 `"6.2次/月"`)、`idealDays`(理想间隔)、`visits30d`(近30天到店)、`avgSpend`(次均消费) 15. THE BOARD_2_API SHALL 按 `last_visit_date` 降序排列 recent 维度结果 #### 2.8 spend60 维度专属字段 16. WHEN `dimension=spend60` 时,THE BOARD_2_API SHALL 返回:`spend60d`(近60天消费总额)、`visits60d`(近60天到店次数)、`highSpendTag`(是否高消费标记)、`avgSpend`(次均消费) 17. THE BOARD_2_API SHALL 使用 `items_sum` 口径计算 `spend60d`(DWD-DOC 强制规则 1),按 `items_sum_60d` 降序排列 #### 2.9 freq60 维度专属字段 18. WHEN `dimension=freq60` 时,THE BOARD_2_API SHALL 返回:`visits60d`(近60天到店次数)、`avgInterval`(平均到店间隔,如 `"5.0天"`)、`weeklyVisits`(最近8周到店柱状图,`Array<{ val: number, pct: number }>`,固定长度 8)、`spend60d`(近60天消费) 19. THE BOARD_2_API SHALL 按 `visit_count_60d` 降序排列 freq60 维度结果 20. THE BOARD_2_API SHALL 计算 `weeklyVisits` 中每周的 `pct` 为相对于 8 周最大值的百分比(0-100) #### 2.10 loyal 维度专属字段 21. WHEN `dimension=loyal` 时,THE BOARD_2_API SHALL 返回:`intimacy`(专一度指数)、`topCoachName`(最亲密助教姓名)、`topCoachHeart`(最亲密助教亲密度分数)、`topCoachScore`(最亲密助教关系指数)、`coachName`(主助教姓名)、`coachRatio`(主助教占比,如 `"78%"`)、`coachDetails`(助教明细列表,`Array<{ name, cls, heartScore, badge?, avgDuration, serviceCount, coachSpend, relationIdx }>`) 22. THE BOARD_2_API SHALL 按 `max_rs`(最大关系指数)降序排列 loyal 维度结果 #### 2.11 维度切换策略 23. THE BOARD_2_API SHALL 按 `dimension` 参数仅返回对应维度的专属字段(减少传输量和查询开销),切换维度时前端重新请求 ### 需求 3:实现 BOARD-3 经营一览 + 预收资产(T3-3) **用户故事:** 作为管理者,我希望在财务看板中查看经营一览(8 项核心指标及环比)和预收资产(储值卡 + 赠送卡矩阵),并支持时间范围、区域筛选和环比开关,以便全面掌握门店的经营状况和预收资产变动。 #### 验收标准 #### 3.1 请求参数 1. THE BOARD_3_API SHALL 接受 3 个查询参数:`time`(时间范围,8 种枚举:`month`/`lastMonth`/`week`/`lastWeek`/`quarter3`/`quarter`/`lastQuarter`/`half6`)、`area`(区域筛选,7 种枚举:`all`/`hall`/`hallA`/`hallB`/`hallC`/`mahjong`/`teamBuilding`)、`compare`(环比开关,`0` 或 `1`,默认 `0`) 2. THE BOARD_3_API SHALL 根据 `time` 参数计算当期日期范围(`month`=当月1日~末日、`lastMonth`=上月1日~末日、`week`=本周一~本周日、`lastWeek`=上周一~上周日、`quarter3`=前3个月不含本月、`quarter`=本季度首日~末日、`lastQuarter`=上季度、`half6`=最近6个月不含本月) 3. WHEN `compare=1` 时,THE BOARD_3_API SHALL 计算上期日期范围(与当期相同长度的前一个周期),分别查询当期和上期数据后计算环比百分比 4. WHEN `compare=0` 时,THE BOARD_3_API SHALL 不返回任何环比字段(`xxxCompare`/`isDown`/`isFlat`),减少查询开销 #### 3.2 经营一览 overview(8 指标 + 8 环比) 5. THE BOARD_3_API SHALL 返回 `overview` 板块,包含 8 项核心指标:`occurrence`(发生额/正价)、`discount`(总优惠,负值)、`discountRate`(折扣率)、`confirmedRevenue`(成交/确认收入)、`cashIn`(实收/现金流入)、`cashOut`(现金支出)、`cashBalance`(现金结余)、`balanceRate`(结余率) 6. WHEN `compare=1` 时,THE BOARD_3_API SHALL 为 overview 每项指标返回 3 个环比字段:`xxxCompare`(环比百分比字符串,如 `"12.5%"` 或 `"持平"`)、`xxxDown`(是否下降,boolean)、`xxxFlat`(是否持平,boolean) 7. THE BOARD_3_API SHALL 从 `v_dws_finance_daily_summary` 查询经营一览数据(按日期范围聚合),使用 `items_sum` 口径计算所有金额(DWD-DOC 强制规则 1) #### 3.3 预收资产 recharge(储值卡 + 赠送卡矩阵) 8. WHEN `area=all` 时,THE BOARD_3_API SHALL 返回 `recharge` 板块,包含储值卡 5 项指标:`actualIncome`(充值实收)、`firstCharge`(首充)、`renewCharge`(续费)、`consumed`(消耗)、`cardBalance`(储值卡总余额) 9. THE BOARD_3_API SHALL 返回 `recharge.giftRows`(赠送卡 3×4 矩阵),3 行(新增/消费/余额)× 4 列(合计/酒水卡/台费卡/抵用券),每个单元格含值和环比字段,共 24 个数据字段 + 24 个环比字段 10. THE BOARD_3_API SHALL 返回 `recharge.allCardBalance`(全类别会员卡余额合计 = 储值卡 + 赠送卡) 11. WHEN `area` 不等于 `all` 时,THE BOARD_3_API SHALL 将 `recharge` 板块返回 `null`(储值卡数据不按区域拆分,选中具体区域时无意义) 12. THE BOARD_3_API SHALL 从 `v_dws_finance_recharge_summary` 查询预收资产数据 ### 需求 4:实现 BOARD-3 应计收入 + 现金流入(T3-4) **用户故事:** 作为管理者,我希望在财务看板中查看应计收入确认(收入结构表含区域子行、正价/优惠/渠道明细)和现金流入(消费收款 + 充值收款),以便分析收入构成和现金来源。 #### 验收标准 #### 4.1 应计收入确认 revenue 1. THE BOARD_3_API SHALL 返回 `revenue.structureRows`(收入结构表),包含 9 行含子行标记:主行(开台与包厢、助教基础课、助教激励课、食品酒水)+ 子行(A区/B区/C区/团建区/麻将区,属于"开台与包厢"的子行,`isSub=true`),每行含 `id`、`name`、`desc`(可选)、`amount`(发生额)、`discount`(优惠金额)、`booked`(入账金额)、`bookedCompare`(入账环比,可选) 2. THE BOARD_3_API SHALL 对收入结构表中助教行使用 `assistant_pd_money`(基础课/陪打)和 `assistant_cx_money`(激励课/超休)拆分(DWD-DOC 强制规则 2),禁止使用 `service_fee` 3. THE BOARD_3_API SHALL 返回 `revenue.priceItems`(正价明细,4 项)、`revenue.totalOccurrence`(发生额合计)、`revenue.discountItems`(优惠明细,4 项)、`revenue.confirmedTotal`(确认收入合计)、`revenue.channelItems`(渠道明细,3 项:储值卡结算冲销/现金线上支付/团购核销确认收入) 4. THE BOARD_3_API SHALL 从 `v_dws_finance_income_structure`(收入结构主表)+ `v_dws_finance_discount_detail`(优惠明细辅助)查询应计收入数据 #### 4.2 现金流入 cashflow 5. THE BOARD_3_API SHALL 返回 `cashflow` 板块,包含 `consumeItems`(消费收款,3 项:纸币现金/线上收款/团购平台)、`rechargeItems`(充值收款,1 项:会员充值到账)、`total`(现金流入合计) 6. THE BOARD_3_API SHALL 确保 `consumeItems` 中 `platform_settlement_amount` 和 `groupbuy_pay_amount` 互斥(DWD-DOC 强制规则 8:现金流互斥) 7. THE BOARD_3_API SHALL 从 `v_dws_finance_daily_summary` 查询现金流入数据(消费收款 + 充值收款字段均在财务日报中) ### 需求 5:实现 BOARD-3 现金流出 + 助教分析(T3-5) **用户故事:** 作为管理者,我希望在财务看板中查看现金流出(经营/固定/助教分成/平台服务费 4 个子分组)和助教分析(基础课 + 激励课各按 4 等级分行),以便分析支出结构和助教成本。 #### 验收标准 #### 5.1 现金流出 expense 1. THE BOARD_3_API SHALL 返回 `expense` 板块,包含 4 个子分组:`operationItems`(经营支出,3 项:食品饮料/耗材/报销)、`fixedItems`(固定支出,4 项:房租/水电/物业/人员工资)、`coachItems`(助教分成,4 项:基础课分成/激励课分成/充值提成/额外奖金)、`platformItems`(平台服务费,3 项:汇来米/美团/抖音) 2. THE BOARD_3_API SHALL 返回 `expense.total`(现金流出合计)及其环比字段 3. THE BOARD_3_API SHALL 对 `coachItems` 中基础课分成使用 `assistant_pd_money`,激励课分成使用 `assistant_cx_money`(DWD-DOC 强制规则 2) 4. THE BOARD_3_API SHALL 从 `v_dws_finance_expense_summary`(支出明细 4 子分组,含助教分成)+ `v_dws_platform_settlement`(平台服务费:汇来米/美团/抖音)查询现金流出数据 #### 5.2 助教分析 coachAnalysis 5. THE BOARD_3_API SHALL 返回 `coachAnalysis` 板块,包含 `basic`(基础课/陪打)和 `incentive`(激励课/超休)两个子表,结构完全相同 6. THE BOARD_3_API SHALL 为每个子表返回汇总行:`totalPay`(总课时费)、`totalShare`(总分成)、`avgHourly`(平均时薪),各含环比字段 7. THE BOARD_3_API SHALL 为每个子表返回 `rows`(按等级分行,4 行:初级/中级/高级/星级),每行含 `level`(等级名)、`pay`(课时费)、`share`(分成)、`hourly`(时薪),各含环比字段和方向标记(`payDown`/`shareDown`/`hourlyFlat`) 8. THE BOARD_3_API SHALL 从 `v_dws_assistant_salary_calc` 按 `assistant_level_name` 分组聚合助教分析数据 ### 需求 6:实现 CONFIG-1 技能类型列表(T3-6) **用户故事:** 作为管理者,我希望助教看板的技能筛选选项从后端配置表动态获取(而非前端硬编码),以便在新增技能类型时无需发版更新前端。 #### 验收标准 1. THE CONFIG_1_API SHALL 实现 `GET /api/xcx/config/skill-types` 端点,返回技能类型列表,每项含 `key`(枚举值,如 `chinese`/`snooker`/`mahjong`/`karaoke`)、`label`(中文标签)、`emoji`(表情符号)、`cls`(前端样式类) 2. THE CONFIG_1_API SHALL 从 ETL cfg 表读取技能类型配置数据 3. IF ETL cfg 表查询失败或无数据,THEN THE CONFIG_1_API SHALL 返回空数组,前端 `api.ts` 中的硬编码列表作为 mock 回退 4. THE CONFIG_1_API SHALL 对响应设置合理的缓存策略(技能类型变更频率极低) ### 需求 7:前端看板筛选修复(T3-7) **用户故事:** 作为管理者,我希望在看板页面切换筛选条件时能立即看到更新后的数据(而非停留在旧数据),以便实时对比不同维度和时间范围的数据。 #### 验收标准 #### 7.1 BOARD-1 筛选修复(F1, F6) 1. THE Miniprogram SHALL 修复 `board-coach` 页面的 `onSortChange`、`onSkillChange`、`onTimeChange` 事件处理函数,在更新 data 状态后调用 `this.loadData()` 重新请求 API 2. THE Miniprogram SHALL 在 `board-coach` 页面实现 `time=last_6m` + `sort=sv_desc` 的互斥约束:选择 `last_6m` 时禁用 `sv_desc` 选项,或选择 `sv_desc` 时禁用 `last_6m` 选项 #### 7.2 BOARD-2 筛选修复 + 分页补充(F2, F3) 3. THE Miniprogram SHALL 修复 `board-customer` 页面的 `onDimensionChange`、`onProjectChange` 事件处理函数,在更新 data 状态后调用 `this.loadData()` 重新请求 API 4. THE Miniprogram SHALL 为 `board-customer` 页面补充分页参数(`page`/`pageSize`)和"加载更多"懒加载逻辑(`onReachBottom` 触发加载下一页,`pageSize=20`) 5. THE Miniprogram SHALL 修改 `services/api.ts` 中 `fetchBoardCustomers` 函数签名,增加 `page` 和 `pageSize` 参数 #### 7.3 BOARD-3 筛选修复 + 签名扩展(F4, F5) 6. THE Miniprogram SHALL 修改 `services/api.ts` 中 `fetchBoardFinance` 函数签名,从 `{ date?: string }` 扩展为 `{ time: string, area: string, compare: number }` 7. THE Miniprogram SHALL 修复 `board-finance` 页面的 `onTimeChange`、`onAreaChange` 事件处理函数,在更新 data 状态后使用新参数调用 `fetchBoardFinance` 重新请求 API 8. THE Miniprogram SHALL 修复 `board-finance` 页面的 `toggleCompare` 函数,切换环比开关后使用 `compare=0` 或 `compare=1` 参数重新请求 API 9. WHEN `area` 不等于 `all` 时,THE Miniprogram SHALL 隐藏预收资产板块(`recharge` 为 `null` 时不渲染该 section) ### 需求 8:全局约束与数据隔离 **用户故事:** 作为系统管理员,我希望所有看板和配置接口都遵循统一的权限控制、数据隔离和数据质量规则,以确保数据安全和口径一致。 #### 验收标准 #### 8.1 权限与认证 1. THE Backend SHALL 对所有 RNS1.3 接口(BOARD_1_API、BOARD_2_API、BOARD_3_API、CONFIG_1_API)执行 `require_approved()` 权限检查,确保用户状态为 `approved` 2. THE Backend SHALL 对 BOARD_1_API 验证用户具有 `view_board_coach` 权限,对 BOARD_2_API 验证用户具有 `view_board_customer` 权限,对 BOARD_3_API 验证用户具有 `view_board_finance` 权限 3. THE Backend SHALL 对所有 RNS1.3 接口通过 `SET LOCAL app.current_site_id` 实现门店级数据隔离(FDW 查询通过 `_fdw_context` 上下文管理器统一执行) #### 8.2 DWD-DOC 强制规则 4. THE Backend SHALL 对所有涉及金额的字段统一使用 `items_sum` 口径(DWD-DOC 强制规则 1),禁止使用 `consume_money` 5. THE Backend SHALL 对所有涉及助教费用的字段使用 `assistant_pd_money`(陪打/基础课)+ `assistant_cx_money`(超休/激励课)拆分(DWD-DOC 强制规则 2),禁止使用 `service_fee` 6. THE Backend SHALL 对所有涉及会员信息的查询通过 `member_id` LEFT JOIN `v_dim_member`(取 `scd2_is_current=1`)获取姓名和手机号(DWD-DOC 强制规则 DQ-6),禁止直接使用 `settlement_head.member_phone` 或 `member_name` 7. THE Backend SHALL 确保支付渠道恒等式 `balance_amount = recharge_card_amount + gift_card_amount`(DWD-DOC 强制规则 3),三者不可重复计算 8. THE Backend SHALL 确保现金流互斥:`platform_settlement_amount` 和 `groupbuy_pay_amount` 互斥(DWD-DOC 强制规则 8) #### 8.3 优雅降级 9. IF 某个看板板块的数据源查询失败,THEN THE Backend SHALL 对该板块返回空默认值(空对象或空数组),不影响其他板块和整体响应 10. THE Backend SHALL 对所有 FDW 查询异常进行捕获和日志记录,返回降级响应而非 HTTP 500 #### 8.4 环比计算通用规则 11. THE Backend SHALL 对所有环比计算采用统一公式:`compareValue = (当期值 - 上期值) / 上期值 × 100%`,格式化为百分比字符串(如 `"12.5%"`) 12. WHEN 上期值为 0 且当期值不为 0 时,THE Backend SHALL 返回 `xxxCompare: "新增"`,`xxxDown: false`,`xxxFlat: false` 13. WHEN 上期值和当期值均为 0 时,THE Backend SHALL 返回 `xxxCompare: "持平"`,`xxxDown: false`,`xxxFlat: true` 14. THE Backend SHALL 根据环比值设置方向标记:正值 → `isDown=false`,负值 → `isDown=true`,零值 → `isFlat=true` ### 需求 9:正确性属性(Property-Based Testing) **用户故事:** 作为开发者,我希望通过属性测试验证看板接口的数据一致性和业务规则正确性,以便在开发阶段发现口径错误和数据异常。 #### 验收标准 #### 9.1 BOARD-1 排序不变量 1. FOR ALL BOARD_1_API 响应(`sort=perf_desc`),列表 SHALL 按 `perfHours` 降序排列(前一项的 `perfHours` ≥ 后一项的 `perfHours`) 2. FOR ALL BOARD_1_API 响应(`sort=salary_asc`),列表 SHALL 按 `salary` 升序排列(前一项的 `salary` ≤ 后一项的 `salary`) #### 9.2 BOARD-2 分页不变量 3. FOR ALL 相同参数的 BOARD_2_API 请求(相同 `dimension`、`project`),`page=1` 返回的 `total` SHALL 等于 `page=2` 返回的 `total`(总数在分页间保持一致) 4. FOR ALL BOARD_2_API 响应,`items.length` SHALL 小于等于 `pageSize` #### 9.3 BOARD-3 经营一览恒等式 5. FOR ALL BOARD_3_API 响应中的 `overview`,`confirmedRevenue` SHALL 近似等于 `occurrence` 减去 `discount` 的绝对值(在浮点精度范围内),验证收入确认公式 6. FOR ALL BOARD_3_API 响应中的 `overview`,`cashBalance` SHALL 近似等于 `cashIn` 减去 `cashOut`(在浮点精度范围内),验证现金结余公式 #### 9.4 BOARD-3 预收资产区域约束 7. FOR ALL BOARD_3_API 响应(`area` 不等于 `all`),`recharge` SHALL 为 `null`,验证预收资产区域隐藏规则 #### 9.5 BOARD-3 环比开关一致性 8. FOR ALL BOARD_3_API 响应(`compare=0`),响应 JSON 中 SHALL 不包含任何以 `Compare`、`Down`、`Flat` 结尾的字段,验证环比开关关闭时不返回环比数据 #### 9.6 BOARD-3 支付渠道恒等式 9. FOR ALL BOARD_3_API 响应中涉及支付渠道的数据,`balance_amount` SHALL 等于 `recharge_card_amount + gift_card_amount`(DWD-DOC 强制规则 3),验证支付渠道恒等式 #### 9.7 幂等性 10. FOR ALL 相同参数的 BOARD_3_API 请求(相同 `time`、`area`、`compare`),在数据未变更的情况下,两次请求 SHALL 返回相同的 `overview.occurrence` 和 `overview.cashBalance` 值 #### 9.8 BOARD-1 交叉约束 11. FOR ALL BOARD_1_API 请求(`time=last_6m` 且 `sort=sv_desc`),响应 SHALL 为 HTTP 400,验证不兼容参数组合的拒绝规则