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.

108 lines
20 KiB

6 days ago
# Map: 商机模块缺陷修复与新模块可行性(复测裁决 → 修复 → 文档/数据交付)
`wayfinder:map`
## Destination
**商机模块整改交付包,四件事全部落地**:
1. **22 条缺陷复测裁决**(`retest-verdicts.md`)— 以最新原型 web 端 v29(2026-08-28 更新)为第一依据,对 `opportunity-e2e/e2e-report.md` 的 D-01~D-22 逐条裁决:✅ 确认为真实缺陷(附原型证据)/ ⚠ 翻案(原型/PRD 与实测结论不符,说明理由)/ ❓ 存疑(升级用户拍板)。判定依据优先级:**原型 > PRD > 问用户**。
2. **P1 缺陷全部修复 + P2 按裁决修复** — 确认为真的缺陷修完并通过回归测试(复测脚本全绿 + e2e 报告缺陷状态更新为已修复)。
3. **工作计划 / 客户管理可行性裁决** — 基于最新原型的完整模块(A1X 6 页 / A4 30+ 页)评估开发工作量:工作量小 → 简易实现 + 造测试数据 + 开放接口;工作量大 → 标记后续迭代。产出可行性报告 + 用户拍板记录。
4. **交付物刷新** — ① `skill: bruno-sync` 更新 `E:\code\crm-api-docs`(修复后的契约变更 + 新增端点,示例真实可联调);② 精简测试数据集(跨部门场景 + 状态流转样例)刷新。
地图做完 = 裁决有据、修复有验、文档/数据跟上、两个新模块有明确结论(实现或挂起)。
## Notes
### 原型拉取通路(本 session 已验证,票 01 直接照做)
完整操作手册:`.scratch/lanhu-latest/RESEARCH-axure-pipeline.md`。要点:
- **Axure 全部产物在公开 OSS,无需 Cookie/MCP**:清单 `axure-v29.json` 已在本地(182 页 + sitemap),每页 `mapping_md5``html.sign_md5` → 下载 HTML → `extract-html-text.mjs` 提取文本。
- 文本主载体是**页面 HTML 的 `uNNN_text` div**(中文全是 `&#xHHHH;` 实体须解码);data.js 的表格 cell label 全空,别用。
- 每页自带**需求批注区**(需求|需求说明|变更记录:开发说明/详细说明/字段说明/交互说明/业务规则&功能逻辑/验收标准)——这是 PRD 级判定依据,拉取时必须完整提取。
- 原型版本 v29(2026-08-28),比上轮 e2e 用的旧;**裁决一律以 v29 为准**,旧缓存 `.scratch/opportunity-verify/lanhu-cache/` 仅作对照。
### 判定纪律(继承上轮,违者翻车)
- **禁止按 RESTful 推断接口路径**:本项目 flat 风格(`POST /api/opportunity/page`)。判「缺失」前核对 Controller 源码 + Bruno 集合实际路径。
- **PS5.1 发中文 body 会把远程库写坏(mojibake 实锤)**:一切带中文 body 的脚本一律 Python requests;Node fetch(.mjs)无此问题。
- 孤立 401 先重试一次再判缺陷(客户端 Content-Type 问题)。
### 22 条缺陷索引 + 白盒根因锚点(票 02 的输入)
终稿清单:`.scratch/opportunity-e2e/e2e-report.md` §D-01..D-22。白盒根因已定位的:
| 缺陷 | 根因锚点 |
|---|---|
| D-10/11/12(V-CONFIG 三族编辑发布中生新草稿 50001 主键冲突) | `crm-rule` 三族 `resolveDraft` 的编辑分支 `dto.toEntity()` 携带源 id 走 insert:`OpportunityStageTemplateServiceImpl` L250 / `OpportunitySchemeCardTemplateServiceImpl` L193 / `OpportunityPoolRuleServiceImpl` L102 |
| D-13(owner_dept_id 恒空 13/13 NULL) | 创建路径 `OpportunityCreateServiceImpl` 注释「ownerDeptId 传 null」;流转路径 `OpportunityTransitionImpl` L120/L137 依赖前端传 `cmd.ownerDeptId()`(前端不传则 null) |
| D-09(禁领规则 allowFreeClaim=0 未生效) | `PoolRuleMatcher.loadPublished()` 只被 `OpportunityMaintenanceJob`(回收 Job)消费,claim/release 路径未接规则校验 |
| D-01~06(6 个 404 端点) | `OpportunityCustomer`/`OpportunityTeam` 实体已存在(含 customerRole/isPrimaryIntended/deleteKey/projectRole/permission),仅缺 Controller 写端点;`OpportunitySubController` 只有 team/list |
| D-15(公海看板未过滤) | board 两端点源码无 viewType 参数(票 11 坐实) |
### 环境(上轮已验,直接复用)
- 起服:仓库根 `$env:SPRING_PROFILES_ACTIVE='verify'; $env:CRM_MINIO_AK='admin'; $env:CRM_MINIO_SK='Itc@123456'; java -jar crm-app\target\crm-app-1.0.0-SNAPSHOT.jar`(连远程 DB 8.129.84.155);手册 `.scratch/opportunity-e2e/boot-verify.md`
- debug token:`GET /api/auth/debug/token?userId=`(verify profile);分页参数 `current`/`size`。
- 复测基线:`python .scratch/opportunity-e2e/seed-opportunity.py`(先清后造)→ `e2e-core.py` / `e2e-rules.py`;修复后回归直接复用这两个脚本 + 缺陷专项断言。
- 账号矩阵:管理员罗伟健 + 跨部门 A赖永利/B肖琴/C曾偲青(`env-inventory.md`)。
- 测试数据现状:seed 12 条商机可能被上轮实测污染,回归前重跑 seed 重置基线。
### 模块知识(改动前必读)
- `crm-opportunity/CONTEXT.md`:关联客户规则(一商机多客户、有且仅一个主要意向、无删除动作、切主三步事务)、团队成员(行级授权白名单、移交同步维护 team 表)——**补 6 个端点时按这些域规则实现,不是裸 CRUD**。
- `crm-rule/CONTEXT.md`:V-CONFIG 版本化三族同构,修 D-10~12 时三处一起修(同构缺陷同构修)。
- ADR-0017(Controller IO/Param DTO 约定)、ADR-0021(状态机 CAS 乐观锁):新端点/改状态拦截必须遵守。
6 days ago
- 上轮拍板 P1-4:商机详情工作计划 Tab 挂起(A1X 未建)——票 07 重新评估,20260831 拍板 A:精简 Tab 转 task 票 12 实现并已落地(workplan 四端点),全量 A1X 仍挂起。
6 days ago
## Decisions so far
- **原型拉取通路已解决(20260829)** — MCP 对 Axure 不可用(只支持设计图)+ Cookie 直登被风控降级,但发现 Axure 产物全在公开 OSS。五步通路全链路验证(182 页清单 → mapping → HTML → 实体解码提取,团队成员页 478 控件/249 文本全提取成功)。操作手册:`.scratch/lanhu-latest/RESEARCH-axure-pipeline.md`;票 01 直接参数化现成脚本拉全量,预计 182 页 × 2 请求(mapping+html)≈ 400 次公开 OSS GET。
- **原型版本事实已解决(20260829)** — web 端主文档最新 v29(2026-08-28 14:39 GMT),含完整 A1X 工作计划 6 页 + A4 客户管理 30+ 页;同项目另有 H5 端(v16)与 4 个旧版文档(本轮不用)。复测以 v29 为准。
- **修复与复测的顺序拍板(用户原始指令)** — 先复测裁决(票 02)再修复(票 03-06):裁决会翻案部分 P2(如 D-18/19 与上轮拍板相反的项),避免修了不该修的。白盒根因铁实的 P1(D-10~13)裁决基本是走形式,可乐观并行准备方案但合入等裁决。
- **票 01 完成:v29 原型 182/182 页文本库已就绪(20260829)** — `.scratch/opportunity-bugfix/lanhu-pages/`(对账零差异)+ `.scratch/lanhu-latest/pages-index.md` 索引。重点页:A1X×6 / A3×34 / A4×39 / 暂缓-关闭×3。需求批注区(开发说明/字段说明/交互规则/验收标准)已验证完整提取(含 A1X-1-1 字段说明 12 条+交互规则 4 条)。踩坑已记录在票 01 Answer:带 url Folder 需「自身+children」双覆盖(否则静默丢 44 页)、提取窗口 20000(否则超长批注整段丢失)、页名以 sitemap pageName 为准。票 02/07/08 可开工。
- **票 02 完成:22 条裁决 19✅/3⚠/0❓(20260829)** — `retest-verdicts.md`。翻案 3 条(原型/PRD 优先于上轮拍板):D-08 暂缓态关闭实为 PRD E6 合法边(2,3→4,e2e 期望写反);D-18/19 勘察次数必填传参+说明非强制均符合 v29(上轮拍板 P1-2/P1-3 被推翻)。范围变化:票 05 剔 D-08,票 06 剔 D-18/19,D-16 收窄至 4 字段(停留天数/下阶段名无出处,e2e 引「PRD §7.9」失准)。修复方向已写至开工粒度;回归时三处断言需反转(票 09)。修复票 03-06 可开工。
- **票 03 完成:D-10/11/12 三族 50001 + D-13 owner_dept_id 修复实测全绿(20260829)** — A:resolveDraft 第三分支 insert 前清 id/createTime/updateTime(三族对称);单测 95/95(补「insert 时刻主键 null」断言,顺带修 4 个存量失败:CODE_C1 撞 D-01 种子保护编码→CODE_NON_SEED)。B:新建 owner 快照组件三件套 `crm-opportunity/owner/`(服务端覆盖方案,五端点删快照参数,ADR-0017 静默忽略兼容;实现类带 Opportunity 前缀避两域同名 bean 冲突);存量回填 affected=13 残留 0;四路径实测快照跟人走(创建/抛池→assign/handover/claim,注意 E1/E2 前置=待领取(1),验证流须先抛池)。U03:配置层全绿;生效层 release-pool 仍放行=D-09 既有立案(票 05 B:allowManualPool/allowFreeClaim 仅回收 Job 消费,claim/release 入口 0 处接线,Grep 实证;release 按裁决默认不约束),票 03 锚点修复是其前置已就绪。验证脚本 `t03-verify.py` 五段式。票 04/05/06 可开工。
- **票 04 完成:D-01~06 六写端点全部落地(20260829)** — customer/add(直设主要自动降旧主 + 主表快照回写,无 delete)、search(拍板「快照池降级」:A4 未建,候选池 = opportunity_customer 存活行按 customer_id 去重 + 排除已关联 + 分页,切真源签名不变)、set-primary(三步事务降旧主→置新主→主表回写,幂等);team/add(批量,全重拒 66012/局部跳过,username 服务端快照,permission 缺省只读)、update(直接换人 + 快照刷新)、delete(软删 delete_key=id 复用键);负责人行三重锁 66013 仅 duty 可改(新增 duty 列据 v29 A3-1-1-1-8)。验证:t04-verify 27/27 + 单测 18/18 + crm-opportunity 全模块 183/183 + e2e F11/F12 回归 11/11 零缺陷。关键坑:BeanUtils 按名复制 oppId≠opportunityId 静默丢字段报 50001 → toEntity 显式映射;Maven 增量构建静默跳过致 fat jar 落后源码。
- **票 05 完成:D-07 暂缓写禁 13 端点 + D-09 禁领接线(20260830)** — 新组件 OpportunityActionGuard(state/,双方法 ensureNotPaused/ensureClaimAllowed,对齐「业务前置校验归调用方」分工);新码 66014;claim/claim-batch 全量预检(确定性拒绝先拦防部分领取),release/assign 不拦(裁决);addFollow 顺带修「insert 后才查商机」坏顺序。验证:单测 192/192(既有 Sub/SchemeCard 补 @Mock guard 兑容)+ 运行时 26/26(14 端点逐一 66003 + 禁领 66014/预检/放行)+ e2e F14 22✅/PR 10✅;F14 暂缓关闭断言与 e2e-rules U03 断言按 D-08/D-09 裁决同步修正。**测试数据重大发现与修复:ADMIN 是全库唯一 dept_id=NULL 用户**(致创建快照落 null、部门专用规则永不命中)→ 已补;F14 的 11 个 seed 商机被清场软删 → 复活复位(t05-seedreset.py,票 11 可复用)。规则「部门覆盖唯一」64012 是硬约束:同部门第二规则发布被拒非顶替。
- **票 06 完成:P2 修复批七项全绿 + 0 条代码回归(20260830)** — D-14 create 6 必填逐字段 66001 + edit merged 合并校验;D-15 新组件 OpportunityViewFilter 单一事实源(ViewQueryImpl 委托 + board 两端点 viewType,PUBLIC_POOL 状态条件由视图分支提供);D-16 detail 四字段回显(快照优先+存量兜底查卡);D-17 submitCard 主客户卡回写 C4 快照列;D-20 E1-E10 全边落 oplog(STATUS_FLOW/opp_status,E10 SYSTEM 归因);D-21 bizType 四值封闭+缺失/非法统一 66001;D-22 三族 versions DTO 白名单化。**附带实锤两个存量缺陷**:① Opportunity 带锁实体 updateById(新实体) 炸 MP MetaObject(D-17 首版踩中,同票 04 先例改 LambdaUpdateWrapper);② **edit 清字段 bug(实验实锤)**:实体 8 个 String 字段 `= ""` 初始化 + MP NOT_NULL 策略 → update(实体) 把未传字段 SET 空串 → edit 改 wrapper 显式 set。验证:单测 196/196+134/134;t06-verify 运行时专项 32/32;e2e 回归 core 71✅/rules 44✅ 缺陷 0(快照 -t06-regression)。**甄别关键**:F05 编辑回写 ❌ = D-14 预期拦截(e2e 用旧 key opportunityName,DTO 真名 oppName)+ F10 两 ⚠ = D-18/19 翻案断言未同步 → 票 09 断言反转;F14 暂缓 E4 = 轮间状态残留非回归;F09 seed 卡 = 票 05 cleanup 软删 → 票 11 刷新。契约口径给票 10:edit 用 oppName / bizType 四值旧形态作废 / board 新增 viewType。
- **票 09 完成:修复后全量回归 0❌ + 0 缺陷登记,22 条全部闭环(20260830)** — 终版 core ✅99/⚠2/❌0 + rules ✅47/⚠0/❌0 = 合计 ✅146/⚠2/❌0(初验 ✅125/⚠17/❌9);快照 -t09-final,报告已更新(对比表+22 条状态列)。终态分布:19 已修复(D-01~06=票 04 / D-07+09=票 05 / D-10~13=票 03 / D-14/15/17/20/21/22=票 06 / D-16=票 06 四字段+票 09 收尾两字段)+ 3 翻案关闭(D-08/18/19),0 挂起;残留 ⚠2 非缺陷(F08 MinIO 外部依赖 / F13 宽断言样例)。脚本适配:seed 补 D-14 省市必填 + primary=1 时回写主表 primary_customer_id 冗余列(F04/F09 方案预算 null 根因:seed 补行不维护主表列→D-17 回写条件不成立+detail 兜底跳过);e2e-core F01 补省市/F05 改 oppName/F10 按翻案反转;e2e-rules 三条 publish V1.1 占位 ⚠ 换真实断言(V1.0 转停用 status=3)。D-16 收尾(stageStayDays/nextStageName)超出票 02 收窄范围已透明记录,依据=page 已有同源计算列消 page/detail 口径差、回滚点明确。代码改动仅 OpportunityDetailServiceImpl 两字段+单测;验证链 BOM→单测 394/0/0→jarcheck NEW-JAR-WITH-T09→seed→全量回归。**接口已定型**:票 10 用票 06 Answer 契约口径(edit=oppName / bizType 四值封闭 OPP/FOLLOW_UP/SITE_SURVEY/SCHEME_CARD 旧形态作废 / board 新增 viewType)。票 10/11 可开工。
- **票 10 完成:6 新端点 + 22 .bru 契约 patch 入集合,全仓对账 157↔153、EXTRA=0(20260830)** — 新增客户×3(添加关联/候选搜索/设主要)+团队×3(批量添加/编辑/移除)挂商机详情页面文件夹;patch:看板×6 viewType(公海=PUBLIC_POOL/管理=MANAGE/销售=MINE,D-15)、三族 versions 剥审计字段+声明句 DTO 化(D-22)、claim/claim-batch 删快照+desc 66014/全量预检(D-13/D-09)、assign×2 toUserId→userId、handover toUserId→newOwnerUserId(D-13)、pause 三参(pauseReason/pauseExpectedRestartDate/pauseRemark)、close×2 closeReason 可选+closeRemark、release-pool poolReason 可选、create 表 15→14 六必填(D-14)+edit 合并校验说明+attach bizType 四值封闭(D-21)+team list 补 duty;129 锚全命中 0 fail,表述/实参值逐字保留。**MISSING 4 = 历史遗漏**(无页面 tag 接口从未被 tag 范围同步覆盖):region/list+level(省市数据源,真实欠账)+ system/sync/dingtalk+users/admin-role(ADMIN 运维)——不扩票,留拍板。坑:apply save 双 CR bug(\r\r\n)t10-fixcrlf.py 还原 22 文件;Write 大 CJK 载荷丢载荷改走锚点+SearchReplace。docs 仓 22M+6?? 留工作区待人 diff 提交。票 11 可开工。
- **票 11 完成:seed 四遍实跑全绿,基线五升级 + 禁领回归实测 66014(20260830)** — 关联客户 API 化(替掉 DB 直插豁免:6 条推进中每条 2 客户恰 1 主要共 12 行,a2 含 set-primary 切换剧情实测主表快照同步)+ 团队 API 化(a2/b1 完整团队 16 行=12 负责人行+4 API 行,角色用 dict project_role_01~06)+ 部门专用禁领规则(冠军团队 allowFreeClaim=0,autoRecycle=0 防误回收)+ 长期暂缓样例(a3=2027-01-15)+ verify 三账号 MINE 计数(A=4/B=4/C=2 不含公海)+ spot_a2 详情抽查。owner_dept_id 终验 12/12 无空值(上轮漂移随全量重造消失);b4 领取 66014 + a4 往返对照两断言进 checks。幂等:规则/模板/视图全复用,ensure_pool_rule 修正优先复用通用规则。实锤沉淀:用户主表 crm_auth_user.dept_id;opportunity_pool_rule_dept.rule_version_id → 规则版本行 id。票 07/08 数据并入不适用(研究票未拍板),实施后重跑本脚本再补。剩余:票 07/08 产出评估(拍板点停)。
6 days ago
- **票 07 完成:工作计划拍板 A——全量 A1X 挂起 + 精简 Tab graduate 票 12(20260831)** — 全量 A1X=大(17-20 端点/2 新表/多态关联 7 类对象中客户/项目/行业 3 类悬空硬阻塞)挂起,P1-4 备注同步更新;精简 Tab=小(4-5 端点/0 新表复用 `opportunity_work_plan` 5 字段骨架)graduate 为票 12(商机详情工作计划 Tab:list/add/update 含登记完成/delete,扩展 planStatus 逾期实时计算语义),造数并入票 11 seed、文档并入票 10 bruno collection。原型批注自证一期收窄(不建平行台账/连动延后迭代/一期只做当前用户)。评估全文:`feasibility-workplan.md`。
- **票 08 完成:客户管理拍板 A——整模块挂起记 P2 后续迭代(20260831)** — 全量 ≈40 端点/6-8 新表与最小切片 ≈15+ 端点均=大档、无小口径逃生门(公海机制+企查查为最小不可避集);D-02 已由票 04 快照池降级闭环,商机域零硬依赖无技术债;客户主数据域(合并/交割/导入/公海规则/企查查/职务字典六深水区)整体留后续迭代,不 graduate 实现票。评估全文:`feasibility-customer.md`。
- **票 12 完成:商机详情工作计划 Tab 四端点落地,运行时 17/17 + 单测 30/0(20260831)** — graduate 自票 07 拍板 A:`workplan/list|add|update|delete` 复用 `opportunity_work_plan` 子表 0 新表,登记完成服务端回填 finishTime、逾期实时计算不落库;域纪律同构子域(requireOpp 66002 + 暂缓禁写 66003 三入口、ROW_ADD/ROW_DELETE 日志);seed 并入 a2 三形态样例(e2e-wp-,幂等复用+校准)三遍实跑全绿;bruno `商机详情/工作计划/` 4 .bru 入集合待人提交。**附带发现**:crm-auth ResourceServiceImplTest.save_editCatalog_noButtonFields 既有红灯(与本期改动无关,留裁决);fat jar 增量打包静默跳过复刻票 04 坑(clean package 解)。ticket:`issues/12-workplan-tab.md`。
6 days ago
## Ticket 依赖图
```
01 (task: 原型全量拉取) ─┬→ 02 (research: 22条裁决) ─┬→ 03 (task: P1修A V-CONFIG+dept) ─┐
│ ├→ 04 (task: P1修B 404端点×6) ├→ 09 (task: 回归+报告) ─┬→ 10 (task: bruno文档)
│ ├→ 05 (task: P1修C 状态拦截+规则) │ └→ 11 (task: 测试数据)
│ └→ 06 (task: P2修复批) │
6 days ago
├→ 07 (research: 工作计划可行性) ✅拍板A:全量挂起,精简 Tab graduate → 12
└→ 08 (research: 客户管理可行性) ✅拍板A:整模块挂起 P2,不 graduate
6 days ago
```
6 days ago
```
12 (task: 商机详情工作计划 Tab,graduate 自 07) ✅20260831 完成 — 造数并入 11 seed 脚本、文档并入 10 collection 均已闭环
```
- 07/08 已拍板(20260831):07 全量挂起、精简 Tab graduate 为票 12(与修复主线无阻塞,数据并入 11、文档并入 10);08 整模块挂起 P2,不 graduate。
6 days ago
- 10 与 11 并行(都只依赖 09 的接口定型)。
## Not yet specified
- **P2 修复范围弹性** — 裁决后若有翻案/降级(例如 D-21 bizType 契约矛盾实为文档问题),票 06 范围相应收缩;范围变化记回本节。
- **修复的提交方式** — 直接改工作区(沿用本 repo 惯例,无 commit 流程);若用户要求分支/提交,届时提出。
## Out of scope
- **一键拉群后端**(A3-1-1-1-8 弹窗「钉钉建群」/文案提企业微信)— 外部 IM 集成,原型有弹窗但依赖钉钉/企微 API,本轮只裁决不实现(票 02 里对 D-04~06 的修复不含拉群)。
- **推送方案 + 方案推送规则**(A3-1-1-2-5、A7-3-2-3)、**督办**(A3-2-1-1-1)— 外部推送能力,继承上轮 spin-out。
- **H5 端原型**(44ce439e…,v16)— 与 web 端功能镜像,复测用 web 端 v29 即可;除非用户点名。
- **旧版文档**(旧版-线索/旧版-首页+工作计划+商机/旧版-客户)— 历史版本,仅当 v29 页面缺失时作对照。
- **crm-lead / crm-dict / 其他模块的缺陷** — 本图只商机域 + crm-rule 商机规则三族。