Browse Source

docs(opportunity): 票11/12 标 resolved + 回写 map(PRD 后端收官,仅剩前端+A4)

- 票12 底稿补后端落地清单(架构甲)+ 前误判纠正说明,标 resolved
- 票11 后端全链路已通(ConvertOpportunityParam→Cmd→port 消费),标 resolved
- map 前沿小结记录纠偏 + PRD 后端收官结论:16 票后端全落,
  整体上线仅差前端下拉交互 + A4 客户数据源(均在本仓库外)
master
luoweijian 2 weeks ago
parent
commit
58a5a211b4
  1. 2
      .scratch/opportunity-module/issues/11-customerid-in-create-cmd.md
  2. 37
      .scratch/opportunity-module/issues/12-related-lead-validation.md
  3. 10
      .scratch/opportunity-module/map.md

2
.scratch/opportunity-module/issues/11-customerid-in-create-cmd.md

@ -1,7 +1,7 @@
# 11 CreateOpportunityCmd 新增 customerId + 线索侧意向客户下拉
Type: task
Status: open
Status: resolved
Blocked by: 02
## Question

37
.scratch/opportunity-module/issues/12-related-lead-validation.md

@ -1,7 +1,7 @@
# 12 商机侧新增入口:关联线索校验
Type: task
Status: open
Status: resolved
Blocked by: 03
## Question
@ -27,6 +27,41 @@ Blocked by: 03
2. 命中已占用时:`{code: "opp.related_lead.taken", message: "该线索已关联其他商机"}` 之类的明确错误码。
3. 两条入口共用建商机核心逻辑(票 02 定)不变:核心逻辑不关心 `source_lead_id` 从哪来,只负责 insert + 幂等;候选/校验/联动在入口层做。
## ❌ 后端待做(本轮补,拆于 20260826)
**前误纠正**:map 曾将本票标“已落”——实为误判:当时只验了转商机 port(`OpportunityCreationPortImpl`)
路径上的 `source_lead_id` 预检 + 主表 uk,但本票要求的**商机侧直接新建商机入口(A3-1-1-2-1)
后端一行未写** —— 商机侧无任何新建 Controller/Service。产品拍板 A:要现在补。
### 已备资产(可复用)
- 主表 `source_lead_id` 注释已明写“**两条入口都可写**、NULL 不参与唯一=直接创建可多条” + `@Index(unique=true)`(已核实)。
- `opp_source_01`(线索转入)已在 crm-dict `opp_source` 分组。
- Lead 状态常量 `STATUS_CLAIMED=3` / `STATUS_FOLLOWING=4`(`crm-lead/constant/LeadConstants`)。
- 依赖方向 `crm-opportunity → crm-lead` 已存在(pom 已核)。
### 架构拍板(甲,20260826):候选线索查询放 crm-lead
- 在 `ILeadService` 新增入站查询方法 `listConvertibleLeads(userId)`:返回该用户
`status IN (3,4)` 的线索轻量 DTO(id/leadName/phone)——“哪些线索可转商机”的准入规则留在线索域(对齐 `LeadServiceImpl` 转商机准入)。
- “**未被商机占用**”过滤由**商机侧**补(它本就管 opp 表):拿到候选后剔除 `source_lead_id` 已在 opportunity 表占用的。
## 落地清单(后端实现)
1. **crm-lead**:`ILeadService.listConvertibleLeads(Long userId)` + Impl(`status IN (3,4)` + owner 过滤),返 `ConvertibleLeadView`(id/leadName/phone)。
2. **crm-opportunity 新建 API**
- `CreateOpportunityRequest` DTO:`oppSource`(必填)/`sourceLeadId`(可空)/ 商机名/行业/省市/客户 id 等表单字段。
- `POST /api/opportunity` Controller + `IOpportunityCreateService` + Impl。
- **校验**:`oppSource==opp_source_01`(线索转入)→ `sourceLeadId` 必填;否则可空。
- **唯一性预检**:sourceLeadId 非空时查 opp 表已占用 → 报“该线索已关联其他商机”;DB uk 作并发最终防线。
- **候选线索下拉接口** `GET /api/opportunity/convertible-leads`:调 `listConvertibleLeads` 后剔除已被 opp 占用。
3. **复用建商机核心逻辑**(票 02/16):初始状态/阶段落位/初始日志/团队成员 与转商机 port 一致;
直接创建时 `oppSource!=线索转入` 则 sourceLeadId=null(不写来源快照)。
## ❌ 前端(本仓库外)
- 表单【关联线索】下拉交互、客户下拉。后端接口(convertible-leads)就绪后前端接入。
## ⚠ 依赖
- 依赖票 03(主表结构,已 resolved)。

