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.

21 lines
2.3 KiB

3 weeks ago
---
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-0020](0020-convert-opportunity-same-db-transaction-premise.md) 的 `OpportunityCreationPort` 同型 outbound port 模式(方向相反):`crm-rule` 定义出站端口 `PoolLeadOccupationPort`(`hasActiveLeads(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](0023-lead-batch-operations-and-view-stats.md) D5(64005 刻意预留「待独立 ADR/issue 落地」)。