From a7af0ac8ca8f064e167315fce0f9a940b9a28510 Mon Sep 17 00:00:00 2001 From: luoweijian <1329394916@qq.com> Date: Tue, 25 Aug 2026 14:03:08 +0800 Subject: [PATCH] =?UTF-8?q?feat(opportunity):=20=E7=A5=A810=20=E8=AF=BB?= =?UTF-8?q?=E4=BE=A7=E5=9B=9E=E6=98=BE=E5=BD=93=E5=89=8D/=E4=B8=8B?= =?UTF-8?q?=E4=B8=80=E8=8A=82=E7=82=B9=E5=90=8D=20(=E4=BE=9D=20crm-rule=20?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E6=A8=A1=E6=9D=BF)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 注入 IOpportunityStageTemplateService - fillStageNodeNames: current_stage_id → getNodeById 取当前节点 - 下一节点 = 同版本 (node.templateId) 按 seqNo 升序的下一节点, 末节点→空 - 节点展示名 = customNodeName 优先, 空则带入 opp_stage 字典名 (票06口径) - 批量: distinct stageId/templateId/dictCode 去重取值, 无 N+1 - 新增当前+下一节点名 / 末节点无下一 两测试, 132 全绿 --- .../query/impl/OpportunityViewQueryImpl.java | 95 ++++++++++++++++++- .../impl/OpportunityViewQueryImplTest.java | 78 +++++++++++++++ 2 files changed, 169 insertions(+), 4 deletions(-) diff --git a/crm-opportunity/src/main/java/com/crm/opportunity/query/impl/OpportunityViewQueryImpl.java b/crm-opportunity/src/main/java/com/crm/opportunity/query/impl/OpportunityViewQueryImpl.java index 7e0e41a..8325dd8 100644 --- a/crm-opportunity/src/main/java/com/crm/opportunity/query/impl/OpportunityViewQueryImpl.java +++ b/crm-opportunity/src/main/java/com/crm/opportunity/query/impl/OpportunityViewQueryImpl.java @@ -31,6 +31,8 @@ import com.crm.opportunity.mapper.OpportunityStageHistoryMapper; import com.crm.opportunity.mapper.OpportunityViewLogMapper; import com.crm.opportunity.query.OpportunityViewQuery; import com.crm.rule.domain.dto.SysRegionDTO; +import com.crm.rule.domain.entity.OpportunityStageNode; +import com.crm.rule.service.IOpportunityStageTemplateService; import com.crm.rule.service.ISysRegionService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -55,11 +57,10 @@ import java.util.stream.Collectors; * *
票 10 §二数值计算列(节点停留/最近跟进/方案卡状态/方案预算)已批量 join 填充(无 N+1); * 字典/部门/区划名回显(DictQueryService/SysDeptService/SysRegionService,对称 crm-lead fillDisplayFields) - * 已落。
+ * 及当前/下一节点名(IOpportunityStageTemplateService)均已落。 * - *TODO(后续步骤):① 当前/下一节点名(依赖 crm-rule 阶段模板服务);② PARTICIPATED - * 团队白名单可见性叠加详情链路。RECENT 视图已按 {@code opportunity_view_log.last_view_time} 倒序取上限 - * (见 {@link #pageRecent})。
+ *TODO(后续步骤):PARTICIPATED 团队白名单可见性叠加详情链路。RECENT 视图已按 + * {@code opportunity_view_log.last_view_time} 倒序取上限(见 {@link #pageRecent})。
*/ @Component @RequiredArgsConstructor @@ -75,6 +76,7 @@ public class OpportunityViewQueryImpl implements OpportunityViewQuery { private final DictQueryService dictQueryService; private final ISysDeptService sysDeptService; private final ISysRegionService sysRegionService; + private final IOpportunityStageTemplateService stageTemplateService; /** RECENT 视图上限(票 10 P2-2 默认 50;view_log 已被后台 Job 裁剪,此处再兜底截断)。 */ private static final int RECENT_LIMIT = 50; @@ -208,6 +210,7 @@ public class OpportunityViewQueryImpl implements OpportunityViewQuery { fillDictNames(dtos); fillDeptNames(dtos); fillRegionNames(dtos); + fillStageNodeNames(dtos); } /** @@ -269,6 +272,90 @@ public class OpportunityViewQueryImpl implements OpportunityViewQuery { }); } + /** + * 当前/下一节点名回显(票 10 §二口径,依 crm-rule + * {@link IOpportunityStageTemplateService})。 + *批量:按 distinct {@code currentStageId} 取节点(同页去重),按 distinct + * {@code templateId} 取版本节点列表,stageDictCode 字典名也去重后查,避免 N+1。
+ */ + private void fillStageNodeNames(List进入日期 = {@code opportunity_stage_history} 中 {@code to_stage_id = current_stage_id} 的最新
diff --git a/crm-opportunity/src/test/java/com/crm/opportunity/query/impl/OpportunityViewQueryImplTest.java b/crm-opportunity/src/test/java/com/crm/opportunity/query/impl/OpportunityViewQueryImplTest.java
index 2b45513..1bda46c 100644
--- a/crm-opportunity/src/test/java/com/crm/opportunity/query/impl/OpportunityViewQueryImplTest.java
+++ b/crm-opportunity/src/test/java/com/crm/opportunity/query/impl/OpportunityViewQueryImplTest.java
@@ -70,6 +70,8 @@ class OpportunityViewQueryImplTest {
private com.crm.auth.service.ISysDeptService sysDeptService;
@Mock
private com.crm.rule.service.ISysRegionService sysRegionService;
+ @Mock
+ private com.crm.rule.service.IOpportunityStageTemplateService stageTemplateService;
@InjectMocks
private OpportunityViewQueryImpl query;
@@ -88,6 +90,8 @@ class OpportunityViewQueryImplTest {
lenient().when(viewLogMapper.selectList(any())).thenReturn(Collections.emptyList());
lenient().when(sysDeptService.listByIds(any())).thenReturn(Collections.emptyList());
lenient().when(sysRegionService.listByCodes(any())).thenReturn(Collections.emptyList());
+ lenient().when(stageTemplateService.getNodeById(any())).thenReturn(null);
+ lenient().when(stageTemplateService.listNodesOfVersion(any())).thenReturn(Collections.emptyList());
}
@AfterEach
@@ -287,4 +291,78 @@ class OpportunityViewQueryImplTest {
assertThat(dto.getProvinceName()).isEqualTo("广东省");
assertThat(dto.getCityName()).isEqualTo("深圳市");
}
+
+ @Test
+ @DisplayName("节点名:当前节点名(customNodeName 优先/字典名兵底)+ 下一节点(seq 升序)")
+ @SuppressWarnings("unchecked")
+ void stageNodeNames_currentAndNext() {
+ // opp 当前在节点 200(模板版本 8001)
+ Opportunity opp = new Opportunity();
+ opp.setId(7001L);
+ opp.setCurrentStageId(200L);
+ Page