BD 工资总和问题修复

This commit is contained in:
tianfeng 2025-10-16 17:42:37 +08:00
parent dc3ab5b923
commit e985a1305a
13 changed files with 181 additions and 166 deletions

View File

@ -70,4 +70,14 @@ public interface UserBankRunningWaterClientApi {
@PostMapping("/approvalMoneyApply")
ResultResponse<Void> approvalMoneyApply(@RequestBody UserBankApprovalMoneyApplyCmd apply);
/**
* 月用户工资流水
*/
@PostMapping("/getMonthSalaryRunningWater")
ResultResponse<List<UserBankRunningWaterDTO>> getMonthSalaryRunningWater(
@RequestParam("userIds") List<Long> userIds,
@RequestParam("event") String event,
@RequestParam("month") String month);
}

View File

@ -1,17 +1,28 @@
package com.red.circle.other.app.command.team.query;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.other.app.dto.clientobject.team.BdAgentCountCO;
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.service.team.team.TeamBillCycleService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberTargetService;
import com.red.circle.other.infra.database.rds.entity.team.BusinessDevelopmentTeam;
import com.red.circle.other.infra.database.rds.service.team.BusinessDevelopmentTeamService;
import com.red.circle.other.inner.enums.team.TeamBillCycleStatus;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.num.NumUtils;
import com.red.circle.other.app.util.BdSalaryPolicyUtils;
import java.util.List;
import java.util.Optional;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import com.red.circle.wallet.inner.endpoint.bank.UserBankRunningWaterClient;
import com.red.circle.wallet.inner.model.dto.UserBankRunningWaterDTO;
import com.red.circle.wallet.inner.model.enums.UserBankWaterEvent;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@ -26,20 +37,25 @@ public class BdAgentCountQryExe {
private final TeamMemberTargetService teamMemberTargetService;
private final BusinessDevelopmentTeamService businessDevelopmentTeamService;
private final UserBankRunningWaterClient userBankRunningWaterClient;
private final TeamBillCycleService teamBillCycleService;
public BdAgentCountCO execute(AppExtCommand cmd) {
// TODO 临时方案
List<Long> teamIds = Optional.ofNullable(businessDevelopmentTeamService.query()
.select(BusinessDevelopmentTeam::getTeamId)
.eq(BusinessDevelopmentTeam::getUserId, cmd.requireReqSysOriginEnum())
.eq(BusinessDevelopmentTeam::getUserId, cmd.requiredReqUserId())
.last(PageConstant.MAX_LIMIT)
.list())
.map(teams -> teams.stream().map(BusinessDevelopmentTeam::getTeamId)
.collect(Collectors.toList()))
.orElseGet(CollectionUtils::newArrayList);
Long target = teamMemberTargetService.countThisMonthTeamMemberTarget(teamIds);
Map<Long, TeamBillCycle> longTeamBillCycleMap = teamBillCycleService.mapByTeamIds(new HashSet<>(teamIds), ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt(), TeamBillCycleStatus.SETTLED);
BigDecimal target = longTeamBillCycleMap.values().stream().map(value -> Optional.ofNullable(value.getSettleResult())
.map(TeamBillSettleResult::getTotalSalary)
.orElse(BigDecimal.ZERO)).reduce(BigDecimal.ZERO, BigDecimal::add);
Long agentQuantity = businessDevelopmentTeamService.countTeamByBdUserId(cmd.requiredReqUserId());
// 计算BD薪资等级
@ -48,7 +64,7 @@ public class BdAgentCountQryExe {
return new BdAgentCountCO()
.setAgentQuantity(agentQuantity)
.setThisMonthTotalTarget(target)
.setThisMonthTotalTargetFormat(NumUtils.formatLong(target))
.setThisMonthTotalTargetFormat(NumUtils.formatBigDecimal(target))
.setBdLevel(salaryResult.getLevel())
.setForeverPercentage(salaryResult.getForeverPercentage())
.setQualified(salaryResult.getQualified())
@ -60,14 +76,23 @@ public class BdAgentCountQryExe {
public BdAgentCountCO executeLastMonth(AppExtCommand cmd) {
List<Long> teamIds = Optional.ofNullable(businessDevelopmentTeamService.query()
.select(BusinessDevelopmentTeam::getTeamId)
.eq(BusinessDevelopmentTeam::getUserId, cmd.requireReqSysOriginEnum())
.eq(BusinessDevelopmentTeam::getUserId, cmd.requiredReqUserId())
.last(PageConstant.MAX_LIMIT)
.list())
.map(teams -> teams.stream().map(BusinessDevelopmentTeam::getTeamId)
.collect(Collectors.toList()))
.orElseGet(CollectionUtils::newArrayList);
Long target = teamMemberTargetService.countLastMonthTeamMemberTarget(teamIds);
List<TeamBillCycle> teamBillCycles = teamBillCycleService.listLastMonthByTeamIds(new HashSet<>(teamIds));
BigDecimal target = teamBillCycles.stream().map(e -> {
BigDecimal totalSalary = BigDecimal.ZERO;
TeamBillSettleResult settleResult = e.getSettleResult();
if (settleResult != null) {
totalSalary = totalSalary.add(Optional.ofNullable(settleResult.getTotalSalary()).orElse(BigDecimal.ZERO));
}
return totalSalary;
}).reduce(BigDecimal.ZERO, BigDecimal::add);
Long agentQuantity = businessDevelopmentTeamService.countTeamByBdUserId(cmd.requiredReqUserId());
// 计算BD薪资等级
@ -76,7 +101,7 @@ public class BdAgentCountQryExe {
return new BdAgentCountCO()
.setAgentQuantity(agentQuantity)
.setThisMonthTotalTarget(target)
.setThisMonthTotalTargetFormat(NumUtils.formatLong(target))
.setThisMonthTotalTargetFormat(NumUtils.formatBigDecimal(target))
.setBdLevel(salaryResult.getLevel())
.setForeverPercentage(salaryResult.getForeverPercentage())
.setQualified(salaryResult.getQualified())

View File

@ -20,10 +20,7 @@ import com.red.circle.tool.core.date.DateFormatConstant;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@ -58,7 +55,8 @@ public class BdTeamAgentListQryExe {
return CollectionUtils.newArrayList();
}
Map<Long, TeamBillCycle> billCycleMap = getBillCycleMap(pageTeam);
Set<Long> teamIdSet = pageTeam.stream().map(BusinessDevelopmentTeam::getTeamId).collect(Collectors.toSet());
Map<Long, TeamBillCycle> billCycleMap = getBillCycleMap(teamIdSet, ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt());
Map<Long, TeamProfile> teamProfileMap = getTeamProfileMap(pageTeam);
Map<Long, UserProfileDTO> teamUserProfileMap = getTeamUserProfileMap(pageTeam);
Map<Long, TeamBillCycle> lastMonthBillCycleMap = getLastMonthBillCycleMap(pageTeam);
@ -72,7 +70,7 @@ public class BdTeamAgentListQryExe {
return pageTeam.stream().map(team -> {
TeamBillCycle billCycle = billCycleMap.get(team.getTeamId());
TeamBillCycle billCycle = billCycleMap.getOrDefault(team.getTeamId(), new TeamBillCycle());
TeamProfile teamProfile = teamProfileMap.get(team.getTeamId());
return new TeamDbAgentMemberCO()
@ -129,10 +127,8 @@ public class BdTeamAgentListQryExe {
pageTeam.stream().map(BusinessDevelopmentTeam::getTeamId).collect(Collectors.toSet()));
}
private Map<Long, TeamBillCycle> getBillCycleMap(List<BusinessDevelopmentTeam> pageTeam) {
return teamBillCycleService
.mapByTeamIds(pageTeam.stream().map(BusinessDevelopmentTeam::getTeamId).collect(
Collectors.toSet()), TeamBillCycleStatus.UNPAID);
private Map<Long, TeamBillCycle> getBillCycleMap(Set<Long> teamIdSet, Integer billBelong) {
return teamBillCycleService.mapByTeamIds(teamIdSet, billBelong, TeamBillCycleStatus.SETTLED);
}
private List<BusinessDevelopmentTeam> listByUserId(AppFlowCmd cmd) {

View File

@ -4,6 +4,8 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
import java.math.BigDecimal;
/**
* BD薪资政策工具类.
*
@ -76,7 +78,7 @@ public class BdSalaryPolicyUtils {
* @param teamSalary 团队薪资
* @return BD薪资结果
*/
public static BdSalaryResult calculateBdSalaryLevel(Long agentQuantity, Long teamSalary) {
public static BdSalaryResult calculateBdSalaryLevel(Long agentQuantity, BigDecimal teamSalary) {
if (agentQuantity == null || teamSalary == null) {
return new BdSalaryResult(null, null, false, null, null);
}
@ -139,7 +141,7 @@ public class BdSalaryPolicyUtils {
* @param currentTeamSalary 当前团队薪资
* @return 下一个等级的要求如果已经是最高等级则返回null
*/
public static BdSalaryResult getNextLevelRequirement(Long currentAgentQuantity, Long currentTeamSalary) {
public static BdSalaryResult getNextLevelRequirement(Long currentAgentQuantity, BigDecimal currentTeamSalary) {
if (currentAgentQuantity == null || currentTeamSalary == null) {
return getBdSalaryLevelInfo(1);
}

View File

@ -7,6 +7,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
/**
* 代理.
*
@ -27,7 +29,7 @@ public class BdAgentCountCO extends ClientObject {
* 本月总目标.
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long thisMonthTotalTarget;
private BigDecimal thisMonthTotalTarget;
/**
* 本月总目标 格式化.

View File

@ -20,7 +20,7 @@ public interface TeamBillCycleService {
/**
* 获取一组账单信息.
*/
Map<Long, TeamBillCycle> mapByTeamIds(Set<Long> teamIds, TeamBillCycleStatus status);
Map<Long, TeamBillCycle> mapByTeamIds(Set<Long> teamIds, Integer billBelong, TeamBillCycleStatus status);
/**
* 获取一组账单信息.

View File

@ -6,6 +6,7 @@ import com.mongodb.BasicDBObject;
import com.mongodb.client.model.Filters;
import com.red.circle.component.mongodb.config.MongoPrimaryService;
import com.red.circle.framework.mybatis.constant.PageConstant;
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.service.team.team.TeamBillCycleService;
import com.red.circle.other.inner.model.cmd.team.TeamBillCmd;
@ -19,6 +20,7 @@ import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
@ -27,6 +29,7 @@ import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
@ -49,14 +52,16 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
private final MongoPrimaryService mongoPrimaryService;
@Override
public Map<Long, TeamBillCycle> mapByTeamIds(Set<Long> teamIds, TeamBillCycleStatus status) {
public Map<Long, TeamBillCycle> mapByTeamIds(Set<Long> teamIds, Integer billBelong, TeamBillCycleStatus status) {
if (CollectionUtils.isEmpty(teamIds) || Objects.isNull(status)) {
return Maps.newHashMap();
}
Criteria criteria = getBillBelongCriteria(ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt());
List<TeamBillCycle> teamBillCycles = mongoTemplate.find(
Query.query(Criteria.where("teamId").in(teamIds).and("status").is(status)),
Query.query(criteria.and("teamId").in(teamIds).and("status").is(status)),
TeamBillCycle.class);
if (CollectionUtils.isEmpty(teamBillCycles)) {
@ -64,7 +69,37 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
}
return teamBillCycles.stream()
.collect(Collectors.toMap(TeamBillCycle::getTeamId, v -> v));
.collect(Collectors.toMap(
TeamBillCycle::getTeamId,
v -> v,
(v1, v2) -> {
// 当teamId重复时累加settleResult中的totalSalary
BigDecimal totalSalary1 = BigDecimal.ZERO;
BigDecimal totalSalary2 = BigDecimal.ZERO;
// 获取v1的totalSalary
if (v1.getSettleResult() != null && v1.getSettleResult().getTotalSalary() != null) {
totalSalary1 = v1.getSettleResult().getTotalSalary();
}
// 获取v2的totalSalary
if (v2.getSettleResult() != null && v2.getSettleResult().getTotalSalary() != null) {
totalSalary2 = v2.getSettleResult().getTotalSalary();
}
// 累加totalSalary
BigDecimal sumTotalSalary = totalSalary1.add(totalSalary2);
// 确保v1有settleResult对象
if (v1.getSettleResult() == null) {
v1.setSettleResult(new TeamBillSettleResult());
}
// 设置累加后的totalSalary
v1.getSettleResult().setTotalSalary(sumTotalSalary);
return v1;
}
));
}
@Override
@ -90,21 +125,7 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
return Maps.newHashMap();
}
int lastMonthYYYYMM = Integer.parseInt(
ZonedDateTimeAsiaRiyadhUtils.now().minusMonths(1)
.format(DateTimeFormatter.ofPattern(DateFormatConstant.yyyyMM)));
// 计算8位格式的范围yyyyMM01 yyyyMM31
int rangeStart = lastMonthYYYYMM * 100; // 例如202509 * 100 = 20250900
int rangeEnd = lastMonthYYYYMM * 100 + 99; // 例如202509 * 100 + 99 = 20250999
// 匹配条件
// 1. billBelong = 202509 (6位旧格式)
// 2. billBelong 20250901 20250999 之间 (8位新格式)
Criteria criteria = new Criteria().orOperator(
Criteria.where("billBelong").is(lastMonthYYYYMM),
Criteria.where("billBelong").gte(rangeStart).lte(rangeEnd)
);
Criteria criteria = getBillBelongCriteria(getLastMonth());
List<TeamBillCycle> teamBillCycles = mongoTemplate.find(
Query.query(criteria
@ -120,6 +141,30 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
.collect(Collectors.toMap(TeamBillCycle::getTeamId, v -> v));
}
private static int getLastMonth() {
return Integer.parseInt(
ZonedDateTimeAsiaRiyadhUtils.now().minusMonths(1)
.format(DateTimeFormatter.ofPattern(DateFormatConstant.yyyyMM)));
}
@NotNull
private static Criteria getBillBelongCriteria(int yyyyMM) {
int lastMonthYYYYMM = yyyyMM;
// 计算8位格式的范围yyyyMM01 yyyyMM31
int rangeStart = lastMonthYYYYMM * 100; // 例如202509 * 100 = 20250900
int rangeEnd = lastMonthYYYYMM * 100 + 99; // 例如202509 * 100 + 99 = 20250999
// 匹配条件
// 1. billBelong = 202509 (6位旧格式)
// 2. billBelong 20250901 20250999 之间 (8位新格式)
Criteria criteria = new Criteria().orOperator(
Criteria.where("billBelong").is(lastMonthYYYYMM),
Criteria.where("billBelong").gte(rangeStart).lte(rangeEnd)
);
return criteria;
}
@Override
public void createIfAbsent(TeamBillCmd param) {
@ -145,19 +190,7 @@ public class TeamBillCycleServiceImpl implements TeamBillCycleService {
@Override
public List<TeamBillCycle> listLastMonthByTeamIds(Set<Long> teamIds) {
int currentYearMonth = ZonedDateTimeAsiaRiyadhUtils.nowYearMonthToInt();
// 计算8位格式的范围yyyyMM01 yyyyMM99
int rangeStart = currentYearMonth * 100; // 例如202510 * 100 = 20251000
int rangeEnd = currentYearMonth * 100 + 99; // 例如202510 * 100 + 99 = 20251099
// 匹配条件
// 1. billBelong = 202510 (6位旧格式)
// 2. billBelong 20251001 20251099 之间 (8位新格式)
Criteria criteria = new Criteria().orOperator(
Criteria.where("billBelong").is(currentYearMonth),
Criteria.where("billBelong").gte(rangeStart).lte(rangeEnd)
);
Criteria criteria = getBillBelongCriteria(getLastMonth());
return mongoTemplate.find(
Query.query(criteria

View File

@ -1,111 +0,0 @@
import com.red.circle.other.app.util.BdSalaryPolicyUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Assertions;
/**
* BD薪资政策工具类测试.
*
* @author system
*/
public class BdSalaryPolicyUtilsTest {
@Test
public void testCalculateBdSalaryLevel() {
// 测试等级1 - 3个代理$50团队薪资1%
BdSalaryPolicyUtils.BdSalaryResult result1 = BdSalaryPolicyUtils.calculateBdSalaryLevel(3L, 50L);
Assertions.assertEquals(1, result1.getLevel());
Assertions.assertEquals(1, result1.getForeverPercentage());
Assertions.assertTrue(result1.getQualified());
// 测试等级2 - 5个代理$500团队薪资2%
BdSalaryPolicyUtils.BdSalaryResult result2 = BdSalaryPolicyUtils.calculateBdSalaryLevel(5L, 500L);
Assertions.assertEquals(2, result2.getLevel());
Assertions.assertEquals(2, result2.getForeverPercentage());
Assertions.assertTrue(result2.getQualified());
// 测试等级3 - 7个代理$1000团队薪资3%
BdSalaryPolicyUtils.BdSalaryResult result3 = BdSalaryPolicyUtils.calculateBdSalaryLevel(7L, 1000L);
Assertions.assertEquals(3, result3.getLevel());
Assertions.assertEquals(3, result3.getForeverPercentage());
Assertions.assertTrue(result3.getQualified());
// 测试等级4 - 9个代理$3000团队薪资4%
BdSalaryPolicyUtils.BdSalaryResult result4 = BdSalaryPolicyUtils.calculateBdSalaryLevel(9L, 3000L);
Assertions.assertEquals(4, result4.getLevel());
Assertions.assertEquals(4, result4.getForeverPercentage());
Assertions.assertTrue(result4.getQualified());
// 测试等级5 - 10个代理$5000团队薪资5%
BdSalaryPolicyUtils.BdSalaryResult result5 = BdSalaryPolicyUtils.calculateBdSalaryLevel(10L, 5000L);
Assertions.assertEquals(5, result5.getLevel());
Assertions.assertEquals(5, result5.getForeverPercentage());
Assertions.assertTrue(result5.getQualified());
// 测试不达标情况 - 代理数量不足
BdSalaryPolicyUtils.BdSalaryResult resultNotQualified1 = BdSalaryPolicyUtils.calculateBdSalaryLevel(2L, 100L);
Assertions.assertNull(resultNotQualified1.getLevel());
Assertions.assertNull(resultNotQualified1.getForeverPercentage());
Assertions.assertFalse(resultNotQualified1.getQualified());
// 测试不达标情况 - 团队薪资不足
BdSalaryPolicyUtils.BdSalaryResult resultNotQualified2 = BdSalaryPolicyUtils.calculateBdSalaryLevel(5L, 30L);
Assertions.assertNull(resultNotQualified2.getLevel());
Assertions.assertNull(resultNotQualified2.getForeverPercentage());
Assertions.assertFalse(resultNotQualified2.getQualified());
// 测试边界情况 - 刚好达到等级3的要求
BdSalaryPolicyUtils.BdSalaryResult resultBoundary = BdSalaryPolicyUtils.calculateBdSalaryLevel(7L, 1000L);
Assertions.assertEquals(3, resultBoundary.getLevel());
Assertions.assertTrue(resultBoundary.getQualified());
// 测试超过最高等级的情况
BdSalaryPolicyUtils.BdSalaryResult resultMax = BdSalaryPolicyUtils.calculateBdSalaryLevel(15L, 10000L);
Assertions.assertEquals(5, resultMax.getLevel());
Assertions.assertEquals(5, resultMax.getForeverPercentage());
Assertions.assertTrue(resultMax.getQualified());
}
@Test
public void testGetBdSalaryLevelInfo() {
BdSalaryPolicyUtils.BdSalaryResult levelInfo = BdSalaryPolicyUtils.getBdSalaryLevelInfo(3);
Assertions.assertEquals(3, levelInfo.getLevel());
Assertions.assertEquals(3, levelInfo.getForeverPercentage());
Assertions.assertEquals(7, levelInfo.getRequiredAgentNumber());
Assertions.assertEquals(1000, levelInfo.getRequiredTeamSalary());
// 测试不存在的等级
BdSalaryPolicyUtils.BdSalaryResult invalidLevel = BdSalaryPolicyUtils.getBdSalaryLevelInfo(10);
Assertions.assertNull(invalidLevel);
}
@Test
public void testGetNextLevelRequirement() {
// 测试当前等级1获取等级2的要求
BdSalaryPolicyUtils.BdSalaryResult nextLevel = BdSalaryPolicyUtils.getNextLevelRequirement(3L, 50L);
Assertions.assertEquals(2, nextLevel.getLevel());
Assertions.assertEquals(5, nextLevel.getRequiredAgentNumber());
Assertions.assertEquals(500, nextLevel.getRequiredTeamSalary());
// 测试当前没达到任何等级
BdSalaryPolicyUtils.BdSalaryResult firstLevel = BdSalaryPolicyUtils.getNextLevelRequirement(1L, 10L);
Assertions.assertEquals(1, firstLevel.getLevel());
// 测试已经是最高等级
BdSalaryPolicyUtils.BdSalaryResult maxLevel = BdSalaryPolicyUtils.getNextLevelRequirement(10L, 5000L);
Assertions.assertNull(maxLevel);
}
@Test
public void testNullInputs() {
BdSalaryPolicyUtils.BdSalaryResult nullResult = BdSalaryPolicyUtils.calculateBdSalaryLevel(null, null);
Assertions.assertNull(nullResult.getLevel());
Assertions.assertNull(nullResult.getForeverPercentage());
Assertions.assertFalse(nullResult.getQualified());
BdSalaryPolicyUtils.BdSalaryResult nullAgentResult = BdSalaryPolicyUtils.calculateBdSalaryLevel(null, 1000L);
Assertions.assertFalse(nullAgentResult.getQualified());
BdSalaryPolicyUtils.BdSalaryResult nullSalaryResult = BdSalaryPolicyUtils.calculateBdSalaryLevel(5L, null);
Assertions.assertFalse(nullSalaryResult.getQualified());
}
}

View File

@ -51,4 +51,14 @@ public interface UserBankRunningWaterService {
*/
String calculateTotal(UserBankRunningWaterQryCmd query);
/**
* 月用户工资流水.
*
* @param userIds 用户ID列表
* @param event 事件类型
* @param month 月份格式: yyyy-MM
* @return 流水记录列表
*/
List<UserBankRunningWater> getMonthSalaryRunningWater(List<Long> userIds, String event, String month);
}

View File

@ -7,6 +7,9 @@ import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.wallet.infra.database.mongo.entity.bank.UserBankRunningWater;
import com.red.circle.wallet.infra.database.mongo.service.bank.UserBankRunningWaterService;
import com.red.circle.wallet.inner.model.cmd.UserBankRunningWaterQryCmd;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@ -151,4 +154,33 @@ public class UserBankRunningWaterServiceImpl implements UserBankRunningWaterServ
}
@Override
public List<UserBankRunningWater> getMonthSalaryRunningWater(List<Long> userIds, String event, String month) {
// 解析月份参数 (yyyy-MM)
YearMonth yearMonth = YearMonth.parse(month, DateTimeFormatter.ofPattern("yyyyMM"));
LocalDate startDate = yearMonth.atDay(1);
LocalDate endDate = yearMonth.atEndOfMonth();
// 转换为Timestamp
java.sql.Timestamp startTime = java.sql.Timestamp.valueOf(startDate.atStartOfDay());
java.sql.Timestamp endTime = java.sql.Timestamp.valueOf(endDate.atTime(23, 59, 59));
// 构建查询条件
Criteria criteria = new Criteria();
criteria.and("userId").in(userIds);
// 使用正则表达式匹配以event开头的所有事件类型
// 例如: SYSTEM_SETTLEMENT_WAGES 可以匹配 SYSTEM_SETTLEMENT_WAGES_AGENT, SYSTEM_SETTLEMENT_WAGES_MEMBER
criteria.and("event").regex("^" + event);
criteria.andOperator(
Criteria.where("createTime").gte(startTime),
Criteria.where("createTime").lte(endTime)
);
// 执行查询
Query query = Query.query(criteria)
.with(Sort.by(Sort.Order.desc("createTime")));
return mongoTemplate.find(query, UserBankRunningWater.class);
}
}

View File

@ -93,4 +93,9 @@ public class UserBankRunningWaterClientEndpoint implements UserBankRunningWaterC
return ResultResponse.success();
}
@Override
public ResultResponse<List<UserBankRunningWaterDTO>> getMonthSalaryRunningWater(List<Long> userIds, String event, String month) {
return ResultResponse.success(userBankRunningWaterClientService.getMonthSalaryRunningWater(userIds, event, month));
}
}

View File

@ -67,4 +67,9 @@ public interface UserBankRunningWaterClientService {
* 审核申请记录.
*/
void approvalMoneyApply(UserBankApprovalMoneyApplyCmd apply);
/**
* 月用户工资流水.
*/
List<UserBankRunningWaterDTO> getMonthSalaryRunningWater(List<Long> userIds, String event, String month);
}

View File

@ -88,4 +88,10 @@ public class UserBankRunningWaterClientServiceImpl implements UserBankRunningWat
bankWithdrawMoneyApplyService.approvalMoneyApply(apply);
}
@Override
public List<UserBankRunningWaterDTO> getMonthSalaryRunningWater(List<Long> userIds, String event, String month) {
return userBankInnerConvertor.toListUserBankRunningWaterDTO(
userBankRunningWaterService.getMonthSalaryRunningWater(userIds, event, month));
}
}