From 4d34525b7bd1ae9b5a236c08cc84f6d08bd21dd7 Mon Sep 17 00:00:00 2001 From: b2894lxlx <517289602@qq.com> Date: Mon, 7 Sep 2026 19:37:08 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E7=BB=93=E7=AE=97=E6=A8=A1?= =?UTF-8?q?=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pojo/entity/TransportReconciliation.java | 1 + .../excel/VehicleReconciliationExcel.java | 2 +- .../IReceivablePayableDetailService.java | 7 + .../ReceivablePayableDetailServiceImpl.java | 8 ++ .../TransportReconciliationServiceImpl.java | 125 ++++++++++++++++-- .../impl/WaybillImportBatchServiceImpl.java | 78 +++++++---- ...lade_transport_reconciliation_20260818.sql | 2 +- ..._reconciliation_customer_name_20260907.sql | 25 ++++ 8 files changed, 208 insertions(+), 40 deletions(-) create mode 100644 doc/sql/transport/blade_transport_reconciliation_customer_name_20260907.sql diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportReconciliation.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportReconciliation.java index ee00039..4aa5738 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportReconciliation.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/TransportReconciliation.java @@ -41,6 +41,7 @@ public class TransportReconciliation extends TenantEntity { private Long contractId; private String contractNo; private String contractName; + private String customerName; private String payerName; private String payeeName; private String currency; diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/VehicleReconciliationExcel.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/VehicleReconciliationExcel.java index 035d082..8a36075 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/VehicleReconciliationExcel.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/excel/VehicleReconciliationExcel.java @@ -33,7 +33,7 @@ public class VehicleReconciliationExcel implements Serializable { @ExcelProperty("里程(KM)") @NumberFormat("0.00") private BigDecimal mileage; @ExcelProperty("批次号") private String batchNo; @ExcelProperty("运输单价") @NumberFormat("0.00") private BigDecimal unitPrice; - @ExcelProperty("运费") @NumberFormat("0.00") private BigDecimal freightAmount; + @ExcelProperty("运输费") @NumberFormat("0.00") private BigDecimal freightAmount; @ExcelProperty("费用项目1") @NumberFormat("0.00") private BigDecimal feeItemOne; @ExcelProperty("结算费用合计") @NumberFormat("0.00") private BigDecimal settlementAmount; @ExcelIgnore private String errorMessage; diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IReceivablePayableDetailService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IReceivablePayableDetailService.java index 454e311..6cc8546 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IReceivablePayableDetailService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IReceivablePayableDetailService.java @@ -31,6 +31,7 @@ import org.springblade.transport.pojo.dto.ReceivablePayableTransferRequest; import org.springblade.transport.pojo.dto.ReceivablePayableUpdateFeeRequest; import org.springblade.transport.pojo.entity.MasterOrder; import org.springblade.transport.pojo.entity.ReceivablePayableDetail; +import org.springblade.transport.pojo.entity.Waybill; import org.springblade.transport.pojo.vo.ReceivablePayableChangeRecordVO; import org.springblade.transport.pojo.vo.ReceivablePayableCargoFeeVO; import org.springblade.transport.pojo.vo.ReceivablePayableDetailVO; @@ -81,6 +82,12 @@ public interface IReceivablePayableDetailService extends BaseService waybillIds); + /** + * 批量导入完成运单后按合同系统计费模式生成应收、应付明细。 + *

与导入事务共用同一事务,运单尚未提交,因此直接传入实体而非主键。

+ */ + void generateForImportedWaybills(List waybills); + /** 完成配载单后按其记录的承运商合同汇总生成一条应付明细。 */ void generateForCompletedLoading(List waybillIds, Long carrierContractId, String loadingNo); 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 f15d213..cbebb0e 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 @@ -641,6 +641,14 @@ public class ReceivablePayableDetailServiceImpl this::resolveWaybillCarrierContract, AuthUtil.getUserId(), new Date()); } + @Override + @Transactional(rollbackFor = Exception.class) + public void generateForImportedWaybills(List waybills) { + if (Func.isEmpty(waybills)) return; + generateAutomaticWaybillDetails(waybills, true, + this::resolveWaybillCarrierContract, AuthUtil.getUserId(), new Date()); + } + @Override @Transactional(propagation = org.springframework.transaction.annotation.Propagation.REQUIRES_NEW, rollbackFor = Exception.class) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportReconciliationServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportReconciliationServiceImpl.java index 410e974..a4e0bea 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportReconciliationServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/TransportReconciliationServiceImpl.java @@ -52,6 +52,7 @@ import org.springblade.transport.pojo.vo.TransportReconciliationVO; import org.springblade.transport.service.ITransportReconciliationService; import org.springblade.transport.wrapper.TransportReconciliationWrapper; import org.springframework.stereotype.Service; +import org.springframework.transaction.interceptor.TransactionAspectSupport; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; @@ -139,6 +140,9 @@ public class TransportReconciliationServiceImpl @Override public TransportReconciliationVO detail(Long id) { TransportReconciliationVO vo = TransportReconciliationWrapper.build().entityVO(existing(id)); + if (Func.isEmpty(vo.getCustomerName())) { + vo.setCustomerName("receivable".equals(vo.getSettlementType()) ? vo.getPayerName() : vo.getPayeeName()); + } vo.setInternalDetails(internalRows(id)); vo.setExternalDetails(externalRows(id)); vo.setChangeRecords(changeRecordMapper.selectList(Wrappers.lambdaQuery() @@ -196,32 +200,115 @@ public class TransportReconciliationServiceImpl @Override @Transactional(rollbackFor = Exception.class) public List importVehicles(Long id, List rows) { + if (Func.isEmpty(rows)) throw new ServiceException("导入数据不能为空"); TransportReconciliation bill = editable(id); if (!VEHICLE.equals(bill.getReconciliationMode())) throw new ServiceException("当前对账模式不是整车总额对账"); resetExternal(id); List failures = new ArrayList<>(); + List validExternals = new ArrayList<>(); for (int index = 0; index < rows.size(); index++) { VehicleReconciliationExcel row = rows.get(index); + List validationErrors = validateImportVehicle(row); + if (Func.isNotEmpty(validationErrors)) { + VehicleReconciliationFailureExcel failure = new VehicleReconciliationFailureExcel(); + BeanUtil.copyProperties(row, failure); + failure.setErrorMessage(org.springblade.common.excel.ImportFailureExcelUtil.formatErrorMessage(validationErrors)); + failures.add(failure); + continue; + } try { - validateExternal(row.getVehicleNo(), row.getCargoName(), row.getTransportQuantity(), row.getSettlementAmount()); - TransportReconciliationExternal external = new TransportReconciliationExternal(); - BeanUtil.copyProperties(row, external); - external.setReconciliationId(id); external.setExternalLineNo(index + 2); - external.setActualDepartureTime(parseTime(row.getActualDepartureTime(), "实际发货时间")); - external.setActualCompletionTime(parseTimeNullable(row.getActualCompletionTime(), "实际完成时间")); - external.setFeeItemsJson(JsonUtil.toJson(Map.of("费用项目1", money(row.getFeeItemOne())))); - external.setMatchStatus(UNMATCHED); external.setSuspectedDuplicate(false); - external.setRawDataJson(JsonUtil.toJson(row)); externalMapper.insert(external); + validExternals.add(buildVehicleExternal(id, index, row)); } catch (Exception exception) { VehicleReconciliationFailureExcel failure = new VehicleReconciliationFailureExcel(); - BeanUtil.copyProperties(row, failure); failure.setErrorMessage(exception.getMessage()); + BeanUtil.copyProperties(row, failure); + failure.setErrorMessage(org.springblade.common.excel.ImportFailureExcelUtil.formatErrorMessage(List.of( + exception instanceof ServiceException ? exception.getMessage() : "导入失败"))); failures.add(failure); } } + if (Func.isNotEmpty(failures)) { + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + return failures; + } + for (TransportReconciliationExternal external : validExternals) { + if (externalMapper.insert(external) <= 0) throw new ServiceException("外部账单保存失败"); + } refreshStats(id); return failures; } + private TransportReconciliationExternal buildVehicleExternal(Long reconciliationId, int index, + VehicleReconciliationExcel row) { + TransportReconciliationExternal external = new TransportReconciliationExternal(); + BeanUtil.copyProperties(row, external); + external.setReconciliationId(reconciliationId); + external.setExternalLineNo(index + 2); + external.setActualDepartureTime(parseTime(row.getActualDepartureTime(), "实际发货时间")); + external.setActualCompletionTime(parseTimeNullable(row.getActualCompletionTime(), "实际完成时间")); + external.setFeeItemsJson(JsonUtil.toJson(Map.of("费用项目1", money(row.getFeeItemOne())))); + external.setMatchStatus(UNMATCHED); + external.setSuspectedDuplicate(false); + external.setRawDataJson(JsonUtil.toJson(row)); + return external; + } + + private List validateImportVehicle(VehicleReconciliationExcel row) { + List validationErrors = new ArrayList<>(); + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, + Func.isEmpty(row.getVehicleNo()), "车牌号不能为空"); + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, + Func.isEmpty(row.getCargoName()), "货物名称不能为空"); + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, + Func.isEmpty(row.getActualDepartureTime()), "实际发货时间不能为空"); + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, + Func.isEmpty(row.getTransportQuantity()), "运输总量不能为空"); + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, + Func.isEmpty(row.getSettlementAmount()), "结算费用合计不能为空"); + + addImportLengthError(validationErrors, row.getVehicleNo(), 30, "车牌号不能超过30字"); + addImportLengthError(validationErrors, row.getDepartureAddress(), 500, "发货地址不能超过500字"); + addImportLengthError(validationErrors, row.getArrivalAddress(), 500, "到货地址不能超过500字"); + addImportLengthError(validationErrors, row.getTransportType(), 100, "运输类型不能超过100字"); + addImportLengthError(validationErrors, row.getCargoName(), 500, "货物名称不能超过500字"); + addImportLengthError(validationErrors, row.getCargoType(), 500, "货物类型不能超过500字"); + addImportLengthError(validationErrors, row.getBatchNo(), 100, "批次号不能超过100字"); + + addImportDecimalErrors(validationErrors, row.getTransportQuantity(), "运输总量", 6); + addImportDecimalErrors(validationErrors, row.getMileage(), "里程(KM)", 2); + addImportDecimalErrors(validationErrors, row.getUnitPrice(), "运输单价", 2); + addImportDecimalErrors(validationErrors, row.getFreightAmount(), "运输费", 2); + addImportDecimalErrors(validationErrors, row.getFeeItemOne(), "费用项目1", 2); + addImportDecimalErrors(validationErrors, row.getSettlementAmount(), "结算费用合计", 2); + + LocalDateTime departureTime = parseImportTime(row.getActualDepartureTime(), "实际发货时间", validationErrors); + LocalDateTime completionTime = parseImportTime(row.getActualCompletionTime(), "实际完成时间", validationErrors); + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, + departureTime != null && completionTime != null && completionTime.isBefore(departureTime), + "实际完成时间不能早于实际发货时间"); + return validationErrors; + } + + private LocalDateTime parseImportTime(String value, String field, List validationErrors) { + if (Func.isEmpty(value)) return null; + try { + return parseTimeNullable(value, field); + } catch (ServiceException exception) { + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, true, exception.getMessage()); + return null; + } + } + + private void addImportLengthError(List validationErrors, String value, int maxLength, String message) { + org.springblade.common.excel.ImportFailureExcelUtil.addLengthValidationError(validationErrors, value, maxLength, message); + } + + private void addImportDecimalErrors(List validationErrors, BigDecimal value, String field, int scale) { + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, + value != null && value.compareTo(BigDecimal.ZERO) < 0, field + "不能小于0"); + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, + value != null && value.stripTrailingZeros().scale() > scale, field + "最多保留" + scale + "位小数"); + } + @Override @Transactional(rollbackFor = Exception.class) public List importCargoes(Long id, List rows) { @@ -563,6 +650,7 @@ public class TransportReconciliationServiceImpl bill.setFormalSettlementId(formal.getId()); bill.setFormalSettlementNo(formal.getFormalSettlementNo()); bill.setSettlementType(formal.getSettlementType()); bill.setProjectId(formal.getProjectId()); bill.setProjectName(formal.getProjectName()); bill.setDeptId(formal.getDeptId()); bill.setDeptName(formal.getDeptName()); bill.setContractId(formal.getContractId()); bill.setContractNo(formal.getContractNo()); bill.setContractName(formal.getContractName()); + bill.setCustomerName("receivable".equals(formal.getSettlementType()) ? formal.getPayerName() : formal.getPayeeName()); bill.setPayerName(formal.getPayerName()); bill.setPayeeName(formal.getPayeeName()); bill.setCurrency(formal.getCurrency()); bill.setSettlementAmount(money(formal.getSettlementAmount())); bill.setPaidAmount(money(formal.getPaidAmount())); List preNos = formalSourceMapper.selectList(Wrappers.lambdaQuery().eq(FormalSettlementSource::getFormalSettlementId, formal.getId())) @@ -637,5 +725,20 @@ public class TransportReconciliationServiceImpl private BigDecimal sumExternalQuantity(List rows) { return rows.stream().map(TransportReconciliationExternal::getTransportQuantity).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add); } private BigDecimal sumInternalAmount(List rows) { return rows.stream().map(TransportReconciliationInternal::getSettlementAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add); } private BigDecimal sumExternalAmount(List rows) { return rows.stream().map(TransportReconciliationExternal::getSettlementAmount).map(this::money).reduce(BigDecimal.ZERO, BigDecimal::add); } - private String nextNo() { return "DZ" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")); } + private synchronized String nextNo() { + String prefix = "DZD" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); + int sequence = list(Wrappers.lambdaQuery() + .select(TransportReconciliation::getReconciliationNo) + .likeRight(TransportReconciliation::getReconciliationNo, prefix)) + .stream() + .map(TransportReconciliation::getReconciliationNo) + .filter(number -> number != null && number.length() == prefix.length() + 5) + .map(number -> number.substring(prefix.length())) + .filter(suffix -> suffix.chars().allMatch(Character::isDigit)) + .mapToInt(Integer::parseInt) + .max() + .orElse(0) + 1; + if (sequence > 99999) throw new ServiceException("当日运输对账单号流水已用完"); + return prefix + String.format("%05d", sequence); + } } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillImportBatchServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillImportBatchServiceImpl.java index 690c4bd..64b1076 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillImportBatchServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/WaybillImportBatchServiceImpl.java @@ -25,6 +25,7 @@ import org.springblade.transport.pojo.vo.BusinessRemoveResultVO; import org.springblade.transport.pojo.vo.WaybillImportBatchVO; import org.springblade.transport.service.ICustomerArchiveService; import org.springblade.transport.service.IProjectApplyService; +import org.springblade.transport.service.IReceivablePayableDetailService; import org.springblade.transport.service.ITransportPlanService; import org.springblade.transport.service.IWaybillImportBatchService; import org.springblade.transport.service.IWaybillService; @@ -48,56 +49,75 @@ import java.util.stream.Collectors; public class WaybillImportBatchServiceImpl extends BaseServiceImpl implements IWaybillImportBatchService { private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + /** 批量导入状态仅保留草稿与导入完成两种。 */ + private static final String STATUS_DRAFT = "draft"; + private static final String STATUS_COMPLETED = "completed"; + private static final String IMPORT_TYPE_WAYBILL = "waybill"; + private static final String IMPORT_TYPE_SETTLEMENT = "settlement"; private final IWaybillService waybillService; private final ICustomerArchiveService customerArchiveService; private final IProjectApplyService projectApplyService; private final ITransportPlanService transportPlanService; + private final IReceivablePayableDetailService receivablePayableDetailService; @Override @Transactional(rollbackFor = Exception.class) public WaybillImportBatch saveDraft(WaybillImportBatchRequest request) { - WaybillImportBatch batch = buildBatch(request, "draft"); - batch.setWaybillCount(0); - if (Func.isNotEmpty(request.getId())) { - WaybillImportBatch oldBatch = getById(request.getId()); - if (oldBatch == null || Objects.equals(oldBatch.getIsDeleted(), 1)) throw new ServiceException("运单批次不存在"); - batch.setId(oldBatch.getId()); - batch.setBatchNo(oldBatch.getBatchNo()); - } - saveOrUpdate(batch); - return batch; + return persist(request, STATUS_DRAFT); } @Override @Transactional(rollbackFor = Exception.class) public WaybillImportBatch confirm(WaybillImportBatchRequest request) { if (Func.isEmpty(request.getRows())) throw new ServiceException("请上传至少一条运单明细"); - String importStatus = "processing".equals(request.getStatus()) ? "processing" : "completed"; + return persist(request, STATUS_DRAFT.equals(request.getStatus()) ? STATUS_DRAFT : STATUS_COMPLETED); + } + + /** 草稿与确认导入共用落库流程,差异仅在于运单是否走校验以及是否生成应收应付明细。 */ + private WaybillImportBatch persist(WaybillImportBatchRequest request, String importStatus) { + boolean draft = STATUS_DRAFT.equals(importStatus); WaybillImportBatch batch = buildBatch(request, importStatus); if (Func.isNotEmpty(request.getId())) { WaybillImportBatch oldBatch = getById(request.getId()); if (oldBatch == null || Objects.equals(oldBatch.getIsDeleted(), 1)) throw new ServiceException("运单批次不存在"); - if (!"draft".equals(oldBatch.getImportStatus())) throw new ServiceException("仅草稿状态的批次允许确认导入"); + if (!STATUS_DRAFT.equals(oldBatch.getImportStatus())) throw new ServiceException("仅草稿状态的批次允许编辑"); batch.setId(oldBatch.getId()); batch.setBatchNo(oldBatch.getBatchNo()); } batch.setWaybillCount(0); saveOrUpdate(batch); + // 重新落库前清理批次已生成的运单,避免草稿反复保存产生重复运单。 + clearBatchWaybills(batch.getId()); - for (int index = 0; index < request.getRows().size(); index++) { + List> rows = Func.isEmpty(request.getRows()) ? List.of() : request.getRows(); + List waybills = new ArrayList<>(); + for (int index = 0; index < rows.size(); index++) { try { - Waybill waybill = buildWaybill(request.getRows().get(index), batch, request.getCarrierContractId()); - waybillService.submit(waybill); + Waybill waybill = buildWaybill(rows.get(index), batch, request.getCarrierContractId(), draft); + if (draft) waybillService.saveDraft(waybill); else waybillService.submit(waybill); + waybills.add(waybill); } catch (Exception exception) { - throw new ServiceException("第" + (index + 1) + "行导入失败:" + exception.getMessage()); + throw new ServiceException("第" + (index + 1) + "行" + (draft ? "保存" : "导入") + "失败:" + exception.getMessage()); } } - batch.setWaybillCount(request.getRows().size()); - batch.setImportStatus(importStatus); + batch.setWaybillCount(waybills.size()); updateById(batch); + // 导入完成且导入类型为运单时,按合同费用生成模式(系统生成)同步生成应收应付明细。 + if (!draft && IMPORT_TYPE_WAYBILL.equals(batch.getImportType())) { + receivablePayableDetailService.generateForImportedWaybills(waybills); + } return batch; } + private void clearBatchWaybills(Long batchId) { + if (Func.isEmpty(batchId)) return; + List waybills = waybillService.list(Wrappers.lambdaQuery() + .eq(Waybill::getImportBatchId, batchId).eq(Waybill::getIsDeleted, 0)); + if (Func.isNotEmpty(waybills)) { + waybillService.deleteLogic(waybills.stream().map(Waybill::getId).toList()); + } + } + @Override public IPage page(IPage page, WaybillImportBatchRequest request) { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() @@ -143,7 +163,7 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl row, WaybillImportBatch batch, Long carrierContractId) { + private Waybill buildWaybill(Map row, WaybillImportBatch batch, Long carrierContractId, boolean draft) { if (row == null) throw new ServiceException("运单数据不正确"); Waybill waybill = new Waybill(); waybill.setOriginalNo(stringValue(row, "originalNo")); @@ -207,12 +227,13 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl "草稿"; case "processing" -> "进行中"; default -> "完成"; }); + vo.setImportTypeName(IMPORT_TYPE_SETTLEMENT.equals(batch.getImportType()) ? "结算单" : "运单"); + vo.setStatusName(STATUS_DRAFT.equals(batch.getImportStatus()) ? "草稿" : "导入完成"); vo.setCreateUserName(UserCache.getUserRealName(batch.getCreateUser())); vo.setUpdateUserName(UserCache.getUserRealName(batch.getUpdateUser())); return vo; diff --git a/doc/sql/transport/blade_transport_reconciliation_20260818.sql b/doc/sql/transport/blade_transport_reconciliation_20260818.sql index 9c539e1..db7bf0e 100644 --- a/doc/sql/transport/blade_transport_reconciliation_20260818.sql +++ b/doc/sql/transport/blade_transport_reconciliation_20260818.sql @@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS `blade_transport_reconciliation` ( `reconciliation_no` varchar(100) NOT NULL, `formal_settlement_id` bigint(20) NOT NULL, `formal_settlement_no` varchar(100) NOT NULL, `pre_settlement_nos` varchar(1000) DEFAULT NULL, `settlement_type` varchar(30) NOT NULL, `reconciliation_mode` varchar(30) NOT NULL, `project_id` bigint(20) DEFAULT NULL, `project_name` varchar(100) DEFAULT NULL, `dept_id` bigint(20) DEFAULT NULL, `dept_name` varchar(100) DEFAULT NULL, - `contract_id` bigint(20) DEFAULT NULL, `contract_no` varchar(100) DEFAULT NULL, `contract_name` varchar(200) DEFAULT NULL, + `contract_id` bigint(20) DEFAULT NULL, `contract_no` varchar(100) DEFAULT NULL, `contract_name` varchar(200) DEFAULT NULL, `customer_name` varchar(200) DEFAULT NULL COMMENT '客户/承运商', `payer_name` varchar(200) DEFAULT NULL, `payee_name` varchar(200) DEFAULT NULL, `currency` varchar(20) DEFAULT 'RMB', `settlement_amount` decimal(18,2) DEFAULT 0, `paid_amount` decimal(18,2) DEFAULT 0, `reconciler_id` bigint(20) DEFAULT NULL, `reconciler_name` varchar(100) DEFAULT NULL, `reconciliation_date` date DEFAULT NULL, `reconciliation_status` varchar(30) NOT NULL DEFAULT 'unfinished', diff --git a/doc/sql/transport/blade_transport_reconciliation_customer_name_20260907.sql b/doc/sql/transport/blade_transport_reconciliation_customer_name_20260907.sql new file mode 100644 index 0000000..1747645 --- /dev/null +++ b/doc/sql/transport/blade_transport_reconciliation_customer_name_20260907.sql @@ -0,0 +1,25 @@ +SET @db_name = DATABASE(); +SET @column_exists = 0; + +SELECT COUNT(*) +INTO @column_exists +FROM information_schema.columns +WHERE table_schema = @db_name + AND table_name = 'blade_transport_reconciliation' + AND column_name = 'customer_name'; + +SET @alter_sql = IF( + @column_exists = 0, + 'ALTER TABLE `blade_transport_reconciliation` ADD COLUMN `customer_name` varchar(200) DEFAULT NULL COMMENT ''客户/承运商'' AFTER `contract_name`', + 'SELECT 1' +); +PREPARE alter_statement FROM @alter_sql; +EXECUTE alter_statement; +DEALLOCATE PREPARE alter_statement; + +UPDATE `blade_transport_reconciliation` +SET `customer_name` = CASE + WHEN `settlement_type` = 'receivable' THEN `payer_name` + ELSE `payee_name` +END +WHERE `customer_name` IS NULL OR `customer_name` = '';