diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/bd/query/TeamBdMemberBillListQryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/bd/query/TeamBdMemberBillListQryExe.java index 36bb7dbb..7d6b6389 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/bd/query/TeamBdMemberBillListQryExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/bd/query/TeamBdMemberBillListQryExe.java @@ -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 bdTeamList = new ArrayList<>(); - - if ("BD".equals(cmd.getType())) { - bdTeamList.addAll(businessDevelopmentTeamService.listByUserId(cmd.getReqUserId())); - } else { - List baseInfos = businessDevelopmentBaseInfoService.listBdByLeadUserId(cmd.getReqUserId()); - - - Set bdIdSet = baseInfos.stream() - .map(BusinessDevelopmentBaseInfo::getUserId) - .collect(Collectors.toSet()); - Map userProfileMap = userProfileAppConvertor.toMapUserProfileDTO( - userProfileGateway.mapByUserIds(bdIdSet)); - - List 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 bdTeamList = businessDevelopmentTeamService.listByUserId(bdUserId); + + if (CollectionUtils.isEmpty(bdTeamList)) { + return createEmptyResult(); + } + + // 2. 获取当前账单周期 + Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong(); + + // 3. 获取团队ID集合 Set teamIdSet = bdTeamList.stream() .map(BusinessDevelopmentTeam::getTeamId) .collect(Collectors.toSet()); - - // 3. 获取当前账单周期 billBelong - Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong(); // 4. 查询当前周期的账单 Map billCycleMap = teamBillCycleService.mapByTeamIds2( - teamIdSet, currentBillBelong, TeamBillCycleStatus.SETTLED); + teamIdSet, currentBillBelong, TeamBillCycleStatus.UNPAID); - // 5. 获取团队Profile信息(包含团队人数) + // 5. 获取团队Profile信息 Map teamProfileMap = teamProfileService.mapProfileByIds(teamIdSet); // 6. 获取代理用户信息 @@ -135,19 +134,189 @@ public class TeamBdMemberBillListQryExe { Map userProfileMap = userProfileAppConvertor.toMapUserProfileDTO( userProfileGateway.mapByUserIds(agentIdSet)); + // 7. 查询充值数据 Map rechargeMap = getRechargeMap(currentBillBelong, agentIdSet); - // 7. 组装返回结果 - List collect = bdTeamList.stream() - .map(bdTeam -> buildMemberBillCO(bdTeam, billCycleMap, teamProfileMap, userProfileMap,rechargeMap, currentBillBelong)) - .collect(Collectors.toList()); + // 8. 组装成员账单列表(每个 Agent 团队一条) + List 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 bdList = + businessDevelopmentBaseInfoService.listBdByLeadUserId(bdLeaderUserId); + + if (CollectionUtils.isEmpty(bdList)) { + return createEmptyResult(); + } + + // 2. 获取当前账单周期 + Integer currentBillBelong = TeamBillCycleUtils.getCalcBillBelong(); + + // 3. 收集所有 BD 的用户ID + Set bdUserIdSet = bdList.stream() + .map(BusinessDevelopmentBaseInfo::getUserId) + .collect(Collectors.toSet()); + + // 4. 批量查询所有 BD 的用户信息 + Map bdUserProfileMap = userProfileAppConvertor.toMapUserProfileDTO( + userProfileGateway.mapByUserIds(bdUserIdSet)); + + // 5. 为每个 BD 构建汇总数据 + List 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 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 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 teamIdSet = bdTeamList.stream() + .map(BusinessDevelopmentTeam::getTeamId) + .collect(Collectors.toSet()); + + // 6. 查询账单数据 + Map 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 agentIdSet = bdTeamList.stream() + .map(BusinessDevelopmentTeam::getAgentId) + .collect(Collectors.toSet()); + + // 9. 查询充值数据并汇总 + Map 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 salaryPolicies = bdSalaryPolicyService.listEnabledByType(BdPolicyType.TEAM_SALARY); + List rechargePolicies = bdSalaryPolicyService.listEnabledByType(BdPolicyType.TEAM_RECHARGE); + + // 匹配政策1:Team Salary Policy + BigDecimal salarySalary = BdSalarySettlementServiceImpl.matchAndCalculate( + salaryPolicies, agencyNumber, teamSalaryAmount, BdPolicyType.TEAM_SALARY, tempRecord); + + // 匹配政策2:Team 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; + } } diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/BdSalarySettlementServiceImpl.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/BdSalarySettlementServiceImpl.java index 91bb629f..98577041 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/BdSalarySettlementServiceImpl.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/BdSalarySettlementServiceImpl.java @@ -405,7 +405,7 @@ public class BdSalarySettlementServiceImpl implements BdSalarySettlementService /** * 匹配政策并计算工资. */ - private BigDecimal matchAndCalculate(List policies, Integer agencyNumber, + public static BigDecimal matchAndCalculate(List policies, Integer agencyNumber, BigDecimal teamAmount, BdPolicyType policyType, BdSalarySettlementRecord record) { if (CollectionUtils.isEmpty(policies)) { diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/TeamBdMemberCO.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/TeamBdMemberCO.java index 2043468f..1163fad6 100644 --- a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/TeamBdMemberCO.java +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/TeamBdMemberCO.java @@ -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 memberBillList; + private BdHistoryCO bdHistoryCO; + }