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.
 
 
 
 
 
 

13 KiB

票 01 — 缺陷修复白盒验收核对清单(23 条)

effort: opportunity-acceptance · ticket: 01 · date: 20260831 · mode: 静态白盒(不起服)

结论

  • 23/23 条修复锚点全部在位,0 条 (opportunity-fix D-01 ×1 + bugfix D-01~D-22 ×22,其中 D-08/18/19 为翻案关闭项,核对「非缺陷形态保持」)。
  • 次要瑕疵 3 处(均不阻塞验收,见 §C):D-01 方法 javadoc 残留旧方案描述 ×2、OpportunitySubController 重复 import ×1、错误码 64018 两族同值冲突(既有债务)。
  • 全量单测结果见 §D(mvn-test.log)。

A. opportunity-fix D-01(重点:新建商机 500 根因修复)

# 核对点 锚点(文件#行为) 代码现状 结论
A1 fail-fast 无零值兜底 OpportunityIntakeImpl#applyInitialStage L135-152 resolveBindingVersion 返 null → 抛 OpportunityIntakeException(「系统未配置发布中的商机阶段模板…」);listNodesOfVersion 空 → 同抛;stage 三列(stage_template_id/stage_template_version/current_stage_id)仅在命中后赋值,无任何 =0 占位残留
A2 60001 友好错翻译链 OpportunityCreateServiceImpl L94-98(DIRECT→BusinessErrorException(msg)ResultCodeEnum.BUSINESS_ERROR=60001);OpportunityCreationPortImpl L59-63(LEAD_CONVERT→OpportunityCreationException 两条 seam 均在位,HTTP 层不再 500
A3 预设模板不可删/不可停(64018) OpportunityRuleConstants L59/L99(SEED_STAGE_TPL_CODE="OPP_STAGE_TPL_01" / CODE_STAGE_TPL_SEED_PROTECTED=64018);OpportunityStageTemplateServiceImpl#disableTemplate L338-341 / #deleteDraft L354-357 两入口均按 templateCode 拦截(预设模板任何版本不可删/停,非仅发布中版),错误码/文案在位
A4 publish 不破坏不变式 OpportunityStageTemplateServiceImpl#publish L302-329 旧版顶替/默认顶替均直调私有 updateStatus不走 disableTemplate → 编辑发布中预设模板生成新草稿再发布顶替不受保护拦截;「始终有一个发布中默认模板」不变式保持
A5 current_stage_id 赋值链 buildOpportunity L120 → applyInitialStage L149-151 stageTemplateId/stageTemplateVersion/currentStageId(首节点) 三列完整落位;buildOpportunity L96-103 的空串/0 兜底仅覆盖 oppType/bidForm/localityType/partyAClear/provinceCode/cityCode/industryCode(线索转入路径防御),与 D-01 stage 三列无关,非兜底残留
A6 ⚠ 文档残留 ×2 applyInitialStage javadoc L128-133 仍描述已撤销的「显式回填零值占位」旧方案;buildOpportunity L119 行注释「无模板容忍空,走法 A」同样过时 方法体已是 fail-fast(策略 B),注释与方法体矛盾,会误导后续维护;建议票 03(Demo 修正 session)顺手修正 ⚠ 记录

B. opportunity-bugfix D-01~D-22 静态复核

裁决基线 = 票 02 retest-verdicts.md(19 确认 + 3 翻案);运行时终版 = 票 09(146/⚠2/0)。本表核对代码锚点在位

# 缺陷 修复锚点(文件#行为) 代码现状 结论
D-01 关联客户添加 404 OpportunitySubController L71-75 POST /customer/addOpportunitySubServiceImpl#addCustomer L87-125 端点+必填校验(66001)+重复预检(66011 L109-110)+isPrimary 降旧主+快照回写+ROW_ADD 日志全在位
D-02 候选客户搜索 404 SubController L78-81 POST /customer/search;SubServiceImpl#searchCustomers L128-137 searchCandidatePool 分页 + keyword + NOT IN 排除已关联(快照池降级口径)
D-03 设主要意向 404 SubController L84-91;SubServiceImpl#setPrimaryCustomer L141-166 三步事务(降旧主→置新主→refreshPrimarySnapshot 主表回写)+ 已是主要幂等 L155-157 + FIELD_CHANGE 日志
D-04 团队成员添加 404 SubController L226-230 POST /team/add;SubServiceImpl L353(守卫)/addTeamMembers 批量去重保序、全重拒 66012、未知用户 66001、快照服务端取、ROW_ADD
D-05 团队成员移除 404 SubController L241-246 POST /team/delete;SubServiceImpl#deleteTeamMember L447-465 负责人行拒 66013(L455-457)+ 软删 deleteKey=id, deleted=1 + ROW_DELETE
D-06 团队成员编辑 404 SubController L233-238 POST /team/update;SubServiceImpl#updateTeamMember L396-443 直接换人(目标已在队 66012)+ 负责人行三重锁 66013(换人 L406 / 角色 L425 / 权限 L429,仅 duty 可改 L436)
D-07 暂缓态可编辑 OpportunityActionGuard#ensureNotPaused L44-50(66003);接线 grep=17 调用点 SubServiceImpl ×14(含票 12 workplan 三写入口 L492/520/546)+ edit(DetailServiceImpl L84)+ 方案卡 save/submit(SchemeCardServiceImpl L122/228);focus/touch 不拦、close 不拦(D-08 翻案)符合裁决
D-08 暂缓态可关闭(翻案) 裁决:PRD §3.2 E6「2,3→4」合法边 无关闭拦截代码 = 正确形态;e2e 断言已按裁决反转(票 05/09) (非缺陷)
D-09 禁领规则未生效 OpportunityActionGuard#ensureClaimAllowed L59-72(66014,match(ownerDeptId),allowFreeClaim null/≠1 保守禁);OpportunityTransitionController claim L44 / claim-batch L57-59(全量预检 claim/claim-batch 接线在位;release/assign 不拦(裁决:分配是禁领替代路径);CODE_OPP_CLAIM_FORBIDDEN=66014 在 OpportunityConstants L25
D-10 阶段模板编辑发布中 50001 OpportunityStageTemplateServiceImpl#resolveDraft 第三分支 L283-295 insert 前清三毒setId(null)+setCreateTime(null)+setUpdateTime(null) L286-288,注释标 D-10)
D-11 方案卡模板同构 50001 OpportunitySchemeCardTemplateServiceImpl L226-238 清三毒 L229-231(注释标 D-11)
D-12 公海规则同构 50001 OpportunityPoolRuleServiceImpl L135-148 清三毒 L138-140(注释标 D-12)
D-13 owner_dept_id 恒空 crm-opportunity/owner/ 三件套(OwnerSnapshot record / OwnerSnapshotResolver 接口 / OpportunityOwnerSnapshotResolverImpl,bean 名冲突防避注释在位);消费方:OpportunityCreateServiceImpl L87(创建落快照)/ OpportunityCreationPortImpl L50-52(线索转入缺失兜底)/ OpportunityTransitionController 五端点(claim L46 / claim-batch L61 / assign L75 / assign-batch L87 / handover L168,快照参数已删、服务端 of() 解析) 快照跟人走(claim/assign=新负责人,handover=完整过户);TransitionImpl claim/assign/handover 均 .set(OwnerDeptId, cmd.ownerDeptId())
D-14 必填校验 500 类 create:OpportunityCreateServiceImpl L56-64 六必填逐字段 66001(requireText L120-125);edit:OpportunityDetailServiceImpl#edit L75-82 merged(dto,existing) 合并校验 6 字段(名称/来源/招标形式/省/市/属地)×正负路径;edit null=保留原值、空白拒
D-15 公海看板 summary 未过滤 query/OpportunityViewFilter(六视图 switch + providesStatusCondition,PUBLIC_POOL 由分支供状态条件避恒假 AND);OpportunityCollabServiceImpl#applyBoardViewFilter L142-148 board 两端点共用单一事实源;viewType 可选参数默认 MINE
D-16 detail 六联动字段 null OpportunityDetailServiceImpl fillEchoFields:followed L114 / lastFollowTime L125 / schemeCardStatus+schemeBudget L140-144(快照优先+存量兜底实时查)/ stageStayDays L159 / nextStageName L165 6 字段全落位(票 02 收窄 4 + 票 09 补 2,与 page 同源口径)
D-17 方案卡提交后主表未回显 OpportunitySchemeCardServiceImpl L265-271 事务内 LambdaUpdateWrapper 显式 set 两列(SchemeCardStatus=SUBMITTED + SchemeBudget),规避乐观锁实体 updateById 坑
D-18 surveySeq 调用方传(翻案) 裁决:原型「*勘察次数」必填下拉 addSiteSurvey L154 surveySeq 保持 @RequestParam 必填 = 正确形态 (非缺陷)
D-19 勘察说明非必填(翻案) 裁决:原型无星号 L156 surveyDesc required=false 保持 = 正确形态 (非缺陷)
D-20 oplog 流转不留痕 OpportunityTransitionImpl#recordStatusFlowOplog L332-349(FIELD_CHANGE + OplogLogType.STATUS_FLOW + fieldName=opp_status + 旧/新值 + label 文案 + MANUAL/SYSTEM 归因) grep 调用点 ×10 = E1 领取 L134 / E2 分配 L154 / E3 抛池 L103 / E4 暂缓 L197 / E5 恢复 L221 / E6 关闭 L238 / E7 重开 L252 / E8 转项目 L267 / E9 自环(旧=新) L292 / E10 回收 L177,流转边全覆盖
D-21 bizType 契约矛盾 OpportunitySubController L53-58 ATTACHMENT_BIZ_TYPES(Set.of 四值封闭)+ L194-199 判空校验 66001 四值 OPP/FOLLOW_UP/SITE_SURVEY/SCHEME_CARD 与 OpportunityConstants 同源;Set.of contains(null) NPE 先判空教训注释在位
D-22 versions 实体直出泄露 三族 Controller versions:Stage L86-95 / SchemeCard L92-102 / PoolRule L85-94 出参全部 DTO 化(fromEntity 白名单,剥 creatorId/updaterId/deleted),三个 OpportunityXxxVersionDTO 新文件在位,注释标 D-22/ADR-0017
D-13+票12 工作计划四端点 OpportunitySubController L261-288(list/add/update/delete);OpportunitySubServiceImpl L470-553 list(deleteKey=0, createTime 升序)/ add(oppId+planContent 必填≤1000)/ update(planStatus 值域 0/1 封闭 66001、部分更新显式 set、finishTime 0→1 回填 1→0 清空)/ delete(软删+ROW_DELETE);三写入口全接 requireOpp(66002)+ensureNotPaused(66003);DTO deadline@DateTimeFormat

C. 次要瑕疵与工作区观察(不阻塞验收)

  1. ⚠ D-01 方法 javadoc 残留旧方案(§A6)——行为正确、注释过时,建议下次触碰该文件时顺手修正(也可留待打字窗口,本图不为此开票)。
  2. OpportunitySubController L36-37 import java.util.Set; 重复两次——javac 合法(无错),纯整洁性问题。
  3. ⚠ 错误码 64018 两族同值CODE_STAGE_TPL_SEED_PROTECTED(阶段模板,L99)与 CODE_SCHEME_TPL_INVALID(方案卡模板,L139)均为 64018——D-01 插入 64018 时方案卡族区间注释未顺延。既有债务,排查日志时两族错误码需按接口路径区分,不在本图修。
  4. 工作区状态盘点(git status,20260831):
    • 票 12 增量在位且完整:untracked OpportunityWorkPlanAddDTO/UpdateDTO 2 文件 + OpportunitySubController/OpportunitySubServiceImpl/IOpportunitySubServiceMM 二次未暂存修改(workplan 节)+ OpportunitySubServiceImplTest(30 用例,AM)。待打包增量 = 工作区 vs HEAD(938aed9…32ac292 已含 opportunity-fix + bugfix 部分 commit;bugfix 主体为已暂存未 commit)。
    • 并行 effort 混入提示crm-authResourceServiceImpl(+Test) 存在 auth-perms effort 的未暂存改动——本图票 02 起服打包(clean package)会把这批改动一并带进 fat jar;crm-auth 域不受商机验收影响但需知悉。
    • logs/crm-app.log 存在 DU(unmerged)状态残留——log 文件本身已被 32ac292 停止跟踪,不影响构建,但首次 commit 时需留意。
  5. 既有红灯豁免项:crm-auth ResourceServiceImplTest.save_editCatalog_noButtonFields(map Notes 豁免口径)——auth-perms 票 02 正在处理中,本轮 mvn test 实测结果见 §D。

D. 全量单测(mvn test,10 模块 reactor)

20260831 实测:BUILD SUCCESS,MVN-TEST-EXIT=0,合计 873/0/0(Failures/Errors/Skipped),Total 01:26 min。 日志:mvn-test.log

模块 Tests F/E/S
crm-base 38 0/0/0
crm-file 84 0/0/0
crm-auth 210 0/0/0
crm-dict 51 0/0/0
crm-rule 134 0/0/0
crm-preference 16 0/0/0
crm-lead 131 0/0/0
crm-opportunity 209 0/0/0(与票 12 Answer 209/0/0 一致)
crm-app (无测试段)
  • 豁免项失效(好消息):map Notes 的既有红灯 ResourceServiceImplTest.save_editCatalog_noButtonFields 本轮未复现——crm-auth 210/0/0。原因:该用例已被 auth-perms effort 票 02(perms-hardening,工作区未暂存改动)改写为「编辑 catalog 时 perms 只读保留 DB 原值」语义(Test L434-452),红灯随语义改写消失。商机域验收不受影响,豁免口径自动解除。
  • 工具链:mvn=D:\apache-maven-3.9.9\bin\mvn.cmd(非 bugfix 票面写的 IDEA 捆绑路径,已失效),JDK17=C:\Users\luowj\.jdks\jdk-17.0.15

变更追溯

  • 复核输入:.scratch/opportunity-fix/map.md(最终定案节)、.scratch/opportunity-bugfix/issues/02/03/04/05/06/09/12retest-verdicts.md
  • 复核方式:纯静态(Read/Grep 源码锚点比对),不起服;运行时行为验证归票 02(全量 E2E 重跑)