调整收付款问题

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
@@ -30,12 +30,15 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.springblade.transport.pojo.entity.KingdeeReceiptFlow; import org.springblade.transport.pojo.entity.KingdeeReceiptFlow;
import org.springblade.transport.pojo.entity.ReceiptFlowRecord;
import org.springframework.format.annotation.DateTimeFormat; import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serial; import java.io.Serial;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/** /**
* 收款流水视图实体类 * 收款流水视图实体类
@@ -70,4 +73,6 @@ public class ReceiptFlowVO extends KingdeeReceiptFlow {
@TableField(exist = false) @TableField(exist = false)
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime transactionEndTime; private LocalDateTime transactionEndTime;
@TableField(exist = false)
private List<ReceiptFlowRecord> claimRecords = new ArrayList<>();
} }
@@ -73,7 +73,6 @@ import java.time.format.DateTimeFormatter;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream;
/** 付款申请服务实现。 @author Chill */ /** 付款申请服务实现。 @author Chill */
@Service @Service
@@ -114,6 +113,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
.orderByDesc(PaymentApplication::getCreateTime); .orderByDesc(PaymentApplication::getCreateTime);
return page(page, wrapper).convert(item -> { return page(page, wrapper).convert(item -> {
PaymentApplicationVO vo = PaymentApplicationWrapper.build().entityVO(item); PaymentApplicationVO vo = PaymentApplicationWrapper.build().entityVO(item);
if (!APPROVED.equals(item.getApprovalStatus())) vo.setPaidAmount(BigDecimal.ZERO);
return vo; return vo;
}); });
} }
@@ -471,15 +471,14 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
} }
private void validateQuota(PaymentApplication entity) { 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( ProjectApply project = entity.getProjectId() == null ? null : projectApplyMapper.selectOne(
Wrappers.<ProjectApply>lambdaQuery().eq(ProjectApply::getId, entity.getProjectId()).last("FOR UPDATE")); Wrappers.<ProjectApply>lambdaQuery().eq(ProjectApply::getId, entity.getProjectId()).last("FOR UPDATE"));
if (project != null && project.getFundLimit() != null) { if (project != null && project.getFundLimit() != null) {
BigDecimal projectLimit = projectFundLimit(project); BigDecimal projectLimit = projectFundLimit(project);
BigDecimal projectOccupiedAmount = quotaOccupiedAmount(Wrappers.<PaymentApplication>lambdaQuery() if (appliedAmount.compareTo(projectLimit) > 0) {
.eq(PaymentApplication::getProjectId, entity.getProjectId()) throw new ServiceException("申请付款金额不能超过项目额度");
.ne(entity.getId() != null, PaymentApplication::getId, entity.getId()), entity);
if (projectOccupiedAmount.compareTo(projectLimit) > 0) {
throw new ServiceException("申请付款金额超过项目剩余资金使用额度(已扣减收票金额并包含在途申请)");
} }
} }
if (Func.isNotEmpty(entity.getPayeeName())) { if (Func.isNotEmpty(entity.getPayeeName())) {
@@ -488,13 +487,8 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
.eq(CustomerArchive::getIsDeleted, 0).last("limit 1 FOR UPDATE")); .eq(CustomerArchive::getIsDeleted, 0).last("limit 1 FOR UPDATE"));
if (customer != null && customer.getMaxCreditLimit() != null) { if (customer != null && customer.getMaxCreditLimit() != null) {
BigDecimal customerLimit = customer.getMaxCreditLimit().multiply(BigDecimal.valueOf(10000)); BigDecimal customerLimit = customer.getMaxCreditLimit().multiply(BigDecimal.valueOf(10000));
List<String> customerNames = Stream.of(customer.getFullName(), customer.getShortName()) if (appliedAmount.compareTo(customerLimit) > 0) {
.filter(Func::isNotEmpty).map(String::trim).distinct().toList(); throw new ServiceException("申请付款金额不能超过客户额度");
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("申请付款金额超过客户剩余资金使用额度(已扣减收票金额并包含在途申请)");
} }
} }
} }
@@ -512,19 +506,6 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
return money(project.getFundLimit()).add(temporaryLimit).multiply(BigDecimal.valueOf(10000)); 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) { private BigDecimal sumApplied(LambdaQueryWrapper<PaymentApplication> wrapper) {
return list(wrapper.ne(PaymentApplication::getApprovalStatus, VOIDED)).stream() return list(wrapper.ne(PaymentApplication::getApprovalStatus, VOIDED)).stream()
.map(PaymentApplication::getAppliedAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add); .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.PreSettlementDetailMapper;
import org.springblade.transport.mapper.PreSettlementMapper; import org.springblade.transport.mapper.PreSettlementMapper;
import org.springblade.transport.mapper.PreSettlementSummaryFeeMapper; import org.springblade.transport.mapper.PreSettlementSummaryFeeMapper;
import org.springblade.transport.mapper.PaymentApplicationMapper;
import org.springblade.transport.mapper.ReceivablePayableCargoFeeMapper; import org.springblade.transport.mapper.ReceivablePayableCargoFeeMapper;
import org.springblade.transport.mapper.ReceivablePayableDetailMapper; import org.springblade.transport.mapper.ReceivablePayableDetailMapper;
import org.springblade.transport.pojo.dto.PreSettlementAdvanceRequest; 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.PreSettlementDetail;
import org.springblade.transport.pojo.entity.PreSettlementDetailFee; import org.springblade.transport.pojo.entity.PreSettlementDetailFee;
import org.springblade.transport.pojo.entity.PreSettlementSummaryFee; 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.ProjectApply;
import org.springblade.transport.pojo.entity.ReceivablePayableCargoFee; import org.springblade.transport.pojo.entity.ReceivablePayableCargoFee;
import org.springblade.transport.pojo.entity.ReceivablePayableDetail; import org.springblade.transport.pojo.entity.ReceivablePayableDetail;
@@ -113,6 +115,7 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
private final PreSettlementDetailFeeMapper detailFeeMapper; private final PreSettlementDetailFeeMapper detailFeeMapper;
private final PreSettlementSummaryFeeMapper summaryFeeMapper; private final PreSettlementSummaryFeeMapper summaryFeeMapper;
private final PreSettlementAdvanceMapper advanceMapper; private final PreSettlementAdvanceMapper advanceMapper;
private final PaymentApplicationMapper paymentApplicationMapper;
private final PreSettlementChangeRecordMapper changeRecordMapper; private final PreSettlementChangeRecordMapper changeRecordMapper;
private final ReceivablePayableDetailMapper sourceDetailMapper; private final ReceivablePayableDetailMapper sourceDetailMapper;
private final ReceivablePayableCargoFeeMapper sourceFeeMapper; private final ReceivablePayableCargoFeeMapper sourceFeeMapper;
@@ -124,7 +127,36 @@ public class PreSettlementServiceImpl extends BaseServiceImpl<PreSettlementMappe
@Override @Override
public IPage<PreSettlementVO> selectPage(IPage<PreSettlement> page, PreSettlementVO query) { 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 @Override
@@ -54,7 +54,9 @@ import java.math.RoundingMode;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
/** /**
@@ -94,14 +96,35 @@ public class ReceiptClaimRecordServiceImpl extends BaseServiceImpl<ReceiptClaimM
if (record == null) { if (record == null) {
throw new ServiceException("认领记录不存在或无权查看"); throw new ServiceException("认领记录不存在或无权查看");
} }
record.setSettlements(claimSettlementMapper.selectList( List<ReceiptClaimSettlement> settlements = claimSettlementMapper.selectList(
Wrappers.<ReceiptClaimSettlement>lambdaQuery() Wrappers.<ReceiptClaimSettlement>lambdaQuery()
.eq(ReceiptClaimSettlement::getReceiptClaimId, id) .eq(ReceiptClaimSettlement::getReceiptClaimId, id)
.orderByAsc(ReceiptClaimSettlement::getCreateTime))); .orderByAsc(ReceiptClaimSettlement::getCreateTime));
fillSettlementClaimedAmounts(settlements);
record.setSettlements(settlements);
fillStatusNames(record); fillStatusNames(record);
return 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 @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateAttachments(ReceiptClaimAttachmentsRequest request) { public void updateAttachments(ReceiptClaimAttachmentsRequest request) {
@@ -111,6 +111,7 @@ public class ReceiptFlowServiceImpl extends BaseServiceImpl<KingdeeReceiptFlowMa
.le(query.getTransactionEndTime() != null, KingdeeReceiptFlow::getTransactionTime, .le(query.getTransactionEndTime() != null, KingdeeReceiptFlow::getTransactionTime,
query.getTransactionEndTime()) query.getTransactionEndTime())
.eq(KingdeeReceiptFlow::getStatus, 1) .eq(KingdeeReceiptFlow::getStatus, 1)
.orderByDesc(KingdeeReceiptFlow::getTransactionTime)
.orderByDesc(KingdeeReceiptFlow::getCreateTime); .orderByDesc(KingdeeReceiptFlow::getCreateTime);
return page(page, wrapper).convert(ReceiptFlowWrapper.build()::entityVO); 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); Dept dept = deptId == null ? null : SysCache.getDept(deptId);
vo.setClaimerDeptName(dept == null ? null : dept.getDeptName()); vo.setClaimerDeptName(dept == null ? null : dept.getDeptName());
vo.setClaimDate(LocalDate.now()); vo.setClaimDate(LocalDate.now());
vo.setClaimRecords(recordMapper.selectList(Wrappers.<ReceiptFlowRecord>lambdaQuery()
.eq(ReceiptFlowRecord::getReceiptFlowId, id)
.eq(ReceiptFlowRecord::getActionType, "claim")
.orderByDesc(ReceiptFlowRecord::getCreateTime)));
return vo; return vo;
} }