Browse Source

docs(dict): 票09 两级树实现落地收尾, 标 done + map.md 行业口径落地

- 票 09 Status resolved→done, 追加 5 步实现落地记录 + item 168→220 演进 + 种子对 builtin 权威语义注记
- map.md: 行业口径从挂起/立票→已落地(全系统通用两级树, 商机存一级/客户到二级), 字典清单 22 组 item 220, 回显改查 industry 分组
master
luoweijian 2 weeks ago
parent
commit
458ee623c2
  1. 11
      .scratch/data-dictionary/issues/09-hierarchical-item.md
  2. 6
      .scratch/opportunity-module/map.md

11
.scratch/data-dictionary/issues/09-hierarchical-item.md

@ -2,7 +2,7 @@
**Type:** grilling → task(本票先 grill 拍板不变式,再落地)
**Status:** resolved
**Status:** done
**Blocked by:** 04
@ -83,3 +83,12 @@
3. `DictQueryService``listTree`/`listChildren`(Q4),扁平内存组树。
4. 种子:`industry` 分组重种新树(9 一级 + 全二级,覆盖旧 8 项);测试断言同步。
5. 回归现有 45 扁平测试全绿 + 新增树形测试。
### 实现落地(20260825,5 步全绿,Status → done)
- **步1** DictItem/DictItemDTO 加 parentId(nullable,顶层=null);H2 测试 schema dict_item 加 parent_id;45 全绿。
- **步2** saveItem 父项校验(同组/父为一级/禁自引用,父不存在 63012、跨组或超两级 63001);doDeleteItem 删一级项若有存活子项则拒 63010;enrich effectiveSelectable 批量回溯父状态;+3 测试,48 全绿。
- **步3** listTree 复用扁平启用列表内存组两级树(不新建缓存 key);listChildren 取一级直接启用子项;DictItemDTO 加 children;getItem/listEnabledItems 扁平接口不变,消费方零改动;+2 测试,50 全绿。
- **步4** ItemSeed 加 parentCode(兼容旧 6 参构造);upsertItem 按 parentCode 同组解析 parentId;run 增 pruneStaleBuiltinItems(种子对 builtin 项权威,剪除旧 8 扁平项连 ref_count,用户项 builtin=false 绝不触碰);industry 8 旧项 → 9 一级+51 二级;首装 168→220、用户跳过 130→182;removedFromSeed 语义翻转为剪除 + 新增用户项不剪除测试;51 全绿。
- **步5** OpportunityViewQueryImpl.fillDictNames 从不存在的 industry_code 分组改查 industry 两级树分组;回归 dict 51 / lead 116 / opportunity 152 全绿。
**item 总量演进**:168 →(industry 8→60)→ **220**。**注意**:pruneStaleBuiltinItems 使种子成为 builtin 项的权威源(此前“只加不删”语义在 builtin 项上被 Q5 覆盖决策取代;用户项 builtin=false 仍绝不触碰,US-41 不变)。

6
.scratch/opportunity-module/map.md

