# 01 — Creation planner seam **What to build:** 新建 `com.crm.lead.creation` 包:`LeadCreationPlanner` 接口(单方法 `Lead plan(LeadDTO dto, LeadCreateContext ctx)`)、`LeadCreateContext` record(`operatorUserId / admin / assignToUserId / claimOnCreate` 纯值入参)、`LeadCreationPlannerImpl`(`@Component`,依赖仅 leadPoolService / ownerSnapshotResolver / claimLimitChecker 三个 bean,零静态依赖)。把 `createLead` 的四分支规则树(销售自建强制主部门池 / 选人即分配 / 管理员建未分发 / 管理员指定池)、资格链(ADMIN_ONLY + ClaimLimitChecker)、归池仪式(池快照 / deptId / teamDeptId / 失效计时,4 setter)与领取仪式(状态 / 领取人快照 / claimTime / 回收计时,7 setter)整体搬入 planner,行为与错误码逐字保持。`createLead` 瘦成 `validateLeadFields → planner.plan → save → followOnCreate → historyRecorder.record(CREATE)`。决策全文见 `docs/adr/0026-lead-creation-planner-deep-module.md`。 **Blocked by:** None — 可立即开始 **Status:** resolved - [x] `com.crm.lead.creation` 包含三文件:`LeadCreationPlanner` 接口(单方法 `Lead plan(LeadDTO, LeadCreateContext)`)、`LeadCreateContext` record(`Long operatorUserId, boolean admin, Long assignToUserId, boolean claimOnCreate`)、`LeadCreationPlannerImpl`(`@Component`,impl 落 `creation/impl/` 子包,与 state / query / history / owner 四机制包同构) - [x] 四分支产出字段与现 `createLead` 逐字段一致(搬移前拍快照对照) - [x] 销售自建:忽略前端 poolId,强制主部门池;主部门无池抛「本部门尚未配置公海池」 - [x] 选人即分配:要求 poolId 非空;不校验 ADMIN_ONLY(现行行为保持) - [x] 管理员建未分发:status=1、无池无领取人 - [x] claimOnCreate 全部现行调用点走 ClaimLimitChecker 完整校验链(P0-4 修复后行为保持) - [x] planner 不 import `SecurityUtils` / `AuthConstants`(角色与当前用户只从 ctx 进入) - [x] `validateLeadFields` 与 `followOnCreate` 留在 service(前者 create / edit 共用,后者是创建后副作用) - [x] `createLead` 编排 ≤ 20 行;`ILeadService` / `LeadController` / 错误码 / wire 契约零变化 - [x] 删除 impl 中与接口 default 重复的 3 参 `createLead` 重载(事务性由内层 4 参方法保证) - [x] `LeadCreationPlannerImplTest`:纯 ctx 表驱动,覆盖四分支 × claimOnCreate / 额度超限 / ADMIN_ONLY 拒 / 主部门无池 / 选人即分配缺池,零 `mockStatic`(13 用例;命名按四机制包 ImplTest 惯例) - [x] `LeadServiceImplTest` 留 2-3 个委派验证(service 只验证「调了 planner、存了、记了历史」),claim / assign / edit / delete 既有用例不动(实际留 3 个:委派验证 + followOnCreate true/false) - [x] crm-lead 全量测试通过(`mvn test -pl crm-lead`,106/106) - [x] 所有新文件 UTF-8 无 BOM ## Comments **2026-08-20 实施记录:** - 落位文件:`crm-lead/src/main/java/com/crm/lead/creation/{LeadCreationPlanner, LeadCreateContext}` + `creation/impl/LeadCreationPlannerImpl.java`;测试 `crm-lead/src/test/java/com/crm/lead/creation/impl/LeadCreationPlannerImplTest.java` - 仪式收拢为三个私有方法:`applyPoolBinding`(归池 5 setter,原 3 处副本)、`applyClaim`(领取 6 setter,原 3 处实体版副本)、`requireSelfClaimable`(ADMIN_ONLY 判定,原创建路径 2 处副本)——CAS 版仪式仍在 `LeadTransitionImpl`(那是锁不是规则) - `LeadServiceImpl` 633 → 549 行;`createLead` 编排体 19 行(validateLeadFields → plan → save → followOnCreate → record 五步) - 票面写 `LeadCreationPlannerTest`,实际落名 `LeadCreationPlannerImplTest`——与 state / query / history / owner 四机制包的测试命名同构(LeadTransitionImplTest 等) - 迁移的 5 个旧用例(P0-4 ×2 + P0-7 ×3)改为 13 个 planner 用例(四分支 × claimOnCreate 全矩阵 + 异常路径),另加管理员未分发 + claimOnCreate=true 时 claim 被忽略的边缘行为钉子 - `LeadBatchServiceTest` 构造器从 9 参补到 10 参(新增 creationPlanner 依赖)