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.
6.7 KiB
6.7 KiB
02 lead→opp port 消费侧契约落地
Type: grilling Status: resolved
Question
商机侧实现 crm-lead/port/outbound/OpportunityCreationPort(线索 ticket 08 已定稿的出站契约),把"线索转商机"这条断线接通。契约既定,本票钉的是商机侧落地细节:
- 幂等落点:
UNIQUE(source_lead_id)建在商机主表哪个字段;重复转商机(幂等命中)时返回既有商机 id 还是抛异常。 - 带出快照的落库:
CreateOpportunityCmd的 sourceLeadName/sourcePhone/sourceProductCode/ownerUserId/ownerDeptId/poolId 分别落到商机主表哪些字段;哪些是快照(不随线索变)哪些是引用。 - 事务边界:port 同步、在线索事务内触发、失败抛
OpportunityCreationException使线索整体回滚——商机侧建表/写子表的哪些步骤必须在这个同步事务内完成,哪些可异步。 - 直接创建商机入口(跳过线索)与"由线索转入"入口的字段差异:
source_lead_id可空?两条入口如何共用建商机逻辑。 - 转商机成功后线索侧写
lead_history(转商机)用到的商机 id 由createOpportunity返回——确认返回值语义。
不改线索侧契约(已定稿);只定商机侧实现规格。
Answer
四簇全部拍板(grilling,产品逐条确认)。注:grill 过程中冒出一处必须改线索契约的决策(意向客户下拉选客户 → 带 customerId),已越出「不改线索契约」的原定边界,产品明确要求改,见「契约变更」段 + 派生新票。
簇 A — 幂等落点
- 幂等键 = 商机主表
UNIQUE(source_lead_id)。source_lead_id IS NULL(直接创建)不参与唯一约束,可多条并存。 - 幂等命中 = 安静返回已有商机 id(写法一,真幂等),不抛异常——
OpportunityCreationPortjavadoc 的「幂等语义」即此意。重复转商机(重试)当作成功,返回既有商机 id。 - 并发防护:两个转商机事务同时命中同一
source_lead_id,先查都查不到、都 insert,DB 唯一索引让后提交者抛DuplicateKeyException。商机侧须捕获唯一键冲突 → 回查既有商机 → 返回其 id,不外抛。这样「安静返回已有 id」在并发下也成立。 - 返回值语义:
createOpportunity返回的 Long = 商机 id(新建或既有),线索侧据此写lead_history(转商机)。
簇 B — 带出快照落库(cmd 字段全部落库,无一丢弃)
| Cmd 字段 | 落主表 | 引用/快照 | 说明 |
|---|---|---|---|
opportunityName |
商机名称 | — | 商机自有业务字段 |
industryCode |
行业 | — | 字典码 |
partyA |
甲方 | — | 自由文本 |
intendedCustomer |
意向客户名 | 快照 | 客户名快照(见契约变更:与新 customerId 并存,走法 B) |
regionCode |
地区 | — | 国标码 |
remark |
备注 | — | |
ownerUserId |
owner_user_id |
引用 | 领取人 = 归属本身 |
ownerDeptId |
领取人所属部门 | 快照 | 转商机那刻部门;领取人调岗不变;抛公海清领取人后仍可归档/报表 |
sourceLeadId |
source_lead_id |
引用(幂等键) | 来源线索血缘 |
sourceLeadName |
来源线索名快照 | 快照 | |
sourcePhone |
联系电话快照 | 快照 | |
sourceProductCode |
需求产品码快照 | 快照 | |
poolId |
来源公海池 id | 引用/归档 | 存下来,纯血缘归档、用于后续排查问题;不参与商机自身公海逻辑(票 05 另有商机公海规则) |
簇 C — 两条入口共用建商机核心逻辑
-
商机侧一个内部建商机核心方法(建主表行 + 初始状态/阶段 + 初始操作日志 + 子表);线索转入 / 直接创建两条入口共用,进入平权(票 01)。
-
差异只在入口层(进核心逻辑前):
差异点 线索转入 直接创建 source_lead_id有值 NULL oppSource(商机来源)默认「线索转入」 用户弹窗选 来源快照(线索名/电话/产品码/池 id) 从 cmd 带 全空 owner_dept_id快照cmd 传的 当前用户当前部门 幂等检查 要(查 source_lead_id)不要 -
oppSource默认「线索转入」由商机侧入口层填(CreateOpportunityCmd无此字段,不回头改线索契约加它)。 -
新商机 = 状态「推进中」+ 阶段「模板第一步」(阶段模板细节留票 06,本票只定「落第一步」规则)。
-
直接创建入口的完整 API/字段规格留票 03;本票只钉「两条入口共用核心逻辑 + 差异表」这条边界。
簇 D — 事务边界 + 转商机时的子表
- 必须同步(线索事务内,失败抛
OpportunityCreationException→ 线索整体回滚):- 幂等检查(查
source_lead_id) - 建商机主表行(全部快照字段 + 初始状态/阶段)
- 写一条初始操作日志(「由线索转入创建」)
- 建团队成员一条:领取人 = 团队成员,项目角色 = 商机负责人
- 建关联客户一条:关系标记 主要意向客户,
customer_id= cmd 带来的customerId(引用)+intendedCustomer客户名快照
- 幂等检查(查
- 可异步(事务提交后,失败不回滚线索):通知/提醒(「你有新商机」)、建群/推送(本 out of scope)、其他非核心派生数据。
契约变更(越出「不改线索契约」原边界,产品明确要求)
CreateOpportunityCmd新增customerId(Long,必填);intendedCustomer保留为客户名快照(走法 B:引用 + 快照并存,与 CONTEXT.md「关联客户」术语一致)。- 线索转商机弹窗:意向客户改为下拉选客户(选中拿到
customer_id)——线索转商机前置要求「必须有意向客户」。 - 项目角色首项:「销售负责人」→ 「商机负责人」(改
crm-opportunity/CONTEXT.md「团队成员」术语)。 - ⚠ 客户实体归 A4 客户模块(未建)。此变更依赖「线索侧下拉能查到客户列表」的能力落地——契约字段/领域决策本票钉死,真正改
crm-lead代码 + A4 客户下拉能力另开新票(.scratch/opportunity-module/issues/11-customerid-in-create-cmd.md)。
已核实事实
OpportunityCreationPort/CreateOpportunityCmd/OpportunityCreationException现存于crm-lead/src/main/java/com/crm/lead/port/outbound/(线索票 08 定稿),返回Long= 商机 id。crm-opportunity/CONTEXT.md现存,「关联客户」术语已写「引用 + 快照」模式,与走法 B 一致。