From d0d48d71acc28ecb087deabdfa68afe6ba24604c Mon Sep 17 00:00:00 2001 From: hy001 Date: Thu, 21 May 2026 13:59:36 +0800 Subject: [PATCH] include agent salary in manual settlement --- ...mManualSalaryPaymentClientServiceImpl.java | 185 ++++++++++++++---- 1 file changed, 142 insertions(+), 43 deletions(-) diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/team/impl/TeamManualSalaryPaymentClientServiceImpl.java b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/team/impl/TeamManualSalaryPaymentClientServiceImpl.java index 3094ded6..53a1d9af 100644 --- a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/team/impl/TeamManualSalaryPaymentClientServiceImpl.java +++ b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/team/impl/TeamManualSalaryPaymentClientServiceImpl.java @@ -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 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 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 buildSettlementPayments(TeamPolicyManager policyManager, - TeamBillMemberTarget billTarget, BigDecimal payableSalary, boolean currentLevelSettled) { + TeamBillMemberTarget billTarget, List 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 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 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 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 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 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 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 cyclePayments) { - List details = listValidAnchorDetails(cyclePayments); - BigDecimal totalIssuedSalary = details.stream() + List 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 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 details) { @@ -522,7 +597,7 @@ public class TeamManualSalaryPaymentClientServiceImpl implements + details.getPolicyLevel() + ":" + details.getAnchor(); } - private List listValidAnchorDetails( + private List listValidSalaryDetails( List 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); + } } }