Files
Neo-ZQYY/.kiro/specs/rns1-task-performance-api/requirements.md

18 KiB
Raw Blame History

需求文档 — RNS1.1:任务与绩效接口

简介

RNS1.1 是 NS1 小程序后端 API 补全项目的第二个子 spec负责实现助教日常使用频率最高的 4 个核心接口任务列表扩展、任务详情、绩效概览、绩效明细、pin/unpin 端点、以及对应的前端适配。本 spec 覆盖助教视角的核心工作流,是助教登录后最先接触的功能集合。

依赖

  • RNS1.0基础设施与契约重写必须先完成全局响应包装中间件、camelCase 转换、重写后的 API 契约
  • 前端已有 13 个页面P5.2 交付),当前使用 mock 数据
  • 后端已有 xcx_tasks.py(需扩展)、xcx_notes.pyxcx_auth.py

来源文档

  • docs/prd/Neo_Specs/RNS1-split-plan.md — 拆分计划主文档
  • docs/miniprogram-dev/API-contract.md — API 契约RNS1.0 T0-5 重写后版本)
  • docs/prd/Neo_Specs/storyboard-walkthrough-assistant-view.md — 助教视角走查报告GAP-02~22
  • docs/reports/DWD-DOC/ — 金额口径与字段语义权威标杆文档

术语表

  • BackendFastAPI 后端应用,位于 apps/backend/
  • Miniprogram:微信小程序前端应用,位于 apps/miniprogram/
  • TASK_1_API:任务列表接口 GET /api/xcx/tasks,返回任务列表 + 绩效概览
  • TASK_2_API:任务详情接口 GET /api/xcx/tasks/{taskId},返回单个任务的完整详情
  • PERF_1_API:绩效概览接口 GET /api/xcx/performance,返回助教当月绩效汇总
  • PERF_2_API:绩效明细接口 GET /api/xcx/performance/records,返回按日期分组的服务记录
  • PIN_API:任务置顶/取消置顶接口 POST /api/xcx/tasks/{id}/pinPOST /api/xcx/tasks/{id}/unpin
  • PerformanceSummary任务列表响应中附带的绩效概览数据结构15+ 字段)
  • DateGroup:按日期分组的数据结构,包含日期标签、当日汇总、记录列表
  • FDWPostgreSQL Foreign Data Wrapper用于从业务库 zqyy_app 访问 ETL 库 etl_feiqiu 的数据
  • items_sumDWD-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 要求的拆分字段
  • enrichTask:前端 task-list 页面中对原始任务数据进行扩展的函数,补充 lastVisitDays/balance/aiSuggestion 等字段
  • buildPerfData:前端 task-list 页面中构建绩效进度条数据的函数,消费 PerformanceSummary 的 15+ 字段
  • courseTypeClass:服务记录中课程类型的样式标识,统一使用 basic/vip/tip 枚举(不带 tag- 前缀)
  • user_assistant_binding:业务库中用户与助教身份的绑定关系表,用于数据隔离
  • ai_cache:业务库中 AI 分析结果的缓存表,按 cache_type 区分不同类型的 AI 输出

需求

需求 1扩展 TASK-1 任务列表绩效概览T1-1

用户故事: 作为助教,我希望在任务列表页面看到完整的绩效进度条(含档位节点、基础/激励课时、升档奖金、收入趋势),以便快速了解本月绩效状态和距升档的差距。

