diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/FormalSettlementController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/FormalSettlementController.java index ef083be..e926e86 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/FormalSettlementController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/FormalSettlementController.java @@ -99,7 +99,7 @@ public class FormalSettlementController extends BladeController { @ApiOperationSupport(order = 7) @Operation(summary = "可选应收应付明细") public R>> candidateDetails(Query query, @RequestParam Long contractId, - @RequestParam String settlementType, @RequestParam(required = false) String batchNo, + @RequestParam(required = false) String settlementType, @RequestParam(required = false) String batchNo, @RequestParam(required = false) String createStartDate, @RequestParam(required = false) String createEndDate) { return R.data(preSettlementService.candidateDetailsByCreateTime(Condition.getPage(query), contractId, settlementType, batchNo, createStartDate, createEndDate)); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/PaymentApplicationController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/PaymentApplicationController.java index 34bc11d..e2c6aaf 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/PaymentApplicationController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/PaymentApplicationController.java @@ -41,6 +41,8 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + /** 付款申请控制器。 @author Chill */ @RestController @AllArgsConstructor @@ -92,4 +94,10 @@ public class PaymentApplicationController extends BladeController { @ApiOperationSupport(order = 10) @Operation(summary = "生成金蝶付款单") public R syncKingdee(@RequestParam Long id) { return R.data(paymentApplicationService.syncKingdee(id)); } + @PostMapping("/sync-kingdee-batch") + @ApiOperationSupport(order = 11) + @Operation(summary = "批量生成金蝶付款单并同步付款信息") + public R> syncKingdeeBatch(@RequestBody List ids) { + return R.data(paymentApplicationService.syncKingdeeBatch(ids)); + } } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IPaymentApplicationService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IPaymentApplicationService.java index 2ba2efe..26779ed 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IPaymentApplicationService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IPaymentApplicationService.java @@ -27,6 +27,8 @@ import org.springblade.transport.pojo.entity.PaymentApplication; import org.springblade.transport.pojo.vo.PaymentApplicationReferenceAmountVO; import org.springblade.transport.pojo.vo.PaymentApplicationVO; +import java.util.List; + /** 付款申请服务。 @author Chill */ public interface IPaymentApplicationService extends BaseService { IPage selectPage(IPage page, PaymentApplicationVO query); @@ -39,4 +41,5 @@ public interface IPaymentApplicationService extends BaseService syncKingdeeBatch(List ids); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java index 50fb6f5..d122787 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/FormalSettlementServiceImpl.java @@ -315,9 +315,8 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl !Objects.equals(contractId, item.getContractId()) || !Objects.equals(settlementType, item.getSettlementType())) || directDetails.stream().anyMatch(item -> !Objects.equals(contractId, item.getContractId()) - || !Objects.equals(settlementType, item.getSettlementType()) || (!sources.isEmpty() && !Objects.equals(sources.get(0).getCurrency(), item.getCurrency())))) { - throw new ServiceException("合并的预结算单必须属于同一合同、结算类型及币种"); + throw new ServiceException("合并的结算明细必须属于同一合同及币种"); } PreSettlement first = sources.isEmpty() ? null : sources.get(0); ContractManage contract = contractManageService.getById(contractId); @@ -1064,6 +1063,15 @@ public class FormalSettlementServiceImpl extends BaseServiceImpl APPROVED.equals(relationStatuses.get(item.getPaymentApplicationId()))) .map(PaymentApplicationSettlement::getPaidAmount).map(this::money) .reduce(BigDecimal.ZERO, BigDecimal::add)); + if ("payable".equals(settlement.getSettlementType())) { + List sources = sourceMapper.selectList(Wrappers.lambdaQuery() + .eq(FormalSettlementSource::getFormalSettlementId, settlement.getId()) + .eq(FormalSettlementSource::getIsDeleted, 0)); + appliedAmount = appliedAmount.add(sources.stream().map(FormalSettlementSource::getAdvanceAppliedAmount) + .map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)); + paidAmount = paidAmount.add(sources.stream().map(FormalSettlementSource::getAdvancePaidAmount) + .map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)); + } if ("receivable".equals(settlement.getSettlementType())) { paidAmount = receiptClaimSettlementMapper.selectList( Wrappers.lambdaQuery() diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java index b4f530b..f71af8d 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/MasterOrderServiceImpl.java @@ -25,7 +25,6 @@ import org.springblade.transport.pojo.vo.MasterOrderVO; import org.springblade.transport.service.IMasterOrderService; import org.springblade.transport.service.IContractManageService; import org.springblade.transport.service.IProjectApplyService; -import org.springblade.transport.service.IReceivablePayableDetailService; import org.springblade.transport.service.ITransportPlanService; import org.springblade.transport.service.IWaybillService; import org.springblade.transport.support.TransportBusinessSupport; @@ -57,15 +56,13 @@ public class MasterOrderServiceImpl extends BaseServiceImpl { waybill.setEndDate(LocalDate.now()); waybillService.updateById(waybill); }); - receivablePayableDetailService.generateForClosedMasterOrder(masterOrder); } return updated; } @@ -172,8 +168,17 @@ public class MasterOrderServiceImpl extends BaseServiceImpl> dispatches : planGroups.values()) createTransportPlan(masterOrder, dispatches); - for (List> dispatches : waybillGroups.values()) createWaybill(masterOrder, dispatches); - refreshStatus(masterOrder); + boolean waybillCreated = false; + for (List> dispatches : waybillGroups.values()) { + if (!createWaybill(masterOrder, dispatches)) throw new ServiceException("运单创建失败"); + waybillCreated = true; + } + if (waybillCreated) { + masterOrder.setBusinessStatus("dispatching"); + if (!updateById(masterOrder)) throw new ServiceException("总单状态更新失败"); + } else { + refreshStatus(masterOrder); + } return detail(masterOrder.getId()); } @@ -214,7 +219,7 @@ public class MasterOrderServiceImpl extends BaseServiceImpl> dispatches) { + private boolean createWaybill(MasterOrder masterOrder, List> dispatches) { Map dispatch = dispatches.get(0); Waybill waybill = new Waybill(); waybill.setProjectId(masterOrder.getProjectId()); waybill.setProjectName(masterOrder.getProjectName()); @@ -240,7 +245,7 @@ public class MasterOrderServiceImpl extends BaseServiceImpl> dispatches) { diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PaymentApplicationServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PaymentApplicationServiceImpl.java index 1a03c74..c06b24c 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PaymentApplicationServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/PaymentApplicationServiceImpl.java @@ -43,6 +43,8 @@ import org.springblade.transport.mapper.PaymentApplicationInvoiceMapper; import org.springblade.transport.mapper.PaymentApplicationMapper; import org.springblade.transport.mapper.PaymentApplicationRecordMapper; import org.springblade.transport.mapper.PaymentApplicationSettlementMapper; +import org.springblade.transport.mapper.FormalSettlementSourceMapper; +import org.springblade.transport.mapper.PreSettlementAdvanceMapper; import org.springblade.transport.mapper.TemporaryCreditLimitMapper; import org.springblade.transport.pojo.dto.PaymentApplicationInvoiceRequest; import org.springblade.transport.pojo.dto.PaymentApplicationRecordRequest; @@ -60,6 +62,8 @@ import org.springblade.transport.pojo.entity.PaymentApplication; import org.springblade.transport.pojo.entity.PaymentApplicationInvoice; import org.springblade.transport.pojo.entity.PaymentApplicationRecord; import org.springblade.transport.pojo.entity.PaymentApplicationSettlement; +import org.springblade.transport.pojo.entity.FormalSettlementSource; +import org.springblade.transport.pojo.entity.PreSettlementAdvance; import org.springblade.transport.pojo.entity.TemporaryCreditLimit; import org.springblade.transport.pojo.vo.PaymentApplicationVO; import org.springblade.transport.pojo.vo.PaymentApplicationReferenceAmountVO; @@ -74,8 +78,10 @@ import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; /** 付款申请服务实现。 @author Chill */ @Service @@ -90,6 +96,8 @@ public class PaymentApplicationServiceImpl extends BaseServiceImpllambdaQuery().likeRight(PaymentApplication::getKingdeeBillNo, "FKD" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE))) + 1); - entity.setKingdeeBillNo(no); entity.setKingdeeStatus("synced"); updateById(entity); return no; + entity.setKingdeeBillNo(no); + entity.setKingdeeStatus("synced"); + entity.setPaidAmount(money(entity.getAppliedAmount()).setScale(2, RoundingMode.HALF_UP)); + mockPaymentRecords(entity); + updateById(entity); + syncPreSettlementAdvance(entity); + syncFormalSettlementPayments(entity); + return no; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public List syncKingdeeBatch(List ids) { + if (ids == null || ids.isEmpty()) throw new ServiceException("请至少选择一条审批通过的付款申请"); + List distinctIds = ids.stream().filter(Objects::nonNull).distinct().toList(); + if (distinctIds.isEmpty()) throw new ServiceException("请至少选择一条审批通过的付款申请"); + List result = new ArrayList<>(); + for (Long id : distinctIds) result.add(syncKingdee(id)); + return result; + } + + private void mockPaymentRecords(PaymentApplication entity) { + recordMapper.delete(Wrappers.lambdaQuery() + .eq(PaymentApplicationRecord::getPaymentApplicationId, entity.getId())); + long cents = money(entity.getAppliedAmount()).movePointRight(2).setScale(0, RoundingMode.HALF_UP).longValue(); + int recordCount = cents >= 3 ? 3 : cents >= 2 ? 2 : 1; + long base = cents / recordCount; + long remainder = cents % recordCount; + String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")); + for (int index = 0; index < recordCount; index++) { + long recordCents = base + (index < remainder ? 1 : 0); + PaymentApplicationRecord record = new PaymentApplicationRecord(); + record.setPaymentApplicationId(entity.getId()); + record.setPaidAmount(BigDecimal.valueOf(recordCents, 2)); + record.setPaidDate(LocalDate.now().minusDays(index)); + record.setPaymentNo(limit("MOCK-PAY-" + entity.getPaymentNo() + "-" + timestamp + "-" + (index + 1), 100)); + record.setKingdeeBillNo(limit(entity.getKingdeeBillNo() + "-" + (index + 1), 100)); + recordMapper.insert(record); + } + } + + private void syncPreSettlementAdvance(PaymentApplication entity) { + if (!"progress_advance".equals(entity.getPaymentType()) || entity.getPreSettlementId() == null) return; + PreSettlementAdvance advance = preSettlementAdvanceMapper.selectList( + Wrappers.lambdaQuery() + .eq(PreSettlementAdvance::getPreSettlementId, entity.getPreSettlementId()) + .eq(PreSettlementAdvance::getIsDeleted, 0) + .ne(PreSettlementAdvance::getBillStatus, VOIDED) + .eq(PreSettlementAdvance::getAdvanceNo, entity.getPaymentNo()) + .last("limit 1")).stream().findFirst().orElse(null); + if (advance == null) { + advance = preSettlementAdvanceMapper.selectList(Wrappers.lambdaQuery() + .eq(PreSettlementAdvance::getPreSettlementId, entity.getPreSettlementId()) + .eq(PreSettlementAdvance::getIsDeleted, 0) + .ne(PreSettlementAdvance::getBillStatus, VOIDED) + .eq(PreSettlementAdvance::getPaidAmount, BigDecimal.ZERO) + .eq(PreSettlementAdvance::getAppliedAmount, money(entity.getAppliedAmount())) + .orderByDesc(PreSettlementAdvance::getCreateTime).last("limit 1")).stream().findFirst().orElse(null); + } + if (advance == null) { + advance = new PreSettlementAdvance(); + advance.setPreSettlementId(entity.getPreSettlementId()); + advance.setAdvanceNo(entity.getPaymentNo()); + advance.setAppliedAmount(money(entity.getAppliedAmount())); + } + advance.setPaidAmount(money(entity.getAppliedAmount())); + advance.setBillStatus("paid"); + advance.setKingdeeAdvanceNo(entity.getKingdeeBillNo()); + if (advance.getId() == null) preSettlementAdvanceMapper.insert(advance); + else preSettlementAdvanceMapper.updateById(advance); + refreshPreSettlementAdvanceSummary(entity.getPreSettlementId()); + formalSettlementSourceMapper.selectList(Wrappers.lambdaQuery() + .eq(FormalSettlementSource::getPreSettlementId, entity.getPreSettlementId()) + .eq(FormalSettlementSource::getIsDeleted, 0)).forEach(source -> { + source.setAdvanceAppliedAmount(findPreSettlementApplied(entity.getPreSettlementId())); + source.setAdvancePaidAmount(findPreSettlementPaid(entity.getPreSettlementId())); + formalSettlementSourceMapper.updateById(source); + }); + formalSettlementService.refreshPaymentSummariesForPreSettlement(entity.getPreSettlementId()); + } + + private BigDecimal findPreSettlementPaid(Long preSettlementId) { + return preSettlementAdvanceMapper.selectList(Wrappers.lambdaQuery() + .eq(PreSettlementAdvance::getPreSettlementId, preSettlementId) + .eq(PreSettlementAdvance::getIsDeleted, 0) + .ne(PreSettlementAdvance::getBillStatus, VOIDED)).stream() + .map(PreSettlementAdvance::getPaidAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add); + } + + private BigDecimal findPreSettlementApplied(Long preSettlementId) { + return preSettlementAdvanceMapper.selectList(Wrappers.lambdaQuery() + .eq(PreSettlementAdvance::getPreSettlementId, preSettlementId) + .eq(PreSettlementAdvance::getIsDeleted, 0) + .ne(PreSettlementAdvance::getBillStatus, VOIDED)).stream() + .map(PreSettlementAdvance::getAppliedAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add); + } + + private void refreshPreSettlementAdvanceSummary(Long preSettlementId) { + List advances = preSettlementAdvanceMapper.selectList(Wrappers.lambdaQuery() + .eq(PreSettlementAdvance::getPreSettlementId, preSettlementId) + .eq(PreSettlementAdvance::getIsDeleted, 0) + .ne(PreSettlementAdvance::getBillStatus, VOIDED)); + PreSettlement settlement = preSettlementMapper.selectById(preSettlementId); + if (settlement == null) throw new ServiceException("预结算单不存在"); + settlement.setAdvanceNo(advances.stream().map(PreSettlementAdvance::getAdvanceNo) + .filter(Objects::nonNull).collect(Collectors.joining(","))); + settlement.setAdvanceAppliedAmount(advances.stream().map(PreSettlementAdvance::getAppliedAmount) + .map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)); + settlement.setAdvancePaidAmount(advances.stream().map(PreSettlementAdvance::getPaidAmount) + .map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add)); + preSettlementMapper.updateById(settlement); + } + + private void syncFormalSettlementPayments(PaymentApplication entity) { + if (!"settlement_payment".equals(entity.getPaymentType())) return; + List relations = settlementRelationMapper.selectList( + Wrappers.lambdaQuery() + .eq(PaymentApplicationSettlement::getPaymentApplicationId, entity.getId()) + .eq(PaymentApplicationSettlement::getIsDeleted, 0)); + if (relations.isEmpty() && entity.getSettlementId() != null) { + createFormalSettlementPayment(entity.getSettlementId(), entity.getAppliedAmount(), entity.getPaidAmount(), entity); + formalSettlementService.refreshPaymentSummary(entity.getSettlementId()); + return; + } + BigDecimal remainingPaid = money(entity.getPaidAmount()); + for (int index = 0; index < relations.size(); index++) { + PaymentApplicationSettlement relation = relations.get(index); + BigDecimal paid = index == relations.size() - 1 ? remainingPaid + : money(relation.getAppliedAmount()).min(remainingPaid); + relation.setPaidAmount(paid); + settlementRelationMapper.updateById(relation); + createFormalSettlementPayment(relation.getFormalSettlementId(), relation.getAppliedAmount(), paid, entity); + remainingPaid = remainingPaid.subtract(paid); + } + relations.stream().map(PaymentApplicationSettlement::getFormalSettlementId).filter(Objects::nonNull).distinct() + .forEach(formalSettlementService::refreshPaymentSummary); + } + + private void createFormalSettlementPayment(Long settlementId, BigDecimal appliedAmount, BigDecimal paidAmount, + PaymentApplication application) { + FormalSettlementPayment payment = formalSettlementPaymentMapper.selectList( + Wrappers.lambdaQuery() + .eq(FormalSettlementPayment::getFormalSettlementId, settlementId) + .eq(FormalSettlementPayment::getPaymentNo, application.getPaymentNo()) + .eq(FormalSettlementPayment::getIsDeleted, 0).last("limit 1")).stream().findFirst().orElse(null); + if (payment == null) { + payment = new FormalSettlementPayment(); + payment.setFormalSettlementId(settlementId); + payment.setPaymentNo(application.getPaymentNo()); + } + payment.setPaymentType("final"); + payment.setAppliedAmount(money(appliedAmount)); + payment.setPaidAmount(money(paidAmount)); + payment.setBillStatus("paid"); + payment.setKingdeeBillNo(application.getKingdeeBillNo()); + payment.setRemark(limit(application.getRemark(), 200)); + if (payment.getId() == null) formalSettlementPaymentMapper.insert(payment); + else formalSettlementPaymentMapper.updateById(payment); } private void validateRequest(PaymentApplicationSaveRequest request) { 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 0cc9081..5ce49ef 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 @@ -263,7 +263,7 @@ public class PreSettlementServiceImpl extends BaseServiceImpl query.isNull(ReceivablePayableDetail::getPreSettlementNo) .or().eq(ReceivablePayableDetail::getPreSettlementNo, "")) 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 0e4cec3..adcc1ac 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 @@ -325,8 +325,11 @@ public class ReceivablePayableDetailServiceImpl Set allowedFeeItems = new LinkedHashSet<>(contractFeeItemNames(detail.getContractId())); existingRows.forEach(row -> allowedFeeItems.addAll(parseMap(row.getFeeItemsJson()).keySet())); List changes = new ArrayList<>(); + List changeReasons = new ArrayList<>(); List allRows = new ArrayList<>(existingRows); for (ReceivablePayableAdjustFeeRequest.AdjustRow adjusted : request.getRows()) { + String rowChangeReason = Func.isNotEmpty(adjusted.getChangeReason()) + ? adjusted.getChangeReason() : request.getAdjustReason(); ReceivablePayableCargoFee existing = existingMap.get(adjusted.getId()); if (adjusted.getRemark() != null && adjusted.getRemark().length() > 200) { throw new ServiceException("备注不能超过200个字"); @@ -372,6 +375,9 @@ public class ReceivablePayableDetailServiceImpl changes.add("【手动录入】从[" + Objects.toString(oldCargoName, "") + " " + formatValue(oldAmount) + "]调整为[" + Objects.toString(existing.getCargoName(), "") + " " + formatValue(afterAmount) + "]"); + while (changeReasons.size() < changes.size()) { + changeReasons.add(rowChangeReason); + } continue; } if (existing == null) { @@ -429,12 +435,15 @@ public class ReceivablePayableDetailServiceImpl existing.setAdjustAmount(afterAmount.subtract(money(existing.getOriginalAmount()))); existing.setAfterAmount(afterAmount); cargoFeeMapper.updateById(existing); + while (changeReasons.size() < changes.size()) { + changeReasons.add(rowChangeReason); + } } if (changes.isEmpty()) { throw new ServiceException("未修改任何费用数据"); } for (int i = 0; i < changes.size(); i++) { - saveChangeRecord(detail, changes.get(i), request.getAdjustReason(), String.format("%04d", i + 1)); + saveChangeRecord(detail, changes.get(i), changeReasons.get(i), String.format("%04d", i + 1)); } refreshAdjustedDetail(detail, allRows); } diff --git a/doc/sql/transport/blade_receivable_payable_change_record_adjust_reason_20260904.sql b/doc/sql/transport/blade_receivable_payable_change_record_adjust_reason_20260904.sql new file mode 100644 index 0000000..448a1d5 --- /dev/null +++ b/doc/sql/transport/blade_receivable_payable_change_record_adjust_reason_20260904.sql @@ -0,0 +1,32 @@ +-- MySQL 5.7+ 兼容:为应收应付费用变更记录补充调整原因字段。 +-- 请在 transport 数据库执行。本脚本使用 information_schema 判断,可重复执行。 + +DELIMITER $$ + +DROP PROCEDURE IF EXISTS `upgrade_receivable_payable_change_record_adjust_reason_20260904`$$ +CREATE PROCEDURE `upgrade_receivable_payable_change_record_adjust_reason_20260904`() +BEGIN + DECLARE db_name varchar(128); + SET db_name = DATABASE(); + + IF EXISTS ( + SELECT 1 + FROM information_schema.tables + WHERE table_schema = db_name + AND table_name = 'blade_receivable_payable_change_record' + ) AND NOT EXISTS ( + SELECT 1 + FROM information_schema.columns + WHERE table_schema = db_name + AND table_name = 'blade_receivable_payable_change_record' + AND column_name = 'adjust_reason' + ) THEN + ALTER TABLE `blade_receivable_payable_change_record` + ADD COLUMN `adjust_reason` varchar(200) DEFAULT NULL COMMENT '调整原因' AFTER `adjust_user_name`; + END IF; +END$$ + +CALL `upgrade_receivable_payable_change_record_adjust_reason_20260904`()$$ +DROP PROCEDURE `upgrade_receivable_payable_change_record_adjust_reason_20260904`$$ + +DELIMITER ;