From 598a8b89e3fe542c6affae1df2d6e46d3c2824c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E9=B8=BF=E5=B1=95?= <18031053041@163.com> Date: Mon, 9 Feb 2026 10:26:07 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A1=E5=88=92=E6=95=B0=E9=87=8F=E4=B8=BA0?= =?UTF-8?q?=E7=9A=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StockInOrderApplicationService.java | 94 +++++++++++++++---- .../stockInOrder/StockInOrderAssembler.java | 9 ++ 2 files changed, 83 insertions(+), 20 deletions(-) diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java index 9058a6ffc..ad72c6048 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java @@ -30,6 +30,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; @@ -1176,6 +1177,31 @@ public class StockInOrderApplicationService { h.getConsignmentNo(), r.getMaterialName(), r.getMaterialCode(), r.getSkuCode(), r.getWarehouseQuantity(), r.getInboundQuantity()); + // 先检查数量,如果数量为空,直接跳过该明细行(不需要检查物料) + BigDecimal quantity = r.getWarehouseQuantity(); + if (quantity == null) { + quantity = r.getInboundQuantity(); + } + if (quantity == null) { + log.warn("跳过明细行:仓库数量或入库数量不能为空 - 委托编号NO: [{}], 商品名称: [{}], 料号: [{}], SKU码: [{}]", + h.getConsignmentNo(), r.getMaterialName(), r.getMaterialCode(), r.getSkuCode()); + continue; // 跳过该明细行,继续处理下一行 + } + + // 检查是否为容器类型等非物料信息,如果是则跳过 + String materialName = r.getMaterialName(); + if (StringUtils.isNotBlank(materialName)) { + String lowerName = materialName.trim(); + // 常见的容器类型关键词(不区分大小写) + if (lowerName.contains("尺柜") || lowerName.contains("尺集装箱") || + lowerName.contains("Container") || lowerName.contains("container") || + (lowerName.contains("柜") && (lowerName.contains("20") || lowerName.contains("40") || lowerName.contains("45")))) { + log.info("跳过明细行:识别为容器类型信息,非实际物料 - 委托编号NO: [{}], 商品名称: [{}]", + h.getConsignmentNo(), materialName); + continue; // 跳过该明细行,继续处理下一行 + } + } + // 根据明细表中的字段查询物料基础信息(优先:料号 > 商品SKU码 > 商品名称) // 注意:查询时必须加上货主ID条件,确保查询到的是该货主绑定的物料 Long materialBaseInfoId = null; @@ -1203,13 +1229,17 @@ public class StockInOrderApplicationService { log.info("通过料号查询到物料基础信息,料号: {}, 物料ID: {}, 货主ID: {}", r.getMaterialCode(), materialBaseInfoId, shipperId); } else { - log.warn("通过料号未查询到物料基础信息,料号: [{}], 货主ID: [{}]", r.getMaterialCode(), shipperId); + // 如果提供了料号但查询不到,直接报错,不允许导入 + String errorMsg = String.format("导入失败:该货主下不存在该料号(委托编号NO=%s,货主名称=%s,料号=%s)。请确保该料号已在物料管理中创建,且属于该货主", + h.getConsignmentNo(), order.getShipperName(), r.getMaterialCode()); + log.error(errorMsg); + throw new ServiceException(errorMsg); } } else { - log.warn("料号为空,跳过料号查询"); + log.warn("料号为空,跳过料号查询,将尝试使用SKU码或商品名称查询"); } - // 如果料号查询不到,使用商品SKU码查询 + // 只有在料号为空的情况下,才使用商品SKU码查询 if (materialBaseInfoId == null && StringUtils.isNotBlank(r.getSkuCode())) { MaterialBaseInfoDO queryDO = new MaterialBaseInfoDO(); queryDO.setBarCode(r.getSkuCode()); @@ -1261,26 +1291,40 @@ public class StockInOrderApplicationService { log.warn("商品名称为空,跳过商品名称查询"); } - // 如果都查询不到,记录警告但不阻止导入(允许后续手动关联) + // 如果都查询不到物料基础信息,阻止导入并抛出异常 if (materialBaseInfoId == null) { - log.warn("未查询到物料基础信息,料号: [{}], SKU码: [{}], 商品名称: [{}],将使用null值,后续可能需要手动关联", - r.getMaterialCode(), r.getSkuCode(), r.getMaterialName()); + // 检查是否至少有一个查询条件 + boolean hasQueryCondition = StringUtils.isNotBlank(r.getMaterialCode()) + || StringUtils.isNotBlank(r.getSkuCode()) + || StringUtils.isNotBlank(r.getMaterialName()); + + // 构建错误信息,说明物料在物料管理中不存在 + StringBuilder errorMsg = new StringBuilder(); + errorMsg.append("导入失败:物料在物料管理中不存在(委托编号NO=").append(h.getConsignmentNo()); + errorMsg.append(",货主名称=").append(order.getShipperName()); + if (StringUtils.isNotBlank(r.getMaterialCode())) { + errorMsg.append(",料号=").append(r.getMaterialCode()); + } + if (StringUtils.isNotBlank(r.getSkuCode())) { + errorMsg.append(",SKU码=").append(r.getSkuCode()); + } + if (StringUtils.isNotBlank(r.getMaterialName())) { + errorMsg.append(",商品名称=").append(r.getMaterialName()); + } + errorMsg.append(")"); + + if (!hasQueryCondition) { + errorMsg.append("。明细行缺少物料标识信息(料号、SKU码或商品名称至少需要填写一个)"); + } else { + errorMsg.append("。请确保该物料已在物料管理中创建,且料号、SKU码或商品名称与货主信息匹配"); + } + log.error(errorMsg.toString()); + throw new ServiceException(errorMsg.toString()); } - // 使用仓库数量或入库数量(优先使用仓库数量,如果为空则使用入库数量) - BigDecimal quantity = r.getWarehouseQuantity(); - log.info("数量字段检查 - 仓库数量: [{}], 入库数量: [{}]", r.getWarehouseQuantity(), r.getInboundQuantity()); - if (quantity == null) { - quantity = r.getInboundQuantity(); - log.info("仓库数量为空,使用入库数量: [{}]", quantity); - } - // 如果数量为空,跳过该明细行,记录警告,继续处理其他行 - if (quantity == null) { - log.warn("跳过明细行:仓库数量或入库数量不能为空 - 委托编号NO: [{}], 物料基础信息ID: [{}], 商品名称: [{}], 料号: [{}], SKU码: [{}], 仓库数量: [{}], 入库数量: [{}]", - h.getConsignmentNo(), materialBaseInfoId, r.getMaterialName(), r.getMaterialCode(), - r.getSkuCode(), r.getWarehouseQuantity(), r.getInboundQuantity()); - continue; // 跳过该明细行,继续处理下一行 - } + // 数量已在前面检查过,这里直接使用 + log.info("数量字段检查 - 仓库数量: [{}], 入库数量: [{}], 使用数量: [{}]", + r.getWarehouseQuantity(), r.getInboundQuantity(), quantity); InMaterialDetailDO d = new InMaterialDetailDO(); d.setMaterialBaseInfoId(materialBaseInfoId); @@ -1359,6 +1403,16 @@ public class StockInOrderApplicationService { order.setMaterialDetailList(details); + // 导入入库单时,计划数量取所有明细行的入库数量之和 + if (!CollectionUtils.isEmpty(details)) { + BigDecimal totalInboundQuantity = details.stream() + .map(detail -> detail.getInboundQuantity() != null ? detail.getInboundQuantity() : BigDecimal.ZERO) + .reduce(BigDecimal.ZERO, BigDecimal::add); + order.setQuantity(totalInboundQuantity); + log.info("计算计划数量 - 委托编号NO: [{}], 明细行数: {}, 计划数量(入库数量之和): [{}]", + h.getConsignmentNo(), details.size(), totalInboundQuantity); + } + // 在导入时,需要调用shipperParam、supplierParam和setDataDict方法,确保货主信息被正确填充 // 注意:这里只调用shipperParam,因为导入时只提供了货主名称,需要根据名称查找货主ID和编号 try { diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/assember/stockInOrder/StockInOrderAssembler.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/assember/stockInOrder/StockInOrderAssembler.java index b2fd38df6..2c741d1cf 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/assember/stockInOrder/StockInOrderAssembler.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/assember/stockInOrder/StockInOrderAssembler.java @@ -11,7 +11,9 @@ import com.mhd.system.api.model.LoginUser; import com.mhd.wms.domain.stockInOrder.repository.todo.StockInOrderDO; import com.mhd.wms.interfaces.dto.stockInOrder.StockInOrderDTO; import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; +import java.math.BigDecimal; import java.util.Date; /** @@ -78,6 +80,13 @@ public class StockInOrderAssembler { if (orderTypeName == null || orderTypeName.trim().length() == 0) { stockInOrderDO.setOrderTypeName("普通入库单"); } + // 新增入库单时,计划数量取所有明细行的入库数量之和 + if (!CollectionUtils.isEmpty(stockInOrderDO.getMaterialDetailList())) { + BigDecimal totalInboundQuantity = stockInOrderDO.getMaterialDetailList().stream() + .map(detail -> detail.getInboundQuantity() != null ? detail.getInboundQuantity() : BigDecimal.ZERO) + .reduce(BigDecimal.ZERO, BigDecimal::add); + stockInOrderDO.setQuantity(totalInboundQuantity); + } } return stockInOrderDO; }