验收标准

  1. THE TASK_1_API SHALL 在响应的 performance 字段中返回以下扩展字段:tierNodes(档位节点数组,如 [0, 100, 130, 160, 190, 220])、basicHours(基础课时)、bonusHours(激励课时)、currentTier当前档位索引0-basednextTierHours(下一档位工时阈值)、tierCompleted(是否已达最高档)、bonusMoney(升档奖金,元)、incomeTrend(收入趋势描述,如 "↓368")、incomeTrendDirupdown)、prevMonth(上月标签,如 "1月")、currentTierLabel(当前档位名称,如 "初级"
  2. THE TASK_1_API SHALL 从 fdw_etl.v_dws_assistant_salary_calc 查询当前助教的绩效和档位数据,通过 user_assistant_binding 获取 assistant_id 进行数据隔离
  3. THE TASK_1_API SHALL 使用 items_sum 口径计算所有收入金额DWD-DOC 强制规则 1使用 assistant_pd_money(基础课)和 assistant_cx_money激励课拆分助教费用DWD-DOC 强制规则 2
  4. THE TASK_1_API SHALL 通过对比当月和上月的收入数据计算 incomeTrendincomeTrendDir 字段
  5. WHEN tierCompletedtrueTHE TASK_1_API SHALL 将 bonusMoney 设为 0nextTierHours 设为当前档位工时阈值

1.2 任务项扩展字段GAP-03

  1. THE TASK_1_API SHALL 为每个任务 item 返回以下可选扩展字段:lastVisitDays距上次到店天数integerbalance客户余额numberaiSuggestionAI 建议摘要string
  2. THE TASK_1_API SHALL 从 fdw_etl.dwd.dwd_settlement_head 查询客户最后到店日期,计算 lastVisitDays(当前日期与 MAX(settle_time) 的天数差)
  3. THE TASK_1_API SHALL 从 fdw_etl.dwd.dim_member_card_account 查询客户储值卡余额作为 balance 字段值
  4. THE TASK_1_API SHALL 从 biz.ai_cache 查询 cache_type 对应的 AI 建议摘要作为 aiSuggestion 字段值
  5. IF 某个扩展字段的数据源查询失败或无数据THEN THE TASK_1_API SHALL 对该字段返回 null,不影响其他字段和整体响应

需求 2实现 TASK-2 任务详情完整版T1-2

用户故事: 作为助教我希望点击任务后能看到完整的任务详情包括服务记录、维客线索、AI 分析、备注),以便全面了解客户情况并制定跟进策略。

验收标准

  1. THE TASK_2_API SHALL 返回完整的任务详情响应,包含基础信息、维客线索(retentionClues)、话术参考(talkingPoints)、服务记录摘要(serviceSummary)、服务记录列表(serviceRecords、AI 分析(aiAnalysis)、备注列表(notes
  2. THE TASK_2_API SHALL 在响应中包含 customerId 字段(客户唯一 ID供前端跳转 chat 和 customer-service-records 页面使用
  3. WHEN 请求任务详情时THE TASK_2_API SHALL 对服务记录(serviceRecords)和备注(notes)各返回最多 20 条,按时间倒序排列,支持前端懒加载

2.2 维客线索格式统一GAP-06~07

  1. THE TASK_2_API SHALL 返回维客线索的 tag 字段为纯文本字符串(不含换行符 \n),多行标签使用空格分隔
  2. THE TASK_2_API SHALL 返回维客线索的 source 字段为以下枚举值之一:manual(手动创建)、ai_consumptionAI 消费分析生成)、ai_noteAI 备注分析生成)
  3. THE TASK_2_API SHALL 从 public.member_retention_clue 查询维客线索数据,按 created_at 倒序排列

2.3 AI 分析 cache_type 映射GAP-08

  1. THE TASK_2_API SHALL 从 biz.ai_cache 查询 AI 分析数据,使用以下 cache_type 映射:aiAnalysis.summary 来自 app4_analysistalkingPoints 来自 app5_talking_points
  2. IF biz.ai_cache 中无对应 cache_type 的缓存记录THEN THE TASK_2_API SHALL 对 aiAnalysis 返回 { summary: "", suggestions: [] },对 talkingPoints 返回空数组

2.4 服务记录字段GAP-06

  1. THE TASK_2_API SHALL 为每条服务记录返回 courseTypeClass 字段,使用统一枚举值:basic(基础课)、vip(包厢课)、tip(激励课)、recharge(充值)、incentive(激励),不带 tag- 前缀
  2. THE TASK_2_API SHALL 为每条服务记录返回可选字段 recordTypecourserecharge)和 isEstimate是否预估数据boolean
  3. THE TASK_2_API SHALL 使用 items_sum 口径计算服务记录中的 income 字段DWD-DOC 强制规则 1
  4. THE TASK_2_API SHALL 使用 dwd_assistant_service_log_ex.is_trash 排除废单记录