@ -26,7 +26,7 @@
| 07 | 方案卡 | ✅ 已落(模板 + 运行时 + `VersionedConfigSupport` 抽取) |
| 08 | 现场勘察 | ✅ 已落(`OpportunitySiteSurvey` + Mapper,结构) |
| 09 | 子表族(跟进/附件/工作计划/操作日志) | ✅ 已落(四实体 + Mapper + 3 枚举,结构) |
| 10 | 四视图查询口径 | ✅ 已落(底座三表 + ViewType/PageParam/DTO + ViewQuery 六视图 filter + 分页 + 计算列节点停留/最近跟进/方案卡状态/预算 + RECENT view_log 排序 + followed + Controller `/api/opportunity/page`;**读侧回显已补全**:字典名 opp_source/industry_code(PRD §10 契约)+ 部门名 owner_dept_id + 区划名 province/city + 当前/下一节点名(依 crm-rule IOpportunityStageTemplateService,customNodeName 优先/opp_stage 字典名兜底);132 全绿) |
| 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」为误判已纠) |
| 13 | 商机-客户关联子表 | ✅ 已落(实体 `OpportunityCustomer`+约束 + 转商机时建 `is_primary_intended=1` 主要意向客户子表 + 刷主表冗余;仅「下拉选客户」数据源卡 A4) |
@ -60,7 +60,7 @@
## Decisions so far
- **⚠ 行业字典口径待产品拍板(20260825 挂起,未落)** — PRD §10 商机主表 `industry_code`「行业」字段需字典,但存在冲突:crm-dict 已有 `industry` 分组(**客户模块在用**,8 项:制造业/信息技术/金融/医疗健康/教育/零售/房地产/其他,宽泛行业大类);产品 20260825 给的 26 项(普教/高校/党校/公安/检察院/法院…)实为**细分客户类型/项目场景**,与现有 8 项两套口径,不可简单复用/覆盖。**两条待选路**:**路 A**(建议)= 商机单建 `industry_code` 分组种 26 项,客户 `industry` 不动,回显代码查 `industry_code` 天然对上;**路 B** = 26 项覆盖进 `industry` 且商机改查 `industry`,风险=客户存量数据 code 悬空。**另一层疑点**:26 项名义「行业」实为「客户类型」,字段命名与取值口径可能本身错位——需产品确认「是否挂 `industry_code`」。**结论:不擅自落,等产品确认路 A/B + 挂载字段后再种。**
- **✅ 行业字典口径已定案并落地(20260825,票 09 done)** — 产品定:行业改为**全系统通用两级树**(不单建 `industry_code`,客户+商机共用 `industry`),**商机只选到一级**,主表 `industry_code` 存一级 code(Q7);客户选到二级(Q6)。实现=给 `DictItem``parent_id`(两级封顶)+ `listTree`/`listChildren` 树形读 + 父子校验/删除拦截/子项随父停用;`industry` 旧 8 扁平项重种为 9 一级+51 二级(无存量 Q5 直接覆盖)。回显改查 `industry` 分组。详见 `.scratch/data-dictionary/issues/09-hierarchical-item.md`
<!-- 图外先行拍板的 chart 期决策;逐题底稿见对应 issue -->
- **状态/阶段、角色、流转动作、模块边界已定稿(票 01 resolved)** — 商机=独立聚合;两轴 `oppStatus`/`oppStage`;领取人+团队成员角色(按钮可见即可点、与领取人无关);流转动作 = 暂缓/取消暂缓/抛公海/关闭/重启/移交/转项目,**「中止」不存在**(原型活数据 V1.0-20260815 核实);商机来源与来源线索两回事。产出 `crm-opportunity/CONTEXT.md`。详见 `issues/01` + `research-close-pause-actions.md`
@ -102,7 +102,7 @@
3. **customerId 可空占位,不强制非空**:`CreateOpportunityCmd.customerId` / `ConvertOpportunityParam.customerId` 均无 `@NotNull`(已核实);空时跳过建关联子表/不刷冗余,不倒退现有自由文本转商机;A4 下拉就绪后收紧为必填(票 11 终态)。
- **唯一真空洞 = 客户“下拉数据源”**:`customer_id` 从哪来靠上游传入,商机侧全程不需 A4。商机全面开发时这个下拉**前端 mock 几个假 customer_id 或传 null**;功能能全开,只“选真客户”这一步是空的。商机侧不为此建任何 A4 占位/mock 代码(YAGNI,A4 那张图自己建时提供)。
- **商机批量操作与统计接口** — 对称线索 G1–G5(批量领取/分配/关注、列表统计卡片)。等主表 + 四视图定稿后再切成票。
- **商机相关字典项清单**(A7-3-2-6)— ✅ **14 组已种(crm-dict `DictDataInitializer`,产品录入 20260825)**:`opp_source` / `opp_type` / `bid_form` / `result_tag` / `design_config` / `pause_reason` / `pool_reason` / `project_role` / `close_reason` / `locality_type` 项目属地 / `follow_way` 跟进方式 / `survey_seq` 勘察次数 / `apply_way` 申请方式 / `customer_role` 客户角色(分组 7→22、item 97→168,45 全绿)。⚠ **`industry` 行业树形化改造已立票**(20260825 产品定:行业改为全系统通用两级树、商机选到一级;需给 `DictItem``parent_id`——见 `.scratch/data-dictionary/issues/09-hierarchical-item.md`,待 grill 拍板不变式后实现)。**缺值已清零**(attachment_type 已补)
- **商机相关字典项清单**(A7-3-2-6)— ✅ **14 组扁平 + industry 两级树已种(crm-dict `DictDataInitializer`,产品录入 20260825)**:`opp_source` / `opp_type` / `bid_form` / `result_tag` / `design_config` / `pause_reason` / `pool_reason` / `project_role` / `close_reason` / `locality_type` / `follow_way` / `survey_seq` / `apply_way` / `customer_role` / `attachment_type`(均扁平);**`industry` 行业已树形化**(票 09 done:9 一级+51 二级,覆盖旧 8 扁平项)。分组 22、item **220**(168 → industry 8→60),crm-dict 51 全绿。**缺值已清零**
- **方案预算 `scheme_budget`**(方案卡字段)— 商机列表「方案预算」列 = 查主要意向客户(票13)那张方案卡的 budget,主表不建。字段规格归票07,取值锚点归票13。
## Out of scope

Loading…
Cancel
Save