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 33bf1d7fe..96e280efb 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 @@ -342,8 +342,59 @@ public class StockInOrderApplicationService { headerInfo.setManufacturer(value); log.info("从表头第{}行读取到生产商: {}", rowIdx + 1, value); } else if (labelValue.contains("报关员") && StringUtils.isBlank(headerInfo.getCustomsBrokerInfo())) { - headerInfo.setCustomsBrokerInfo(value); - log.info("从表头第{}行读取到报关员姓名及联系方式: {}", rowIdx + 1, value); + // 过滤掉标签文本(包含冒号、常见标签关键词等) + if (StringUtils.isNotBlank(value) && + !value.contains(":") && !value.contains(":") && + !value.contains("完成时间") && !value.contains("下单日期") && !value.contains("入仓日期") && + !value.contains("联系人") && !value.contains("Tel") && !value.contains("Fax") && + !value.contains("客户") && !value.contains("地址") && !value.contains("日期") && + !value.contains("方式") && !value.contains("关区") && !value.contains("关别") && + !value.contains("报关员") && !value.contains("生产商") && !value.contains("承运方")) { + headerInfo.setCustomsBrokerInfo(value); + log.info("从表头第{}行读取到报关员姓名及联系方式: {}", rowIdx + 1, value); + } else { + // 如果找到的值是标签,继续向后查找 + boolean found = false; + for (int searchColIdx = colIdx + 2; searchColIdx < colIdx + 10 && searchColIdx < row.getPhysicalNumberOfCells(); searchColIdx++) { + Cell nextValueCell = row.getCell(searchColIdx); + if (nextValueCell != null) { + String nextValue = getCellValueAsString(nextValueCell); + // 跳过标签文本(包含冒号、常见标签关键词等) + if (StringUtils.isNotBlank(nextValue) && + !nextValue.contains(":") && !nextValue.contains(":") && + !nextValue.contains("完成时间") && !nextValue.contains("下单日期") && !nextValue.contains("入仓日期") && + !nextValue.contains("联系人") && !nextValue.contains("Tel") && !nextValue.contains("Fax") && + !nextValue.contains("客户") && !nextValue.contains("地址") && !nextValue.contains("日期") && + !nextValue.contains("方式") && !nextValue.contains("关区") && !nextValue.contains("关别") && + !nextValue.contains("报关员") && !nextValue.contains("生产商") && !nextValue.contains("承运方")) { + headerInfo.setCustomsBrokerInfo(nextValue); + log.info("从表头第{}行读取到报关员姓名及联系方式: {}", rowIdx + 1, nextValue); + found = true; + break; + } + } + } + // 如果没找到合适的值,尝试查找下一行的同一列 + if (!found) { + Row nextRow = sheet.getRow(rowIdx + 1); + if (nextRow != null) { + Cell nextRowCell = nextRow.getCell(colIdx); + if (nextRowCell != null) { + String nextRowValue = getCellValueAsString(nextRowCell); + if (StringUtils.isNotBlank(nextRowValue) && + !nextRowValue.contains(":") && !nextRowValue.contains(":") && + !nextRowValue.contains("完成时间") && !nextRowValue.contains("下单日期") && !nextRowValue.contains("入仓日期") && + !nextRowValue.contains("联系人") && !nextRowValue.contains("Tel") && !nextRowValue.contains("Fax") && + !nextRowValue.contains("客户") && !nextRowValue.contains("地址") && !nextRowValue.contains("日期") && + !nextRowValue.contains("方式") && !nextRowValue.contains("关区") && !nextRowValue.contains("关别") && + !nextRowValue.contains("报关员") && !nextRowValue.contains("生产商") && !nextRowValue.contains("承运方")) { + headerInfo.setCustomsBrokerInfo(nextRowValue); + log.info("从表头第{}行(下一行)读取到报关员姓名及联系方式: {}", rowIdx + 2, nextRowValue); + } + } + } + } + } } else if (labelValue.contains("送货地址") && StringUtils.isBlank(headerInfo.getDeliveryAddress())) { headerInfo.setDeliveryAddress(value); log.info("从表头第{}行读取到送货地址: {}", rowIdx + 1, value); @@ -384,11 +435,119 @@ public class StockInOrderApplicationService { } log.info("从表头第{}行读取到是否需要运输: {}", rowIdx + 1, value); } else if (labelValue.contains("完成时间") && StringUtils.isBlank(headerInfo.getCompletionTime())) { - headerInfo.setCompletionTime(value); - log.info("从表头第{}行读取到完成时间: {}", rowIdx + 1, value); + // 过滤掉标签文本(包含冒号、常见标签关键词等) + if (StringUtils.isNotBlank(value) && + !value.contains(":") && !value.contains(":") && + !value.contains("下单日期") && !value.contains("入仓日期") && + !value.contains("起运") && !value.contains("运抵国") && !value.contains("地区") && + !value.contains("联系人") && !value.contains("Tel") && !value.contains("Fax") && + !value.contains("客户") && !value.contains("地址") && !value.contains("日期") && + !value.contains("方式") && !value.contains("关区") && !value.contains("关别") && + !value.contains("报关员") && !value.contains("生产商") && !value.contains("承运方")) { + headerInfo.setCompletionTime(value); + log.info("从表头第{}行读取到完成时间: {}", rowIdx + 1, value); + } else { + // 如果找到的值是标签,继续向后查找 + boolean found = false; + for (int searchColIdx = colIdx + 2; searchColIdx < colIdx + 10 && searchColIdx < row.getPhysicalNumberOfCells(); searchColIdx++) { + Cell nextValueCell = row.getCell(searchColIdx); + if (nextValueCell != null) { + String nextValue = getCellValueAsString(nextValueCell); + // 跳过标签文本(包含冒号、常见标签关键词等) + if (StringUtils.isNotBlank(nextValue) && + !nextValue.contains(":") && !nextValue.contains(":") && + !nextValue.contains("下单日期") && !nextValue.contains("入仓日期") && + !nextValue.contains("起运") && !nextValue.contains("运抵国") && !nextValue.contains("地区") && + !nextValue.contains("联系人") && !nextValue.contains("Tel") && !nextValue.contains("Fax") && + !nextValue.contains("客户") && !nextValue.contains("地址") && !nextValue.contains("日期") && + !nextValue.contains("方式") && !nextValue.contains("关区") && !nextValue.contains("关别") && + !nextValue.contains("报关员") && !nextValue.contains("生产商") && !nextValue.contains("承运方")) { + headerInfo.setCompletionTime(nextValue); + log.info("从表头第{}行读取到完成时间: {}", rowIdx + 1, nextValue); + found = true; + break; + } + } + } + // 如果没找到合适的值,尝试查找下一行的同一列 + if (!found) { + Row nextRow = sheet.getRow(rowIdx + 1); + if (nextRow != null) { + Cell nextRowCell = nextRow.getCell(colIdx); + if (nextRowCell != null) { + String nextRowValue = getCellValueAsString(nextRowCell); + if (StringUtils.isNotBlank(nextRowValue) && + !nextRowValue.contains(":") && !nextRowValue.contains(":") && + !nextRowValue.contains("下单日期") && !nextRowValue.contains("入仓日期") && + !nextRowValue.contains("起运") && !nextRowValue.contains("运抵国") && !nextRowValue.contains("地区") && + !nextRowValue.contains("联系人") && !nextRowValue.contains("Tel") && !nextRowValue.contains("Fax") && + !nextRowValue.contains("客户") && !nextRowValue.contains("地址") && !nextRowValue.contains("日期") && + !nextRowValue.contains("方式") && !nextRowValue.contains("关区") && !nextRowValue.contains("关别") && + !nextRowValue.contains("报关员") && !nextRowValue.contains("生产商") && !nextRowValue.contains("承运方")) { + headerInfo.setCompletionTime(nextRowValue); + log.info("从表头第{}行(下一行)读取到完成时间: {}", rowIdx + 2, nextRowValue); + } + } + } + } + } } else if (labelValue.contains("下单日期") && StringUtils.isBlank(headerInfo.getOrderDate())) { - headerInfo.setOrderDate(value); - log.info("从表头第{}行读取到下单日期: {}", rowIdx + 1, value); + // 过滤掉标签文本(包含冒号、常见标签关键词等) + if (StringUtils.isNotBlank(value) && + !value.contains(":") && !value.contains(":") && + !value.contains("起运") && !value.contains("运抵国") && !value.contains("地区") && + !value.contains("完成时间") && !value.contains("入仓日期") && + !value.contains("联系人") && !value.contains("Tel") && !value.contains("Fax") && + !value.contains("客户") && !value.contains("地址") && !value.contains("日期") && + !value.contains("方式") && !value.contains("关区") && !value.contains("关别") && + !value.contains("报关员") && !value.contains("生产商") && !value.contains("承运方")) { + headerInfo.setOrderDate(value); + log.info("从表头第{}行读取到下单日期: {}", rowIdx + 1, value); + } else { + // 如果找到的值是标签,继续向后查找 + boolean found = false; + for (int searchColIdx = colIdx + 2; searchColIdx < colIdx + 10 && searchColIdx < row.getPhysicalNumberOfCells(); searchColIdx++) { + Cell nextValueCell = row.getCell(searchColIdx); + if (nextValueCell != null) { + String nextValue = getCellValueAsString(nextValueCell); + // 跳过标签文本(包含冒号、常见标签关键词等) + if (StringUtils.isNotBlank(nextValue) && + !nextValue.contains(":") && !nextValue.contains(":") && + !nextValue.contains("起运") && !nextValue.contains("运抵国") && !nextValue.contains("地区") && + !nextValue.contains("完成时间") && !nextValue.contains("入仓日期") && + !nextValue.contains("联系人") && !nextValue.contains("Tel") && !nextValue.contains("Fax") && + !nextValue.contains("客户") && !nextValue.contains("地址") && !nextValue.contains("日期") && + !nextValue.contains("方式") && !nextValue.contains("关区") && !nextValue.contains("关别") && + !nextValue.contains("报关员") && !nextValue.contains("生产商") && !nextValue.contains("承运方")) { + headerInfo.setOrderDate(nextValue); + log.info("从表头第{}行读取到下单日期: {}", rowIdx + 1, nextValue); + found = true; + break; + } + } + } + // 如果没找到合适的值,尝试查找下一行的同一列 + if (!found) { + Row nextRow = sheet.getRow(rowIdx + 1); + if (nextRow != null) { + Cell nextRowCell = nextRow.getCell(colIdx); + if (nextRowCell != null) { + String nextRowValue = getCellValueAsString(nextRowCell); + if (StringUtils.isNotBlank(nextRowValue) && + !nextRowValue.contains(":") && !nextRowValue.contains(":") && + !nextRowValue.contains("起运") && !nextRowValue.contains("运抵国") && !nextRowValue.contains("地区") && + !nextRowValue.contains("完成时间") && !nextRowValue.contains("入仓日期") && + !nextRowValue.contains("联系人") && !nextRowValue.contains("Tel") && !nextRowValue.contains("Fax") && + !nextRowValue.contains("客户") && !nextRowValue.contains("地址") && !nextRowValue.contains("日期") && + !nextRowValue.contains("方式") && !nextRowValue.contains("关区") && !nextRowValue.contains("关别") && + !nextRowValue.contains("报关员") && !nextRowValue.contains("生产商") && !nextRowValue.contains("承运方")) { + headerInfo.setOrderDate(nextRowValue); + log.info("从表头第{}行(下一行)读取到下单日期: {}", rowIdx + 2, nextRowValue); + } + } + } + } + } } else if (labelValue.contains("备注") && StringUtils.isBlank(headerInfo.getRemark())) { headerInfo.setRemark(value); log.info("从表头第{}行读取到备注: {}", rowIdx + 1, value); @@ -682,6 +841,11 @@ public class StockInOrderApplicationService { // 明细 List details = new ArrayList<>(); for (StockInOrderImportRowDTO r : groupRows) { + // 记录当前明细行的关键信息,用于调试 + log.info("处理明细行 - 委托编号NO: {}, 商品名称: [{}], 料号: [{}], SKU码: [{}], 仓库数量: [{}], 入库数量: [{}]", + h.getConsignmentNo(), r.getMaterialName(), r.getMaterialCode(), r.getSkuCode(), + r.getWarehouseQuantity(), r.getInboundQuantity()); + // 根据明细表中的字段查询物料基础信息(优先:料号 > 商品SKU码 > 商品名称) Long materialBaseInfoId = null; LoginUser currentLoginUser = SecurityUtils.getLoginUser(); @@ -695,11 +859,17 @@ public class StockInOrderApplicationService { if (topOrganizationId != null) { queryDO.setTopOrganizationId(topOrganizationId); } + log.info("尝试通过料号查询物料基础信息,料号: [{}], topOrganizationId: {}", r.getMaterialCode(), topOrganizationId); List materialList = materialBaseInfoService.queryList(queryDO); + log.info("料号查询结果,查询到 {} 条记录", materialList != null ? materialList.size() : 0); if (materialList != null && !materialList.isEmpty()) { materialBaseInfoId = materialList.get(0).getMaterialBaseInfoId(); log.info("通过料号查询到物料基础信息,料号: {}, 物料ID: {}", r.getMaterialCode(), materialBaseInfoId); + } else { + log.warn("通过料号未查询到物料基础信息,料号: [{}]", r.getMaterialCode()); } + } else { + log.warn("料号为空,跳过料号查询"); } // 如果料号查询不到,使用商品SKU码查询 @@ -709,11 +879,17 @@ public class StockInOrderApplicationService { if (topOrganizationId != null) { queryDO.setTopOrganizationId(topOrganizationId); } + log.info("尝试通过商品SKU码查询物料基础信息,SKU码: [{}], topOrganizationId: {}", r.getSkuCode(), topOrganizationId); List materialList = materialBaseInfoService.queryList(queryDO); + log.info("SKU码查询结果,查询到 {} 条记录", materialList != null ? materialList.size() : 0); if (materialList != null && !materialList.isEmpty()) { materialBaseInfoId = materialList.get(0).getMaterialBaseInfoId(); log.info("通过商品SKU码查询到物料基础信息,SKU码: {}, 物料ID: {}", r.getSkuCode(), materialBaseInfoId); + } else { + log.warn("通过SKU码未查询到物料基础信息,SKU码: [{}]", r.getSkuCode()); } + } else if (materialBaseInfoId == null) { + log.warn("SKU码为空,跳过SKU码查询"); } // 如果料号和SKU码都查询不到,使用商品名称查询 @@ -723,26 +899,38 @@ public class StockInOrderApplicationService { if (topOrganizationId != null) { queryDO.setTopOrganizationId(topOrganizationId); } + log.info("尝试通过商品名称查询物料基础信息,商品名称: [{}], topOrganizationId: {}", r.getMaterialName(), topOrganizationId); List materialList = materialBaseInfoService.queryList(queryDO); + log.info("商品名称查询结果,查询到 {} 条记录", materialList != null ? materialList.size() : 0); if (materialList != null && !materialList.isEmpty()) { materialBaseInfoId = materialList.get(0).getMaterialBaseInfoId(); log.info("通过商品名称查询到物料基础信息,商品名称: {}, 物料ID: {}", r.getMaterialName(), materialBaseInfoId); + } else { + log.warn("通过商品名称未查询到物料基础信息,商品名称: [{}]", r.getMaterialName()); } + } else if (materialBaseInfoId == null) { + log.warn("商品名称为空,跳过商品名称查询"); } // 如果都查询不到,记录警告但不阻止导入(允许后续手动关联) if (materialBaseInfoId == null) { - log.warn("未查询到物料基础信息,料号: {}, SKU码: {}, 商品名称: {},将使用null值,后续可能需要手动关联", + log.warn("未查询到物料基础信息,料号: [{}], SKU码: [{}], 商品名称: [{}],将使用null值,后续可能需要手动关联", r.getMaterialCode(), r.getSkuCode(), r.getMaterialName()); } // 使用仓库数量或入库数量(优先使用仓库数量,如果为空则使用入库数量) BigDecimal quantity = r.getWarehouseQuantity(); + log.info("数量字段检查 - 仓库数量: [{}], 入库数量: [{}]", r.getWarehouseQuantity(), r.getInboundQuantity()); if (quantity == null) { quantity = r.getInboundQuantity(); + log.info("仓库数量为空,使用入库数量: [{}]", quantity); } + // 如果数量为空,跳过该明细行,记录警告,继续处理其他行 if (quantity == null) { - throw new ServiceException("导入失败:仓库数量或入库数量不能为空(委托编号NO=" + h.getConsignmentNo() + ",物料基础信息ID=" + materialBaseInfoId + ")"); + log.warn("跳过明细行:仓库数量或入库数量不能为空 - 委托编号NO: [{}], 物料基础信息ID: [{}], 商品名称: [{}], 料号: [{}], SKU码: [{}], 仓库数量: [{}], 入库数量: [{}]", + h.getConsignmentNo(), materialBaseInfoId, r.getMaterialName(), r.getMaterialCode(), + r.getSkuCode(), r.getWarehouseQuantity(), r.getInboundQuantity()); + continue; // 跳过该明细行,继续处理下一行 } InMaterialDetailDO d = new InMaterialDetailDO(); @@ -780,12 +968,31 @@ public class StockInOrderApplicationService { d.setTotalPrice(r.getTotalPrice()); d.setCurrency(r.getCurrency()); d.setRemark(r.getDetailRemark()); + + // 记录即将保存的明细数据,用于调试 + log.info("准备保存明细数据 - 商品名称: [{}], 料号: [{}], SKU码: [{}], 规格型号: [{}], 入库数量: [{}], 数量: [{}], 单位: [{}], 总净重: [{}], 总毛重: [{}], 总体积: [{}], 总面积: [{}], 原产国: [{}], 币制: [{}], 备注: [{}]", + r.getMaterialName(), r.getMaterialCode(), r.getSkuCode(), r.getSpecificationModel(), + r.getInboundQuantity(), quantity, unit, d.getTotalNetWeight(), d.getTotalGrossWeight(), + d.getTotalVolume(), d.getTotalArea(), r.getOriginCountry(), r.getCurrency(), r.getDetailRemark()); + details.add(d); } + + // 如果该订单的所有明细行都被跳过(details为空),跳过该订单 + if (details.isEmpty()) { + log.warn("跳过入库单:委托编号NO [{}] 的所有明细行都因数据不完整被跳过,该入库单将不会被导入", h.getConsignmentNo()); + continue; // 跳过该订单,继续处理下一个订单 + } + order.setMaterialDetailList(details); orderList.add(order); } + // 如果所有订单都被跳过(orderList为空),抛出异常提示用户 + if (orderList.isEmpty()) { + throw new ServiceException("导入失败:所有入库单的明细行都因数据不完整(数量为空或物料基础信息缺失)被跳过,请检查Excel数据"); + } + return stockInOrderDomainService.batchInsert(orderList); } catch (ServiceException e) { throw e; diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInOrder/service/StockInOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInOrder/service/StockInOrderDomainService.java index 66993f687..8b1737de1 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInOrder/service/StockInOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInOrder/service/StockInOrderDomainService.java @@ -301,6 +301,15 @@ public class StockInOrderDomainService { }); stockReceiptOrderDO.setMaterialDetailList(receiptMaterialDetailDOList); stockReceiptOrderDO.setMaterialQuantity(receiptMaterialDetailDOList.size()); + // 重新计算计划数量:从物料明细中汇总quantity字段 + BigDecimal quantity = receiptMaterialDetailDOList.stream() + .map(ReceiptMaterialDetailDO::getQuantity) + .filter(Objects::nonNull) + .reduce(BigDecimal.ZERO, BigDecimal::add); + stockReceiptOrderDO.setQuantity(quantity); + } else { + // 如果没有物料明细,将数量设置为0 + stockReceiptOrderDO.setQuantity(BigDecimal.ZERO); } stockReceiptOrderDOList.add(stockReceiptOrderDO); });