# crm-lead 视图统计接口 /stats + statusIn 契约变更 Type: task Status: resolved Depends on: — ADR: docs/adr/0023-lead-batch-operations-and-view-stats.md (D3/D4) ## Question(实现目标) 新增顶部统计卡片接口,口径=当前视图(非全库);并把列表 status 筛选升级为多值以支持复合卡片下钻。 ## 交付物 ### 契约变更(crm-lead) - `domain/param/LeadPageParam.java`:`Integer status` → `List statusIn`(`/page` 与 `/stats` 共用)。 - Schema 说明:多值,支持复合卡片下钻(如「已被领取」传 `[3,4]`)。 ### DTO(crm-lead) - `domain/dto/LeadStatsDTO.java`:`int total / claimed / converted / todayNew / undistributed`(默认 0)。 ### 读侧(crm-lead query 深模块,ADR-0022) - `LeadViewQuery` 增 `LeadStatsDTO countStats(LeadPageParam param)`。 - `LeadViewQueryImpl`: - 抽出 `private LambdaQueryWrapper buildViewWrapper(param, currentUserId)`,被 `pageLeads` 与 `countStats` **共用**,确保统计口径 = 列表口径(同 viewType + 同筛选 + 同 `@DataScope`)。 - status 过滤由 `.eq(status)` 改为 `.in(CollUtil.isNotEmpty(statusIn), Lead::getStatus, statusIn)`。 - `pageLeads` = `buildViewWrapper(...).orderByDesc(createTime)` 后分页(行为不变)。 - `countStats` = `selectList(buildViewWrapper(...))` 后按 status 分组计数:claimed=status∈{3,4}、converted=5、undistributed=1、total=全部、todayNew=createTime 为今天。 ### service + controller(crm-lead) - `ILeadService` 增 `LeadStatsDTO countStats(LeadPageParam)` → 委派 `leadViewQuery.countStats`。 - `LeadController` 增 `@PostMapping("/stats")`,入参 `LeadPageParam`,返回 `Result`。 ## 验收 - 编译:`mvn -q -pl crm-lead -am compile`。无 BOM。 - 现有 `/page` 相关测试改 `status`→`statusIn` 后仍绿。 - 新测:四视图下 `countStats` 口径与 `pageLeads` 一致(同筛选集);`statusIn=[3,4]` 下钻能正确回到 `/page`。 - 注意:`buildViewWrapper` 重构不得改变 `pageLeads` 既有行为(读写分离 query 模块为本会话前未提交改动,勿破坏)。 ## Comments ## Answer 已交付(ADR-0023 D3/D4): - **statusIn 契约变更**:`LeadPageParam.status(Integer)` → `statusIn(List)`(支撑复合卡片下钻);wrapper 由 `.eq(status)` 改为 `.in(CollUtil.isNotEmpty, status, statusIn)`。全库仅 1 处引用(LeadViewQueryImpl),无测试引用 param.status。 - **统计口**:`LeadStatsDTO`(total/claimed/converted/todayNew/undistributed);`LeadViewQuery.countStats` + `LeadServiceImpl.countStats` 委派;`LeadController` `POST /api/lead/stats`(同 /page 吃 `LeadPageParam`)。 - **口径共享**:抽取 `buildViewWrapper(param, userId)`(viewType 数据集 + 公共筛选,不含排序/分页),`pageLeads` 与 `countStats` 共用,保证「统计口径 = 列表口径」+ @DataScope 一致。claimed = status IN(已领取,跟进中);todayNew 按 createTime.toLocalDate() == today。 验收:无 BOM;`mvn -pl crm-lead -am compile` BUILD SUCCESS;`LeadViewQueryImplTest` 6/6(+2 统计:status 分组、todayNew 今日),crm-lead 全套 64/64 绿无回归。(crm-auth 模块存在无关本票的 junit 发现失败,已隔离验证 crm-lead。)