From 915edfdb9af8a91f735bd0dcc97f4a4f77066e86 Mon Sep 17 00:00:00 2001
From: luoweijian <1329394916@qq.com>
Date: Tue, 1 Sep 2026 14:57:40 +0800
Subject: [PATCH] feat(opportunity-board): group board by stage display name,
drop status filter
- rule: validate display-name uniqueness within a template version on publish (64017)
- rule: add describeStageNames / resolveStageIdsByDisplayName batch contracts
- opportunity: board stops filtering by advancing(2), rows with current_stage_id go on board
- opportunity: boardStageSummary groups by display name, ordered full/empty viewport columns
- opportunity: boardCards takes stageName and returns oppStatus
- tests: rule unit tests + opportunity service tests + H2 board integration test
- docs: sync board Bruno collection (stageName param, oppStatus field, drop stageId)
---
crm-opportunity/pom.xml | 6 +
.../OpportunityCollabController.java | 6 +-
.../query/OpportunityViewFilter.java | 13 +-
.../service/IOpportunityCollabService.java | 15 +-
.../impl/OpportunityCollabServiceImpl.java | 153 +++++--
.../impl/OpportunityBoardIntegrationTest.java | 385 ++++++++++++++++++
.../OpportunityCollabServiceImplTest.java | 282 +++++++++++++
.../IOpportunityStageTemplateService.java | 16 +
.../OpportunityStageTemplateServiceImpl.java | 121 +++++-
...portunityStageTemplateServiceImplTest.java | 89 ++++
10 files changed, 1041 insertions(+), 45 deletions(-)
create mode 100644 crm-opportunity/src/test/java/com/crm/opportunity/service/impl/OpportunityBoardIntegrationTest.java
create mode 100644 crm-opportunity/src/test/java/com/crm/opportunity/service/impl/OpportunityCollabServiceImplTest.java
diff --git a/crm-opportunity/pom.xml b/crm-opportunity/pom.xml
index bf43010..48b4007 100644
--- a/crm-opportunity/pom.xml
+++ b/crm-opportunity/pom.xml
@@ -61,5 +61,11 @@
spring-boot-starter-test
test
+
+
+ com.h2database
+ h2
+ test
+
diff --git a/crm-opportunity/src/main/java/com/crm/opportunity/controller/OpportunityCollabController.java b/crm-opportunity/src/main/java/com/crm/opportunity/controller/OpportunityCollabController.java
index a920bd8..3f8a474 100644
--- a/crm-opportunity/src/main/java/com/crm/opportunity/controller/OpportunityCollabController.java
+++ b/crm-opportunity/src/main/java/com/crm/opportunity/controller/OpportunityCollabController.java
@@ -72,15 +72,15 @@ public class OpportunityCollabController {
return Result.success(collabService.boardStageSummary(viewType, stageTemplateId, userId));
}
- @Operation(summary = "看板单阶段卡片列表(viewType 与列表视图同口径,票 06 D-15)",
+ @Operation(summary = "看板单阶段卡片列表(viewType 与列表视图同口径,票 06 D-15;入参 stageName 按展示名取卡)",
tags = {"A3 商机管理/商机公海/看板列表", "A3 商机管理/商机管理/看板列表", "A3 商机管理/销售机会/看板列表"})
@PostMapping("/board/cards")
public Result> boardCards(
@RequestParam(value = "viewType", required = false) String viewType,
- @RequestParam("stageId") Long stageId,
+ @RequestParam("stageName") String stageName,
@RequestParam(value = "offset", defaultValue = "0") int offset,
@RequestParam(value = "limit", defaultValue = "20") int limit) {
Long userId = Long.valueOf(SecurityUtils.getRequiredUserId());
- return Result.success(collabService.boardCards(viewType, stageId, offset, limit, userId));
+ return Result.success(collabService.boardCards(viewType, stageName, offset, limit, userId));
}
}
diff --git a/crm-opportunity/src/main/java/com/crm/opportunity/query/OpportunityViewFilter.java b/crm-opportunity/src/main/java/com/crm/opportunity/query/OpportunityViewFilter.java
index 14470a7..4ae2476 100644
--- a/crm-opportunity/src/main/java/com/crm/opportunity/query/OpportunityViewFilter.java
+++ b/crm-opportunity/src/main/java/com/crm/opportunity/query/OpportunityViewFilter.java
@@ -19,8 +19,7 @@ import org.springframework.stereotype.Component;
*
PARTICIPATED — 团队成员且非负责人(与 MINE 互斥)
* FOLLOWED — opportunity_focus 命中当前用户
* RECENT — 无额外条件(列表侧最近访问走 pageRecent 独立路径取上限;看板侧退化为同基础集)
- * PUBLIC_POOL — opp_status=待领取 且 owner 空(逻辑视图,票 05;status 条件由本分支给出,
- * 调用方不再叠加基础状态条件)
+ * PUBLIC_POOL — opp_status=待领取 且 owner 空(逻辑视图,票 05;status 条件由本分支给出)
* MANAGE — 无额外条件,@DataScope 兜底部门天花板
*
*/
@@ -28,8 +27,9 @@ import org.springframework.stereotype.Component;
public class OpportunityViewFilter {
/**
- * 叠加视图数据集条件。调用方先按场景落基础条件(如看板的推进中状态、阶段锚点),
- * 再调本方法;PUBLIC_POOL 视图下基础状态条件由本方法给出(调用方须跳过自己的状态叠加)。
+ * 叠加视图数据集条件。调用方先按场景落基础条件(如看板的阶段锚点:current_stage_id 非空),
+ * 再调本方法。看板不再按 opp_status=推进中 过滤(ADR-0032:有阶段值即上板),
+ * 公海视图的 status 条件由本方法在 PUBLIC_POOL 分支给出。
*/
public void apply(LambdaQueryWrapper wrapper,
OpportunityViewType viewType, Long currentUserId) {
@@ -55,9 +55,4 @@ public class OpportunityViewFilter {
case MANAGE -> { /* @DataScope handles dept ceiling */ }
}
}
-
- /** PUBLIC_POOL 视图的基础状态由视图分支给出(调用方跳过自己的状态叠加),供调用方判断。 */
- public boolean providesStatusCondition(OpportunityViewType viewType) {
- return viewType == OpportunityViewType.PUBLIC_POOL;
- }
}
diff --git a/crm-opportunity/src/main/java/com/crm/opportunity/service/IOpportunityCollabService.java b/crm-opportunity/src/main/java/com/crm/opportunity/service/IOpportunityCollabService.java
index 9a93306..73e8321 100644
--- a/crm-opportunity/src/main/java/com/crm/opportunity/service/IOpportunityCollabService.java
+++ b/crm-opportunity/src/main/java/com/crm/opportunity/service/IOpportunityCollabService.java
@@ -17,9 +17,18 @@ public interface IOpportunityCollabService {
/** 访问上报(upsert last_view_time) */
void touch(Long oppId, Long userId);
- /** 看板阶段汇总:List<{stageId, stageName, count, totalAmount}>;viewType 与列表视图同口径(票 06 D-15),空→MINE。 */
+ /**
+ * 看板阶段汇总(票 04):List<{stageName, count, totalAmount}>,按当前节点展示名分组;
+ * 空列 count=0 也返回,列顺序由视口阶段模板决定(stageTemplateId 仅视口选择器,null →
+ * 当前用户部门绑定模板 → 全公司默认模板),视口外按各自模板 seq_no 追加列末,跨模板同名合并。
+ * viewType 与列表视图同口径(票 06 D-15),空→MINE。
+ */
List