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