6.2 KiB
01 · 客户三 workspace 查询口径收敛(boardSummary 漂移修复 + 守恒断言)
- Status: resolved
- Type: task
- 来源: /improve-codebase-architecture 2026-09-06 报告候选 #1(
.scratch/architecture-review-20260906-102629.html),grilling 五决策已全部拍板
背景(缺陷事实)
CustomerMapper 的 workspace 公共 WHERE(内置视图 × 公共筛选 × groupColumn)手写了 4 份:pageWorkspace 的 overview / mine+pool 两分支各一份 + boardSummary 的两分支。其中 boardSummary 的两份已漂移——相对 pageWorkspace 静默缺少 3 个条件:
FOLLOW_UP_DUE(待跟进视图 EXISTS)industryCodeprovinceCode
后果:同一参数下看板列头汇总数 ≠ boardCards(走 pageWorkspace)计数;javadoc 却声称「完全一致」。无测试覆盖该一致性(返工票 03 只测了 pool 拒绝)。CustomerWorkspacePageParam 为列表与看板共用基类,三个漂移参数在前端请求看板端点的路径上完全可达。
拍板决策(grilling 定案,不再重议)
- 漂移 3 条件按 bug 修:以
pageWorkspace完整条件为准,boardSummary 补齐。唯一保留的有意差异 = saved-view 条件(票 10 明文「看板不接自定义视图」;savedViewConditions为 null 时共享片段天然不拼,无需特判)。 - 载体 = 注解 SQL +
static final String常量编译期拼接:公共片段(c.列前缀 +q.参数名,四处上下文无关)提为接口常量,各语句@Select("""…""" + COMMON_WHERE + """…""")拼接。不引 XML mapper——全工程零 XML mapper 先例,且 H2 测试手工MybatisConfiguration.addMapper()自举不解析 XML(会 Invalid bound statement),爆炸半径大于收益。理由写进类 javadoc。 - 守恒断言 = 现有测试类加 4 用例:
CustomerWorkspaceOwnershipIntegrationTest内,造数后同一参数Σ boardSummary.cnt == pageWorkspace.total。4 用例 = 基础集 +viewType=FOLLOW_UP_DUE+industryCode+provinceCode各一。不做全矩阵。 /api/customer/page不动:查实它是「客户管理」页面端点(e2edefs_a4.py有消费、API-SUMMARY 独立行登记),与三 workspace 不是双轨。- 范围 = R1 最小票:只动
CustomerMapper(两条 SQL、四处公共块)+CustomerWorkspaceOwnershipIntegrationTest(4 用例)。不碰 service / controller / param / bruno——无契约变化。其余 5 条语句(selectSimilar×2 / selectByCreditCode / selectMaxCustomerNo / searchForOpportunity)各自单份无重复,不动。
做法
CustomerMapper内提公共 WHERE 常量(内置视图 ifs + 公共筛选 ifs + groupColumn ifs + saved-view foreach 按现有结构整合),pageWorkspace两分支与boardSummary两分支改为常量拼接。boardSummary补齐 3 个漂移条件(含两分支)。注意 overview 分支的FOLLOW_UP_DUEEXISTS 在 boardSummary 现状里完全缺失,mine/pool 分支同理。- 类 javadoc「两处同步」警示改写为「公共片段在 XXX 常量,新增筛选同步加进常量」;补一段载体决策理由(为何不用 XML mapper——见拍板 2)。
CustomerWorkspaceOwnershipIntegrationTest加 4 个守恒用例(口径见拍板 3;overview + mine 两 workspace 至少各覆盖一次)。crm-customer/CONTEXT.md在「客户总览」词条(或邻近)补一句:「看板 summary/cards 与列表同口径(同一份列表数据三种渲染),守恒由集成测试断言」。
验收
mvn test -pl crm-customer绿(既有 135+ 用例不回归 + 新增 4 用例);- 修复前先写守恒用例跑一次确认能红(证明用例真覆盖漂移),再修 SQL 转绿;
CustomerMapper内公共 WHERE 字面只出现一份;- BOM 扫描通过(新增 Java 文件无 EF BB BF)。
Answer
红 → 绿两段式完成,验收 4 条全部满足。
红灯证据(先写测试坐实漂移)
4 守恒用例先行(assertBoardListConservation:同参数下 Σ boardSummary.cnt == page.total),改造 SQL 前跑 CustomerWorkspaceOwnershipIntegrationTest:
- 21 跑 3 红 0 回归:
conservation_followUpDue/conservation_industry/conservation_province三用例红,expected: 1L but was: 2L——看板把未命中筛选的客户也计入,3 条件漂移坐实; conservation_base(无筛选路径)绿——证明断言机制本身无误,红是漂移不是断言写错;- 既有 17 用例全绿。
修复内容
CustomerMapper.java(306 行重写,净减 ~120 行):
- 提
MINE_POOL_DATASET(mine 白名单 / pool 部门折算<choose>)+WORKSPACE_COMMON_FILTERS(归档排除 + 5 内置视图 + 7 列筛选 + 3 groupValue + saved-view foreach)两个接口常量; pageWorkspace/boardSummary四处公共 WHERE 全部改为""" + 常量 + """编译期拼接——公共 WHERE 字面全工程只此一份;boardSummary两分支补齐FOLLOW_UP_DUEEXISTS /industryCode/provinceCode三条件(saved-view 保留不拼,票 10 有意差异);- 类 javadoc + 两语句 javadoc 改写:载体决策理由(拒 XML mapper 的两个事实)、「新增筛选同步加进常量」警示、D-15 同口径 + 守恒断言说明。
CustomerWorkspaceOwnershipIntegrationTest.java(+60 行):4 守恒用例 + helper,overview / mine 两 workspace 均覆盖。
crm-customer/CONTEXT.md:「客户总览」词条补「看板 summary/cards 与列表同口径(对称商机 D-15;公共 WHERE 在 CustomerMapper 常量单一事实源,守恒由集成测试断言)」。
绿灯证据
mvn -pl crm-customer -am test(2026-09-06):14 个测试类 164 跑 0 失败 0 错误 0 跳过:
CustomerWorkspaceOwnershipIntegrationTest:21 跑全绿(4 守恒用例转绿 + 17 旧用例零回归);CustomerWorkspaceSavedViewIntegrationTest:8 跑全绿(saved-view foreach 路径未受常量拼接影响)。
收尾核验
- BOM 扫描:全工程 716 个
.java(排除 target)clean; - 环境注记:本地仓库 crm-rule 快照过旧,
mvn -pl crm-customer test不带-am会编译失败(与本次改动无关),验收命令须带-am。