fix: 拦截已调整的正式结算单再次发起付款

This commit is contained in:
刘泉佳
2026-10-29 02:15:54 +08:00
parent adbc87e2e4
commit 82724ceaa0
3 changed files with 22 additions and 1 deletions
@@ -61,6 +61,9 @@ public final class TransportBusiConstant {
/** 审批状态:已作废(终态)。 */
public static final String VOIDED = "voided";
/** 正式结算单调整标识:已调整(结算调整重推后的归档原单,金额已作废,不可再用于下游业务)。 */
public static final String SETTLEMENT_ADJUST_STATUS_ADJUSTED = "adjusted";
/**
* 「未分配组织」筛选项的哨兵值,不是真实组织名。
* <p>
@@ -790,7 +790,7 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
// 原单只加标记,业务字段不动
update(Wrappers.<FormalSettlement>lambdaUpdate()
.eq(FormalSettlement::getId, settlementId)
.set(FormalSettlement::getAdjustStatus, "adjusted"));
.set(FormalSettlement::getAdjustStatus, TransportBusiConstant.SETTLEMENT_ADJUST_STATUS_ADJUSTED));
kingdeeBillLockService.unlockByAdjustRepush(KingdeeLockConstant.SOURCE_SETTLEMENT, settlementId, AuthUtil.getUserName());
saveChange(settlementId, "结算单基本信息", null, "调整",
"结算调整单" + Func.toStr(adjustmentNo) + "重推生成新单" + Func.toStr(newSettlementNo) + ",原单标记已调整", null);
@@ -1251,6 +1251,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl<FormalSettlemen
private String createPayment(FormalSettlement settlement, BigDecimal appliedAmount, String remark) {
if (!TransportBusiConstant.APPROVED.equals(settlement.getApprovalStatus())) throw new ServiceException("仅审批通过的正式结算单允许发起付款申请");
if (!"payable".equals(settlement.getSettlementType())) throw new ServiceException("仅应付正式结算单允许发起付款申请");
if (TransportBusiConstant.SETTLEMENT_ADJUST_STATUS_ADJUSTED.equals(settlement.getAdjustStatus()))
throw new ServiceException("结算单[" + Func.toStr(settlement.getFormalSettlementNo()) + "]已因结算调整作废,不可再发起付款,请使用调整后的新单");
long activePaymentCount = paymentMapper.selectCount(Wrappers.<FormalSettlementPayment>lambdaQuery()
.eq(FormalSettlementPayment::getFormalSettlementId, settlement.getId())
.eq(FormalSettlementPayment::getIsDeleted, 0)
@@ -299,6 +299,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
if (!TransportBusiConstant.APPROVED.equals(formalSettlement.getApprovalStatus())) {
throw new ServiceException("只能选择审批通过、未作废的正式结算单");
}
assertFormalSettlementPayable(formalSettlement);
settlementAmount = money(formalSettlement.getSettlementAmount());
} else {
// 尾款付款也允许关联预结算单
@@ -2145,6 +2146,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
}
} else {
if (!TransportBusiConstant.APPROVED.equals(source.getApprovalStatus())) throw new ServiceException("只能选择审批通过、未作废的正式结算单");
assertFormalSettlementPayable(source);
entity.setSettlementId(source.getId()); entity.setSettlementNo(source.getFormalSettlementNo()); entity.setPreSettlementId(null); entity.setPreSettlementNo(null);
entity.setProjectId(source.getProjectId()); entity.setProjectName(source.getProjectName()); entity.setDeptId(source.getDeptId()); entity.setDeptName(source.getDeptName()); entity.setContractId(source.getContractId()); entity.setContractNo(source.getContractNo()); entity.setContractName(source.getContractName()); entity.setPayerName(source.getPayerName()); entity.setPayeeName(source.getPayeeName()); entity.setSettlementAmount(source.getSettlementAmount()); entity.setPayableAmount(payableOfFormalSettlement(source.getId(), source.getSettlementAmount(), entity.getId())); entity.setBillType("正式结算单");
}
@@ -2199,6 +2201,7 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
|| !TransportBusiConstant.APPROVED.equals(item.getApprovalStatus()) || !"payable".equals(item.getSettlementType()))) {
throw new ServiceException("只能选择审批通过的应付正式结算单");
}
settlements.forEach(this::assertFormalSettlementPayable);
Long contractId = settlements.get(0).getContractId();
if (contractId == null || settlements.stream().anyMatch(item -> !Objects.equals(contractId, item.getContractId()))) {
throw new ServiceException("多选正式结算单必须属于同一合同");
@@ -2206,6 +2209,19 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl<PaymentApplic
return settlements;
}
/**
* 付款链路闸门:结算调整重推会把原单标记为已调整并冲销金蝶旧单,
* 原单仅作存档,剩余应付口径归新单,此处拦截避免对已作废金额重复付款
*
* @param settlement 待付款的正式结算单
*/
private void assertFormalSettlementPayable(FormalSettlement settlement) {
if (TransportBusiConstant.SETTLEMENT_ADJUST_STATUS_ADJUSTED.equals(settlement.getAdjustStatus())) {
throw new ServiceException("结算单[" + Func.toStr(settlement.getFormalSettlementNo())
+ "]已因结算调整作废,不可再发起付款,请使用调整后的新单");
}
}
private boolean hasMultipleFormalReferences(PaymentApplicationSaveRequest request) {
return TransportBusiConstant.PAYMENT_TYPE_SETTLEMENT.equals(request.getPaymentType()) && request.getSettlementIds() != null
&& request.getSettlementIds().stream().filter(Objects::nonNull).distinct().count() > 1;