BD列表实时显示问题处理

This commit is contained in:
tianfeng 2025-11-24 18:29:18 +08:00
parent 5db66317f7
commit 76591646a1
3 changed files with 289 additions and 62 deletions

View File

@ -1,14 +1,24 @@
package com.red.circle.other.app.command.bd.query;
import com.alibaba.fastjson.JSON;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.component.redis.RedisKeys;
import com.red.circle.component.redis.service.RedisService;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.order.inner.endpoint.InAppPurchaseDetailsClient;
import com.red.circle.order.inner.model.dto.inapp.BatchUserRechargeStatisticsDTO;
import com.red.circle.other.app.convertor.user.UserProfileAppConvertor;
import com.red.circle.other.app.dto.clientobject.TeamBdMemberBillCO;
import com.red.circle.other.app.dto.clientobject.TeamBdMemberCO;
import com.red.circle.other.app.dto.clientobject.team.BdHistoryCO;
import com.red.circle.other.app.dto.cmd.TeamBdMemberBillCmd;
import com.red.circle.other.app.service.BdSalarySettlementServiceImpl;
import com.red.circle.other.domain.gateway.user.UserProfileGateway;
import com.red.circle.other.infra.database.mongo.entity.bd.BdSalaryPolicy;
import com.red.circle.other.infra.database.mongo.entity.bd.BdSalarySettlementRecord;
import com.red.circle.other.infra.database.mongo.service.bd.BdSalaryPolicyService;
import com.red.circle.other.infra.enums.BdPolicyType;
import com.red.circle.other.infra.enums.BdSettlementStatus;
import com.red.circle.other.infra.database.mongo.dto.team.TeamBillSettleResult;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamBillCycle;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamMember;
@ -32,11 +42,13 @@ import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@ -55,10 +67,11 @@ public class TeamBdMemberBillListQryExe {
private final TeamProfileService teamProfileService;
private final UserProfileGateway userProfileGateway;
private final UserProfileAppConvertor userProfileAppConvertor;
private final BdTeamLeaderClient bdTeamLeaderClient;
private final TeamMemberService teamMemberService;
private final BusinessDevelopmentBaseInfoService businessDevelopmentBaseInfoService;
private final InAppPurchaseDetailsClient inAppPurchaseDetailsClient;
private final RedisService redisService;
private final BdSalaryPolicyService bdSalaryPolicyService;
/**
* 执行查询.
@ -67,65 +80,51 @@ public class TeamBdMemberBillListQryExe {
* @return 账单列表
*/
public TeamBdMemberCO execute(TeamBdMemberBillCmd cmd) {
List<BusinessDevelopmentTeam> bdTeamList = new ArrayList<>();
if ("BD".equals(cmd.getType())) {
bdTeamList.addAll(businessDevelopmentTeamService.listByUserId(cmd.getReqUserId()));
} else {
List<BusinessDevelopmentBaseInfo> baseInfos = businessDevelopmentBaseInfoService.listBdByLeadUserId(cmd.getReqUserId());
Set<Long> bdIdSet = baseInfos.stream()
.map(BusinessDevelopmentBaseInfo::getUserId)
.collect(Collectors.toSet());
Map<Long, UserProfileDTO> userProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
userProfileGateway.mapByUserIds(bdIdSet));
List<TeamBdMemberBillCO> list = baseInfos.stream().map(e -> {
TeamBdMemberBillCO billCO = new TeamBdMemberBillCO();
// 代理用户信息
UserProfileDTO userProfile = userProfileMap.get(e.getUserId());
if (userProfile != null) {
billCO.setAgentId(userProfile.getId());
billCO.setAgentAccount(userProfile.getAccount());
billCO.setAgentName(userProfile.getUserNickname());
billCO.setAgentAvatar(userProfile.getUserAvatar());
}
billCO.setTeamSalaryAmount(BigDecimal.ZERO);
billCO.setTeamMemberCount(e.getMemberQuantity().intValue());
return billCO;
}).toList();
TeamBdMemberCO teamBdMemberCO = new TeamBdMemberCO();
teamBdMemberCO.setMemberBillList(list);
teamBdMemberCO.setTotalSalary(BigDecimal.ZERO);
teamBdMemberCO.setTotalRecharge(BigDecimal.ZERO);
teamBdMemberCO.setBillTitle(TeamBillCycleUtils.parseBillBelongToDateRangeStr(TeamBillCycleUtils.getCalcBillBelong()));
return teamBdMemberCO;
}
// 1. 查询BD关联的所有代理
if (CollectionUtils.isEmpty(bdTeamList)) {
return new TeamBdMemberCO();
// 1. 缓存查询
String key = "bdcenter:" + cmd.getType() + ":" + cmd.getReqUserId();
TeamBdMemberCO cached = redisService.getStringToObject(key, TeamBdMemberCO.class);
if (cached != null) {
return cached;
}
// 2. 获取团队ID集合
// 2. 根据类型执行不同的查询逻辑
TeamBdMemberCO result;
if ("BD".equals(cmd.getType())) {
result = queryBdTeamData(cmd.getReqUserId());
} else {
result = queryBdLeaderTeamData(cmd.getReqUserId());
}
// 3. 缓存结果
redisService.setString(key, JSON.toJSONString(result), 2, TimeUnit.MINUTES);
return result;
}
/**
* 查询 BD 的团队数据返回 Agent 团队列表.
*/
private TeamBdMemberCO queryBdTeamData(Long bdUserId) {
// 1. 查询该 BD 的所有团队
List<BusinessDevelopmentTeam> bdTeamList = businessDevelopmentTeamService.listByUserId(bdUserId);
if (CollectionUtils.isEmpty(bdTeamList)) {
return createEmptyResult();
}
// 2. 获取当前账单周期
Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong();
// 3. 获取团队ID集合
Set<Long> teamIdSet = bdTeamList.stream()
.map(BusinessDevelopmentTeam::getTeamId)
.collect(Collectors.toSet());
// 3. 获取当前账单周期 billBelong
Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong();
// 4. 查询当前周期的账单
Map<Long, TeamBillCycle> billCycleMap = teamBillCycleService.mapByTeamIds2(
teamIdSet, currentBillBelong, TeamBillCycleStatus.SETTLED);
teamIdSet, currentBillBelong, TeamBillCycleStatus.UNPAID);
// 5. 获取团队Profile信息包含团队人数
// 5. 获取团队Profile信息
Map<Long, TeamProfile> teamProfileMap = teamProfileService.mapProfileByIds(teamIdSet);
// 6. 获取代理用户信息
@ -135,19 +134,189 @@ public class TeamBdMemberBillListQryExe {
Map<Long, UserProfileDTO> userProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
userProfileGateway.mapByUserIds(agentIdSet));
// 7. 查询充值数据
Map<Long, BigDecimal> rechargeMap = getRechargeMap(currentBillBelong, agentIdSet);
// 7. 组装返回结果
List<TeamBdMemberBillCO> collect = bdTeamList.stream()
.map(bdTeam -> buildMemberBillCO(bdTeam, billCycleMap, teamProfileMap, userProfileMap,rechargeMap, currentBillBelong))
.collect(Collectors.toList());
// 8. 组装成员账单列表每个 Agent 团队一条
List<TeamBdMemberBillCO> memberBillList = bdTeamList.stream()
.map(bdTeam -> buildMemberBillCO(bdTeam, billCycleMap, teamProfileMap,
userProfileMap, rechargeMap, currentBillBelong))
.collect(Collectors.toList());
TeamBdMemberCO teamBdMemberCO = new TeamBdMemberCO();
teamBdMemberCO.setMemberBillList(collect);
teamBdMemberCO.setTotalSalary(collect.stream().map(TeamBdMemberBillCO::getTeamSalaryAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
teamBdMemberCO.setTotalRecharge(collect.stream().map(TeamBdMemberBillCO::getTeamRechargeAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
teamBdMemberCO.setBillTitle(TeamBillCycleUtils.parseBillBelongToDateRangeStr(TeamBillCycleUtils.getCalcBillBelong()));
return teamBdMemberCO;
// 9. 计算汇总数据
BigDecimal totalSalary = memberBillList.stream()
.map(TeamBdMemberBillCO::getTeamSalaryAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal totalRecharge = memberBillList.stream()
.map(TeamBdMemberBillCO::getTeamRechargeAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 10. 组装返回结果
TeamBdMemberCO result = new TeamBdMemberCO();
result.setMemberBillList(memberBillList);
result.setTotalSalary(totalSalary);
result.setTotalRecharge(totalRecharge);
result.setBillTitle(TeamBillCycleUtils.parseBillBelongToDateRangeStr(currentBillBelong));
// 11. 计算当前账单的 BD 工资信息
BdHistoryCO bdHistoryCO = calculateCurrentBdBill(currentBillBelong,
bdTeamList.size(), totalSalary, totalRecharge);
result.setBdHistoryCO(bdHistoryCO);
return result;
}
/**
* 查询 BD Leader 的团队数据返回 BD 列表每个 BD 汇总其所有团队.
*/
private TeamBdMemberCO queryBdLeaderTeamData(Long bdLeaderUserId) {
// 1. 查询该 Leader 下的所有 BD
List<BusinessDevelopmentBaseInfo> bdList =
businessDevelopmentBaseInfoService.listBdByLeadUserId(bdLeaderUserId);
if (CollectionUtils.isEmpty(bdList)) {
return createEmptyResult();
}
// 2. 获取当前账单周期
Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong();
// 3. 收集所有 BD 的用户ID
Set<Long> bdUserIdSet = bdList.stream()
.map(BusinessDevelopmentBaseInfo::getUserId)
.collect(Collectors.toSet());
// 4. 批量查询所有 BD 的用户信息
Map<Long, UserProfileDTO> bdUserProfileMap = userProfileAppConvertor.toMapUserProfileDTO(
userProfileGateway.mapByUserIds(bdUserIdSet));
// 5. 为每个 BD 构建汇总数据
List<TeamBdMemberBillCO> memberBillList = bdList.stream()
.map(bdInfo -> buildBdSummaryBillCO(bdInfo, bdUserProfileMap, currentBillBelong))
.collect(Collectors.toList());
// 6. 计算总汇总数据
BigDecimal totalSalary = memberBillList.stream()
.map(TeamBdMemberBillCO::getTeamSalaryAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal totalRecharge = memberBillList.stream()
.map(TeamBdMemberBillCO::getTeamRechargeAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 7. 计算总的 Agent 数量所有 BD Agent 总和
Integer totalAgentCount = memberBillList.stream()
.map(TeamBdMemberBillCO::getTeamMemberCount)
.reduce(0, Integer::sum);
// 8. 组装返回结果
TeamBdMemberCO result = new TeamBdMemberCO();
result.setMemberBillList(memberBillList);
result.setTotalSalary(totalSalary);
result.setTotalRecharge(totalRecharge);
result.setBillTitle(TeamBillCycleUtils.parseBillBelongToDateRangeStr(currentBillBelong));
// 9. 计算当前账单的 BD Leader 工资信息使用总的 Agent 数量
BdHistoryCO bdHistoryCO = calculateCurrentBdBill(currentBillBelong,
totalAgentCount, totalSalary, totalRecharge);
result.setBdHistoryCO(bdHistoryCO);
return result;
}
/**
* 构建 BD 汇总账单 CO汇总该 BD 下所有团队的数据.
*/
private TeamBdMemberBillCO buildBdSummaryBillCO(
BusinessDevelopmentBaseInfo bdInfo,
Map<Long, UserProfileDTO> bdUserProfileMap,
Integer currentBillBelong) {
TeamBdMemberBillCO co = new TeamBdMemberBillCO();
// 1. 设置 BD 用户信息这里的 Agent 字段实际上是 BD 信息
UserProfileDTO bdUserProfile = bdUserProfileMap.get(bdInfo.getUserId());
if (bdUserProfile != null) {
co.setAgentId(bdUserProfile.getId());
co.setAgentAccount(bdUserProfile.getAccount());
co.setAgentName(bdUserProfile.getUserNickname());
co.setAgentAvatar(bdUserProfile.getUserAvatar());
}
// 2. 查询该 BD 的所有团队
List<BusinessDevelopmentTeam> bdTeamList =
businessDevelopmentTeamService.listByUserId(bdInfo.getUserId());
if (CollectionUtils.isEmpty(bdTeamList)) {
co.setTeamMemberCount(0);
co.setTeamSalaryAmount(BigDecimal.ZERO);
co.setTeamRechargeAmount(BigDecimal.ZERO);
co.setStartDate("");
co.setEndDate("");
return co;
}
// 3. 设置团队数量 BD 管理的 Agent 数量
co.setTeamMemberCount(bdTeamList.size());
// 4. 账单周期日期
String[] dates = TeamBillCycleUtils.parseBillBelongToDateRange(currentBillBelong);
co.setStartDate(dates[0]);
co.setEndDate(dates[1]);
// 5. 获取团队ID集合
Set<Long> teamIdSet = bdTeamList.stream()
.map(BusinessDevelopmentTeam::getTeamId)
.collect(Collectors.toSet());
// 6. 查询账单数据
Map<Long, TeamBillCycle> billCycleMap = teamBillCycleService.mapByTeamIds2(
teamIdSet, currentBillBelong, TeamBillCycleStatus.UNPAID);
// 7. 汇总所有团队的工资
BigDecimal totalSalary = BigDecimal.ZERO;
for (BusinessDevelopmentTeam bdTeam : bdTeamList) {
TeamBillCycle billCycle = billCycleMap.get(bdTeam.getTeamId());
if (billCycle != null && billCycle.getSettleResult() != null) {
BigDecimal teamSalary = billCycle.getSettleResult().getTotalSalary();
if (teamSalary != null) {
totalSalary = totalSalary.add(teamSalary);
}
}
}
co.setTeamSalaryAmount(totalSalary);
// 8. 获取所有 Agent ID
Set<Long> agentIdSet = bdTeamList.stream()
.map(BusinessDevelopmentTeam::getAgentId)
.collect(Collectors.toSet());
// 9. 查询充值数据并汇总
Map<Long, BigDecimal> rechargeMap = getRechargeMap(currentBillBelong, agentIdSet);
BigDecimal totalRecharge = rechargeMap.values().stream()
.reduce(BigDecimal.ZERO, BigDecimal::add);
co.setTeamRechargeAmount(totalRecharge);
return co;
}
/**
* 创建空结果.
*/
private TeamBdMemberCO createEmptyResult() {
Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong();
TeamBdMemberCO result = new TeamBdMemberCO();
result.setMemberBillList(Collections.emptyList());
result.setTotalSalary(BigDecimal.ZERO);
result.setTotalRecharge(BigDecimal.ZERO);
result.setBillTitle(TeamBillCycleUtils.parseBillBelongToDateRangeStr(currentBillBelong));
// 空结果也要计算 BD 工资信息全部为0
BdHistoryCO bdHistoryCO = calculateCurrentBdBill(currentBillBelong,
0, BigDecimal.ZERO, BigDecimal.ZERO);
result.setBdHistoryCO(bdHistoryCO);
return result;
}
@NotNull
@ -236,4 +405,59 @@ public class TeamBdMemberBillListQryExe {
return co;
}
/**
* 计算当前未结算的 BD 账单信息.
*
* @param billBelong 账单周期
* @param agencyNumber Agent 数量
* @param teamSalaryAmount 团队工资总额
* @param teamRechargeAmount 团队充值总额
* @return BD 历史账单 CO
*/
private BdHistoryCO calculateCurrentBdBill(Integer billBelong,
Integer agencyNumber,
BigDecimal teamSalaryAmount,
BigDecimal teamRechargeAmount) {
String billTitle = TeamBillCycleUtils.parseBillBelongToDateRangeStr(billBelong);
BdHistoryCO currentBill = new BdHistoryCO();
currentBill.setBillTitle(billTitle);
currentBill.setBillBelong(billBelong);
currentBill.setAgencyNumber(agencyNumber);
currentBill.setTeamSalaryAmount(teamSalaryAmount);
currentBill.setTeamRechargeAmount(teamRechargeAmount);
currentBill.setStatus(BdSettlementStatus.PENDING.name());
currentBill.setStatusText("In Progress");
// 创建临时结算记录用于政策匹配
BdSalarySettlementRecord tempRecord = new BdSalarySettlementRecord();
// 获取所有启用的政策
List<BdSalaryPolicy> salaryPolicies = bdSalaryPolicyService.listEnabledByType(BdPolicyType.TEAM_SALARY);
List<BdSalaryPolicy> rechargePolicies = bdSalaryPolicyService.listEnabledByType(BdPolicyType.TEAM_RECHARGE);
// 匹配政策1Team Salary Policy
BigDecimal salarySalary = BdSalarySettlementServiceImpl.matchAndCalculate(
salaryPolicies, agencyNumber, teamSalaryAmount, BdPolicyType.TEAM_SALARY, tempRecord);
// 匹配政策2Team Recharge Policy
BigDecimal rechargeSalary = BdSalarySettlementServiceImpl.matchAndCalculate(
rechargePolicies, agencyNumber, teamRechargeAmount, BdPolicyType.TEAM_RECHARGE, tempRecord);
// 选择最高工资并设置相关字段
if (salarySalary.compareTo(rechargeSalary) >= 0) {
currentBill.setHitPolicyType(BdPolicyType.TEAM_SALARY.name());
currentBill.setSettlementSalary(salarySalary);
} else {
currentBill.setHitPolicyType(BdPolicyType.TEAM_RECHARGE.name());
currentBill.setSettlementSalary(rechargeSalary);
}
// 设置命中的政策等级和提成比例
currentBill.setHitLevel(tempRecord.getHitLevel());
currentBill.setCommissionRate(tempRecord.getCommissionRate());
return currentBill;
}
}

View File

@ -405,7 +405,7 @@ public class BdSalarySettlementServiceImpl implements BdSalarySettlementService
/**
* 匹配政策并计算工资.
*/
private BigDecimal matchAndCalculate(List<BdSalaryPolicy> policies, Integer agencyNumber,
public static BigDecimal matchAndCalculate(List<BdSalaryPolicy> policies, Integer agencyNumber,
BigDecimal teamAmount, BdPolicyType policyType,
BdSalarySettlementRecord record) {
if (CollectionUtils.isEmpty(policies)) {

View File

@ -1,5 +1,6 @@
package com.red.circle.other.app.dto.clientobject;
import com.red.circle.other.app.dto.clientobject.team.BdHistoryCO;
import lombok.Data;
import java.math.BigDecimal;
@ -16,4 +17,6 @@ public class TeamBdMemberCO {
private List<TeamBdMemberBillCO> memberBillList;
private BdHistoryCO bdHistoryCO;
}