You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5.8 KiB
5.8 KiB
线索视图统计卡片改版(/api/lead/stats)
Destination
一份可交付的 /api/lead/stats 改版 spec:明确改版后四视图各自要展示哪些统计卡片、每张卡片的口径(映射到哪个 status / 派生条件)、LeadStatsDTO 的字段形态,以及口径与「列表可见范围」冲突时的取舍规则。产出决策而非代码;spec 交付后再另起 session 实现。
目的地扩容(2026 grill 决策 01 后):新增一项前置领域小改 —— 作废态保留
owner_user_id(不再清空),使销售能在「我的线索」看到自己作废的线索;名额hold_limit/ 可转商机目录不受影响(二者按 status IN (3,4) 排除,本就不看 owner 是否为空)。本图目的地因此从「纯 stats spec」扩为「作废保留 owner 的状态机小改 + stats 改版 spec」;stats 口径是这个语义改动的下游消费者。
新需求(用户给定)——四视图卡片清单:
- 线索公海:线索总量、待领取、今日新增
- 我的线索:线索总量、已领取、跟进中、已转商机、线索作废、过期失效
- 我的关注:线索总量、待领取、已领取、跟进中、已转商机、线索作废、过期失效
- 线索管理:线索总量、今日新增、未分发、待领取、销售持有、已转商机、过期失效(销售持有 = 已领取 + 跟进中)
Notes
- 域:
crm-lead线索模块。状态机 7 态(LeadConstants):1未分发 / 2待领取 / 3已领取 / 4跟进中 / 5已转商机(终态) / 6过期失效 / 7线索作废。 - 现状代码:接口
LeadController#stats→ILeadService#countStats→LeadViewQueryImpl#countStats;DTOLeadStatsDTO(现有字段 total/waiting/claimed/converted/todayNew/undistributed/feedbackValid/feedbackInvalid/feedbackNone)。统计口径复用applyViewFilters,即「统计口径 = 列表口径」是当前的硬约束(P1-7)。 - 关键冲突(本图的核心):现有视图过滤——
MY_LEAD=owner_user_id = 当前用户;PUBLIC_POOL仅可见 status ∈ {2,3,4}(PUBLIC_POOL_VISIBLE_STATUSES)。- CONTEXT:线索作废(7) 进入时清空
owner_user_id→ 按现有MY_LEAD口径,作废线索不在我的线索里,但需求要 我的线索 统计「线索作废」。 - 过期失效(6) 保留领取人 → 在 我的线索 里可见,口径无冲突。
- 这决定了「统计口径 = 列表口径」这条硬约束是否还成立,是全图的根。
- 参考:
crm-lead/CONTEXT.md(状态/归属语义)、.scratch/clue-module/(原历史 map 与 PRD)。 - 用到的 skill:
/grilling、/domain-modeling;如需查历史决策用/research。
Decisions so far
- 作废/过期线索的统计口径能否突破「列表可见范围」 — 定了作废态保留 owner_user_id(不再清空):名额 hold_limit / 可转商机目录均按 status IN(3,4) 排除作废,不依赖 owner=null,故保留 owner 不影响名额;清 owner 原本唯一副作用就是让作废线索离开「我的线索」,而那正是不想要的。目的地据此扩容(选 i)。
- 作废保留 owner 的状态机小改 — 字段取舍(owner/name/claim_time 保留、recycle_deadline 清 null);回收/激活/DataScope/边#15 均自洽或选定“顶替”;列出文档待改行号与回归断言。下游 02 预填两格:各视图作废计数=自然过滤+status=7、「我的线索」含 owner=我的作废。
- 四视图口径映射表 — 定了核心公式:所有分卡 =
applyViewFilters+ 单 status 条件,无逐格特判、不叠 owner 断言。开展六项定镀:“线索总量”=视图内 count(*);卡片吃全部/page动态筛选;“今日”按 JVM 时区LocalDate.now()+create_time范围条件(不看当前 status);销售持有 =status IN(3,4)纯 status;「我的关注」含别人 owner 的作废/过期;MANAGE = 无业务过滤 +@DataScope(数字随角色变);需求✗格不追问。 - 今日新增卡片下钻的列表联动入参 — 缺口:
/page的LeadPageParam无 create_time 入参,「今日新增」(不看 status 的时间窗)无法用statusIn下钻。定方案 B:加语义布尔todayNewOnly,时间窗由后端按LocalDate.now()展开并下沉到applyViewFilters(page/stats 共用同一段,前后端同一个"今天",严守 P1-7);弃通用区间方案 A(YAGNI)。前端点今日新增传todayNewOnly:true且不传 statusIn。 - DTO 字段形态与前端返回契约 — 定了最终 10 字段 shape:
claimed收窄为仅 status=3(语义改),新增following(4)/expired(6)/voided(7)/sellerHolding(3+4);删 feedback 三字段及其 GROUP BY SQL(选甲)。全量返回、四视图同 shape、后端不知视图勾选表(选甲)。statusIn照传照吃、严守 P1-7、卡片归零是前端渲染事(选丁)。钉定 10 个重写的countStats_*断言用例(@DataScope合并 1 个、✗格字段如实计算)。
Not yet specified
- 作废保留 owner 的残留触点(已 graduate 为 ticket 04,不再是雾):回收 N / 激活 /
@DataScope/ 边#15 重新分配 / PRD·CONTEXT 文档 —— 见 04。
全部 decision ticket(01/04/02/03)已 resolved。spec 完整,下一步是实现 session(不在本 wayfinder 图内)。