From d799d68946314f3d92f5796d038158c438a8b6be Mon Sep 17 00:00:00 2001 From: hy001 Date: Mon, 25 May 2026 20:34:00 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B7=A5=E8=B5=84=E5=8F=91?= =?UTF-8?q?=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../agency/TeamManualSalaryPaymentDTO.java | 5 + .../app/team/TeamSalaryBackServiceImpl.java | 1 + .../clienobject/team/TeamManualSalaryCO.java | 1 + ...mManualSalaryPaymentClientServiceImpl.java | 59 ++-- ...ualSalaryPaymentClientServiceImplTest.java | 258 +++++++++++++++++- 5 files changed, 295 insertions(+), 29 deletions(-) diff --git a/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/agency/agency/TeamManualSalaryPaymentDTO.java b/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/agency/agency/TeamManualSalaryPaymentDTO.java index d25592d8..d48b09c5 100644 --- a/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/agency/agency/TeamManualSalaryPaymentDTO.java +++ b/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/agency/agency/TeamManualSalaryPaymentDTO.java @@ -81,6 +81,11 @@ public class TeamManualSalaryPaymentDTO implements Serializable { */ private Boolean satisfyLevel; + /** + * 当前用户是否为代理. + */ + private Boolean agentMember; + /** * 当前账期按积分档位计算出的工资. */ diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/team/TeamSalaryBackServiceImpl.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/team/TeamSalaryBackServiceImpl.java index 51a9ba4c..06e23df6 100644 --- a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/team/TeamSalaryBackServiceImpl.java +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/team/TeamSalaryBackServiceImpl.java @@ -215,6 +215,7 @@ public class TeamSalaryBackServiceImpl implements TeamSalaryBackService { .setCurrentTarget(dto.getCurrentTarget()) .setPolicyLevel(dto.getPolicyLevel()) .setSatisfyLevel(dto.getSatisfyLevel()) + .setAgentMember(dto.getAgentMember()) .setExpectedSalary(dto.getExpectedSalary()) .setExpectedMemberSalary(dto.getExpectedMemberSalary()) .setExpectedAgentSalary(dto.getExpectedAgentSalary()) diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/team/TeamManualSalaryCO.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/team/TeamManualSalaryCO.java index 46b8ed1c..933f23a5 100644 --- a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/team/TeamManualSalaryCO.java +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/team/TeamManualSalaryCO.java @@ -39,6 +39,7 @@ public class TeamManualSalaryCO implements Serializable { private Long currentTarget; private Integer policyLevel; private Boolean satisfyLevel; + private Boolean agentMember; private BigDecimal expectedSalary; private BigDecimal expectedMemberSalary; private BigDecimal expectedAgentSalary; 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 f756861d..350677de 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 @@ -21,6 +21,7 @@ import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberTar import com.red.circle.other.infra.database.mongo.service.team.team.TeamPolicyManagerService; import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService; import com.red.circle.other.infra.database.mongo.service.team.team.TeamSalaryPaymentService; +import com.red.circle.other.inner.enums.team.TeamMemberRole; import com.red.circle.other.inner.enums.team.TeamPolicyTypeEnum; import com.red.circle.other.inner.model.cmd.team.TeamManualSalaryPaymentCmd; import com.red.circle.other.inner.model.cmd.team.TeamManualSalaryPaymentQryCmd; @@ -365,14 +366,17 @@ public class TeamManualSalaryPaymentClientServiceImpl implements TeamPolicyManager policyManager = getPolicyManager(target.getSysOrigin(), region, countryCode, policyCache); TeamBillMemberTarget billTarget = calculateBillTarget(target, policyManager); + boolean includeAgentSalary = isAgentMember(member, teamProfile, target.getUserId()); List cyclePayments = listCyclePayments(salaryPaymentMap, target.getUserId(), billBelong); PaymentSummary receivedPaymentSummary = summarizeReceivedPayments( - new ArrayList<>(salaryPaymentMap.values()), target.getUserId()); + new ArrayList<>(salaryPaymentMap.values()), target.getUserId(), includeAgentSalary); BigDecimal expectedMemberSalary = salaryValue(billTarget.getMemberSalary()); - BigDecimal expectedAgentSalary = salaryValue(billTarget.getOwnSalary()); - BigDecimal expectedSalary = expectedTotalSalary(billTarget); + BigDecimal expectedAgentSalary = includeAgentSalary ? salaryValue(billTarget.getOwnSalary()) + : BigDecimal.ZERO.setScale(2, RoundingMode.DOWN); + BigDecimal expectedSalary = expectedMemberSalary.add(expectedAgentSalary) + .setScale(2, RoundingMode.DOWN); BigDecimal payableSalary = expectedSalary.subtract(receivedPaymentSummary.getTotalIssuedSalary()) .setScale(2, RoundingMode.DOWN); BigDecimal payableMemberSalary = expectedMemberSalary @@ -382,10 +386,10 @@ public class TeamManualSalaryPaymentClientServiceImpl implements .subtract(receivedPaymentSummary.getAgentIssuedSalary()) .setScale(2, RoundingMode.DOWN); boolean currentLevelSettled = areCurrentRolesSettled(cyclePayments, target.getUserId(), region, - billTarget, payableSalary); + billTarget, expectedMemberSalary, expectedAgentSalary, payableSalary); List policyPayments = buildSettlementPayments(policyManager, billTarget, - cyclePayments, target.getUserId(), region, receivedPaymentSummary, payableSalary, - currentLevelSettled); + cyclePayments, target.getUserId(), region, receivedPaymentSummary, expectedMemberSalary, + expectedAgentSalary, payableSalary, currentLevelSettled); TeamManualSalaryPaymentDTO dto = new TeamManualSalaryPaymentDTO() .setId(target.getId()) @@ -400,6 +404,7 @@ public class TeamManualSalaryPaymentClientServiceImpl implements .setCurrentTarget(target.sumAcceptGiftValue()) .setPolicyLevel(billTarget.getLevel()) .setSatisfyLevel(billTarget.getSatisfyLevel()) + .setAgentMember(includeAgentSalary) .setExpectedSalary(expectedSalary) .setExpectedMemberSalary(expectedMemberSalary) .setExpectedAgentSalary(expectedAgentSalary) @@ -418,6 +423,19 @@ public class TeamManualSalaryPaymentClientServiceImpl implements return new ManualSalaryRow(dto, target, teamProfile, policyManager, billTarget, policyPayments); } + private boolean isAgentMember(TeamMember member, TeamProfile teamProfile, Long userId) { + if (Objects.isNull(userId)) { + return false; + } + Long teamOwnUserId = Optional.ofNullable(teamProfile) + .map(TeamProfile::getOwnUserId) + .orElse(null); + TeamMemberRole role = Optional.ofNullable(member) + .map(TeamMember::getRole) + .orElse(null); + return Objects.equals(teamOwnUserId, userId) || TeamMemberRole.OWN.eq(role); + } + private TeamPolicyManager getPolicyManager(String sysOrigin, String region, String countryCode, Map policyCache) { if (StringUtils.isBlank(sysOrigin) || StringUtils.isBlank(region)) { @@ -468,15 +486,6 @@ public class TeamManualSalaryPaymentClientServiceImpl implements .setSatisfyLevel(Boolean.FALSE); } - 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) @@ -485,8 +494,8 @@ public class TeamManualSalaryPaymentClientServiceImpl implements private List buildSettlementPayments(TeamPolicyManager policyManager, TeamBillMemberTarget billTarget, List cyclePayments, Long userId, - String region, PaymentSummary paymentSummary, BigDecimal payableSalary, - boolean currentLevelSettled) { + String region, PaymentSummary paymentSummary, BigDecimal memberExpected, + BigDecimal agentExpected, BigDecimal payableSalary, boolean currentLevelSettled) { if (currentLevelSettled || Objects.isNull(billTarget) || Objects.isNull(billTarget.getLevel())) { return List.of(); @@ -496,8 +505,6 @@ public class TeamManualSalaryPaymentClientServiceImpl implements BigDecimal remainingPayable = payableSalary.compareTo(BigDecimal.ZERO) > 0 ? payableSalary.setScale(2, RoundingMode.DOWN) : BigDecimal.ZERO.setScale(2, RoundingMode.DOWN); - 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()) @@ -549,15 +556,16 @@ public class TeamManualSalaryPaymentClientServiceImpl implements } private boolean areCurrentRolesSettled(List cyclePayments, Long userId, - String region, TeamBillMemberTarget billTarget, BigDecimal payableSalary) { + String region, TeamBillMemberTarget billTarget, BigDecimal expectedMemberSalary, + BigDecimal expectedAgentSalary, 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())) + expectedMemberSalary) && isRoleSettled(cyclePayments, userId, region, billTarget.getLevel(), Boolean.FALSE, - salaryValue(billTarget.getOwnSalary())); + expectedAgentSalary); } private boolean isRoleSettled(List cyclePayments, Long userId, String region, @@ -583,17 +591,14 @@ public class TeamManualSalaryPaymentClientServiceImpl implements .orElse(0L); } - private PaymentSummary summarizePayments(List cyclePayments) { - return summarizeDetails(listValidSalaryDetails(cyclePayments)); - } - private PaymentSummary summarizeReceivedPayments(List cyclePayments, - Long receiverUserId) { + Long receiverUserId, boolean includeAgentSalary) { if (Objects.isNull(receiverUserId)) { return emptyPaymentSummary(); } List details = listValidSalaryDetails(cyclePayments).stream() .filter(detail -> Objects.equals(receiverUserId, getSalaryReceiverUserId(detail))) + .filter(detail -> includeAgentSalary || Boolean.TRUE.equals(detail.getAnchor())) .collect(Collectors.toList()); return summarizeDetails(details); } diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/test/java/com/red/circle/other/app/inner/service/team/impl/TeamManualSalaryPaymentClientServiceImplTest.java b/rc-service/rc-service-other/other-inner-endpoint/src/test/java/com/red/circle/other/app/inner/service/team/impl/TeamManualSalaryPaymentClientServiceImplTest.java index 5a3d3538..8614c81b 100644 --- a/rc-service/rc-service-other/other-inner-endpoint/src/test/java/com/red/circle/other/app/inner/service/team/impl/TeamManualSalaryPaymentClientServiceImplTest.java +++ b/rc-service/rc-service-other/other-inner-endpoint/src/test/java/com/red/circle/other/app/inner/service/team/impl/TeamManualSalaryPaymentClientServiceImplTest.java @@ -28,6 +28,7 @@ import com.red.circle.other.infra.database.mongo.service.team.team.TeamPolicyMan import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService; import com.red.circle.other.infra.database.mongo.service.team.team.TeamSalaryPaymentService; import com.red.circle.other.inner.enums.team.TeamMemberTargetIndex; +import com.red.circle.other.inner.enums.team.TeamMemberRole; import com.red.circle.other.inner.model.cmd.team.TeamManualSalaryPaymentCmd; import com.red.circle.other.inner.model.dto.agency.agency.TeamManualSalaryPaymentResultDTO; import com.red.circle.wallet.inner.endpoint.bank.UserBankBalanceClient; @@ -73,7 +74,7 @@ class TeamManualSalaryPaymentClientServiceImplTest { List payments = ReflectionTestUtils.invokeMethod(service, "buildSettlementPayments", null, billTarget, List.of(currentPayment), userId, region, paymentSummary, - new BigDecimal("12.25"), false); + new BigDecimal("35.00"), new BigDecimal("8.75"), new BigDecimal("12.25"), false); assertEquals(1, payments.size()); Object payment = payments.get(0); @@ -101,7 +102,7 @@ class TeamManualSalaryPaymentClientServiceImplTest { List payments = ReflectionTestUtils.invokeMethod(service, "buildSettlementPayments", null, billTarget, List.of(), userId, region, paymentSummary, - new BigDecimal("-1.25"), false); + new BigDecimal("35.00"), new BigDecimal("8.75"), new BigDecimal("-1.25"), false); assertEquals(2, payments.size()); assertEquals(BigDecimal.ZERO.setScale(2), ReflectionTestUtils.getField(payments.get(0), @@ -215,6 +216,227 @@ class TeamManualSalaryPaymentClientServiceImplTest { anyString(), any(), any()); } + @Test + void payShouldNotRepeatAgentSalaryAlreadyPaidToTeamOwner() { + RedisService redisService = mock(RedisService.class); + TeamMemberService teamMemberService = mock(TeamMemberService.class); + TeamProfileService teamProfileService = mock(TeamProfileService.class); + UserBankBalanceClient userBankBalanceClient = mock(UserBankBalanceClient.class); + TeamMemberTargetService teamMemberTargetService = mock(TeamMemberTargetService.class); + TeamSalaryPaymentService teamSalaryPaymentService = mock(TeamSalaryPaymentService.class); + TeamPolicyManagerService teamPolicyManagerService = mock(TeamPolicyManagerService.class); + UserBankRunningWaterClient userBankRunningWaterClient = mock(UserBankRunningWaterClient.class); + TeamManualSalaryPaymentClientServiceImpl service = new TeamManualSalaryPaymentClientServiceImpl( + redisService, teamMemberService, teamProfileService, userBankBalanceClient, + teamMemberTargetService, teamSalaryPaymentService, teamPolicyManagerService, + userBankRunningWaterClient); + + String sysOrigin = "LIKEI"; + String countryCode = "PH"; + String region = "2046067717605224449"; + Long userId = 2052023053021409281L; + Long ownerUserId = 2051169779338768386L; + Long teamId = 2051672510944047106L; + Integer billBelong = TeamBillCycleUtils.getCalcBillBelong(); + String paymentId = userId + "_" + billBelong; + TeamMemberTarget target = new TeamMemberTarget() + .setId("target-id") + .setTimeId(1779030072251003137L) + .setSysOrigin(sysOrigin) + .setRegion(region) + .setCountryCode(countryCode) + .setTeamId(teamId) + .setUserId(userId) + .setBillBelong(billBelong) + .setDailyTargets(List.of(new TeamMemberTargetIndex() + .setOwnOnlineTime(4586L) + .setAcceptGiftValue(2104843L))); + TeamSalaryPayment existingPayment = new TeamSalaryPayment() + .setId(paymentId) + .setUserId(userId) + .setDateNumber(billBelong) + .setSalarySendDetails(List.of( + new TeamSalaryPaymentDetails() + .setTeamMemberId(userId) + .setTeamOwnId(ownerUserId) + .setTeamRegionId(region) + .setPolicyLevel(4) + .setAnchor(Boolean.TRUE) + .setSalary(new BigDecimal("8.00")) + .setRecycled(Boolean.FALSE), + new TeamSalaryPaymentDetails() + .setTeamMemberId(userId) + .setTeamOwnId(ownerUserId) + .setTeamRegionId(region) + .setPolicyLevel(4) + .setAnchor(Boolean.FALSE) + .setSalary(new BigDecimal("2.00")) + .setRecycled(Boolean.FALSE))); + TeamPolicyManager policyManager = new TeamPolicyManager() + .setSysOrigin(sysOrigin) + .setRegion(region) + .setCountryCode(countryCode) + .setPolicy(List.of(new TeamPolicy() + .setLevel(4) + .setTarget(2000000L) + .setOnlineTime(10L) + .setEffectiveDay(0) + .setMemberSalary(new BigDecimal("8.00")) + .setOwnSalary(new BigDecimal("2.00")) + .setTotalSalary(new BigDecimal("10.00")))); + + when(redisService.lock(anyString(), anyLong())).thenReturn(true); + when(teamMemberTargetService.listManualSalaryTargets(eq(sysOrigin), eq(countryCode), anySet(), + eq(billBelong))).thenReturn(List.of(target)); + when(teamMemberService.mapByMemberIds(anySet())).thenReturn(Map.of(userId, + new TeamMember().setMemberId(userId).setTeamId(teamId))); + when(teamProfileService.mapProfileByIds(anySet())).thenReturn(Map.of(teamId, + new TeamProfile().setId(teamId).setOwnUserId(ownerUserId).setRegion(region))); + when(teamSalaryPaymentService.listByPaymentOrRecipientUserIdsAndDateNumbers(eq(sysOrigin), + anySet(), anySet())).thenReturn(List.of(existingPayment)); + when(teamPolicyManagerService.getReleaseByRegionAndType(sysOrigin, region, null, countryCode)) + .thenReturn(policyManager); + when(userBankBalanceClient.getBalance(userId)) + .thenReturn(ResultResponse.success(BankBalanceDTO.of(0L))); + + List results = service.pay(new TeamManualSalaryPaymentCmd() + .setSysOrigin(sysOrigin) + .setCountryCode(countryCode) + .setUserIds(List.of(userId))); + + assertEquals(0, results.size()); + verify(teamSalaryPaymentService, never()).createIfAbsent(anyLong(), any(), anyString()); + verify(userBankBalanceClient, never()).incr(any()); + verify(userBankRunningWaterClient, never()).add(any()); + verify(teamSalaryPaymentService, never()).paymentSalary(anyString(), any()); + } + + @Test + void payShouldOnlyIssueMemberSalaryForNormalAnchor() { + RedisService redisService = mock(RedisService.class); + TeamMemberService teamMemberService = mock(TeamMemberService.class); + TeamProfileService teamProfileService = mock(TeamProfileService.class); + UserBankBalanceClient userBankBalanceClient = mock(UserBankBalanceClient.class); + TeamMemberTargetService teamMemberTargetService = mock(TeamMemberTargetService.class); + TeamSalaryPaymentService teamSalaryPaymentService = mock(TeamSalaryPaymentService.class); + TeamPolicyManagerService teamPolicyManagerService = mock(TeamPolicyManagerService.class); + UserBankRunningWaterClient userBankRunningWaterClient = mock(UserBankRunningWaterClient.class); + TeamManualSalaryPaymentClientServiceImpl service = new TeamManualSalaryPaymentClientServiceImpl( + redisService, teamMemberService, teamProfileService, userBankBalanceClient, + teamMemberTargetService, teamSalaryPaymentService, teamPolicyManagerService, + userBankRunningWaterClient); + + String sysOrigin = "LIKEI"; + String countryCode = "PH"; + String region = "2046067717605224449"; + Long userId = 2052023053021409281L; + Long ownerUserId = 2051169779338768386L; + Long teamId = 2051672510944047106L; + Integer billBelong = TeamBillCycleUtils.getCalcBillBelong(); + String paymentId = userId + "_" + billBelong; + TeamMemberTarget target = manualSalaryTarget(sysOrigin, countryCode, region, userId, teamId, + billBelong); + TeamPolicyManager policyManager = manualSalaryPolicy(sysOrigin, countryCode, region); + + when(redisService.lock(anyString(), anyLong())).thenReturn(true); + when(teamMemberTargetService.listManualSalaryTargets(eq(sysOrigin), eq(countryCode), anySet(), + eq(billBelong))).thenReturn(List.of(target)); + when(teamMemberService.mapByMemberIds(anySet())).thenReturn(Map.of(userId, + new TeamMember().setMemberId(userId).setTeamId(teamId).setRole(TeamMemberRole.MEMBER))); + when(teamProfileService.mapProfileByIds(anySet())).thenReturn(Map.of(teamId, + new TeamProfile().setId(teamId).setOwnUserId(ownerUserId).setRegion(region))); + when(teamSalaryPaymentService.listByPaymentOrRecipientUserIdsAndDateNumbers(eq(sysOrigin), + anySet(), anySet())).thenReturn(List.of()); + when(teamPolicyManagerService.getReleaseByRegionAndType(sysOrigin, region, null, countryCode)) + .thenReturn(policyManager); + when(teamSalaryPaymentService.createIfAbsent(userId, billBelong, sysOrigin)) + .thenReturn(new TeamSalaryPayment().setId(paymentId)); + when(userBankBalanceClient.getBalance(userId)) + .thenReturn(ResultResponse.success(BankBalanceDTO.of(0L))) + .thenReturn(ResultResponse.success(BankBalanceDTO.of(800L))); + when(userBankBalanceClient.incr(any())).thenReturn(ResultResponse.success(Boolean.TRUE)); + when(userBankRunningWaterClient.add(any())).thenReturn(ResultResponse.success()); + when(teamSalaryPaymentService.mapPolicy(paymentId)).thenReturn(new HashMap<>()); + + List results = service.pay(new TeamManualSalaryPaymentCmd() + .setSysOrigin(sysOrigin) + .setCountryCode(countryCode) + .setUserIds(List.of(userId))); + + assertEquals(1, results.size()); + assertEquals(userId, results.get(0).getUserId()); + assertEquals(new BigDecimal("8.00"), results.get(0).getIssuedSalary()); + ArgumentCaptor detailsCaptor = + ArgumentCaptor.forClass(TeamSalaryPaymentDetails.class); + verify(teamSalaryPaymentService).paymentSalary(eq(paymentId), detailsCaptor.capture()); + assertEquals(Boolean.TRUE, detailsCaptor.getValue().getAnchor()); + assertEquals(new BigDecimal("8.00"), detailsCaptor.getValue().getSalary()); + } + + @Test + void payShouldIssueMemberAndAgentSalaryWhenAnchorIsTeamOwner() { + RedisService redisService = mock(RedisService.class); + TeamMemberService teamMemberService = mock(TeamMemberService.class); + TeamProfileService teamProfileService = mock(TeamProfileService.class); + UserBankBalanceClient userBankBalanceClient = mock(UserBankBalanceClient.class); + TeamMemberTargetService teamMemberTargetService = mock(TeamMemberTargetService.class); + TeamSalaryPaymentService teamSalaryPaymentService = mock(TeamSalaryPaymentService.class); + TeamPolicyManagerService teamPolicyManagerService = mock(TeamPolicyManagerService.class); + UserBankRunningWaterClient userBankRunningWaterClient = mock(UserBankRunningWaterClient.class); + TeamManualSalaryPaymentClientServiceImpl service = new TeamManualSalaryPaymentClientServiceImpl( + redisService, teamMemberService, teamProfileService, userBankBalanceClient, + teamMemberTargetService, teamSalaryPaymentService, teamPolicyManagerService, + userBankRunningWaterClient); + + String sysOrigin = "LIKEI"; + String countryCode = "PH"; + String region = "2046067717605224449"; + Long userId = 2052023053021409281L; + Long teamId = 2051672510944047106L; + Integer billBelong = TeamBillCycleUtils.getCalcBillBelong(); + String paymentId = userId + "_" + billBelong; + TeamMemberTarget target = manualSalaryTarget(sysOrigin, countryCode, region, userId, teamId, + billBelong); + TeamPolicyManager policyManager = manualSalaryPolicy(sysOrigin, countryCode, region); + + when(redisService.lock(anyString(), anyLong())).thenReturn(true); + when(teamMemberTargetService.listManualSalaryTargets(eq(sysOrigin), eq(countryCode), anySet(), + eq(billBelong))).thenReturn(List.of(target)); + when(teamMemberService.mapByMemberIds(anySet())).thenReturn(Map.of(userId, + new TeamMember().setMemberId(userId).setTeamId(teamId).setRole(TeamMemberRole.OWN))); + when(teamProfileService.mapProfileByIds(anySet())).thenReturn(Map.of(teamId, + new TeamProfile().setId(teamId).setOwnUserId(userId).setRegion(region))); + when(teamSalaryPaymentService.listByPaymentOrRecipientUserIdsAndDateNumbers(eq(sysOrigin), + anySet(), anySet())).thenReturn(List.of()); + when(teamPolicyManagerService.getReleaseByRegionAndType(sysOrigin, region, null, countryCode)) + .thenReturn(policyManager); + when(teamSalaryPaymentService.createIfAbsent(userId, billBelong, sysOrigin)) + .thenReturn(new TeamSalaryPayment().setId(paymentId)); + when(userBankBalanceClient.getBalance(userId)) + .thenReturn(ResultResponse.success(BankBalanceDTO.of(0L))) + .thenReturn(ResultResponse.success(BankBalanceDTO.of(800L))) + .thenReturn(ResultResponse.success(BankBalanceDTO.of(800L))) + .thenReturn(ResultResponse.success(BankBalanceDTO.of(1000L))); + when(userBankBalanceClient.incr(any())).thenReturn(ResultResponse.success(Boolean.TRUE)); + when(userBankRunningWaterClient.add(any())).thenReturn(ResultResponse.success()); + when(teamSalaryPaymentService.mapPolicy(paymentId)).thenReturn(new HashMap<>()); + + List results = service.pay(new TeamManualSalaryPaymentCmd() + .setSysOrigin(sysOrigin) + .setCountryCode(countryCode) + .setUserIds(List.of(userId))); + + assertEquals(2, results.size()); + assertEquals(new BigDecimal("8.00"), results.get(0).getIssuedSalary()); + assertEquals(new BigDecimal("2.00"), results.get(1).getIssuedSalary()); + ArgumentCaptor detailsCaptor = + ArgumentCaptor.forClass(TeamSalaryPaymentDetails.class); + verify(teamSalaryPaymentService, org.mockito.Mockito.times(2)).paymentSalary(eq(paymentId), + detailsCaptor.capture()); + assertEquals(Boolean.TRUE, detailsCaptor.getAllValues().get(0).getAnchor()); + assertEquals(Boolean.FALSE, detailsCaptor.getAllValues().get(1).getAnchor()); + } + private Object paymentSummary(BigDecimal totalIssuedSalary, BigDecimal memberIssuedSalary, BigDecimal agentIssuedSalary) throws Exception { Class summaryClass = Class.forName( @@ -236,4 +458,36 @@ class TeamManualSalaryPaymentClientServiceImplTest { BigDecimal.ZERO.setScale(2), BigDecimal.ZERO.setScale(2)); } + + private TeamMemberTarget manualSalaryTarget(String sysOrigin, String countryCode, String region, + Long userId, Long teamId, Integer billBelong) { + return new TeamMemberTarget() + .setId("target-id") + .setTimeId(1779030072251003137L) + .setSysOrigin(sysOrigin) + .setRegion(region) + .setCountryCode(countryCode) + .setTeamId(teamId) + .setUserId(userId) + .setBillBelong(billBelong) + .setDailyTargets(List.of(new TeamMemberTargetIndex() + .setOwnOnlineTime(4586L) + .setAcceptGiftValue(2104843L))); + } + + private TeamPolicyManager manualSalaryPolicy(String sysOrigin, String countryCode, + String region) { + return new TeamPolicyManager() + .setSysOrigin(sysOrigin) + .setRegion(region) + .setCountryCode(countryCode) + .setPolicy(List.of(new TeamPolicy() + .setLevel(4) + .setTarget(2000000L) + .setOnlineTime(10L) + .setEffectiveDay(0) + .setMemberSalary(new BigDecimal("8.00")) + .setOwnSalary(new BigDecimal("2.00")) + .setTotalSalary(new BigDecimal("10.00")))); + } }