From 3bf88ff06b379f2d0c8fcafa815c1fd6aaca2480 Mon Sep 17 00:00:00 2001
From: tianfeng <769204422@qq.com>
Date: Fri, 28 Nov 2025 11:57:55 +0800
Subject: [PATCH] =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98=E4=B8=AD=E5=BF=83?=
=?UTF-8?q?=E6=80=BB=E8=A7=88=E6=8E=A5=E5=8F=A3=E5=AE=8C=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../adapter/app/BdTeamRestController.java | 13 +
.../command/bd/query/BdTeamSummaryQryExe.java | 289 ++++++++++++++++++
.../other/app/service/BdTeamServiceImpl.java | 8 +
.../app/dto/clientobject/BdTeamSummaryCO.java | 48 +++
.../other/app/service/BdTeamService.java | 12 +
5 files changed, 370 insertions(+)
create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/bd/query/BdTeamSummaryQryExe.java
create mode 100644 rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/BdTeamSummaryCO.java
diff --git a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/BdTeamRestController.java b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/BdTeamRestController.java
index f53aa366..0e8c309b 100644
--- a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/BdTeamRestController.java
+++ b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/BdTeamRestController.java
@@ -1,7 +1,9 @@
package com.red.circle.other.adapter.app;
+import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.other.app.dto.clientobject.BdTeamMemberDetailCO;
import com.red.circle.other.app.dto.clientobject.BdTeamOverviewCO;
+import com.red.circle.other.app.dto.clientobject.BdTeamSummaryCO;
import com.red.circle.other.app.dto.cmd.BdTeamMemberDetailQueryCmd;
import com.red.circle.other.app.dto.cmd.BdTeamQueryCmd;
import com.red.circle.other.app.service.BdTeamService;
@@ -49,4 +51,15 @@ public class BdTeamRestController {
public BdTeamMemberDetailCO queryMemberDetail(@RequestBody BdTeamMemberDetailQueryCmd cmd) {
return bdTeamService.queryMemberDetail(cmd);
}
+
+ /**
+ * 查询BD团队总览
+ *
+ * 返回当前用户在BD_LEADER、BD、AGENCY三个角色下的汇总数据
+ *
+ */
+ @PostMapping("/summary")
+ public BdTeamSummaryCO queryTeamSummary(AppExtCommand cmd) {
+ return bdTeamService.queryTeamSummary(cmd.getReqUserId());
+ }
}
diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/bd/query/BdTeamSummaryQryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/bd/query/BdTeamSummaryQryExe.java
new file mode 100644
index 00000000..16e74d82
--- /dev/null
+++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/bd/query/BdTeamSummaryQryExe.java
@@ -0,0 +1,289 @@
+package com.red.circle.other.app.command.bd.query;
+
+import com.alibaba.fastjson.JSON;
+import com.red.circle.component.redis.service.RedisService;
+import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
+import com.red.circle.other.app.dto.clientobject.BdTeamMemberCO;
+import com.red.circle.other.app.dto.clientobject.BdTeamSummaryCO;
+import com.red.circle.other.domain.gateway.user.UserProfileGateway;
+import com.red.circle.other.infra.database.mongo.dto.team.TeamBillMemberTarget;
+import com.red.circle.other.infra.database.mongo.entity.team.team.TeamBillCycle;
+import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMemberTarget;
+import com.red.circle.other.infra.database.mongo.entity.team.team.TeamPolicyManager;
+import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
+import com.red.circle.other.infra.database.mongo.service.team.TeamBillCycleUtils;
+import com.red.circle.other.infra.database.mongo.service.team.team.TeamBillCycleService;
+import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberTargetService;
+import com.red.circle.other.infra.database.mongo.service.team.team.TeamPolicyManagerService;
+import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
+import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentBaseInfo;
+import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentTeam;
+import com.red.circle.other.infra.database.rds.entity.team.RoomBdLead;
+import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentBaseInfoService;
+import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentTeamService;
+import com.red.circle.other.infra.database.rds.service.team.RoomBdLeadService;
+import com.red.circle.other.inner.enums.team.TeamBillCycleStatus;
+import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
+import com.red.circle.tool.core.collection.CollectionUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * BD团队总览查询执行器
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class BdTeamSummaryQryExe {
+
+ private final BusinessDevelopmentTeamService businessDevelopmentTeamService;
+ private final BusinessDevelopmentBaseInfoService businessDevelopmentBaseInfoService;
+ private final TeamBillCycleService teamBillCycleService;
+ private final TeamProfileService teamProfileService;
+ private final TeamMemberTargetService teamMemberTargetService;
+ private final TeamPolicyManagerService teamPolicyManagerService;
+ private final UserProfileGateway userProfileGateway;
+ private final UserProfileAppConvertor userProfileAppConvertor;
+ private final RoomBdLeadService roomBdLeadService;
+ private final RedisService redisService;
+
+ /**
+ * 执行查询
+ */
+ public BdTeamSummaryCO execute(Long userId) {
+ // 缓存查询
+ String cacheKey = "bdteam:summary:" + userId;
+ BdTeamSummaryCO cached = redisService.getStringToObject(cacheKey, BdTeamSummaryCO.class);
+ if (cached != null) {
+ return cached;
+ }
+
+ // 查询数据
+ BdTeamSummaryCO result = queryTeamSummary(userId);
+
+ // 缓存结果(2分钟)
+ redisService.setString(cacheKey, JSON.toJSONString(result), 2, TimeUnit.MINUTES);
+
+ return result;
+ }
+
+ /**
+ * 查询团队总览
+ */
+ private BdTeamSummaryCO queryTeamSummary(Long userId) {
+ BdTeamSummaryCO summary = new BdTeamSummaryCO();
+
+ // 获取当前账单周期
+ Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong();
+
+ // 查询三个角色的数据
+ BdTeamSummaryCO.TeamSummaryItem bdLeaderTeams = queryBdLeaderSummary(userId, currentBillBelong);
+ BdTeamSummaryCO.TeamSummaryItem bdTeams = queryBdSummary(userId, currentBillBelong);
+ BdTeamSummaryCO.TeamSummaryItem agencyTeams = queryAgencySummary(userId, currentBillBelong);
+
+ summary.setBdLeaderTeams(bdLeaderTeams);
+ summary.setBdTeams(bdTeams);
+ summary.setAgencyTeams(agencyTeams);
+
+ // Team earnings this period = BD Teams 的 totalIncome
+ summary.setTeamEarningsThisPeriod(bdTeams.getTotalIncome());
+
+ return summary;
+ }
+
+ /**
+ * 查询 BD Leader 汇总
+ */
+ private BdTeamSummaryCO.TeamSummaryItem queryBdLeaderSummary(Long bdLeaderUserId, Integer currentBillBelong) {
+ BdTeamSummaryCO.TeamSummaryItem item = new BdTeamSummaryCO.TeamSummaryItem();
+
+ // 查询该 Leader 下的所有 BD
+ List bdList =
+ businessDevelopmentBaseInfoService.listBdByLeadUserId(bdLeaderUserId);
+
+ if (CollectionUtils.isEmpty(bdList)) {
+ item.setCount(0);
+ item.setTotalIncome(BigDecimal.ZERO);
+ return item;
+ }
+
+ // 过滤BD Leader
+ Set bdIdSet = bdList.stream()
+ .map(BusinessDevelopmentBaseInfo::getUserId)
+ .collect(Collectors.toSet());
+ List roomBdLeads = roomBdLeadService.listByUserIds(bdIdSet);
+
+ if (CollectionUtils.isEmpty(roomBdLeads)) {
+ item.setCount(0);
+ item.setTotalIncome(BigDecimal.ZERO);
+ return item;
+ }
+
+ List bdLeaderIdList = roomBdLeads.stream()
+ .map(RoomBdLead::getUserId)
+ .toList();
+ bdList = bdList.stream()
+ .filter(e -> !e.getUserId().equals(bdLeaderUserId))
+ .filter(e -> bdLeaderIdList.contains(e.getUserId()))
+ .collect(Collectors.toList());
+
+ item.setCount(bdList.size());
+
+ // 汇总所有 BD 的收入
+ BigDecimal totalIncome = BigDecimal.ZERO;
+ for (BusinessDevelopmentBaseInfo bdInfo : bdList) {
+ List bdTeamList =
+ businessDevelopmentTeamService.listByUserId(bdInfo.getUserId());
+ if (CollectionUtils.isNotEmpty(bdTeamList)) {
+ BigDecimal bdIncome = calculateBdTotalIncome(bdTeamList, currentBillBelong);
+ totalIncome = totalIncome.add(bdIncome);
+ }
+ }
+
+ item.setTotalIncome(totalIncome);
+ return item;
+ }
+
+ /**
+ * 查询 BD 汇总
+ */
+ private BdTeamSummaryCO.TeamSummaryItem queryBdSummary(Long bdUserId, Integer currentBillBelong) {
+ BdTeamSummaryCO.TeamSummaryItem item = new BdTeamSummaryCO.TeamSummaryItem();
+
+ // 查询该用户下的所有 Agency 团队
+ List bdTeamList = businessDevelopmentTeamService.listByUserId(bdUserId);
+
+ if (CollectionUtils.isEmpty(bdTeamList)) {
+ item.setCount(0);
+ item.setTotalIncome(BigDecimal.ZERO);
+ return item;
+ }
+
+ item.setCount(bdTeamList.size());
+
+ // 计算总收入
+ BigDecimal totalIncome = calculateBdTotalIncome(bdTeamList, currentBillBelong);
+ item.setTotalIncome(totalIncome);
+
+ return item;
+ }
+
+ /**
+ * 查询 Agency 汇总
+ */
+ private BdTeamSummaryCO.TeamSummaryItem queryAgencySummary(Long agencyUserId, Integer currentBillBelong) {
+ BdTeamSummaryCO.TeamSummaryItem item = new BdTeamSummaryCO.TeamSummaryItem();
+
+ // 查询该用户的所有团队
+ List bdTeamList = businessDevelopmentTeamService.listByUserId(agencyUserId);
+
+ if (CollectionUtils.isEmpty(bdTeamList)) {
+ item.setCount(0);
+ item.setTotalIncome(BigDecimal.ZERO);
+ return item;
+ }
+
+ item.setCount(bdTeamList.size());
+
+ // 获取团队ID集合
+ Set teamIdSet = bdTeamList.stream()
+ .map(BusinessDevelopmentTeam::getTeamId)
+ .collect(Collectors.toSet());
+
+ // 查询账单数据
+ Map billCycleMap = teamBillCycleService.mapByTeamIds2(
+ teamIdSet, currentBillBelong, TeamBillCycleStatus.UNPAID);
+
+ Map> memberTargetMap =
+ teamMemberTargetService.mapMemberBillTarget(teamIdSet, currentBillBelong);
+
+ // 查询区域政策
+ Map policyManagerMap = teamPolicyManagerService.mapRegionRelease(
+ billCycleMap.values().stream()
+ .map(TeamBillCycle::getRegion)
+ .collect(Collectors.toSet()));
+
+ // 计算总收入
+ BigDecimal totalIncome = BigDecimal.ZERO;
+ for (BusinessDevelopmentTeam bdTeam : bdTeamList) {
+ BigDecimal teamIncome = getTeamTotalSalary(
+ billCycleMap, memberTargetMap, policyManagerMap, bdTeam.getTeamId());
+ totalIncome = totalIncome.add(teamIncome);
+ }
+
+ item.setTotalIncome(totalIncome);
+ return item;
+ }
+
+ /**
+ * 计算 BD 的总收入(汇总其所有 Agency 团队的收入)
+ */
+ private BigDecimal calculateBdTotalIncome(List bdTeamList, Integer currentBillBelong) {
+ // 1. 获取所有团队ID
+ Set teamIdSet = bdTeamList.stream()
+ .map(BusinessDevelopmentTeam::getTeamId)
+ .collect(Collectors.toSet());
+
+ // 2. 查询账单周期
+ Map billCycleMap = teamBillCycleService.mapByTeamIds2(
+ teamIdSet, currentBillBelong, TeamBillCycleStatus.UNPAID);
+
+ // 3. 查询成员目标
+ Map> memberTargetMap =
+ teamMemberTargetService.mapMemberBillTarget(teamIdSet, currentBillBelong);
+
+ // 4. 查询区域政策
+ Map policyManagerMap = teamPolicyManagerService.mapRegionRelease(
+ billCycleMap.values().stream()
+ .map(TeamBillCycle::getRegion)
+ .collect(Collectors.toSet()));
+
+ // 5. 计算每个团队的收入并汇总
+ BigDecimal totalIncome = BigDecimal.ZERO;
+ for (BusinessDevelopmentTeam bdTeam : bdTeamList) {
+ Long teamId = bdTeam.getTeamId();
+ BigDecimal teamIncome = getTeamTotalSalary(billCycleMap, memberTargetMap, policyManagerMap, teamId);
+ totalIncome = totalIncome.add(teamIncome);
+ }
+
+ return totalIncome;
+ }
+
+ /**
+ * 计算单个团队的总收入
+ */
+ private BigDecimal getTeamTotalSalary(
+ Map billCycleMap,
+ Map> teamMemberTargetMap,
+ Map policyManagerMap,
+ Long teamId) {
+
+ TeamBillCycle billCycle = billCycleMap.get(teamId);
+ if (billCycle == null) {
+ return BigDecimal.ZERO;
+ }
+
+ List targetList = teamMemberTargetMap.get(teamId);
+ List memberTargets = TeamBillCycleUtils.calculatorPolicyTarget(
+ targetList, policyManagerMap.get(billCycle.getRegion()));
+
+ return ownTotalSalary(memberTargets);
+ }
+
+ /**
+ * 汇总成员工资
+ */
+ private BigDecimal ownTotalSalary(List teamBillMemberTargets) {
+ return teamBillMemberTargets.stream()
+ .map(TeamBillMemberTarget::getTotalSalary)
+ .reduce(BigDecimal.ZERO, BigDecimal::add)
+ .setScale(2, RoundingMode.DOWN);
+ }
+}
diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/BdTeamServiceImpl.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/BdTeamServiceImpl.java
index 1d0bd78e..a6061035 100644
--- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/BdTeamServiceImpl.java
+++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/BdTeamServiceImpl.java
@@ -2,8 +2,10 @@ package com.red.circle.other.app.service;
import com.red.circle.other.app.command.bd.query.BdTeamMemberDetailQryExe;
import com.red.circle.other.app.command.bd.query.BdTeamQryExe;
+import com.red.circle.other.app.command.bd.query.BdTeamSummaryQryExe;
import com.red.circle.other.app.dto.clientobject.BdTeamMemberDetailCO;
import com.red.circle.other.app.dto.clientobject.BdTeamOverviewCO;
+import com.red.circle.other.app.dto.clientobject.BdTeamSummaryCO;
import com.red.circle.other.app.dto.cmd.BdTeamMemberDetailQueryCmd;
import com.red.circle.other.app.dto.cmd.BdTeamQueryCmd;
import lombok.RequiredArgsConstructor;
@@ -20,6 +22,7 @@ public class BdTeamServiceImpl implements BdTeamService {
private final BdTeamQryExe bdTeamQryExe;
private final BdTeamMemberDetailQryExe bdTeamMemberDetailQryExe;
+ private final BdTeamSummaryQryExe bdTeamSummaryQryExe;
@Override
public BdTeamOverviewCO queryTeamOverview(BdTeamQueryCmd cmd) {
@@ -30,4 +33,9 @@ public class BdTeamServiceImpl implements BdTeamService {
public BdTeamMemberDetailCO queryMemberDetail(BdTeamMemberDetailQueryCmd cmd) {
return bdTeamMemberDetailQryExe.execute(cmd);
}
+
+ @Override
+ public BdTeamSummaryCO queryTeamSummary(Long userId) {
+ return bdTeamSummaryQryExe.execute(userId);
+ }
}
diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/BdTeamSummaryCO.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/BdTeamSummaryCO.java
new file mode 100644
index 00000000..e73e0fed
--- /dev/null
+++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/BdTeamSummaryCO.java
@@ -0,0 +1,48 @@
+package com.red.circle.other.app.dto.clientobject;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * BD团队总览
+ */
+@Data
+public class BdTeamSummaryCO {
+
+ /**
+ * 本期团队收入(My BD Teams 的 totalIncome)
+ */
+ private BigDecimal teamEarningsThisPeriod;
+
+ /**
+ * My BD Leader Teams 信息
+ */
+ private TeamSummaryItem bdLeaderTeams;
+
+ /**
+ * My BD Teams 信息
+ */
+ private TeamSummaryItem bdTeams;
+
+ /**
+ * My Agency Teams 信息
+ */
+ private TeamSummaryItem agencyTeams;
+
+ /**
+ * 团队汇总项
+ */
+ @Data
+ public static class TeamSummaryItem {
+ /**
+ * 团队数量
+ */
+ private Integer count;
+
+ /**
+ * 总收入
+ */
+ private BigDecimal totalIncome;
+ }
+}
diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/BdTeamService.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/BdTeamService.java
index cabb97df..cd2801e0 100644
--- a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/BdTeamService.java
+++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/BdTeamService.java
@@ -2,6 +2,7 @@ package com.red.circle.other.app.service;
import com.red.circle.other.app.dto.clientobject.BdTeamMemberDetailCO;
import com.red.circle.other.app.dto.clientobject.BdTeamOverviewCO;
+import com.red.circle.other.app.dto.clientobject.BdTeamSummaryCO;
import com.red.circle.other.app.dto.cmd.BdTeamMemberDetailQueryCmd;
import com.red.circle.other.app.dto.cmd.BdTeamQueryCmd;
@@ -33,4 +34,15 @@ public interface BdTeamService {
* @return 成员详情
*/
BdTeamMemberDetailCO queryMemberDetail(BdTeamMemberDetailQueryCmd cmd);
+
+ /**
+ * 查询BD团队总览
+ *
+ * 返回当前用户在BD_LEADER、BD、AGENCY三个角色下的汇总数据
+ *
+ *
+ * @param userId 用户ID
+ * @return 团队总览
+ */
+ BdTeamSummaryCO queryTeamSummary(Long userId);
}