2.5 权限与数据隔离

  1. THE TASK_2_API SHALL 验证请求的 taskId 属于当前登录助教(通过 user_assistant_binding 获取 assistant_id,校验 coach_tasks.assistant_id 匹配)
  2. IF 请求的 taskId 不属于当前助教THEN THE TASK_2_API SHALL 返回 HTTP 403 { code: 403, message: "无权访问该任务" }

需求 3实现 PERF-1 绩效概览T1-3

用户故事: 作为助教,我希望查看本月绩效概览(包括收入明细、档位进度、服务记录按日期分组、新客和常客列表),以便了解本月工作成果和收入构成。

验收标准

  1. THE PERF_1_API SHALL 接受 yearmonth 查询参数,返回指定月份的绩效概览数据
  2. THE PERF_1_API SHALL 通过 user_assistant_binding 获取当前助教的 assistant_id,仅查询该助教自己的绩效数据

3.2 本月服务记录 DateGroup 结构GAP-12

  1. THE PERF_1_API SHALL 将 thisMonthRecords 以 DateGroup 结构返回:每组包含 date(日期标签,如 "2月7日")、totalHours(当日总工时,格式化字符串)、totalIncome(当日总收入,格式化字符串)、records(记录列表)
  2. THE PERF_1_API SHALL 为 DateGroup 中每条记录返回以下字段:customerNameavatarChar(姓氏首字)、avatarColor(头像渐变色)、timeRange(时间段,如 "20:00-22:00")、hours(工时,格式化字符串)、courseType(课程类型,如 "基础课")、courseTypeClass(样式标识:basic/vip/tip,不带 tag- 前缀)、location(台桌/包厢名)、income(收入,格式化字符串)
  3. THE PERF_1_API SHALL 从 fdw_etl.v_dwd_assistant_service_log 查询服务记录,按 settle_time 日期分组,每组内按时间倒序排列

3.3 收入档位数据GAP-13

  1. THE PERF_1_API SHALL 返回收入档位数据:currentTier(当前档,含 basicRateincentiveRate)、nextTier(下一档,含 basicRateincentiveRate)、upgradeHoursNeeded距升档所需工时numberupgradeBonus升档奖金number
  2. THE PERF_1_API SHALL 从 fdw_etl.v_dws_assistant_salary_calc 查询档位和费率数据

