bd bdleader admin 发放工资增加幂等校验

This commit is contained in:
tianfeng 2026-01-04 15:11:12 +08:00
parent 39c7b45b4b
commit 0b0e859fcc
11 changed files with 106 additions and 15 deletions

View File

@ -8,10 +8,7 @@ import com.red.circle.wallet.inner.model.cmd.SalaryWithdrawInnerCmd;
import com.red.circle.wallet.inner.model.dto.SalaryAccountBalanceDTO;
import com.red.circle.wallet.inner.model.dto.SalaryIssueResultDTO;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
@ -47,6 +44,12 @@ public interface UserSalaryAccountClientApi {
ResultResponse<PageResult<SalaryRunningWaterDTO>> queryRunningWater(
@RequestBody SalaryRunningWaterQueryInnerCmd cmd);
/**
* 是否存在记录
*/
@PostMapping("/exist")
ResultResponse<SalaryRunningWaterDTO> existRunningWater(@RequestParam("trackId") String trackId);
/**
* 查询用户累计收入.
*/

View File

@ -26,6 +26,11 @@ public class SalaryRunningWaterQueryInnerCmd implements Serializable {
*/
private Integer type;
/**
* 跟踪ID
*/
private String trackId;
/**
* 账单归属YYYYMM.
*/

View File

@ -1,9 +1,9 @@
package com.red.circle.other.app.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.app.command.bd.query.BdTeamSummaryQryExe;
import com.red.circle.other.app.dto.clientobject.AdminSalarySettlementCO;
import com.red.circle.other.app.dto.clientobject.BdTeamSummaryCO;
@ -15,7 +15,6 @@ import com.red.circle.other.infra.database.mongo.entity.bd.BdSalarySettlementRec
import com.red.circle.other.infra.database.mongo.service.bd.AdminSalaryPolicyService;
import com.red.circle.other.infra.database.mongo.service.bd.AdminSalarySettlementRecordService;
import com.red.circle.other.infra.database.mongo.service.bd.BdSalarySettlementRecordService;
import com.red.circle.other.infra.database.rds.dao.sys.AdministratorDAO;
import com.red.circle.other.infra.database.rds.entity.sys.Administrator;
import com.red.circle.other.infra.database.rds.service.sys.AdministratorService;
import com.red.circle.other.infra.enums.AdminPolicyType;
@ -24,6 +23,8 @@ import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.wallet.inner.endpoint.salary.UserSalaryAccountClient;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
import com.red.circle.wallet.inner.model.enums.SalaryEvent;
import com.red.circle.wallet.inner.model.enums.SalaryType;
import lombok.RequiredArgsConstructor;
@ -33,7 +34,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.List;
/**
@ -150,7 +150,7 @@ public class AdminSalarySettlementServiceImpl implements AdminSalarySettlementSe
if (record.getTotalSalary().compareTo(BigDecimal.ZERO) > 0) {
try {
issueSalary(adminUserId, record);
log.info("管理员 {} 工资发放成功,金额:{} USD", adminUserId, record.getTotalSalary());
} catch (Exception e) {
log.error("管理员 {} 工资发放失败", adminUserId, e);
adminSalarySettlementRecordService.updateStatus(record.getId(), BdSettlementStatus.FAILED, e.getMessage());
@ -377,6 +377,13 @@ public class AdminSalarySettlementServiceImpl implements AdminSalarySettlementSe
* 发放工资到工资账户.
*/
private void issueSalary(Long adminUserId, AdminSalarySettlementRecord record) {
String bizNo = record.getBizNo();
SalaryRunningWaterDTO runningWaterDTO = userSalaryAccountClient.existRunningWater(bizNo).getBody();
if (runningWaterDTO != null) {
return;
}
SalaryIssueInnerCmd innerCmd = new SalaryIssueInnerCmd();
innerCmd.setBillBelong(record.getBillBelong());
innerCmd.setUserId(adminUserId);
@ -384,9 +391,11 @@ public class AdminSalarySettlementServiceImpl implements AdminSalarySettlementSe
innerCmd.setSalaryType(SalaryType.ADMIN_SALARY.getCode());
innerCmd.setEventDesc(SalaryEvent.SALARY_ADMIN.getCode());
innerCmd.setAmount(record.getTotalSalary());
innerCmd.setTrackId(record.getId());
innerCmd.setTrackId(bizNo);
innerCmd.setBdId(adminUserId);
userSalaryAccountClient.issueSalary(innerCmd);
log.info("管理员 {} 工资发放成功,金额:{} USD", adminUserId, record.getTotalSalary());
}
/**

View File

@ -22,6 +22,7 @@ import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.wallet.inner.endpoint.bank.UserBankBalanceClient;
import com.red.circle.wallet.inner.endpoint.salary.UserSalaryAccountClient;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
import com.red.circle.wallet.inner.model.enums.SalaryType;
import com.red.circle.wallet.inner.model.enums.SalaryEvent;
import lombok.RequiredArgsConstructor;
@ -193,7 +194,6 @@ public class BdLeaderSalarySettlementServiceImpl implements BdLeaderSalarySettle
// 调用钱包服务发放工资
issueSalary(bdLeaderUserId, record);
log.info("BD Leader {} 工资发放成功,金额:{} USD", bdLeaderUserId, record.getSettlementSalary());
} catch (Exception e) {
log.error("BD Leader {} 工资发放失败", bdLeaderUserId, e);
bdLeaderSalarySettlementRecordService.updateStatus(record.getId(), BdSettlementStatus.FAILED, e.getMessage());
@ -270,6 +270,13 @@ public class BdLeaderSalarySettlementServiceImpl implements BdLeaderSalarySettle
* 发放工资到美元账户.
*/
private void issueSalary(Long bdLeaderUserId, BdLeaderSalarySettlementRecord record) {
String bizNo = record.getBizNo();
SalaryRunningWaterDTO runningWaterDTO = userSalaryAccountClient.existRunningWater(bizNo).getBody();
if (runningWaterDTO != null) {
return;
}
SalaryIssueInnerCmd innerCmd = new SalaryIssueInnerCmd();
innerCmd.setBillBelong(record.getBillBelong());
innerCmd.setUserId(bdLeaderUserId);
@ -277,9 +284,11 @@ public class BdLeaderSalarySettlementServiceImpl implements BdLeaderSalarySettle
innerCmd.setSalaryType(SalaryType.BD_LEADER_SALARY.getCode());
innerCmd.setEventDesc(SalaryEvent.SALARY_BD_LEADER.getCode());
innerCmd.setAmount(record.getSettlementSalary());
innerCmd.setTrackId(record.getId());
innerCmd.setTrackId(record.getBizNo());
innerCmd.setBdId(bdLeaderUserId);
userSalaryAccountClient.issueSalary(innerCmd);
log.info("BD Leader {} 工资发放成功,金额:{} USD", bdLeaderUserId, record.getSettlementSalary());
}
/**

View File

@ -3,6 +3,7 @@ package com.red.circle.other.app.service;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.red.circle.common.business.core.enums.ReceiptType;
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.app.dto.clientobject.BdSalarySettlementCO;
import com.red.circle.other.app.dto.clientobject.BdTeamStatisticsCO;
@ -33,7 +34,9 @@ import com.red.circle.wallet.inner.endpoint.bank.UserBankBalanceClient;
import com.red.circle.wallet.inner.endpoint.bank.UserBankRunningWaterClient;
import com.red.circle.wallet.inner.endpoint.salary.UserSalaryAccountClient;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
import com.red.circle.wallet.inner.model.cmd.UserBankBalanceIncrCmd;
import com.red.circle.wallet.inner.model.dto.SalaryRunningWaterDTO;
import com.red.circle.wallet.inner.model.dto.UserBankRunningWaterDTO;
import com.red.circle.wallet.inner.model.enums.SalaryEvent;
import com.red.circle.wallet.inner.model.enums.SalaryType;
@ -149,8 +152,7 @@ public class BdSalarySettlementServiceImpl implements BdSalarySettlementService
try {
// 调用钱包服务发放工资
issueSalary(bdUserId, record);
log.info("BD {} 工资发放成功,金额:{} USD", bdUserId, record.getSettlementSalary());
} catch (Exception e) {
log.error("BD {} 工资发放失败", bdUserId, e);
bdSalarySettlementRecordService.updateStatus(record.getId(), BdSettlementStatus.FAILED, e.getMessage());
@ -455,6 +457,13 @@ public class BdSalarySettlementServiceImpl implements BdSalarySettlementService
* 发放工资到美元账户.
*/
private void issueSalary(Long bdUserId, BdSalarySettlementRecord record) {
String bizNo = record.getBizNo();
SalaryRunningWaterDTO runningWaterDTO = userSalaryAccountClient.existRunningWater(bizNo).getBody();
if (runningWaterDTO != null) {
return;
}
SalaryIssueInnerCmd innerCmd = new SalaryIssueInnerCmd();
innerCmd.setBillBelong(record.getBillBelong());
innerCmd.setUserId(bdUserId);
@ -462,9 +471,11 @@ public class BdSalarySettlementServiceImpl implements BdSalarySettlementService
innerCmd.setSalaryType(SalaryType.BD_SALARY.getCode());
innerCmd.setEventDesc(SalaryEvent.SALARY_BD.getCode());
innerCmd.setAmount(record.getSettlementSalary());
innerCmd.setTrackId(record.getId());
innerCmd.setTrackId(record.getBizNo());
innerCmd.setBdId(bdUserId);
userSalaryAccountClient.issueSalary(innerCmd);
log.info("BD {} 工资发放成功,金额:{} USD", bdUserId, record.getSettlementSalary());
}
/**

View File

@ -58,6 +58,10 @@ public class SalaryRunningWaterQryExe {
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
wrapper.le(SalaryAccountRunningWater::getCreateTime, endTime);
}
if (StringUtils.isNotBlank(cmd.getTrackId())) {
wrapper.eq(SalaryAccountRunningWater::getTrackId, cmd.getTrackId());
}
wrapper.orderByDesc(SalaryAccountRunningWater::getCreateTime);

View File

@ -26,6 +26,11 @@ public class SalaryRunningWaterQueryCmd extends PageQueryCmd {
*/
private Integer type;
/**
* 跟踪ID
*/
private String trackId;
/**
* 账单归属YYYYMM.
*/

View File

@ -7,6 +7,7 @@ import com.red.circle.wallet.app.dto.clientobject.SalaryRunningWaterCO;
import com.red.circle.wallet.app.dto.cmd.SalaryIssueCmd;
import com.red.circle.wallet.app.dto.cmd.SalaryRunningWaterQueryCmd;
import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountRunningWater;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryWithdrawInnerCmd;
@ -70,6 +71,7 @@ public class SalaryAccountInnerConvertor {
cmd.setUserId(innerCmd.getUserId());
cmd.setSalaryType(innerCmd.getSalaryType());
cmd.setType(innerCmd.getType());
cmd.setTrackId(innerCmd.getTrackId());
cmd.setBillBelong(innerCmd.getBillBelong());
cmd.setStartTime(innerCmd.getStartTime());
cmd.setEndTime(innerCmd.getEndTime());
@ -129,4 +131,29 @@ public class SalaryAccountInnerConvertor {
dto.setCreatedAt(co.getCreatedAt());
return dto;
}
public SalaryRunningWaterDTO toRunningWaterDTO(SalaryAccountRunningWater runningWater) {
if (Objects.isNull(runningWater)) {
return null;
}
SalaryRunningWaterDTO dto = new SalaryRunningWaterDTO();
dto.setId(runningWater.getId());
dto.setUserId(runningWater.getUserId());
dto.setAcceptUserId(runningWater.getAcceptUserId());
dto.setType(runningWater.getType());
dto.setSalaryType(runningWater.getSalaryType());
dto.setAmount(runningWater.getAmount());
dto.setBalance(runningWater.getBalance());
dto.setAvailableBalance(runningWater.getAvailableBalance());
dto.setSalaryEvent(runningWater.getSalaryEvent());
dto.setEventDesc(runningWater.getEventDesc());
dto.setTrackId(runningWater.getTrackId());
dto.setBillBelong(runningWater.getBillBelong());
dto.setTeamId(runningWater.getTeamId());
dto.setBdId(runningWater.getBdId());
dto.setAgentId(runningWater.getAgentId());
dto.setRemark(runningWater.getRemark());
return dto;
}
}

View File

@ -51,6 +51,11 @@ public class UserSalaryAccountClientEndpoint implements UserSalaryAccountClientA
return ResultResponse.success(userSalaryAccountClientService.queryRunningWater(cmd));
}
@Override
public ResultResponse<SalaryRunningWaterDTO> existRunningWater(String trackId) {
return ResultResponse.success(userSalaryAccountClientService.existRunningWater(trackId));
}
@Override
public ResultResponse<BigDecimal> getTotalIncome(Long userId, String salaryType, String salaryEvent, String startTime, String endTime) {
return ResultResponse.success(userSalaryAccountClientService.getTotalIncome(userId, salaryType, salaryEvent, startTime, endTime));

View File

@ -35,6 +35,8 @@ public interface UserSalaryAccountClientService {
*/
PageResult<SalaryRunningWaterDTO> queryRunningWater(SalaryRunningWaterQueryInnerCmd cmd);
SalaryRunningWaterDTO existRunningWater(String trackId);
/**
* 查询用户累计收入.
*/

View File

@ -1,5 +1,6 @@
package com.red.circle.wallet.inner.service.salary.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.wallet.app.dto.clientobject.SalaryAccountBalanceCO;
import com.red.circle.wallet.app.dto.clientobject.SalaryIssueResultCO;
@ -8,6 +9,8 @@ import com.red.circle.wallet.app.dto.cmd.SalaryIssueCmd;
import com.red.circle.wallet.app.dto.cmd.SalaryRunningWaterQueryCmd;
import com.red.circle.wallet.app.dto.cmd.SalaryWithdrawCmd;
import com.red.circle.wallet.app.service.SalaryAccountService;
import com.red.circle.wallet.infra.database.rds.entity.salary.SalaryAccountRunningWater;
import com.red.circle.wallet.infra.database.rds.service.salary.SalaryAccountRunningWaterService;
import com.red.circle.wallet.inner.convertor.SalaryAccountInnerConvertor;
import com.red.circle.wallet.inner.model.cmd.SalaryIssueInnerCmd;
import com.red.circle.wallet.inner.model.cmd.SalaryRunningWaterQueryInnerCmd;
@ -32,6 +35,7 @@ public class UserSalaryAccountClientServiceImpl implements UserSalaryAccountClie
private final SalaryAccountService salaryAccountService;
private final SalaryAccountInnerConvertor salaryAccountInnerConvertor;
private final SalaryAccountRunningWaterService salaryAccountRunningWaterService;
@Override
public SalaryAccountBalanceDTO getBalance(Long userId, String salaryType) {
@ -69,6 +73,13 @@ public class UserSalaryAccountClientServiceImpl implements UserSalaryAccountClie
return pageResult;
}
@Override
public SalaryRunningWaterDTO existRunningWater(String trackId) {
LambdaQueryWrapper<SalaryAccountRunningWater> wrapper = new LambdaQueryWrapper<>();
SalaryAccountRunningWater one = salaryAccountRunningWaterService.getOne(wrapper.eq(SalaryAccountRunningWater::getTrackId, trackId));
return salaryAccountInnerConvertor.toRunningWaterDTO(one);
}
@Override
public BigDecimal getTotalIncome(Long userId, String salaryType, String salaryEvent, String startTime, String endTime) {
BigDecimal totalIncome = salaryAccountService.getTotalIncome(userId, salaryType, salaryEvent, startTime, endTime);