fix manual salary settlement net payable
This commit is contained in:
parent
a48fddb613
commit
3cef4fc322
@ -31,4 +31,14 @@ public class TeamManualSalaryPaymentQryCmd extends PageCommand {
|
|||||||
* 用户 id.
|
* 用户 id.
|
||||||
*/
|
*/
|
||||||
private Long userId;
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序字段.
|
||||||
|
*/
|
||||||
|
private String sortField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序方向.
|
||||||
|
*/
|
||||||
|
private String sortOrder;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,12 @@ public class TeamManualSalaryPaymentDTO implements Serializable {
|
|||||||
private Boolean satisfyLevel;
|
private Boolean satisfyLevel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应发工资.
|
* 当前账期按积分档位计算出的工资.
|
||||||
|
*/
|
||||||
|
private BigDecimal expectedSalary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 待结算工资 = 当前账期应发工资 - 当前账期实收工资.
|
||||||
*/
|
*/
|
||||||
private BigDecimal payableSalary;
|
private BigDecimal payableSalary;
|
||||||
|
|
||||||
@ -91,6 +96,11 @@ public class TeamManualSalaryPaymentDTO implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private BigDecimal totalIssuedSalary;
|
private BigDecimal totalIssuedSalary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前账期多发工资.
|
||||||
|
*/
|
||||||
|
private BigDecimal overIssuedSalary;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前工资余额.
|
* 当前工资余额.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -215,8 +215,10 @@ public class TeamSalaryBackServiceImpl implements TeamSalaryBackService {
|
|||||||
.setCurrentTarget(dto.getCurrentTarget())
|
.setCurrentTarget(dto.getCurrentTarget())
|
||||||
.setPolicyLevel(dto.getPolicyLevel())
|
.setPolicyLevel(dto.getPolicyLevel())
|
||||||
.setSatisfyLevel(dto.getSatisfyLevel())
|
.setSatisfyLevel(dto.getSatisfyLevel())
|
||||||
|
.setExpectedSalary(dto.getExpectedSalary())
|
||||||
.setPayableSalary(dto.getPayableSalary())
|
.setPayableSalary(dto.getPayableSalary())
|
||||||
.setTotalIssuedSalary(dto.getTotalIssuedSalary())
|
.setTotalIssuedSalary(dto.getTotalIssuedSalary())
|
||||||
|
.setOverIssuedSalary(dto.getOverIssuedSalary())
|
||||||
.setCurrentSalaryBalance(dto.getCurrentSalaryBalance())
|
.setCurrentSalaryBalance(dto.getCurrentSalaryBalance())
|
||||||
.setPaid(dto.getPaid());
|
.setPaid(dto.getPaid());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -39,8 +39,10 @@ public class TeamManualSalaryCO implements Serializable {
|
|||||||
private Long currentTarget;
|
private Long currentTarget;
|
||||||
private Integer policyLevel;
|
private Integer policyLevel;
|
||||||
private Boolean satisfyLevel;
|
private Boolean satisfyLevel;
|
||||||
|
private BigDecimal expectedSalary;
|
||||||
private BigDecimal payableSalary;
|
private BigDecimal payableSalary;
|
||||||
private BigDecimal totalIssuedSalary;
|
private BigDecimal totalIssuedSalary;
|
||||||
|
private BigDecimal overIssuedSalary;
|
||||||
private BigDecimal currentSalaryBalance;
|
private BigDecimal currentSalaryBalance;
|
||||||
private Boolean paid;
|
private Boolean paid;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import com.red.circle.other.infra.database.mongo.entity.team.team.TeamPolicyMana
|
|||||||
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamSalaryPayment;
|
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamSalaryPayment;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 团队工资实时支付记录.
|
* 团队工资实时支付记录.
|
||||||
@ -82,6 +83,12 @@ public interface TeamSalaryPaymentService {
|
|||||||
*/
|
*/
|
||||||
TeamSalaryPayment getOneById(String id);
|
TeamSalaryPayment getOneById(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按用户和账期批量获得数据.
|
||||||
|
*/
|
||||||
|
Map<String, TeamSalaryPayment> mapByUserIdsAndDateNumbers(String sysOrigin, Set<Long> userIds,
|
||||||
|
Set<Integer> dateNumbers);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于父ID修改子记录状态为已退款.
|
* 基于父ID修改子记录状态为已退款.
|
||||||
*
|
*
|
||||||
|
|||||||
@ -17,6 +17,8 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||||
@ -183,6 +185,26 @@ public class TeamSalaryPaymentServiceImpl implements TeamSalaryPaymentService {
|
|||||||
return mongoTemplate.findOne(Query.query(Criteria.where("id").is(id)), TeamSalaryPayment.class);
|
return mongoTemplate.findOne(Query.query(Criteria.where("id").is(id)), TeamSalaryPayment.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, TeamSalaryPayment> mapByUserIdsAndDateNumbers(String sysOrigin,
|
||||||
|
Set<Long> userIds, Set<Integer> dateNumbers) {
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(sysOrigin) || CollectionUtils.isEmpty(userIds)
|
||||||
|
|| CollectionUtils.isEmpty(dateNumbers)) {
|
||||||
|
return Maps.newHashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
Criteria criteria = Criteria.where("sysOrigin").is(sysOrigin)
|
||||||
|
.and("userId").in(userIds)
|
||||||
|
.and("dateNumber").in(dateNumbers);
|
||||||
|
|
||||||
|
return mongoTemplate.find(Query.query(criteria), TeamSalaryPayment.class)
|
||||||
|
.stream()
|
||||||
|
.filter(payment -> StringUtils.isNotBlank(payment.getId()))
|
||||||
|
.collect(Collectors.toMap(TeamSalaryPayment::getId, payment -> payment,
|
||||||
|
(first, second) -> first));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateDetails(String id, List<TeamSalaryPaymentDetails> salarySendDetails) {
|
public void updateDetails(String id, List<TeamSalaryPaymentDetails> salarySendDetails) {
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,7 @@ import java.math.RoundingMode;
|
|||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -65,6 +66,11 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
|
|
||||||
private static final String MANUAL_SALARY_LOCK_PREFIX = "TeamManualSalaryPayment:";
|
private static final String MANUAL_SALARY_LOCK_PREFIX = "TeamManualSalaryPayment:";
|
||||||
private static final int LOCK_SECONDS = 300;
|
private static final int LOCK_SECONDS = 300;
|
||||||
|
private static final String SORT_FIELD_CURRENT_SALARY_BALANCE = "currentSalaryBalance";
|
||||||
|
private static final String SORT_FIELD_PAYABLE_SALARY = "payableSalary";
|
||||||
|
private static final String SORT_FIELD_TOTAL_ISSUED_SALARY = "totalIssuedSalary";
|
||||||
|
private static final String SORT_ORDER_ASCEND = "ascend";
|
||||||
|
private static final int LEGACY_HALF_MONTH_COMPAT_BILL_BELONG = 202605;
|
||||||
|
|
||||||
private final RedisService redisService;
|
private final RedisService redisService;
|
||||||
private final TeamMemberService teamMemberService;
|
private final TeamMemberService teamMemberService;
|
||||||
@ -81,6 +87,7 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
|
|
||||||
List<ManualSalaryRow> rows = buildRows(cmd.getSysOrigin(), cmd.getCountryCode(),
|
List<ManualSalaryRow> rows = buildRows(cmd.getSysOrigin(), cmd.getCountryCode(),
|
||||||
singletonUserId(cmd.getUserId()), TeamBillCycleUtils.getCalcBillBelong());
|
singletonUserId(cmd.getUserId()), TeamBillCycleUtils.getCalcBillBelong());
|
||||||
|
rows = sortRows(rows, cmd.getSortField(), cmd.getSortOrder());
|
||||||
|
|
||||||
int cursor = 1;
|
int cursor = 1;
|
||||||
int limit = 20;
|
int limit = 20;
|
||||||
@ -132,18 +139,28 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
continue;
|
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(row.getUserId());
|
||||||
String detailsId = IdWorkerUtils.getIdStr();
|
String detailsId = IdWorkerUtils.getIdStr();
|
||||||
|
|
||||||
|
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(row.getUserId())
|
||||||
.setSysOrigin(row.getSysOrigin())
|
.setSysOrigin(row.getSysOrigin())
|
||||||
.setAmount(PennyAmount.ofDollar(policyPayment.getSalary()))));
|
.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(row.getUserId());
|
||||||
|
if (issueSalary.compareTo(BigDecimal.ZERO) > 0) {
|
||||||
addRunningWater(detailsId, row.getUserId(), row.getSysOrigin(),
|
addRunningWater(detailsId, row.getUserId(), row.getSysOrigin(),
|
||||||
policyPayment.getSalary(), afterBalance, cmd.getOperationUserId());
|
issueSalary, afterBalance, cmd.getOperationUserId());
|
||||||
|
}
|
||||||
|
String settlementRemark = issueSalary.compareTo(BigDecimal.ZERO) > 0
|
||||||
|
? "后台手动发放主播工资"
|
||||||
|
: "后台手动结算主播工资,实收已大于等于应发,本次发放0";
|
||||||
|
|
||||||
teamSalaryPaymentService.paymentSalary(payment.getId(), new TeamSalaryPaymentDetails()
|
teamSalaryPaymentService.paymentSalary(payment.getId(), new TeamSalaryPaymentDetails()
|
||||||
.setId(detailsId)
|
.setId(detailsId)
|
||||||
@ -155,12 +172,12 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
.setTeamBillId(Long.valueOf(billBelong))
|
.setTeamBillId(Long.valueOf(billBelong))
|
||||||
.setTeamRegionId(row.getRegion())
|
.setTeamRegionId(row.getRegion())
|
||||||
.setRemarks(List.of(new TeamSalaryPaymentRemark()
|
.setRemarks(List.of(new TeamSalaryPaymentRemark()
|
||||||
.setRemark("后台手动发放主播工资")
|
.setRemark(settlementRemark)
|
||||||
.setCreateTime(TimestampUtils.now())))
|
.setCreateTime(TimestampUtils.now())))
|
||||||
.setAnchor(Boolean.TRUE)
|
.setAnchor(Boolean.TRUE)
|
||||||
.setHostSalaryToAgent(Boolean.FALSE)
|
.setHostSalaryToAgent(Boolean.FALSE)
|
||||||
.setTarget(row.getCurrentTarget())
|
.setTarget(row.getCurrentTarget())
|
||||||
.setSalary(policyPayment.getSalary())
|
.setSalary(issueSalary)
|
||||||
.setPolicyLevel(policyPayment.getLevel())
|
.setPolicyLevel(policyPayment.getLevel())
|
||||||
.setPolicy(policyPayment.getPolicy()));
|
.setPolicy(policyPayment.getPolicy()));
|
||||||
|
|
||||||
@ -177,7 +194,7 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
.setBillBelong(billBelong)
|
.setBillBelong(billBelong)
|
||||||
.setBeforeSalaryBalance(beforeBalance)
|
.setBeforeSalaryBalance(beforeBalance)
|
||||||
.setAfterSalaryBalance(afterBalance)
|
.setAfterSalaryBalance(afterBalance)
|
||||||
.setIssuedSalary(policyPayment.getSalary())
|
.setIssuedSalary(issueSalary)
|
||||||
.setCurrentTarget(row.getCurrentTarget())
|
.setCurrentTarget(row.getCurrentTarget())
|
||||||
.setPolicyLevel(policyPayment.getLevel()));
|
.setPolicyLevel(policyPayment.getLevel()));
|
||||||
}
|
}
|
||||||
@ -215,17 +232,55 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
Map<Long, TeamMember> memberMap = teamMemberService.mapByMemberIds(memberIds);
|
Map<Long, TeamMember> memberMap = teamMemberService.mapByMemberIds(memberIds);
|
||||||
Map<Long, TeamProfile> teamProfileMap = teamProfileService.mapProfileByIds(teamIds);
|
Map<Long, TeamProfile> teamProfileMap = teamProfileService.mapProfileByIds(teamIds);
|
||||||
|
Map<String, TeamSalaryPayment> salaryPaymentMap =
|
||||||
|
teamSalaryPaymentService.mapByUserIdsAndDateNumbers(sysOrigin, memberIds,
|
||||||
|
getMergedSalaryPaymentBillBelongs(billBelong));
|
||||||
|
|
||||||
Map<String, TeamPolicyManager> policyCache = CollectionUtils.newHashMap();
|
Map<String, TeamPolicyManager> policyCache = CollectionUtils.newHashMap();
|
||||||
return targets.stream()
|
return targets.stream()
|
||||||
.map(target -> buildRow(target, memberMap, teamProfileMap, policyCache, billBelong,
|
.map(target -> buildRow(target, memberMap, teamProfileMap, policyCache, billBelong,
|
||||||
countryCode))
|
countryCode, salaryPaymentMap))
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.sorted(Comparator.comparing(ManualSalaryRow::getCurrentTarget).reversed()
|
.sorted(Comparator.comparing(ManualSalaryRow::getCurrentTarget).reversed()
|
||||||
.thenComparing(ManualSalaryRow::getUserId))
|
.thenComparing(ManualSalaryRow::getUserId))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<ManualSalaryRow> sortRows(List<ManualSalaryRow> rows, String sortField,
|
||||||
|
String sortOrder) {
|
||||||
|
if (CollectionUtils.isEmpty(rows) || StringUtils.isBlank(sortField)
|
||||||
|
|| StringUtils.isBlank(sortOrder)) {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
Comparator<ManualSalaryRow> comparator = getSalarySortComparator(sortField);
|
||||||
|
if (Objects.isNull(comparator)) {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
if (!SORT_ORDER_ASCEND.equalsIgnoreCase(sortOrder)) {
|
||||||
|
comparator = comparator.reversed();
|
||||||
|
}
|
||||||
|
return rows.stream()
|
||||||
|
.sorted(comparator.thenComparing(ManualSalaryRow::getUserId))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Comparator<ManualSalaryRow> getSalarySortComparator(String sortField) {
|
||||||
|
if (SORT_FIELD_PAYABLE_SALARY.equals(sortField)) {
|
||||||
|
return Comparator.comparing(row -> decimalValue(row.getPayableSalary()));
|
||||||
|
}
|
||||||
|
if (SORT_FIELD_TOTAL_ISSUED_SALARY.equals(sortField)) {
|
||||||
|
return Comparator.comparing(row -> decimalValue(row.getTotalIssuedSalary()));
|
||||||
|
}
|
||||||
|
if (SORT_FIELD_CURRENT_SALARY_BALANCE.equals(sortField)) {
|
||||||
|
return Comparator.comparing(row -> decimalValue(row.getCurrentSalaryBalance()));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal decimalValue(BigDecimal value) {
|
||||||
|
return Objects.isNull(value) ? BigDecimal.ZERO : value;
|
||||||
|
}
|
||||||
|
|
||||||
private Set<Long> singletonUserId(Long userId) {
|
private Set<Long> singletonUserId(Long userId) {
|
||||||
if (Objects.isNull(userId)) {
|
if (Objects.isNull(userId)) {
|
||||||
return Set.of();
|
return Set.of();
|
||||||
@ -242,9 +297,36 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Set<Integer> getMergedSalaryPaymentBillBelongs(Integer billBelong) {
|
||||||
|
if (Objects.isNull(billBelong)) {
|
||||||
|
return Set.of();
|
||||||
|
}
|
||||||
|
Set<Integer> billBelongs = new HashSet<>();
|
||||||
|
billBelongs.add(billBelong);
|
||||||
|
Integer month = TeamBillCycleUtils.extractMonth(billBelong);
|
||||||
|
if (Objects.equals(month, LEGACY_HALF_MONTH_COMPAT_BILL_BELONG)) {
|
||||||
|
billBelongs.add(month);
|
||||||
|
billBelongs.add(month * 100 + 1);
|
||||||
|
billBelongs.add(month * 100 + 16);
|
||||||
|
}
|
||||||
|
return billBelongs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TeamSalaryPayment> listCyclePayments(
|
||||||
|
Map<String, TeamSalaryPayment> salaryPaymentMap, Long userId, Integer billBelong) {
|
||||||
|
if (Objects.isNull(userId) || CollectionUtils.isEmpty(salaryPaymentMap)) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return getMergedSalaryPaymentBillBelongs(billBelong).stream()
|
||||||
|
.map(item -> salaryPaymentMap.get(paymentId(userId, item)))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
private ManualSalaryRow buildRow(TeamMemberTarget target, Map<Long, TeamMember> memberMap,
|
private ManualSalaryRow buildRow(TeamMemberTarget target, Map<Long, TeamMember> memberMap,
|
||||||
Map<Long, TeamProfile> teamProfileMap, Map<String, TeamPolicyManager> policyCache,
|
Map<Long, TeamProfile> teamProfileMap, Map<String, TeamPolicyManager> policyCache,
|
||||||
Integer billBelong, String requestedCountryCode) {
|
Integer billBelong, String requestedCountryCode,
|
||||||
|
Map<String, TeamSalaryPayment> salaryPaymentMap) {
|
||||||
TeamMember member = memberMap.get(target.getUserId());
|
TeamMember member = memberMap.get(target.getUserId());
|
||||||
TeamProfile teamProfile = teamProfileMap.get(target.getTeamId());
|
TeamProfile teamProfile = teamProfileMap.get(target.getTeamId());
|
||||||
if (Objects.isNull(member) || Objects.isNull(teamProfile)
|
if (Objects.isNull(member) || Objects.isNull(teamProfile)
|
||||||
@ -264,14 +346,16 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
policyCache);
|
policyCache);
|
||||||
TeamBillMemberTarget billTarget = calculateBillTarget(target, policyManager);
|
TeamBillMemberTarget billTarget = calculateBillTarget(target, policyManager);
|
||||||
|
|
||||||
TeamSalaryPayment payment = teamSalaryPaymentService.getOneById(paymentId(target.getUserId(),
|
List<TeamSalaryPayment> cyclePayments = listCyclePayments(salaryPaymentMap,
|
||||||
billBelong));
|
target.getUserId(), billBelong);
|
||||||
List<PolicyPayment> policyPayments = listUnpaidPolicyPayments(policyManager, billTarget,
|
PaymentSummary paymentSummary = summarizePayments(cyclePayments);
|
||||||
payment, target.getUserId(), region);
|
BigDecimal expectedSalary = expectedMemberSalary(billTarget);
|
||||||
BigDecimal payableSalary = policyPayments.stream()
|
BigDecimal payableSalary = expectedSalary.subtract(paymentSummary.getTotalIssuedSalary())
|
||||||
.map(PolicyPayment::getSalary)
|
|
||||||
.reduce(BigDecimal.ZERO, BigDecimal::add)
|
|
||||||
.setScale(2, RoundingMode.DOWN);
|
.setScale(2, RoundingMode.DOWN);
|
||||||
|
boolean currentLevelSettled = isCurrentLevelSettled(cyclePayments, target.getUserId(), region,
|
||||||
|
billTarget.getLevel(), payableSalary);
|
||||||
|
List<PolicyPayment> policyPayments = buildSettlementPayments(policyManager, billTarget,
|
||||||
|
payableSalary, currentLevelSettled);
|
||||||
|
|
||||||
TeamManualSalaryPaymentDTO dto = new TeamManualSalaryPaymentDTO()
|
TeamManualSalaryPaymentDTO dto = new TeamManualSalaryPaymentDTO()
|
||||||
.setId(target.getId())
|
.setId(target.getId())
|
||||||
@ -282,15 +366,16 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
.setTeamOwnId(teamProfile.getOwnUserId())
|
.setTeamOwnId(teamProfile.getOwnUserId())
|
||||||
.setUserId(target.getUserId())
|
.setUserId(target.getUserId())
|
||||||
.setBillBelong(billBelong)
|
.setBillBelong(billBelong)
|
||||||
.setLastSettlementTarget(getLastSettlementTarget(payment))
|
.setLastSettlementTarget(getLastSettlementTarget(cyclePayments))
|
||||||
.setCurrentTarget(target.sumAcceptGiftValue())
|
.setCurrentTarget(target.sumAcceptGiftValue())
|
||||||
.setPolicyLevel(billTarget.getLevel())
|
.setPolicyLevel(billTarget.getLevel())
|
||||||
.setSatisfyLevel(billTarget.getSatisfyLevel())
|
.setSatisfyLevel(billTarget.getSatisfyLevel())
|
||||||
|
.setExpectedSalary(expectedSalary)
|
||||||
.setPayableSalary(payableSalary)
|
.setPayableSalary(payableSalary)
|
||||||
.setTotalIssuedSalary(getTotalIssuedSalary(payment))
|
.setTotalIssuedSalary(paymentSummary.getTotalIssuedSalary())
|
||||||
|
.setOverIssuedSalary(paymentSummary.getOverIssuedSalary())
|
||||||
.setCurrentSalaryBalance(getAccurateBalance(target.getUserId()))
|
.setCurrentSalaryBalance(getAccurateBalance(target.getUserId()))
|
||||||
.setPaid(Objects.nonNull(billTarget.getLevel())
|
.setPaid(currentLevelSettled);
|
||||||
&& BigDecimal.ZERO.compareTo(payableSalary) == 0);
|
|
||||||
|
|
||||||
return new ManualSalaryRow(dto, target, teamProfile, policyManager, billTarget, policyPayments);
|
return new ManualSalaryRow(dto, target, teamProfile, policyManager, billTarget, policyPayments);
|
||||||
}
|
}
|
||||||
@ -345,51 +430,55 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
.setSatisfyLevel(Boolean.FALSE);
|
.setSatisfyLevel(Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PolicyPayment> listUnpaidPolicyPayments(TeamPolicyManager policyManager,
|
private BigDecimal expectedMemberSalary(TeamBillMemberTarget billTarget) {
|
||||||
TeamBillMemberTarget billTarget, TeamSalaryPayment payment, Long userId, String region) {
|
return Optional.ofNullable(billTarget)
|
||||||
if (Objects.isNull(policyManager) || CollectionUtils.isEmpty(policyManager.getPolicy())
|
.map(TeamBillMemberTarget::getMemberSalary)
|
||||||
|
.orElse(BigDecimal.ZERO)
|
||||||
|
.setScale(2, RoundingMode.DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PolicyPayment> buildSettlementPayments(TeamPolicyManager policyManager,
|
||||||
|
TeamBillMemberTarget billTarget, BigDecimal payableSalary, boolean currentLevelSettled) {
|
||||||
|
if (currentLevelSettled || Objects.isNull(billTarget)
|
||||||
|| Objects.isNull(billTarget.getLevel())) {
|
|| Objects.isNull(billTarget.getLevel())) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TeamPolicy> completePolicies = policyManager.getPolicy().stream()
|
BigDecimal issueSalary = payableSalary.compareTo(BigDecimal.ZERO) > 0
|
||||||
.filter(policy -> Objects.nonNull(policy.getLevel()))
|
? payableSalary.setScale(2, RoundingMode.DOWN)
|
||||||
.filter(policy -> policy.getLevel() <= billTarget.getLevel())
|
: BigDecimal.ZERO.setScale(2, RoundingMode.DOWN);
|
||||||
.sorted(Comparator.comparing(TeamPolicy::getLevel))
|
return List.of(new PolicyPayment(findPolicy(policyManager, billTarget.getLevel()),
|
||||||
.collect(Collectors.toList());
|
billTarget.getLevel(), issueSalary));
|
||||||
if (CollectionUtils.isEmpty(completePolicies)) {
|
|
||||||
return List.of();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PolicyPayment> payments = new ArrayList<>();
|
private TeamPolicy findPolicy(TeamPolicyManager policyManager, Integer level) {
|
||||||
for (int i = 0; i < completePolicies.size(); i++) {
|
if (Objects.isNull(policyManager) || CollectionUtils.isEmpty(policyManager.getPolicy())
|
||||||
TeamPolicy policy = completePolicies.get(i);
|
|| Objects.isNull(level)) {
|
||||||
if (Objects.nonNull(payment) && Boolean.TRUE.equals(
|
return null;
|
||||||
teamSalaryPaymentService.checkRepeatPayment(payment.getId(), userId, region,
|
}
|
||||||
policy.getLevel(), Boolean.TRUE))) {
|
return policyManager.getPolicy().stream()
|
||||||
continue;
|
.filter(policy -> Objects.equals(policy.getLevel(), level))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
BigDecimal salary = Optional.ofNullable(policy.getMemberSalary()).orElse(BigDecimal.ZERO);
|
private boolean isCurrentLevelSettled(List<TeamSalaryPayment> cyclePayments, Long userId,
|
||||||
if (i > 0) {
|
String region, Integer policyLevel, BigDecimal payableSalary) {
|
||||||
salary = salary.subtract(Optional.ofNullable(completePolicies.get(i - 1).getMemberSalary())
|
return Objects.nonNull(policyLevel)
|
||||||
.orElse(BigDecimal.ZERO));
|
&& payableSalary.compareTo(BigDecimal.ZERO) <= 0
|
||||||
}
|
&& hasPaidPolicy(cyclePayments, userId, region, policyLevel);
|
||||||
salary = salary.setScale(2, RoundingMode.DOWN);
|
|
||||||
if (salary.compareTo(BigDecimal.ZERO) <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
payments.add(new PolicyPayment(policy, policy.getLevel(), salary));
|
private boolean hasPaidPolicy(List<TeamSalaryPayment> cyclePayments, Long userId, String region,
|
||||||
}
|
Integer policyLevel) {
|
||||||
return payments;
|
return listValidAnchorDetails(cyclePayments).stream()
|
||||||
|
.anyMatch(details -> Objects.equals(details.getTeamMemberId(), userId)
|
||||||
|
&& Objects.equals(details.getTeamRegionId(), region)
|
||||||
|
&& Objects.equals(details.getPolicyLevel(), policyLevel));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Long getLastSettlementTarget(TeamSalaryPayment payment) {
|
private Long getLastSettlementTarget(List<TeamSalaryPayment> cyclePayments) {
|
||||||
return Optional.ofNullable(payment)
|
return listValidAnchorDetails(cyclePayments).stream()
|
||||||
.map(TeamSalaryPayment::getSalarySendDetails)
|
|
||||||
.stream()
|
|
||||||
.flatMap(List::stream)
|
|
||||||
.filter(this::validAnchorDetails)
|
.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))))
|
||||||
@ -397,15 +486,54 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
.orElse(0L);
|
.orElse(0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal getTotalIssuedSalary(TeamSalaryPayment payment) {
|
private PaymentSummary summarizePayments(List<TeamSalaryPayment> cyclePayments) {
|
||||||
return Optional.ofNullable(payment)
|
List<TeamSalaryPaymentDetails> details = listValidAnchorDetails(cyclePayments);
|
||||||
.map(TeamSalaryPayment::getSalarySendDetails)
|
BigDecimal totalIssuedSalary = details.stream()
|
||||||
.stream()
|
.map(detail -> Optional.ofNullable(detail.getSalary()).orElse(BigDecimal.ZERO))
|
||||||
.flatMap(List::stream)
|
|
||||||
.filter(this::validAnchorDetails)
|
|
||||||
.map(details -> Optional.ofNullable(details.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) {
|
||||||
|
if (CollectionUtils.isEmpty(details)) {
|
||||||
|
return BigDecimal.ZERO.setScale(2, RoundingMode.DOWN);
|
||||||
|
}
|
||||||
|
Set<String> issuedKeys = new HashSet<>();
|
||||||
|
return details.stream()
|
||||||
|
.sorted(Comparator.comparing(detail -> Optional.ofNullable(detail.getCreateTime())
|
||||||
|
.orElse(new Timestamp(0))))
|
||||||
|
.filter(detail -> !issuedKeys.add(paymentDetailsPolicyKey(detail)))
|
||||||
|
.map(detail -> Optional.ofNullable(detail.getSalary()).orElse(BigDecimal.ZERO))
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add)
|
||||||
|
.setScale(2, RoundingMode.DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String paymentDetailsPolicyKey(TeamSalaryPaymentDetails details) {
|
||||||
|
if (Objects.isNull(details)
|
||||||
|
|| Objects.isNull(details.getTeamMemberId())
|
||||||
|
|| StringUtils.isBlank(details.getTeamRegionId())
|
||||||
|
|| Objects.isNull(details.getPolicyLevel())
|
||||||
|
|| Objects.isNull(details.getAnchor())) {
|
||||||
|
return Optional.ofNullable(details).map(TeamSalaryPaymentDetails::getId)
|
||||||
|
.orElse(String.valueOf(System.identityHashCode(details)));
|
||||||
|
}
|
||||||
|
return details.getTeamMemberId() + ":" + details.getTeamRegionId() + ":"
|
||||||
|
+ details.getPolicyLevel() + ":" + details.getAnchor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TeamSalaryPaymentDetails> listValidAnchorDetails(
|
||||||
|
List<TeamSalaryPayment> cyclePayments) {
|
||||||
|
if (CollectionUtils.isEmpty(cyclePayments)) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
return cyclePayments.stream()
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.flatMap(payment -> Optional.ofNullable(payment.getSalarySendDetails())
|
||||||
|
.stream()
|
||||||
|
.flatMap(List::stream))
|
||||||
|
.filter(this::validAnchorDetails)
|
||||||
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validAnchorDetails(TeamSalaryPaymentDetails details) {
|
private boolean validAnchorDetails(TeamSalaryPaymentDetails details) {
|
||||||
@ -471,6 +599,25 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
return userId + "_" + billBelong;
|
return userId + "_" + billBelong;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class PaymentSummary {
|
||||||
|
|
||||||
|
private final BigDecimal totalIssuedSalary;
|
||||||
|
private final BigDecimal overIssuedSalary;
|
||||||
|
|
||||||
|
private PaymentSummary(BigDecimal totalIssuedSalary, BigDecimal overIssuedSalary) {
|
||||||
|
this.totalIssuedSalary = totalIssuedSalary;
|
||||||
|
this.overIssuedSalary = overIssuedSalary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getTotalIssuedSalary() {
|
||||||
|
return totalIssuedSalary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getOverIssuedSalary() {
|
||||||
|
return overIssuedSalary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class ManualSalaryRow {
|
private static class ManualSalaryRow {
|
||||||
|
|
||||||
private final TeamManualSalaryPaymentDTO dto;
|
private final TeamManualSalaryPaymentDTO dto;
|
||||||
@ -527,6 +674,18 @@ public class TeamManualSalaryPaymentClientServiceImpl implements
|
|||||||
return dto.getCurrentTarget();
|
return dto.getCurrentTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BigDecimal getPayableSalary() {
|
||||||
|
return dto.getPayableSalary();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getTotalIssuedSalary() {
|
||||||
|
return dto.getTotalIssuedSalary();
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigDecimal getCurrentSalaryBalance() {
|
||||||
|
return dto.getCurrentSalaryBalance();
|
||||||
|
}
|
||||||
|
|
||||||
private TeamPolicyManager getPolicyManager() {
|
private TeamPolicyManager getPolicyManager() {
|
||||||
return policyManager;
|
return policyManager;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user