3.4 上月收入与收入明细GAP-14~15

  1. THE PERF_1_API SHALL 返回 lastMonthIncome 字段(上月收入,格式化字符串,如 "¥16,880"
  2. THE PERF_1_API SHALL 为 incomeItems 每项返回 desc 字段(费率×工时的拆分描述,如 "80元/h × 75h"),由后端根据费率和工时数据计算生成
  3. THE PERF_1_API SHALL 使用 items_sum 口径计算所有收入金额DWD-DOC 强制规则 1使用 assistant_pd_moneyassistant_cx_money 拆分助教费用DWD-DOC 强制规则 2

3.5 新客与常客列表GAP-16

  1. THE PERF_1_API SHALL 为 newCustomers 每项返回 lastService(最后服务日期,如 "2月7日")和 count服务次数number字段
  2. THE PERF_1_API SHALL 为 regularCustomers 每项返回 hours总工时numberincome(总收入,格式化字符串)字段
  3. THE PERF_1_API SHALL 通过 member_id JOIN fdw_etl.dwd.dim_member(取 scd2_is_current=1获取客户姓名DWD-DOC 强制规则 DQ-6禁止直接使用 member_phonemember_name

需求 4实现 PERF-2 绩效明细T1-4

用户故事: 作为助教,我希望查看指定月份的绩效明细(按日期分组的服务记录列表),以便回顾每天的工作详情。

验收标准

  1. THE PERF_2_API SHALL 接受 yearmonthpagepageSize 查询参数,返回指定月份的绩效明细数据
  2. THE PERF_2_API SHALL 每页返回最多 20 条记录(默认 pageSize=20),按日期分组为 dateGroups 结构,并返回 hasMore 标记指示是否有更多数据

4.2 按日期分组GAP-19~20

  1. THE PERF_2_API SHALL 将服务记录按日期分组,每组包含 date(日期标签)、totalHours(当日总工时)、totalIncome(当日总收入)、records(记录列表)
  2. THE PERF_2_API SHALL 为每条记录返回 courseTypeClass 字段,使用统一枚举值 basic/vip/tip(不带 tag- 前缀)
  3. THE PERF_2_API SHALL 不返回 avatarCharavatarColor 字段(前端通过 nameToAvatarColor() 工具函数从 customerName 自行计算)

4.3 月度汇总

  1. THE PERF_2_API SHALL 返回月度汇总数据 summarytotalCount(总记录数)、totalHours(总工时)、totalHoursRaw(原始工时,未折算)、totalIncome(总收入)
  2. THE PERF_2_API SHALL 使用 items_sum 口径计算 totalIncome 和每条记录的 incomeDWD-DOC 强制规则 1
  3. THE PERF_2_API SHALL 通过 member_id JOIN fdw_etl.dwd.dim_member(取 scd2_is_current=1获取客户姓名DWD-DOC 强制规则 DQ-6

需求 5实现 pin/unpin API 端点T1-5

用户故事: 作为助教,我希望将重要任务置顶或取消置顶,以便优先处理关键客户的跟进任务。

验收标准

  1. THE Backend SHALL 实现 POST /api/xcx/tasks/{taskId}/pin 端点,将指定任务的 is_pinned 字段设为 true
  2. THE Backend SHALL 实现 POST /api/xcx/tasks/{taskId}/unpin 端点,将指定任务的 is_pinned 字段设为 false
  3. WHEN pin 或 unpin 操作成功时THE PIN_API SHALL 返回 { isPinned: true }{ isPinned: false }
  4. THE PIN_API SHALL 验证请求的 taskId 属于当前登录助教(通过 user_assistant_binding 校验),不属于时返回 HTTP 403
  5. IF 请求的 taskId 不存在THEN THE PIN_API SHALL 返回 HTTP 404 { code: 404, message: "任务不存在" }
  6. THE Miniprogram SHALL 在 services/api.ts 中新增 pinTask(taskId: string)unpinTask(taskId: string) 函数,分别调用 pin 和 unpin 端点
  7. WHEN pin/unpin API 调用成功后THE Miniprogram SHALL 更新本地任务列表状态(将任务移入/移出置顶分组),无需重新请求完整任务列表

需求 6前端适配 — 任务页面T1-6 任务部分)

用户故事: 作为助教,我希望任务列表和任务详情页面能正确展示后端返回的真实数据(替代当前的 mock 数据),以便看到真实的客户信息和绩效状态。

验收标准

6.1 createNote 补充用户手动评分参数GAP-05

  1. THE Miniprogram SHALL 修改 services/api.tscreateNote 函数的签名,增加可选参数 manualScore?: number用户手动评分1-5 星)
  2. WHEN 用户在备注弹窗中提交备注时THE Miniprogram SHALL 将 manualScore 字段一并传递给 POST /api/xcx/notes 端点
  3. THE Backend SHALL 修改 POST /api/xcx/notes 端点,接受请求体中的可选 manualScore 字段number1-5并存入 biz.notes.score 列。注意:此字段为用户手动评分(再次服务意愿 + 再来店可能性),与 AI 应用 6 的 aiScore1-10 分,展示用)语义不同

