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.
 
 
 
 
 

2.3 KiB

status
accepted

公海池删除守卫跨模块 seam:PoolLeadOccupationPort(crm-rule 声明,crm-lead 实现)

P0-1 要求删除公海池前校验「池下无非终态线索」(status ∈ 未分发/待领取/已领取/跟进中),有活跃线索则拒删抛 CODE_POOL_HAS_ACTIVE_LEAD(64005)。但 crm-rule 不得反向依赖 crm-lead(单向 crm-lead → crm-rule),而 lead 表归 crm-lead。参照 ADR-0020OpportunityCreationPort 同型 outbound port 模式(方向相反):crm-rule 定义出站端口 PoolLeadOccupationPorthasActiveLeads(poolId)),crm-lead 提供 @Component 实现 PoolLeadOccupationAdapter(查 lead 表 count)。crm-lead 本就依赖 crm-rule,依赖倒置(DIP)不破坏方向。crm-rule 通过 ObjectProvider<PoolLeadOccupationPort> 注入(可选注入,与 OpportunityCreationPort 一致),port 为 null 时 fail-safe 拒删(抛 CODE_POOL_INVALID「占用校验服务不可用」)。

Considered Options

  • A(选中):crm-rule 定义 outbound port,crm-lead 实现(依赖倒置)——与 OpportunityCreationPort 同型模式,依赖方向不破坏;port 未实现时 fail-safe 拒删。
  • B:crm-rule 直接 SQL 查 lead 表——无 Java 依赖但 DB 层耦合,违背 seam 精神,否。
  • C:删除编排上移 crm-lead——但删除端点在 LeadPoolController(crm-rule),改动面大且破坏域归属,否。

Consequences

  • LeadPoolServiceImpl.deletePool() 删除前调 port.hasActiveLeads(id),有活跃线索抛 64005;deletePoolBatch() 逐条调单条 deletePool()(self 代理独立事务),失败项记 PoolBatchFailReason.HAS_ACTIVE_LEAD偿还 ADR-0023 D5 刻意预留的 64005 决策债)。
  • port 为 null(crm-lead 不在 classpath,如纯 crm-rule 单测)时 fail-safe 拒删,不得放行——单测须 mock port。
  • 非终态口径 = {1,2,3,4}(未分发/待领取/已领取/跟进中);终态 {5,6,7}(已转商机/过期失效/作废)不阻止删除。
  • 决策来源:ticket 02 P0-1 裁决(实现遗漏)+ ticket 05 + ADR-0023 D5(64005 刻意预留「待独立 ADR/issue 落地」)。