调整收付款问题

This commit is contained in:
2026-08-31 12:40:27 +08:00
parent 12996eb739
commit 27ed35f9dd
5 changed files with 75 additions and 29 deletions
@@ -73,7 +73,6 @@ import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;
/** 付款申请服务实现。 @author Chill */
@Service
@@ -114,6 +113,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
.orderByDesc(PaymentApplication::getCreateTime);
return page(page, wrapper).convert(item -> {
PaymentApplicationVO vo = PaymentApplicationWrapper.build().entityVO(item);
if (!APPROVED.equals(item.getApprovalStatus())) vo.setPaidAmount(BigDecimal.ZERO);
return vo;
});
}
@@ -471,15 +471,14 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
}
private void validateQuota(PaymentApplication entity) {
if (!"project_advance".equals(entity.getPaymentType())) return;
BigDecimal appliedAmount = money(entity.getAppliedAmount());
ProjectApply project = entity.getProjectId() == null ? null : projectApplyMapper.selectOne(
Wrappers.<ProjectApply>lambdaQuery().eq(ProjectApply::getId, entity.getProjectId()).last("FOR UPDATE"));
if (project != null && project.getFundLimit() != null) {
BigDecimal projectLimit = projectFundLimit(project);
BigDecimal projectOccupiedAmount = quotaOccupiedAmount(Wrappers.<PaymentApplication>lambdaQuery()
.eq(PaymentApplication::getProjectId, entity.getProjectId())
.ne(entity.getId() != null, PaymentApplication::getId, entity.getId()), entity);
if (projectOccupiedAmount.compareTo(projectLimit) > 0) {
throw new ServiceException("申请付款金额超过项目剩余资金使用额度(已扣减收票金额并包含在途申请)");
if (appliedAmount.compareTo(projectLimit) > 0) {
throw new ServiceException("申请付款金额不能超过项目额度");
}
}
if (Func.isNotEmpty(entity.getPayeeName())) {
@@ -488,13 +487,8 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
.eq(CustomerArchive::getIsDeleted, 0).last("limit 1 FOR UPDATE"));
if (customer != null && customer.getMaxCreditLimit() != null) {
BigDecimal customerLimit = customer.getMaxCreditLimit().multiply(BigDecimal.valueOf(10000));
List<String> customerNames = Stream.of(customer.getFullName(), customer.getShortName())
.filter(Func::isNotEmpty).map(String::trim).distinct().toList();
BigDecimal customerOccupiedAmount = quotaOccupiedAmount(Wrappers.<PaymentApplication>lambdaQuery()
.in(PaymentApplication::getPayeeName, customerNames)
.ne(entity.getId() != null, PaymentApplication::getId, entity.getId()), entity);
if (customerOccupiedAmount.compareTo(customerLimit) > 0) {
throw new ServiceException("申请付款金额超过客户剩余资金使用额度(已扣减收票金额并包含在途申请)");
if (appliedAmount.compareTo(customerLimit) > 0) {
throw new ServiceException("申请付款金额不能超过客户额度");
}
}
}
@@ -512,19 +506,6 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
return money(project.getFundLimit()).add(temporaryLimit).multiply(BigDecimal.valueOf(10000));
}
private BigDecimal quotaOccupiedAmount(LambdaQueryWrapper<PaymentApplication> wrapper,
PaymentApplication currentApplication) {
List<PaymentApplication> applications = list(wrapper.ne(PaymentApplication::getApprovalStatus, VOIDED)
.last("FOR UPDATE"));
BigDecimal appliedAmount = applications.stream().map(PaymentApplication::getAppliedAmount)
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)
.add(money(currentApplication.getAppliedAmount()));
BigDecimal receivedInvoiceAmount = applications.stream().map(PaymentApplication::getMatchedInvoiceAmount)
.map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)
.add(money(currentApplication.getMatchedInvoiceAmount()));
return appliedAmount.subtract(receivedInvoiceAmount).max(BigDecimal.ZERO);
}
private BigDecimal sumApplied(LambdaQueryWrapper<PaymentApplication> wrapper) {
return list(wrapper.ne(PaymentApplication::getApprovalStatus, VOIDED)).stream()
.map(PaymentApplication::getAppliedAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add);
@@ -42,6 +42,7 @@ import org.springblade.transport.mapper.PreSettlementDetailFeeMapper;
import org.springblade.transport.mapper.PreSettlementDetailMapper;
import org.springblade.transport.mapper.PreSettlementMapper;
import org.springblade.transport.mapper.PreSettlementSummaryFeeMapper;
import org.springblade.transport.mapper.PaymentApplicationMapper;
import org.springblade.transport.mapper.ReceivablePayableCargoFeeMapper;
import org.springblade.transport.mapper.ReceivablePayableDetailMapper;
import org.springblade.transport.pojo.dto.PreSettlementAdvanceRequest;
@@ -56,6 +57,7 @@ import org.springblade.transport.pojo.entity.PreSettlementChangeRecord;
import org.springblade.transport.pojo.entity.PreSettlementDetail;
import org.springblade.transport.pojo.entity.PreSettlementDetailFee;
import org.springblade.transport.pojo.entity.PreSettlementSummaryFee;
import org.springblade.transport.pojo.entity.PaymentApplication;
import org.springblade.transport.pojo.entity.ProjectApply;
import org.springblade.transport.pojo.entity.ReceivablePayableCargoFee;
import org.springblade.transport.pojo.entity.ReceivablePayableDetail;
@@ -113,6 +115,7 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
private final PreSettlementDetailFeeMapper detailFeeMapper;
private final PreSettlementSummaryFeeMapper summaryFeeMapper;
private final PreSettlementAdvanceMapper advanceMapper;
private final PaymentApplicationMapper paymentApplicationMapper;
private final PreSettlementChangeRecordMapper changeRecordMapper;
private final ReceivablePayableDetailMapper sourceDetailMapper;
private final ReceivablePayableCargoFeeMapper sourceFeeMapper;
@@ -124,7 +127,36 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
@Override
public IPage<PreSettlementVO> selectPage(IPage<PreSettlement> page, PreSettlementVO query) {
return PreSettlementWrapper.build().pageVO(page(page, buildQuery(query)));
IPage<PreSettlementVO> result = PreSettlementWrapper.build().pageVO(page(page, buildQuery(query)));
fillPaymentApplicationAmounts(result.getRecords());
return result;
}
private void fillPaymentApplicationAmounts(List<PreSettlementVO> records) {
if (Func.isEmpty(records)) return;
Set<Long> preSettlementIds = records.stream().map(PreSettlementVO::getId)
.filter(Objects::nonNull).collect(Collectors.toSet());
if (preSettlementIds.isEmpty()) return;
List<PaymentApplication> applications = paymentApplicationMapper.selectList(
Wrappers.<PaymentApplication>lambdaQuery()
.select(PaymentApplication::getPreSettlementId, PaymentApplication::getAppliedAmount,
PaymentApplication::getPaidAmount, PaymentApplication::getApprovalStatus)
.eq(PaymentApplication::getPaymentType, "progress_advance")
.in(PaymentApplication::getPreSettlementId, preSettlementIds)
.in(PaymentApplication::getApprovalStatus, STATUS_REVIEWING, STATUS_APPROVED)
.eq(PaymentApplication::getIsDeleted, 0));
Map<Long, BigDecimal> reviewingAmounts = new HashMap<>();
Map<Long, BigDecimal> approvedAmounts = new HashMap<>();
applications.forEach(application -> {
boolean reviewing = STATUS_REVIEWING.equals(application.getApprovalStatus());
Map<Long, BigDecimal> amounts = reviewing ? reviewingAmounts : approvedAmounts;
BigDecimal amount = reviewing ? application.getAppliedAmount() : application.getPaidAmount();
amounts.merge(application.getPreSettlementId(), money(amount), BigDecimal::add);
});
records.forEach(record -> {
record.setAdvanceAppliedAmount(money(reviewingAmounts.get(record.getId())));
record.setAdvancePaidAmount(money(approvedAmounts.get(record.getId())));
});
}
@Override
@@ -54,7 +54,9 @@ import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
@@ -94,14 +96,35 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
if (record == null) {
throw new ServiceException("认领记录不存在或无权查看");
}
record.setSettlements(claimSettlementMapper.selectList(
List<ReceiptClaimSettlement> settlements = claimSettlementMapper.selectList(
Wrappers.<ReceiptClaimSettlement>lambdaQuery()
.eq(ReceiptClaimSettlement::getReceiptClaimId, id)
.orderByAsc(ReceiptClaimSettlement::getCreateTime)));
.orderByAsc(ReceiptClaimSettlement::getCreateTime));
fillSettlementClaimedAmounts(settlements);
record.setSettlements(settlements);
fillStatusNames(record);
return record;
}
private void fillSettlementClaimedAmounts(List<ReceiptClaimSettlement> settlements) {
List<Long> settlementIds = settlements.stream()
.map(ReceiptClaimSettlement::getFormalSettlementId)
.filter(Objects::nonNull)
.distinct()
.toList();
if (settlementIds.isEmpty()) {
return;
}
Map<Long, BigDecimal> claimedAmountMap = new HashMap<>();
claimSettlementMapper.selectList(Wrappers.<ReceiptClaimSettlement>lambdaQuery()
.in(ReceiptClaimSettlement::getFormalSettlementId, settlementIds)
.eq(ReceiptClaimSettlement::getStatus, 1))
.forEach(relation -> claimedAmountMap.merge(relation.getFormalSettlementId(),
money(relation.getAllocatedReceiptAmount()), BigDecimal::add));
settlements.forEach(settlement -> settlement.setClaimedReceiptAmount(
money(claimedAmountMap.get(settlement.getFormalSettlementId()))));
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateAttachments(ReceiptClaimAttachmentsRequest request) {
@@ -111,6 +111,7 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
.le(query.getTransactionEndTime() != null, KingdeeReceiptFlow::getTransactionTime,
query.getTransactionEndTime())
.eq(KingdeeReceiptFlow::getStatus, 1)
.orderByDesc(KingdeeReceiptFlow::getTransactionTime)
.orderByDesc(KingdeeReceiptFlow::getCreateTime);
return page(page, wrapper).convert(ReceiptFlowWrapper.build()::entityVO);
}
@@ -123,6 +124,10 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
Dept dept = deptId == null ? null : SysCache.getDept(deptId);
vo.setClaimerDeptName(dept == null ? null : dept.getDeptName());
vo.setClaimDate(LocalDate.now());
vo.setClaimRecords(recordMapper.selectList(Wrappers.<ReceiptFlowRecord>lambdaQuery()
.eq(ReceiptFlowRecord::getReceiptFlowId, id)
.eq(ReceiptFlowRecord::getActionType, "claim")
.orderByDesc(ReceiptFlowRecord::getCreateTime)));
return vo;
}