|
|
|
@ -25,7 +25,7 @@ A5 项目管理(crm-project,独立建表 `crm_project`,见 deliverable-spe |
|
|
|
## Decision |
|
|
|
|
|
|
|
1. **归属列**:`oppId`(not null) → `ownerType`(tinyint: 1=OPPORTUNITY/2=PROJECT, default 1) + `ownerId`(bigint not null)。唯一约束 `uk_osc_opp_customer(opp_id, customer_id, delete_key)` → `uk_osc_owner_customer(owner_type, owner_id, customer_id, delete_key)`;`opp_id` 命名陷阱检查通过(AGENTS.md,无需钉列名)。 |
|
|
|
2. **存量迁移**:启动期 `SchemeCardOwnerMigrationRunner`(幂等,按列/索引存在性判断)——老库补列、存量行回填 `owner_type=1, owner_id=opp_id`、唯一约束换轨;旧列 `opp_id` 与旧索引 `idx_osc_opp` 保留为只读死列(共享库不做破坏性 DROP,应用代码零引用)。 |
|
|
|
2. **存量迁移**:启动期 `SchemeCardOwnerMigrationRunner`(幂等,按列/索引存在性判断)——老库补列、存量行回填 `owner_type=1, owner_id=opp_id`、唯一约束换轨;旧列 `opp_id` 放宽为**可空死列**(实体已不映射,新插卡不带该列,NOT NULL 会让 A3 新建卡 INSERT 失败——真实环境实测修正;旧行值保留供审计)。 |
|
|
|
3. **商机侧行为不变**:`OpportunitySchemeCardService` 商机入口签名不动(`listCards(oppId)` 等内部过滤 `owner_type=OPPORTUNITY`);商机卡保存的客户校验(必属本商机关联客户,无孤立卡)原样保留;商机列表/详情的方案卡列 join 加 `ownerType=OPPORTUNITY` 过滤(`OpportunityViewQueryImpl.fillSchemeCardColumns`、`OpportunityDetailServiceImpl` 兜底查)。 |
|
|
|
4. **PROJECT 归属校验接口化**:新增出站端口 `SchemeCardProjectPort`(crm-opportunity 声明 + Noop 桩,真实现住 crm-project `@Primary` 覆盖,对称 `OpportunityOwnerSyncPortImpl`/Noop 范式)。桩 **fail-closed**:`requireLiveProject` 抛 66015 明确拒绝——「无孤立卡」铁律不允许校验缺位时静默放行。保存入口按 `dto.oppId`/`dto.projectId` 互斥分叉(双归属互斥,一次一张归属的卡)。 |
|
|
|
5. **提交路径差异**:项目卡无商机「暂缓」守卫、无商机主表快照回写(D-17 仅商机卡);提交必填校验等其余逻辑共用。 |
|
|
|
|