6.2 storageLevel/relationLevel 前端计算GAP-11

  1. THE Miniprogram SHALL 在 task-detail 页面根据后端返回的 balance 字段值,在前端本地计算 storageLevel(储值等级,如 "非常多"/"较多"/"一般"/"较少"
  2. THE Miniprogram SHALL 在 task-detail 页面根据后端返回的 heartScore 字段值0-10 范围),在前端本地计算 relationLevelrelationLevelTextrelationColor,阈值遵循 P6 AC3 四级映射(>8.5 / >7 / >5 / ≤5

需求 7前端适配 — 绩效页面T1-6 绩效部分)

用户故事: 作为助教,我希望绩效概览和绩效明细页面支持月份切换,以便查看历史月份的绩效数据。

验收标准

7.1 绩效概览月份切换F8, GAP-18

  1. THE Miniprogram SHALL 在 performance 页面添加月份切换控件(左右箭头 + 月份标签),允许用户在当前月和历史月份之间切换
  2. WHEN 用户切换月份时THE Miniprogram SHALL 使用新的 year/month 参数重新调用 fetchPerformanceOverview 接口,加载对应月份的绩效数据
  3. THE Miniprogram SHALL 在月份切换期间显示加载状态,防止用户重复操作

7.2 绩效明细月份切换重置分页F9, GAP-21

  1. WHEN 用户在 performance-records 页面切换月份时THE Miniprogram SHALL 将 page 重置为 1清空已加载的记录列表重新从第一页加载
  2. THE Miniprogram SHALL 修复 switchMonth() 函数中 page 未重置的 Bug

7.3 avatarChar/avatarColor 前端计算GAP-19 决策)

  1. THE Miniprogram SHALL 在 performance 和 performance-records 页面,使用 nameToAvatarColor() 工具函数从 customerName 计算 avatarChar(姓氏首字)和 avatarColor(头像渐变色),不依赖后端返回这两个字段

需求 8全局约束与数据隔离

用户故事: 作为系统管理员,我希望所有任务和绩效接口都遵循统一的权限控制和数据隔离规则,以确保每位助教只能访问自己的数据。

验收标准

  1. THE Backend SHALL 对所有 RNS1.1 接口TASK-1、TASK-2、PERF-1、PERF-2、PIN/UNPIN执行 require_approved() 权限检查,确保用户状态为 approved
  2. THE Backend SHALL 对所有 RNS1.1 接口验证用户具有 view_tasks 权限
  3. THE Backend SHALL 通过 user_assistant_binding 表获取当前用户对应的 assistant_id,所有数据查询均以该 assistant_id 作为过滤条件
  4. IF 当前用户在 user_assistant_binding 中无绑定记录THEN THE Backend SHALL 返回 HTTP 403 { code: 403, message: "未绑定助教身份" }
  5. THE Backend SHALL 对所有涉及金额的字段统一使用 items_sum 口径DWD-DOC 强制规则 1禁止使用 consume_money
  6. THE Backend SHALL 对所有涉及助教费用的字段使用 assistant_pd_money(陪打/基础课)+ assistant_cx_money(超休/激励课拆分DWD-DOC 强制规则 2禁止使用 service_fee
  7. THE Backend SHALL 对所有涉及会员信息的查询通过 member_id LEFT JOIN fdw_etl.dwd.dim_member(取 scd2_is_current=1获取姓名和手机号DWD-DOC 强制规则 DQ-6禁止直接使用 settlement_head.member_phonemember_name
  8. THE Backend SHALL 使用 dwd_assistant_service_log_ex.is_trash 排除废单记录,禁止使用已废弃的 dwd_assistant_trash_event