From 87222f2e8cbd05d1f6d75434287d373bbc12f114 Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Tue, 20 Oct 2026 01:50:55 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E4=BF=AE=E5=A4=8D=E8=BF=9B=E5=BA=A6?= =?UTF-8?q?=E9=A2=84=E4=BB=98=E9=A9=B3=E5=9B=9E=E9=87=8D=E6=8F=90=EF=BC=8C?= =?UTF-8?q?=E5=B9=B6=E6=A0=A1=E6=AD=A3=E7=BB=93=E7=AE=97=E8=B4=B9=E7=94=A8?= =?UTF-8?q?=E4=B8=8E=E8=BF=90=E8=BE=93=E8=AE=A1=E5=88=92=E7=BB=84=E7=BB=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Cursor --- .../dto/PaymentApplicationSaveRequest.java | 2 + .../controller/BillLedgerController.java | 11 +- .../transport/service/IBillLedgerService.java | 5 +- .../service/impl/BillLedgerServiceImpl.java | 47 ++++-- .../impl/PaymentApplicationServiceImpl.java | 131 +++++++++++++--- .../impl/PreSettlementServiceImpl.java | 147 ++++++++++-------- .../ReceivablePayableDetailServiceImpl.java | 38 +++-- .../impl/TransportPlanServiceImpl.java | 32 +++- 8 files changed, 302 insertions(+), 111 deletions(-) diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/PaymentApplicationSaveRequest.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/PaymentApplicationSaveRequest.java index d608d7cb..d69690f8 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/PaymentApplicationSaveRequest.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/dto/PaymentApplicationSaveRequest.java @@ -36,6 +36,8 @@ public class PaymentApplicationSaveRequest implements Serializable { private List settlementIds; private Long preSettlementId; private List preSettlementIds; + /** 预结算单号。驳回重提时用于在主键失真后找回预结算单 */ + private String preSettlementNo; private Long projectId; private String projectName; private Long deptId; diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/BillLedgerController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/BillLedgerController.java index 24d695ca..7cce3ffc 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/BillLedgerController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/BillLedgerController.java @@ -61,8 +61,9 @@ public class BillLedgerController extends BladeController { @ApiOperationSupport(order = 4) @Operation(summary = "付款申请可用汇票") public R> availableOptions(@RequestParam(required = false) String keyword, - @RequestParam(required = false) Long deptId, @RequestParam(required = false) Long selectedId) { - return R.data(billLedgerService.availableOptions(keyword, deptId, selectedId)); + @RequestParam(required = false) Long deptId, @RequestParam(required = false) Long selectedId, + @RequestParam(required = false) String payerName, @RequestParam(required = false) String payeeName) { + return R.data(billLedgerService.availableOptions(keyword, deptId, selectedId, payerName, payeeName)); } @GetMapping("/available-page") @@ -70,8 +71,10 @@ public class BillLedgerController extends BladeController { @Operation(summary = "付款申请可用汇票分页") public R> availablePage(Query pageQuery, @RequestParam(required = false) String keyword, @RequestParam(required = false) Long deptId, - @RequestParam(required = false) Long selectedId) { - return R.data(billLedgerService.availablePage(Condition.getPage(pageQuery), keyword, deptId, selectedId)); + @RequestParam(required = false) Long selectedId, @RequestParam(required = false) String payerName, + @RequestParam(required = false) String payeeName) { + return R.data(billLedgerService.availablePage(Condition.getPage(pageQuery), keyword, deptId, selectedId, + payerName, payeeName)); } @PostMapping("/submit") diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IBillLedgerService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IBillLedgerService.java index abd6e5d2..c46522e3 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IBillLedgerService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IBillLedgerService.java @@ -18,8 +18,9 @@ public interface IBillLedgerService extends BaseService { IPage selectPage(IPage page, BillLedgerVO query); BillLedgerVO detail(Long id); Map expiryCounts(); - List availableOptions(String keyword, Long deptId, Long selectedId); - IPage availablePage(IPage page, String keyword, Long deptId, Long selectedId); + List availableOptions(String keyword, Long deptId, Long selectedId, String payerName, String payeeName); + IPage availablePage(IPage page, String keyword, Long deptId, Long selectedId, + String payerName, String payeeName); Long submit(BillLedgerSaveRequest request); void removeLedger(Long id); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/BillLedgerServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/BillLedgerServiceImpl.java index a2728da7..a20a4e0e 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/BillLedgerServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/BillLedgerServiceImpl.java @@ -86,14 +86,15 @@ public class BillLedgerServiceImpl extends BaseServiceImpl availableOptions(String keyword, Long deptId, Long selectedId) { - return availableList(keyword, deptId, selectedId); + public List availableOptions(String keyword, Long deptId, Long selectedId, String payerName, + String payeeName) { + return availableList(keyword, deptId, selectedId, payerName, payeeName); } @Override public IPage availablePage(IPage page, String keyword, Long deptId, - Long selectedId) { - List available = availableList(keyword, deptId, selectedId); + Long selectedId, String payerName, String payeeName) { + List available = availableList(keyword, deptId, selectedId, payerName, payeeName); long current = Math.max(page.getCurrent(), 1); long size = Math.max(page.getSize(), 1); long from = Math.min((current - 1) * size, available.size()); @@ -103,27 +104,50 @@ public class BillLedgerServiceImpl extends BaseServiceImpl availableList(String keyword, Long deptId, Long selectedId) { + private List availableList(String keyword, Long deptId, Long selectedId, String payerName, + String payeeName) { LocalDate today = LocalDate.now(); - // 付款申请仅可选:收票类型、未到期、有可用余额;已选中的汇票始终带回以便回显 + // 未到期且有余额;收票且部门可用,或出票/收票单位与结算收付款方一致(开票、收票都可) return list(Wrappers.lambdaQuery() .and(Func.isNotEmpty(keyword), wrapper -> wrapper.like(BillLedger::getBillNo, keyword) .or().like(BillLedger::getIssuerName, keyword) .or().like(BillLedger::getReceiverName, keyword)) .and(wrapper -> wrapper .and(available -> available - .eq(BillLedger::getBillType, "received") .ge(BillLedger::getMaturityDate, today) .gt(BillLedger::getAvailableBalance, BigDecimal.ZERO)) .or(selectedId != null, child -> child.eq(BillLedger::getId, selectedId))) .orderByAsc(BillLedger::getMaturityDate) .orderByDesc(BillLedger::getCreateTime)).stream() .filter(item -> selectedId != null && Objects.equals(item.getId(), selectedId) - || departmentAvailable(item, deptId)) + || selectableBill(item, deptId, payerName, payeeName)) .map(item -> BillLedgerWrapper.build().entityVO(item)) .toList(); } + /** + * 收票且当前部门在可用范围内,或出票单位、收票单位与结算付款方、收款方一致(顺序不限)。 + */ + private boolean selectableBill(BillLedger ledger, Long deptId, String payerName, String payeeName) { + boolean receivedAndDept = "received".equals(ledger.getBillType()) && departmentAvailable(ledger, deptId); + return receivedAndDept || partiesMatch(ledger.getIssuerName(), ledger.getReceiverName(), payerName, payeeName); + } + + private boolean partiesMatch(String issuerName, String receiverName, String payerName, String payeeName) { + String issuer = trimName(issuerName); + String receiver = trimName(receiverName); + String payer = trimName(payerName); + String payee = trimName(payeeName); + if (issuer.isEmpty() || receiver.isEmpty() || payer.isEmpty() || payee.isEmpty()) { + return false; + } + return (issuer.equals(payer) && receiver.equals(payee)) || (issuer.equals(payee) && receiver.equals(payer)); + } + + private String trimName(String value) { + return value == null ? "" : value.trim(); + } + @Override @Transactional(rollbackFor = Exception.class) public Long submit(BillLedgerSaveRequest request) { @@ -141,6 +165,11 @@ public class BillLedgerServiceImpl extends BaseServiceImpl candidates = new java.util.ArrayList<>(); + if (request.getPreSettlementId() != null) { + candidates.add(request.getPreSettlementId()); + } + if (request.getPreSettlementIds() != null) { + request.getPreSettlementIds().stream().filter(Objects::nonNull).forEach(candidates::add); + } + if (request.getSettlementId() != null) { + candidates.add(request.getSettlementId()); + } + if (request.getSettlementIds() != null) { + request.getSettlementIds().stream().filter(Objects::nonNull).forEach(candidates::add); + } + if (entity != null && entity.getPreSettlementId() != null) { + candidates.add(entity.getPreSettlementId()); + } + for (Long candidate : candidates) { + PreSettlement preSettlement = preSettlementMapper.selectById(candidate); + if (preSettlement != null && !Objects.equals(preSettlement.getIsDeleted(), 1)) { + return preSettlement.getId(); + } + } + String preSettlementNo = request.getPreSettlementNo(); + if (Func.isEmpty(preSettlementNo) && entity != null) { + preSettlementNo = entity.getPreSettlementNo(); + } + if (Func.isNotEmpty(preSettlementNo)) { + String settlementNo = preSettlementNo.split("、")[0].trim(); + PreSettlement preSettlement = preSettlementMapper.selectOne(Wrappers.lambdaQuery() + .eq(PreSettlement::getPreSettlementNo, settlementNo) + .eq(PreSettlement::getIsDeleted, 0) + .last("limit 1")); + if (preSettlement != null) { + return preSettlement.getId(); + } + } + return null; + } + private void fillReference(PaymentApplication entity, PaymentApplicationSaveRequest request) { - if ("project_advance".equals(request.getPaymentType())) { + if ("progress_advance".equals(request.getPaymentType())) { + Long preSettlementId = resolveProgressPreSettlementId(request, entity); + request.setPreSettlementId(preSettlementId); + if (preSettlementId == null) { + throw new ServiceException("进度预付必须关联预结算单"); + } + request.setSettlementId(null); + request.setSettlementIds(null); + fillPreSettlementReference(entity, requireApprovedPreSettlement(request.getPreSettlementId())); + } else if ("project_advance".equals(request.getPaymentType())) { ProjectApply project = projectApplyMapper.selectById(request.getProjectId()); if (project == null || Objects.equals(project.getIsDeleted(), 1)) throw new ServiceException("所属项目不存在"); entity.setSettlementId(null); entity.setSettlementNo(null); entity.setPreSettlementId(null); entity.setPreSettlementNo(null); @@ -1981,6 +2037,10 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpl 0) throw new ServiceException("申请付款金额超过汇票可用余额"); - if (!departmentAvailable(ledger, deptId)) throw new ServiceException("当前使用部门不在汇票可用部门范围内"); + if (!partyMatched && !departmentAvailable(ledger, deptId)) throw new ServiceException("当前使用部门不在汇票可用部门范围内"); + } + + /** 出票单位、收票单位与结算付款方、收款方一致(顺序不限) */ + private boolean settlementPartiesMatch(BillLedger ledger, Long settlementId, Long preSettlementId) { + String payerName = null; + String payeeName = null; + if (settlementId != null) { + FormalSettlement settlement = formalSettlementMapper.selectById(settlementId); + if (settlement != null && !Objects.equals(settlement.getIsDeleted(), 1)) { + payerName = settlement.getPayerName(); + payeeName = settlement.getPayeeName(); + } + } + if ((payerName == null || payeeName == null) && preSettlementId != null) { + PreSettlement settlement = preSettlementMapper.selectById(preSettlementId); + if (settlement != null && !Objects.equals(settlement.getIsDeleted(), 1)) { + payerName = settlement.getPayerName(); + payeeName = settlement.getPayeeName(); + } + } + String issuer = ledger.getIssuerName() == null ? "" : ledger.getIssuerName().trim(); + String receiver = ledger.getReceiverName() == null ? "" : ledger.getReceiverName().trim(); + String payer = payerName == null ? "" : payerName.trim(); + String payee = payeeName == null ? "" : payeeName.trim(); + if (issuer.isEmpty() || receiver.isEmpty() || payer.isEmpty() || payee.isEmpty()) { + return false; + } + return (issuer.equals(payer) && receiver.equals(payee)) || (issuer.equals(payee) && receiver.equals(payer)); } private void useBillBalance(PaymentApplication entity) { BillLedger ledger = lockedBill(entity.getBillLedgerId()); - validateBill(ledger, entity.getDeptId(), entity.getAppliedAmount(), true, null); + validateBill(ledger, entity.getDeptId(), entity.getAppliedAmount(), true, null, + entity.getSettlementId(), entity.getPreSettlementId()); BillLedgerUsage exists = lockedBillUsage(entity.getId()); if (exists != null && TransportBusiConstant.APPROVED.equals(exists.getUsageStatus())) { throw new ServiceException("该付款申请已生成汇票使用记录"); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PreSettlementServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PreSettlementServiceImpl.java index 2b98c34a..f828826f 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PreSettlementServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PreSettlementServiceImpl.java @@ -206,6 +206,9 @@ public class PreSettlementServiceImpl extends BaseServiceImpllambdaQuery() .eq(PreSettlementChangeRecord::getPreSettlementId, id) .eq(PreSettlementChangeRecord::getIsDeleted, 0) + .and(wrapper -> wrapper.isNull(PreSettlementChangeRecord::getChangeContent) + .or() + .ne(PreSettlementChangeRecord::getChangeContent, "预结算审批通过")) .orderByDesc(PreSettlementChangeRecord::getChangeTime))); vo.setPrintTemplates(resolvePrintTemplates(settlement)); return vo; @@ -355,8 +358,10 @@ public class PreSettlementServiceImpl extends BaseServiceImpl summaryBefore = created ? new ArrayList<>() : listSummaryFees(settlement.getId()); rebuildSummaryFees(settlement.getId(), true); applySummaryRequest(settlement.getId(), contractChanged ? List.of() : request.getSummaryFees()); + recordSummaryFeeChanges(settlement.getId(), summaryBefore); refreshSettlementAmount(settlement); projectAdvanceWriteOffService.replaceWriteOffs( TransportBusiConstant.SETTLEMENT_BILL_PRE, @@ -425,7 +430,6 @@ public class PreSettlementServiceImpl extends BaseServiceImpl beforeData = new LinkedHashMap<>(); - Map afterData = new LinkedHashMap<>(); - beforeData.put("费用项", row.getFeeItem()); - beforeData.put("调整金额", before); - beforeData.put("结算金额", money(row.getOriginalAmount().add(before))); - afterData.put("费用项", row.getFeeItem()); - afterData.put("调整金额", row.getAdjustAmount()); - afterData.put("结算金额", money(row.getSettlementAmount())); - saveChange(settlementId, "合计费用项", row.getLineNo(), "调整", - "【" + row.getFeeItem() + "-调整金额】从【" + before + "】调整为【" + row.getAdjustAmount() + "】", - "", beforeData, afterData); - } } for (PreSettlementSummaryFee manualRow : manualRows) { if (!retainedManualIds.contains(manualRow.getId())) { summaryFeeMapper.deleteById(manualRow.getId()); - Map beforeData = new LinkedHashMap<>(); - Map afterData = new LinkedHashMap<>(); - beforeData.put("费用类型", manualRow.getFeeType()); - beforeData.put("费用项", manualRow.getFeeItem()); - beforeData.put("调整金额", money(manualRow.getAdjustAmount())); - beforeData.put("结算金额", money(manualRow.getSettlementAmount())); - beforeData.put("备注", manualRow.getRemark()); - afterData.put("费用类型", ""); - afterData.put("费用项", ""); - afterData.put("调整金额", BigDecimal.ZERO.setScale(2)); - afterData.put("结算金额", BigDecimal.ZERO.setScale(2)); - afterData.put("备注", ""); - saveChange(settlementId, "合计费用项", manualRow.getLineNo(), "删除", - "删除合计费用项【" + manualRow.getFeeItem() + "】金额【" + money(manualRow.getSettlementAmount()) + "】", - "", beforeData, afterData); } } for (PreSettlementSummaryFee generatedRow : existingGeneratedRows) { @@ -1563,38 +1531,87 @@ public class PreSettlementServiceImpl extends BaseServiceImpl changes = new ArrayList<>(); + private void recordSummaryFeeChanges(Long settlementId, List beforeRows) { + List> beforeLines = summaryFeeLines(beforeRows); + List> afterLines = summaryFeeLines(listSummaryFees(settlementId)); + if (beforeLines.equals(afterLines)) { + return; + } + String content = summaryFeeChangeContent(beforeLines, afterLines); + if (Func.isEmpty(content)) { + return; + } Map beforeData = new LinkedHashMap<>(); Map afterData = new LinkedHashMap<>(); - if (creating) { - changes.add("新增合计费用项【" + row.getFeeItem() + "】金额【" + money(row.getSettlementAmount()) + "】"); - beforeData.put("费用类型", ""); - beforeData.put("费用项", ""); - beforeData.put("调整金额", BigDecimal.ZERO.setScale(2)); - beforeData.put("结算金额", BigDecimal.ZERO.setScale(2)); - beforeData.put("备注", ""); - afterData.put("费用类型", row.getFeeType()); - afterData.put("费用项", row.getFeeItem()); - afterData.put("调整金额", money(row.getAdjustAmount())); - afterData.put("结算金额", money(row.getSettlementAmount())); - afterData.put("备注", row.getRemark()); - saveChange(settlementId, "合计费用项", row.getLineNo(), "新增", String.join(";", changes), "", - beforeData, afterData); - return; + beforeData.put("结算合计", beforeLines); + afterData.put("结算合计", afterLines); + String operationType = beforeLines.isEmpty() ? "新增" : afterLines.isEmpty() ? "删除" : "调整"; + saveChange(settlementId, "结算合计", null, operationType, content, "", beforeData, afterData); + } + + private List> summaryFeeLines(List rows) { + Map categoryNames = DictBizCache.getList("fee_category").stream() + .collect(Collectors.toMap(DictBiz::getDictKey, DictBiz::getDictValue, (first, second) -> first)); + List> lines = new ArrayList<>(); + for (PreSettlementSummaryFee row : rows) { + String feeType = row.getFeeType() == null ? "" : row.getFeeType(); + Map line = new LinkedHashMap<>(); + line.put("来源", Integer.valueOf(1).equals(row.getManualFlag()) ? "手工新增" : "系统归集"); + line.put("费用类型", categoryNames.getOrDefault(feeType, feeType)); + line.put("费用项", row.getFeeItem() == null ? "" : row.getFeeItem()); + line.put("原金额", money(row.getOriginalAmount())); + line.put("调整金额", money(row.getAdjustAmount())); + line.put("结算金额", money(row.getSettlementAmount())); + line.put("备注", row.getRemark() == null ? "" : row.getRemark()); + lines.add(line); } - appendTextChange(changes, beforeData, afterData, "费用类型", beforeFeeType, row.getFeeType()); - appendTextChange(changes, beforeData, afterData, "费用项", beforeFeeItem, row.getFeeItem()); - appendChange(changes, beforeData, afterData, "调整金额", beforeAdjustAmount, row.getAdjustAmount()); - appendChange(changes, beforeData, afterData, "结算金额", beforeSettlementAmount, row.getSettlementAmount()); - appendTextChange(changes, beforeData, afterData, "备注", beforeRemark, row.getRemark()); - if (changes.isEmpty()) { - return; + return lines; + } + + private String summaryFeeChangeContent(List> beforeLines, List> afterLines) { + Map> beforeMap = indexSummaryLines(beforeLines); + Map> afterMap = indexSummaryLines(afterLines); + List changes = new ArrayList<>(); + afterMap.forEach((key, afterLine) -> { + Map beforeLine = beforeMap.get(key); + String label = summaryLineLabel(afterLine); + if (beforeLine == null) { + changes.add("新增结算合计【" + label + "】结算金额【" + afterLine.get("结算金额") + "】"); + return; + } + if (!Objects.equals(beforeLine.get("原金额"), afterLine.get("原金额")) + || !Objects.equals(beforeLine.get("调整金额"), afterLine.get("调整金额")) + || !Objects.equals(beforeLine.get("结算金额"), afterLine.get("结算金额")) + || !Objects.equals(String.valueOf(beforeLine.get("备注")), String.valueOf(afterLine.get("备注")))) { + changes.add("调整结算合计【" + label + "】结算金额从【" + beforeLine.get("结算金额") + + "】调整为【" + afterLine.get("结算金额") + "】"); + } + }); + beforeMap.forEach((key, beforeLine) -> { + if (!afterMap.containsKey(key)) { + changes.add("删除结算合计【" + summaryLineLabel(beforeLine) + "】结算金额【" + beforeLine.get("结算金额") + "】"); + } + }); + return String.join(";", changes); + } + + private Map> indexSummaryLines(List> lines) { + Map> indexed = new LinkedHashMap<>(); + Map counts = new HashMap<>(); + for (Map line : lines) { + String base = String.valueOf(line.get("来源")) + "|" + line.get("费用类型") + "|" + line.get("费用项"); + int index = counts.merge(base, 1, Integer::sum); + indexed.put(base + "#" + index, line); } - saveChange(settlementId, "合计费用项", row.getLineNo(), "调整", String.join(";", changes), "", - beforeData, afterData); + return indexed; + } + + private String summaryLineLabel(Map line) { + String feeType = String.valueOf(line.getOrDefault("费用类型", "")); + String feeItem = String.valueOf(line.getOrDefault("费用项", "")); + String source = String.valueOf(line.getOrDefault("来源", "")); + String name = feeType.isBlank() ? feeItem : feeType + "-" + feeItem; + return source + " " + name; } private void saveChange(Long settlementId, String changeType, Integer lineNo, String operationType, diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ReceivablePayableDetailServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ReceivablePayableDetailServiceImpl.java index f27388f7..8ce2f5f7 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ReceivablePayableDetailServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ReceivablePayableDetailServiceImpl.java @@ -424,9 +424,7 @@ public class ReceivablePayableDetailServiceImpl } }); ReceivablePayableFeeDetailVO result = buildFeeDetail(rows); - LinkedHashSet feeItemNames = new LinkedHashSet<>(contractFeeItemNames(detail.getContractId())); - feeItemNames.addAll(result.getFeeItemNames()); - result.setFeeItemNames(new ArrayList<>(feeItemNames)); + // 只展示本明细已生成的费用项。合同上其他计费方案的费用项不能叠到当前明细。 return result; } @@ -1968,21 +1966,35 @@ public class ReceivablePayableDetailServiceImpl } private List calculatedFees(Waybill waybill, ContractManage contract, String planId) { - return calculatedFees(waybill, contract, planId, false); + return calculatedFees(waybill, contract, planId, false, false); } - private List calculatedFees(Waybill waybill, ContractManage contract, String planId, boolean matchOnly) { + private List calculatedFees(Waybill waybill, ContractManage contract, String planId, + boolean matchOnly) { + return calculatedFees(waybill, contract, planId, matchOnly, false); + } + + /** + * @param strictPlan 更新费用时为 true:选定方案有规则但未命中时,不再回退运单历史费用,避免旧费用项叠加 + */ + private List calculatedFees(Waybill waybill, ContractManage contract, String planId, + boolean matchOnly, boolean strictPlan) { List> plans = parseList(contract == null ? null : contract.getBillingPlanJson()); Map plan = "__matched__".equals(planId) ? resolveDefaultBillingPlan(plans, waybill.getTransportType()) : resolveBillingPlan(plans, planId); - return calculatedFees(waybill, plan, matchOnly); + return calculatedFees(waybill, plan, matchOnly, strictPlan); } private List calculatedFees(Waybill waybill, Map plan, boolean matchOnly) { + return calculatedFees(waybill, plan, matchOnly, false); + } + + private List calculatedFees(Waybill waybill, Map plan, + boolean matchOnly, boolean strictPlan) { if (plan == null || !(plan.get("rules") instanceof List)) { - return matchOnly ? List.of() : buildCargoFees(waybill); + return matchOnly || strictPlan ? List.of() : buildCargoFees(waybill); } Map, ReceivablePayableCargoFee> feesByCargo = new LinkedHashMap<>(); Map, Map> feeItemsByCargo = new LinkedHashMap<>(); @@ -2024,7 +2036,11 @@ public class ReceivablePayableDetailServiceImpl ReceivablePayableCargoFee fee = result.get(index); fee.setLineNo(String.format("%04d", index + 1)); } - return result.isEmpty() && !matchOnly ? buildCargoFees(waybill) : result; + // 已选定计费方案时,只保留该方案算出的费用项,不用运单上的历史费用回填。 + if (strictPlan || matchOnly) { + return result; + } + return result.isEmpty() ? buildCargoFees(waybill) : result; } private ReceivablePayableCargoFee buildCalculatedCargoFee(Waybill waybill, Waybill feeWaybill, @@ -2934,7 +2950,7 @@ public class ReceivablePayableDetailServiceImpl throw new ServiceException("关联运单不存在"); } ContractManage contract = contractManageService.getById(detail.getContractId()); - List fees = calculatedFees(waybill, contract, billingPlanId); + List fees = calculatedFees(waybill, contract, billingPlanId, false, true); cargoFeeMapper.delete(Wrappers.lambdaQuery().eq(ReceivablePayableCargoFee::getDetailId, detail.getId())); fees.forEach(fee -> { fee.setDetailId(detail.getId()); cargoFeeMapper.insert(fee); }); BigDecimal freight = fees.stream().map(fee -> money(fee.getFreightAmount())) @@ -2959,7 +2975,7 @@ public class ReceivablePayableDetailServiceImpl ContractManage contract = contractManageService.getById(detail.getContractId()); List masterGoods = masterOrderGoods(masterOrder); List fees = masterGoods.stream() - .flatMap(goods -> calculatedFees(goods, contract, billingPlanId).stream()).toList(); + .flatMap(goods -> calculatedFees(goods, contract, billingPlanId, false, true).stream()).toList(); normalizeMasterFeeLines(fees); cargoFeeMapper.delete(Wrappers.lambdaQuery() .eq(ReceivablePayableCargoFee::getDetailId, detail.getId())); @@ -2995,7 +3011,7 @@ public class ReceivablePayableDetailServiceImpl } ContractManage contract = contractManageService.getById(detail.getContractId()); List fees = waybills.stream() - .flatMap(waybill -> calculatedFees(waybill, contract, billingPlanId).stream()).toList(); + .flatMap(waybill -> calculatedFees(waybill, contract, billingPlanId, false, true).stream()).toList(); normalizeWaybillFeeLines(fees); cargoFeeMapper.delete(Wrappers.lambdaQuery() .eq(ReceivablePayableCargoFee::getDetailId, detail.getId())); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportPlanServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportPlanServiceImpl.java index 5e0fb473..34d9d35f 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportPlanServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportPlanServiceImpl.java @@ -81,6 +81,8 @@ public class TransportPlanServiceImpl extends BaseServiceImpl selectTransportPlanPage(IPage page, TransportPlanVO transportPlan) { + // 历史手工创建未写入 dept_id,allDept=0 按组织过滤时会被排除 + backfillMissingDept(transportPlan); IPage entityPage = page(page, buildQuery(transportPlan)); IPage resultPage = TransportPlanWrapper.build().pageVO(entityPage); fillCustomerNamesFromContracts(resultPage.getRecords()); @@ -151,6 +153,12 @@ public class TransportPlanServiceImpl extends BaseServiceImpllambdaUpdate() + .set(TransportPlan::getDeptId, dept.getId()) + .set(TransportPlan::getDeptName, dept.getDeptName()) + .isNull(TransportPlan::getDeptId) + .eq(TransportPlan::getCreateDept, dept.getId()) + .eq(TransportPlan::getIsDeleted, 0)); + } + private LambdaQueryWrapper buildQuery(TransportPlanVO transportPlan) { TransportBusinessSupport.validateAllDept(transportPlan.getAllDept(), "运输计划"); LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery().eq(TransportPlan::getIsDeleted, 0); if (!Objects.equals(transportPlan.getAllDept(), 1)) { - queryWrapper.eq(TransportPlan::getDeptId, TransportBusinessSupport.currentDeptId("运输计划")); + Long currentDeptId = TransportBusinessSupport.currentDeptId("运输计划"); + // dept_id 为空的历史数据按创建组织归入当前组织 + queryWrapper.and(wrapper -> wrapper.eq(TransportPlan::getDeptId, currentDeptId) + .or(item -> item.isNull(TransportPlan::getDeptId).eq(TransportPlan::getCreateDept, currentDeptId))); } else if (Func.isNotEmpty(transportPlan.getDeptId())) { queryWrapper.eq(TransportPlan::getDeptId, transportPlan.getDeptId()); }