include agent salary in manual settlement

This commit is contained in:
hy001 2026-05-21 13:59:36 +08:00
parent 3cef4fc322
commit d0d48d71ac

View File

@ -135,32 +135,38 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
for (PolicyPayment policyPayment : row.getPayments()) {
if (Boolean.TRUE.equals(teamSalaryPaymentService.checkRepeatPayment(payment.getId(),
row.getUserId(), row.getRegion(), policyPayment.getLevel(), Boolean.TRUE))) {
row.getUserId(), row.getRegion(), policyPayment.getLevel(),
policyPayment.getAnchor()))) {
continue;
}
Long receiverUserId = policyPayment.isAnchor() ? row.getUserId() : row.getTeamOwnId();
if (Objects.isNull(receiverUserId)) {
continue;
}
BigDecimal issueSalary = policyPayment.getSalary().compareTo(BigDecimal.ZERO) > 0
? policyPayment.getSalary()
: BigDecimal.ZERO.setScale(2, RoundingMode.DOWN);
BigDecimal beforeBalance = getAccurateBalance(row.getUserId());
BigDecimal beforeBalance = getAccurateBalance(receiverUserId);
String detailsId = IdWorkerUtils.getIdStr();
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
Boolean incrSuccess = ResponseAssert.requiredSuccess(userBankBalanceClient.incr(new UserBankBalanceIncrCmd()
.setUserId(row.getUserId())
.setUserId(receiverUserId)
.setSysOrigin(row.getSysOrigin())
.setAmount(PennyAmount.ofDollar(issueSalary))));
ResponseAssert.isTrue(CommonErrorCode.OPERATION_CONFLICT, Boolean.TRUE.equals(incrSuccess));
}
BigDecimal afterBalance = getAccurateBalance(row.getUserId());
BigDecimal afterBalance = getAccurateBalance(receiverUserId);
String salaryRoleName = policyPayment.isAnchor() ? "主播" : "代理";
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
addRunningWater(detailsId, row.getUserId(), row.getSysOrigin(),
issueSalary, afterBalance, cmd.getOperationUserId());
addRunningWater(detailsId, receiverUserId, row.getSysOrigin(),
issueSalary, afterBalance, cmd.getOperationUserId(), salaryRoleName);
}
String settlementRemark = issueSalary.compareTo(BigDecimal.ZERO) > 0
? "后台手动发放主播工资"
: "后台手动结算主播工资实收已大于等于应发本次发放0";
? "后台手动发放" + salaryRoleName + "工资"
: "后台手动结算" + salaryRoleName + "工资实收已大于等于应发本次发放0";
teamSalaryPaymentService.paymentSalary(payment.getId(), new TeamSalaryPaymentDetails()
.setId(detailsId)
@ -174,7 +180,7 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
.setRemarks(List.of(new TeamSalaryPaymentRemark()
.setRemark(settlementRemark)
.setCreateTime(TimestampUtils.now())))
.setAnchor(Boolean.TRUE)
.setAnchor(policyPayment.getAnchor())
.setHostSalaryToAgent(Boolean.FALSE)
.setTarget(row.getCurrentTarget())
.setSalary(issueSalary)
@ -190,7 +196,7 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
.setRegion(row.getRegion())
.setTeamId(row.getTeamId())
.setTeamOwnId(row.getTeamOwnId())
.setUserId(row.getUserId())
.setUserId(receiverUserId)
.setBillBelong(billBelong)
.setBeforeSalaryBalance(beforeBalance)
.setAfterSalaryBalance(afterBalance)
@ -349,13 +355,14 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
List<TeamSalaryPayment> cyclePayments = listCyclePayments(salaryPaymentMap,
target.getUserId(), billBelong);
PaymentSummary paymentSummary = summarizePayments(cyclePayments);
BigDecimal expectedSalary = expectedMemberSalary(billTarget);
BigDecimal expectedSalary = expectedTotalSalary(billTarget);
BigDecimal payableSalary = expectedSalary.subtract(paymentSummary.getTotalIssuedSalary())
.setScale(2, RoundingMode.DOWN);
boolean currentLevelSettled = isCurrentLevelSettled(cyclePayments, target.getUserId(), region,
billTarget.getLevel(), payableSalary);
boolean currentLevelSettled = areCurrentRolesSettled(cyclePayments, target.getUserId(), region,
billTarget, payableSalary);
List<PolicyPayment> policyPayments = buildSettlementPayments(policyManager, billTarget,
payableSalary, currentLevelSettled);
cyclePayments, target.getUserId(), region, paymentSummary, payableSalary,
currentLevelSettled);
TeamManualSalaryPaymentDTO dto = new TeamManualSalaryPaymentDTO()
.setId(target.getId())
@ -430,25 +437,73 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
.setSatisfyLevel(Boolean.FALSE);
}
private BigDecimal expectedMemberSalary(TeamBillMemberTarget billTarget) {
return Optional.ofNullable(billTarget)
.map(TeamBillMemberTarget::getMemberSalary)
private BigDecimal expectedTotalSalary(TeamBillMemberTarget billTarget) {
if (Objects.isNull(billTarget)) {
return BigDecimal.ZERO.setScale(2, RoundingMode.DOWN);
}
return salaryValue(billTarget.getMemberSalary())
.add(salaryValue(billTarget.getOwnSalary()))
.setScale(2, RoundingMode.DOWN);
}
private BigDecimal salaryValue(BigDecimal value) {
return Optional.ofNullable(value)
.orElse(BigDecimal.ZERO)
.setScale(2, RoundingMode.DOWN);
}
private List<PolicyPayment> buildSettlementPayments(TeamPolicyManager policyManager,
TeamBillMemberTarget billTarget, BigDecimal payableSalary, boolean currentLevelSettled) {
TeamBillMemberTarget billTarget, List<TeamSalaryPayment> cyclePayments, Long userId,
String region, PaymentSummary paymentSummary, BigDecimal payableSalary,
boolean currentLevelSettled) {
if (currentLevelSettled || Objects.isNull(billTarget)
|| Objects.isNull(billTarget.getLevel())) {
return List.of();
}
BigDecimal issueSalary = payableSalary.compareTo(BigDecimal.ZERO) > 0
TeamPolicy policy = findPolicy(policyManager, billTarget.getLevel());
BigDecimal remainingPayable = payableSalary.compareTo(BigDecimal.ZERO) > 0
? payableSalary.setScale(2, RoundingMode.DOWN)
: BigDecimal.ZERO.setScale(2, RoundingMode.DOWN);
return List.of(new PolicyPayment(findPolicy(policyManager, billTarget.getLevel()),
billTarget.getLevel(), issueSalary));
BigDecimal memberExpected = salaryValue(billTarget.getMemberSalary());
BigDecimal agentExpected = salaryValue(billTarget.getOwnSalary());
BigDecimal memberMissing = memberExpected.subtract(paymentSummary.getMemberIssuedSalary())
.setScale(2, RoundingMode.DOWN);
BigDecimal agentMissing = agentExpected.subtract(paymentSummary.getAgentIssuedSalary())
.setScale(2, RoundingMode.DOWN);
boolean memberSettled = isRoleSettled(cyclePayments, userId, region, billTarget.getLevel(),
Boolean.TRUE, memberExpected);
boolean agentSettled = isRoleSettled(cyclePayments, userId, region, billTarget.getLevel(),
Boolean.FALSE, agentExpected);
List<PolicyPayment> payments = new ArrayList<>();
if (remainingPayable.compareTo(BigDecimal.ZERO) <= 0) {
if (!memberSettled && memberExpected.compareTo(BigDecimal.ZERO) > 0) {
payments.add(new PolicyPayment(policy, billTarget.getLevel(),
BigDecimal.ZERO.setScale(2, RoundingMode.DOWN), Boolean.TRUE));
}
if (!agentSettled && agentExpected.compareTo(BigDecimal.ZERO) > 0) {
payments.add(new PolicyPayment(policy, billTarget.getLevel(),
BigDecimal.ZERO.setScale(2, RoundingMode.DOWN), Boolean.FALSE));
}
return payments;
}
if (!memberSettled && memberMissing.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal issueSalary = memberMissing.min(remainingPayable).setScale(2, RoundingMode.DOWN);
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
payments.add(new PolicyPayment(policy, billTarget.getLevel(), issueSalary, Boolean.TRUE));
remainingPayable = remainingPayable.subtract(issueSalary).setScale(2, RoundingMode.DOWN);
}
}
if (!agentSettled && agentMissing.compareTo(BigDecimal.ZERO) > 0
&& remainingPayable.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal issueSalary = agentMissing.min(remainingPayable).setScale(2, RoundingMode.DOWN);
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
payments.add(new PolicyPayment(policy, billTarget.getLevel(), issueSalary, Boolean.FALSE));
}
}
return payments;
}
private TeamPolicy findPolicy(TeamPolicyManager policyManager, Integer level) {
@ -462,24 +517,35 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
.orElse(null);
}
private boolean isCurrentLevelSettled(List<TeamSalaryPayment> cyclePayments, Long userId,
String region, Integer policyLevel, BigDecimal payableSalary) {
return Objects.nonNull(policyLevel)
&& payableSalary.compareTo(BigDecimal.ZERO) <= 0
&& hasPaidPolicy(cyclePayments, userId, region, policyLevel);
private boolean areCurrentRolesSettled(List<TeamSalaryPayment> cyclePayments, Long userId,
String region, TeamBillMemberTarget billTarget, BigDecimal payableSalary) {
if (Objects.isNull(billTarget) || Objects.isNull(billTarget.getLevel())
|| payableSalary.compareTo(BigDecimal.ZERO) > 0) {
return false;
}
return isRoleSettled(cyclePayments, userId, region, billTarget.getLevel(), Boolean.TRUE,
salaryValue(billTarget.getMemberSalary()))
&& isRoleSettled(cyclePayments, userId, region, billTarget.getLevel(), Boolean.FALSE,
salaryValue(billTarget.getOwnSalary()));
}
private boolean isRoleSettled(List<TeamSalaryPayment> cyclePayments, Long userId, String region,
Integer policyLevel, Boolean anchor, BigDecimal expectedSalary) {
return expectedSalary.compareTo(BigDecimal.ZERO) <= 0
|| hasPaidPolicy(cyclePayments, userId, region, policyLevel, anchor);
}
private boolean hasPaidPolicy(List<TeamSalaryPayment> cyclePayments, Long userId, String region,
Integer policyLevel) {
return listValidAnchorDetails(cyclePayments).stream()
Integer policyLevel, Boolean anchor) {
return listValidSalaryDetails(cyclePayments).stream()
.anyMatch(details -> Objects.equals(details.getTeamMemberId(), userId)
&& Objects.equals(details.getTeamRegionId(), region)
&& Objects.equals(details.getPolicyLevel(), policyLevel));
&& Objects.equals(details.getPolicyLevel(), policyLevel)
&& Objects.equals(details.getAnchor(), anchor));
}
private Long getLastSettlementTarget(List<TeamSalaryPayment> cyclePayments) {
return listValidAnchorDetails(cyclePayments).stream()
.filter(this::validAnchorDetails)
return listValidSalaryDetails(cyclePayments).stream()
.max(Comparator.comparing(details -> Optional.ofNullable(details.getCreateTime())
.orElse(new Timestamp(0))))
.map(TeamSalaryPaymentDetails::getTarget)
@ -487,12 +553,21 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
}
private PaymentSummary summarizePayments(List<TeamSalaryPayment> cyclePayments) {
List<TeamSalaryPaymentDetails> details = listValidAnchorDetails(cyclePayments);
BigDecimal totalIssuedSalary = details.stream()
List<TeamSalaryPaymentDetails> details = listValidSalaryDetails(cyclePayments);
BigDecimal memberIssuedSalary = sumDetailsSalary(details, Boolean.TRUE);
BigDecimal agentIssuedSalary = sumDetailsSalary(details, Boolean.FALSE);
BigDecimal totalIssuedSalary = memberIssuedSalary.add(agentIssuedSalary)
.setScale(2, RoundingMode.DOWN);
return new PaymentSummary(totalIssuedSalary, memberIssuedSalary, agentIssuedSalary,
getOverIssuedSalary(details));
}
private BigDecimal sumDetailsSalary(List<TeamSalaryPaymentDetails> details, Boolean anchor) {
return details.stream()
.filter(detail -> Objects.equals(detail.getAnchor(), anchor))
.map(detail -> Optional.ofNullable(detail.getSalary()).orElse(BigDecimal.ZERO))
.reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(2, RoundingMode.DOWN);
return new PaymentSummary(totalIssuedSalary, getOverIssuedSalary(details));
}
private BigDecimal getOverIssuedSalary(List<TeamSalaryPaymentDetails> details) {
@ -522,7 +597,7 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
+ details.getPolicyLevel() + ":" + details.getAnchor();
}
private List<TeamSalaryPaymentDetails> listValidAnchorDetails(
private List<TeamSalaryPaymentDetails> listValidSalaryDetails(
List<TeamSalaryPayment> cyclePayments) {
if (CollectionUtils.isEmpty(cyclePayments)) {
return List.of();
@ -532,13 +607,13 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
.flatMap(payment -> Optional.ofNullable(payment.getSalarySendDetails())
.stream()
.flatMap(List::stream))
.filter(this::validAnchorDetails)
.filter(this::validSalaryDetails)
.collect(Collectors.toList());
}
private boolean validAnchorDetails(TeamSalaryPaymentDetails details) {
private boolean validSalaryDetails(TeamSalaryPaymentDetails details) {
return Objects.nonNull(details)
&& Boolean.TRUE.equals(details.getAnchor())
&& Objects.nonNull(details.getAnchor())
&& !Boolean.TRUE.equals(details.getRecycled());
}
@ -551,7 +626,7 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
}
private void addRunningWater(String trackId, Long userId, String sysOrigin, BigDecimal salary,
BigDecimal afterBalance, Long operationUserId) {
BigDecimal afterBalance, Long operationUserId, String salaryRoleName) {
try {
userBankRunningWaterClient.add(new UserBankRunningWaterDTO()
.setId(IdWorkerUtils.getId())
@ -562,13 +637,14 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
.setEvent(UserBankWaterEvent.SYSTEM_SETTLEMENT_WAGES.name())
.setEventDescribe(UserBankWaterEvent.SYSTEM_SETTLEMENT_WAGES.getDescribe())
.setTrackId(trackId)
.setRemark("后台手动发放主播工资")
.setRemark("后台手动发放" + salaryRoleName + "工资")
.setBalance(afterBalance)
.setCreateTime(TimestampUtils.now())
.setCreateUser(Optional.ofNullable(operationUserId).orElse(0L))
.setCreateUserOrigin(1));
} catch (Exception e) {
log.error("[后台手动发放主播工资] 插入用户银行流水失败, userId:{}, trackId:{}", userId, trackId, e);
log.error("[后台手动发放{}工资] 插入用户银行流水失败, userId:{}, trackId:{}",
salaryRoleName, userId, trackId, e);
}
}
@ -602,10 +678,15 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
private static class PaymentSummary {
private final BigDecimal totalIssuedSalary;
private final BigDecimal memberIssuedSalary;
private final BigDecimal agentIssuedSalary;
private final BigDecimal overIssuedSalary;
private PaymentSummary(BigDecimal totalIssuedSalary, BigDecimal overIssuedSalary) {
private PaymentSummary(BigDecimal totalIssuedSalary, BigDecimal memberIssuedSalary,
BigDecimal agentIssuedSalary, BigDecimal overIssuedSalary) {
this.totalIssuedSalary = totalIssuedSalary;
this.memberIssuedSalary = memberIssuedSalary;
this.agentIssuedSalary = agentIssuedSalary;
this.overIssuedSalary = overIssuedSalary;
}
@ -613,6 +694,14 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
return totalIssuedSalary;
}
private BigDecimal getMemberIssuedSalary() {
return memberIssuedSalary;
}
private BigDecimal getAgentIssuedSalary() {
return agentIssuedSalary;
}
private BigDecimal getOverIssuedSalary() {
return overIssuedSalary;
}
@ -700,11 +789,13 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
private final TeamPolicy policy;
private final Integer level;
private final BigDecimal salary;
private final Boolean anchor;
private PolicyPayment(TeamPolicy policy, Integer level, BigDecimal salary) {
private PolicyPayment(TeamPolicy policy, Integer level, BigDecimal salary, Boolean anchor) {
this.policy = policy;
this.level = level;
this.salary = salary;
this.anchor = anchor;
}
private TeamPolicy getPolicy() {
@ -718,5 +809,13 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
private BigDecimal getSalary() {
return salary;
}
private Boolean getAnchor() {
return anchor;
}
private boolean isAnchor() {
return Boolean.TRUE.equals(anchor);
}
}
}