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.
5.0 KiB
5.0 KiB
Type: grilling Status: resolved Blocked by:
Question
(由 03 grilling 暴露)用户要求:项目可脱离商机独立新建,但新建时方案卡必填。这与现状冲突——方案卡 OpportunitySchemeCard 的 oppId 必填、物理住在 crm-opportunity、被 26 处代码依赖、并携带 customerId/templateId/字段值表。
需拍板的决策:
- 解耦方式:把
oppId改可空?还是抽出一个可被"商机或项目"任一方拥有的独立方案卡聚合(owner_type + owner_id)? - 归属域:脱离商机后方案卡属于哪个模块——留 crm-opportunity、下沉 crm-base、还是新 crm-scheme?(模块边界决策)
- 依赖来源:独立方案卡的 customerId / templateId / 字段值从哪来(用户手选?还是必须先选客户)?
- 爆炸半径处理:26 处 oppId 引用的兼容策略(分支判空 / 迁移 / 新查询路径)。
- 契约重谈:
ConvertToProjectCmd(opportunityId 必填, schemeCardId 选填)是否要改成 schemeCardId 必填、opportunityId 可空。
产出一份解耦决策 + 迁移影响清单。这是 crm-project 状态机起点(03)与最终 spec(06)的前置。用 /grilling + /domain-modeling,先重读 OpportunitySchemeCard 全部 26 处引用。
Decision (partial, grill 进行中)
D1 — 项目关联方案卡 = 必填(推翻 CONTEXT.md L90「选填」口径)
用户拍板:项目(含独立新建)关联方案卡必填,推翻 crm-opportunity/CONTEXT.md L90「可关联方案卡(选填,归 A5)」与 L118「无孤立方案卡」的既有口径。
连锁后果:
- 方案卡必须解耦(A/B 二选一必做)——独立项目无商机但须有卡,方案卡不能再强绑 oppId。
- 方案卡数据模型改动(A、B 共通):归属列
oppId(必填) →ownerType+ownerId(OPPORTUNITY=商机id / PROJECT=项目id)。A=就地改表不搬家;B=同改动 + 改表名scheme_card+ 搬模块。A/B 差异仅"搬不搬家"。 - 真实爆炸半径 = 2 类(非 26):
OpportunitySchemeCardServiceImpl(写入+客户校验分叉)、OpportunityViewQueryImpl(列表 join 加ownerType=OPPORTUNITY过滤)。 - customerId 新来源:卡的客户现从"商机关联客户"来;独立项目须自带客户 → 新雾「独立建项目客户是否必填前置」。
- CONTEXT.md 须改:L90 / L118 两处口径被推翻,域建模留痕(否则后续会话读旧口径走错)。
- 转项目回调契约:
ConvertToProjectCmd(opportunityId 必填, schemeCardId 选填)中 schemeCardId 地位上升,是否翻转待定。
尚未拍板(07 继续)
- A vs B:就地改列(A,语义脏工作量小)还是搬表改名+可能搬模块(B,语义净工作量大)。
- 归属模块:若 B,方案卡落 crm-opportunity(改名) / crm-base / 新 crm-scheme。
Answer (resolved)
D2 — 解耦方式 = A(就地改列,不搬家)
用户拍板 A。方案卡留在 crm-opportunity、表名保持 opportunity_scheme_card,不搬模块、不改表名。仅做数据模型解耦。
最终落地清单:
- 归属列改造:
oppId(not null) → 新增ownerType(tinyint: 1=OPPORTUNITY / 2=PROJECT) +ownerId(bigint not null)。迁移:存量行ownerType=OPPORTUNITY, ownerId=旧oppId;旧oppId列保留兼容或ALTER ... CHANGE按 ddl-auto 策略处理(注意 AGENTS.md 命名策略:ownerId→owner_id安全、ownerType→owner_type安全,无孤立单大写字母,无需 @Column 钉列)。 - 唯一约束改造:
UNIQUE(opp_id, customer_id, delete_key)→UNIQUE(owner_type, owner_id, customer_id, delete_key)。 - 2 个类改动:
OpportunitySchemeCardServiceImpl:写入/校验把 oppId 换 ownerType+ownerId;客户归属校验分叉——OPPORTUNITY 走opportunity_customer、PROJECT 走项目客户(项目客户来源见新雾「独立建项目客户前置」)。OpportunityViewQueryImpl:商机列表 join 方案卡处加ownerType=OPPORTUNITY过滤,避免查到项目卡。
- 契约:
ConvertToProjectCmd暂不翻转(schemeCardId 仍选填,因商机转项目路径卡已随商机在;必填约束只作用于"项目侧独立新建"入口,由 crm-project 的新建端点强制)。 - CONTEXT.md 留痕(交付 spec 时一并改):crm-opportunity/CONTEXT.md L90 改「选填」→「独立建项目必填」;L118「无孤立方案卡」改为「方案卡归属 ownerType+ownerId,商机卡仍无孤立、项目卡归项目」。
未选 B 理由:A/B 数据模型改动相同,B 仅多"搬模块+改表名"纯语义成本、爆炸半径翻倍、动核心聚合风险高;当前仅商机/项目两个 owner,搬成独立 crm-scheme 属 YAGNI。
遗留给后续的硬依赖(不阻塞 07 关闭,已在 map 雾区):独立建项目的客户前置来源 → 喂 03;CONTEXT.md 改写 → 喂 06 交付。