10
.scratch/opportunity-module/map.md

@ -27,14 +27,18 @@
| 08 | 现场勘察 | ✅ 已落(`OpportunitySiteSurvey` + Mapper,结构) |
| 09 | 子表族(跟进/附件/工作计划/操作日志) | ✅ 已落(四实体 + Mapper + 3 枚举,结构) |
| 10 | 四视图查询口径 | ✅ 已落(底座三表 + ViewType/PageParam/DTO + ViewQuery 六视图 filter + 分页 + 计算列节点停留/最近跟进/方案卡状态/预算 + RECENT view_log 排序 + followed + Controller `/api/opportunity/page`;**读侧回显已补全**:字典名 opp_source/industry(industry 两级树一级 code,票 09)+ 部门名 owner_dept_id + 区划名 province/city + 当前/下一节点名(依 crm-rule IOpportunityStageTemplateService,customNodeName 优先/opp_stage 字典名兜底);132 全绿) |
| 11 | createCmd customerId | ✅ 已落(走法甲:customerId 可空占位,待 A4 下拉就绪收紧必填) |
| 12 | 商机侧新增入口关联线索校验 | ✅ 已落(source_lead_id 唯一性预检 + DB uk 并发防线,零 A4 依赖;原标「卡 A4」为误判已纠) |
| 11 | createCmd customerId | ✅ 后端已全落(ConvertOpportunityParam.customerId → CreateOpportunityCmd.customerId → port 消费建子表;走法甲可空占位,待 A4 下拉就绪收紧必填;仅剩前端下拉交互) |
| 12 | 商机侧新增入口关联线索校验 | ✅ 后端已全落(票 70e2e35:商机侧独立新建入口 A3-1-1-2-1 = CreateController+Service,oppSource=线索转入则 sourceLeadId 必填 + 唯一性预检 + 候选线索下拉;仅剩前端下拉交互。前版误标“已落”实为只验转商机 port 路径,已纠) |
| 13 | 商机-客户关联子表 | ✅ 已落(实体 `OpportunityCustomer`+约束 + 转商机时建 `is_primary_intended=1` 主要意向客户子表 + 刷主表冗余;仅「下拉选客户」数据源卡 A4) |
| 14 | 自定义视图 + 内置视图族 | ✅ 已落(底座三表 team/focus/view_log + `TeamMemberPermission` 枚举;**内置六视图**在 crm-opportunity 枚举/ViewQuery 硬编码;**自定义视图 = crm-preference 平台能力**:`UserSavedView` 实体 + Mapper + `SavedView`/`SavedViewCondition` DTO + `SavedViewService` list/save/delete/setDefault + Impl(默认单值互斥) + Controller `/api/preference/view` + 16 单测;**商机侧接线已完成**:`SavedViewOperator` 六操作符枚举 + `OpportunitySavedViewFilter` 把 filter_json 条件翻译成 wrapper(字段池白名单=票10可筛选列,未知字段/操作符跳过)+ PageParam.savedViewId + ViewQueryImpl 叠加;读默认视图=前端调 /view/list 取 isDefault。144 全绿) |
| 15 | 全局默认阶段模板兜底 seed | ✅ 已落(crm-rule `StageTemplateInitializer`:植入 1 头 5 节点发布中默认模板,客户圈定→关系摸排→资料采集→方案卡→已转项目;对称方案卡兜底范式;零 A4/零字典改动)——见 `issues/15` |
| 16 | 票 02 转商机同步事务补齐(阶段落位+初始日志+团队成员) | ✅ 已落(票 02 簇 D 同步事务 5 步已齐:阶段落位(resolveBindingVersion 首节点,无模板容忍空走法 A)+ 初始操作日志(ROW_ADD「由线索转入创建」)+ 团队成员(领取人=商机负责人 project_role_01/READ_WRITE);零 A4 依赖)——见 `issues/16`,blocked by 15 |
**前沿小结**:商机模块**结构层已全部落地**(主表 + 状态机 + 三族规则 + 六子表 + 视图数据源三表 team/focus/view_log)。剩余:① **票 10 查询层 + 票 14 视图组织/自定义视图 = 可独立开工的读侧大票(不卡 A4)** → 已全部落地 ✅;② **票 11/12/13 转商机写入口(走法甲)已落地** ✅:实现 `OpportunityCreationPortImpl`(唯一性预检 + 建商机 + customerId 非空建主要意向客户子表刷冗余);crm-opportunity 新依赖 crm-lead(**ADR-0029 技术债**:下游反向依赖上游,埋循环雷,同库单体阶段可接受);**仅剩卡 A4 的**:转商机弹窗「下拉选客户」的**数据源**(customerId 现可空占位,A4 就绪后收紧必填)。**票 02 port 消费侧已实现**(`OpportunityCreationPortImpl`),不再卡 A4;**商机全面开发不阻塞** — 详见下「customer_id 契约占位」决策(写入口按 id 入参 + 名快照 + 不做跨模块存在性校验)。**省市地区:已修**(原“省市拆分 TODO”实为命令契约丢字段 bug,CreateOpportunityCmd 已补 provinceCode+cityCode 两级,删同填占位)。
**前沿小结**:商机模块 **16 票后端全部落地 ✅**(结构层 + 状态机 + 三族规则 + 六子表 + 视图数据源三表 + 两条建商机入口)。
**20260826 纠偏 + 收官**:票 12 曾被误标“已落”(实为只验了转商机 port 路径的预检/uk),经核实发现**商机侧独立新建入口(A3-1-1-2-1)后端一行未写**;已补(票 70e2e35):crm-lead `listConvertibleLeads`(候选线索准入留线索域,架构甲)+ crm-opportunity `IOpportunityCreateService`/Controller(POST /api/opportunity、GET /convertible-leads,oppSource=线索转入则 sourceLeadId 必填 + 唯一性预检 + 候选剔除已占用)。至此票 11/12/13 + 15/16 均 resolved。
**PRD 后端收官结论**:本 Java 仓库能交付的后端部分**已全部完成**;整体 PRD 上线仅差两块均在**本仓库外**:① **前端**(转商机弹窗/商机侧新建表单的【客户/关联线索】下拉交互);② **A4 客户模块**(客户下拉数据源)。后端为两块均预留好缝(customerId 可空占位、convertible-leads 接口就绪),A4/前端到位后不需改后端(顶多将 customerId 收紧必填)。
**早期前沿小结**(历史):商机模块**结构层已全部落地**(主表 + 状态机 + 三族规则 + 六子表 + 视图数据源三表 team/focus/view_log)。剩余:① **票 10 查询层 + 票 14 视图组织/自定义视图 = 可独立开工的读侧大票(不卡 A4)** → 已全部落地 ✅;② **票 11/12/13 转商机写入口(走法甲)已落地** ✅:实现 `OpportunityCreationPortImpl`(唯一性预检 + 建商机 + customerId 非空建主要意向客户子表刷冗余);crm-opportunity 新依赖 crm-lead(**ADR-0029 技术债**:下游反向依赖上游,埋循环雷,同库单体阶段可接受);**仅剩卡 A4 的**:转商机弹窗「下拉选客户」的**数据源**(customerId 现可空占位,A4 就绪后收紧必填)。**票 02 port 消费侧已实现**(`OpportunityCreationPortImpl`),不再卡 A4;**商机全面开发不阻塞** — 详见下「customer_id 契约占位」决策(写入口按 id 入参 + 名快照 + 不做跨模块存在性校验)。**省市地区:已修**(原“省市拆分 TODO”实为命令契约丢字段 bug,CreateOpportunityCmd 已补 provinceCode+cityCode 两级,删同填占位)。
### 交付物清单(对齐线索地图的阅读顺序)

Loading…
Cancel
Save