商机读客户:三个只读需求,拖进两套宽 service + 实体 + param
涉及文件
- crm-opportunity/.../service/impl/OpportunitySubServiceImpl.java · 票 11 切真源:注入 ICustomerService + ICustomerContactService
- crm-customer/.../service/ICustomerService.java · searchForOpportunity(javadoc 自述「商机侧客户搜索」)
- crm-customer/.../service/ICustomerContactService.java · listByCustomer / search(javadoc 均点名「商机字段17级联」「商机关键联系人数据源」)
- crm-customer/.../port/ · 已有 6 个 port(含 2 个 outbound 商机 port),唯独缺商机要用的 inbound 目录 port
Before / After
flowchart LR SUB["OpportunitySubServiceImpl
(615 行 grab-bag)"] CS["ICustomerService
8 方法 + MP 全套 CRUD"] CT["ICustomerContactService
8 方法 + MP 全套 CRUD"] E1["Customer 实体(30+ 字段)
CustomerSearchParam 手工构造"] E2["CustomerSearchItemDTO / ContactDTO
逐字段映射"] SUB -->|"getById(取快照)"| CS SUB -->|"searchForOpportunity"| CS SUB -->|"listByCustomer"| CT CS --> E1 CS --> E2 CT --> E2 classDef leak stroke:#dc2626,stroke-width:2px; class E1,E2 leak
contactsOf(customerId) → List<ContactBrief>
requireLive(customerId) → CustomerBrief
问题
商机侧只做三件事——存在性校验取名快照、候选池搜索、联系人级联——却要越过 seam 理解两套宽 service 外加 MyBatis-Plus 全套 CRUD、Customer 实体 30+ 字段、两个 param/DTO 的构造与映射。口径还藏在实现里:getById 只滤 @TableLogic deleted、不滤 archive_status(归档=删除语义),已归档客户照样通过「关联客户存在」校验——消费方从 interface 上无从知道。provider 侧同样受害:宽 service 上长出 searchForOpportunity / listByCustomer / search 三个「为商机而生」的方法,消费方的词汇进了 provider 的 interface。这正是 ADR-0031 修掉的病灶(当时的对象是 crm-lead),在客户侧原样复发。
方案(plain English)
crm-customer 的 port/ 目录新增一个窄 inbound 目录 port(照抄 ConvertibleLeadCatalogPort 的形状:provider 定义、消费方只见 brief 视图):搜索、按客户取联系人、取存活客户摘要三个方法;归档/删除口径、param 构造、实体→brief 映射全部收进实现;宽 service 上的三个商机词汇方法收编(转发或删除)。商机侧注入 port,删掉对 ICustomerService / ICustomerContactService / Customer 实体的全部 import。