Merge branch 'dev_qinhongzhanWMS' into wms_dev

This commit is contained in:
秦鸿展
2026-01-26 17:33:56 +08:00
5 changed files with 415 additions and 60 deletions
@@ -8,6 +8,7 @@ import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.enums.DictCode;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.SystemServiceFeign;
@@ -17,20 +18,20 @@ import com.mhd.system.api.domain.WarehouseFeignPO;
import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
import com.mhd.system.api.model.LoginUser;
import com.mhd.common.core.utils.poi.ExcelUtil;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBaseInfoPO;
import com.mhd.wms.domain.materialBaseInfo.repository.todo.MaterialBaseInfoDO;
import com.mhd.wms.domain.stockInOrder.repository.po.StockInOrderPO;
import com.mhd.wms.domain.stockInOrder.repository.todo.StockInOrderDO;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.stockInOrder.service.StockInOrderDomainService;
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
import com.mhd.wms.domain.materialBaseInfo.repository.todo.MaterialBaseInfoDO;
import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBaseInfoPO;
import com.mhd.wms.interfaces.dto.stockInOrder.StockInOrderImportRowDTO;
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.web.multipart.MultipartFile;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.ParseException;
@@ -260,9 +261,9 @@ public class StockInOrderApplicationService {
}
}
// 客户名称
else if (labelValue.contains("客户名称") && StringUtils.isBlank(headerInfo.getCustomerName())) {
else if (labelValue.contains("客户名称") && StringUtils.isBlank(headerInfo.getShipperName())) {
if (!value.contains("客户") && !value.equals("客户名称")) {
headerInfo.setCustomerName(value);
headerInfo.setShipperName(value);
log.info("从表头第{}行读取到客户名称: {}", rowIdx + 1, value);
}
}
@@ -318,8 +319,87 @@ public class StockInOrderApplicationService {
headerInfo.setContactPerson(value);
log.info("从表头第{}行读取到联系人: {}", rowIdx + 1, value);
} else if ((labelValue.contains("车型") || labelValue.contains("车牌")) && StringUtils.isBlank(headerInfo.getVehicleInfo())) {
headerInfo.setVehicleInfo(value);
log.info("从表头第{}行读取到车型及车牌: {}", rowIdx + 1, value);
// 过滤掉标签文本(包含冒号、常见标签关键词等)
if (StringUtils.isNotBlank(value) &&
!value.contains("") && !value.contains(":") &&
!value.contains("委托编号") && !value.contains("NO") && !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("承运方") &&
!value.contains("柜号") && !value.contains("车型") && !value.contains("车牌")) {
headerInfo.setVehicleInfo(value);
log.info("从表头第{}行读取到车型及车牌: {}", rowIdx + 1, value);
} else {
// 如果找到的值是标签,继续向后查找
boolean found = false;
boolean stopSearch = 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)) {
// 检查是否遇到下一个标签(如"委托编号NO"),如果遇到则停止搜索
if (nextValue.contains("委托编号") || (nextValue.contains("NO") && 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("监管方式") || nextValue.contains("海关是否查验货物") || nextValue.contains("报关员")) {
// 遇到下一个标签,停止搜索
stopSearch = true;
log.warn("表头第{}行,标签'{}'在第{}列,向后搜索到第{}列时遇到下一个标签'{}',停止搜索,车型及车牌字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, searchColIdx + 1, nextValue);
break;
}
// 跳过标签文本(包含冒号、常见标签关键词等)
if (!nextValue.contains("") && !nextValue.contains(":") &&
!nextValue.contains("委托编号") && !nextValue.contains("NO") && !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("承运方") &&
!nextValue.contains("柜号") && !nextValue.contains("车型") && !nextValue.contains("车牌")) {
headerInfo.setVehicleInfo(nextValue);
log.info("从表头第{}行读取到车型及车牌: {}", rowIdx + 1, nextValue);
found = true;
break;
}
}
}
}
// 如果没找到合适的值且未遇到下一个标签,尝试查找下一行的同一列
if (!found && !stopSearch) {
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("NO") && !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("承运方") &&
!nextRowValue.contains("柜号") && !nextRowValue.contains("车型") && !nextRowValue.contains("车牌")) {
headerInfo.setVehicleInfo(nextRowValue);
log.info("从表头第{}行(下一行)读取到车型及车牌: {}", rowIdx + 2, nextRowValue);
found = true;
}
}
}
}
// 如果最终都没找到实际的值,不设置字段(保持为空)
if (!found && !stopSearch) {
log.warn("表头第{}行,标签'{}'在第{}列,找到的值是标签'{}',继续向后查找未找到实际值,车型及车牌字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, value);
}
}
} else if ((labelValue.contains("承运方") || labelValue.contains("承运商")) && StringUtils.isBlank(headerInfo.getCarrier())) {
headerInfo.setCarrier(value);
log.info("从表头第{}行读取到承运方: {}", rowIdx + 1, value);
@@ -390,9 +470,15 @@ public class StockInOrderApplicationService {
!nextRowValue.contains("报关员") && !nextRowValue.contains("生产商") && !nextRowValue.contains("承运方")) {
headerInfo.setCustomsBrokerInfo(nextRowValue);
log.info("从表头第{}行(下一行)读取到报关员姓名及联系方式: {}", rowIdx + 2, nextRowValue);
found = true;
}
}
}
// 如果最终都没找到实际的值,不设置字段(保持为空)
if (!found) {
log.warn("表头第{}行,标签'{}'在第{}列,找到的值是标签'{}',继续向后查找未找到实际值,报关员姓名及联系方式字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, value);
}
}
}
} else if (labelValue.contains("送货地址") && StringUtils.isBlank(headerInfo.getDeliveryAddress())) {
@@ -405,8 +491,87 @@ public class StockInOrderApplicationService {
headerInfo.setOriginDestinationCountry(value);
log.info("从表头第{}行读取到起运/运抵国(地区): {}", rowIdx + 1, value);
} else if (labelValue.contains("柜号") && StringUtils.isBlank(headerInfo.getContainerNo())) {
headerInfo.setContainerNo(value);
log.info("从表头第{}行读取到柜号: {}", rowIdx + 1, value);
// 过滤掉标签文本(包含冒号、常见标签关键词等)
if (StringUtils.isNotBlank(value) &&
!value.contains("") && !value.contains(":") &&
!value.contains("司机签名") && !value.contains("委托编号") && !value.contains("NO") &&
!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("承运方") &&
!value.contains("车型") && !value.contains("车牌")) {
headerInfo.setContainerNo(value);
log.info("从表头第{}行读取到柜号: {}", rowIdx + 1, value);
} else {
// 如果找到的值是标签,继续向后查找
boolean found = false;
boolean stopSearch = 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)) {
// 检查是否遇到下一个标签(如"委托编号NO"、"司机签名"等),如果遇到则停止搜索
if (nextValue.contains("委托编号") || (nextValue.contains("NO") && 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("海关是否查验货物") || nextValue.contains("报关员")) {
// 遇到下一个标签,停止搜索
stopSearch = true;
log.warn("表头第{}行,标签'{}'在第{}列,向后搜索到第{}列时遇到下一个标签'{}',停止搜索,柜号字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, searchColIdx + 1, nextValue);
break;
}
// 跳过标签文本(包含冒号、常见标签关键词等)
if (!nextValue.contains("") && !nextValue.contains(":") &&
!nextValue.contains("司机签名") && !nextValue.contains("委托编号") && !nextValue.contains("NO") &&
!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("承运方") &&
!nextValue.contains("车型") && !nextValue.contains("车牌")) {
headerInfo.setContainerNo(nextValue);
log.info("从表头第{}行读取到柜号: {}", rowIdx + 1, nextValue);
found = true;
break;
}
}
}
}
// 如果没找到合适的值且未遇到下一个标签,尝试查找下一行的同一列
if (!found && !stopSearch) {
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("NO") &&
!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("承运方") &&
!nextRowValue.contains("车型") && !nextRowValue.contains("车牌")) {
headerInfo.setContainerNo(nextRowValue);
log.info("从表头第{}行(下一行)读取到柜号: {}", rowIdx + 2, nextRowValue);
found = true;
}
}
}
}
// 如果最终都没找到实际的值,不设置字段(保持为空)
if (!found && !stopSearch) {
log.warn("表头第{}行,标签'{}'在第{}列,找到的值是标签'{}',继续向后查找未找到实际值,柜号字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, value);
}
}
} else if (labelValue.contains("运输方式") && StringUtils.isBlank(headerInfo.getTransportMethod())) {
headerInfo.setTransportMethod(value);
log.info("从表头第{}行读取到运输方式: {}", rowIdx + 1, value);
@@ -414,12 +579,99 @@ public class StockInOrderApplicationService {
headerInfo.setSupervisionMethod(value);
log.info("从表头第{}行读取到监管方式: {}", rowIdx + 1, value);
} else if (labelValue.contains("海关是否查验货物")) {
if (value.contains("") || value.equals("1")) {
headerInfo.setCustomsInspection(1);
} else if (value.contains("") || value.equals("0")) {
headerInfo.setCustomsInspection(0);
// 过滤掉标签文本(包含冒号、常见标签关键词等)
if (StringUtils.isNotBlank(value) &&
!value.contains("") && !value.contains(":") &&
!value.contains("进出境关别") && !value.contains("委托编号") && !value.contains("NO") &&
!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("车型") && !value.contains("车牌") && !value.contains("柜号")) {
if (value.contains("") || value.equals("1")) {
headerInfo.setCustomsInspection(1);
} else if (value.contains("") || value.equals("0")) {
headerInfo.setCustomsInspection(0);
}
log.info("从表头第{}行读取到海关是否查验货物: {}", rowIdx + 1, value);
} else {
// 如果找到的值是标签,继续向后查找
boolean found = false;
boolean stopSearch = 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)) {
// 检查是否遇到下一个标签(如"委托编号NO"、"进出境关别"等),如果遇到则停止搜索
if (nextValue.contains("委托编号") || (nextValue.contains("NO") && 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("监管方式") || nextValue.contains("报关员")) {
// 遇到下一个标签,停止搜索
stopSearch = true;
log.warn("表头第{}行,标签'{}'在第{}列,向后搜索到第{}列时遇到下一个标签'{}',停止搜索,海关是否查验货物字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, searchColIdx + 1, nextValue);
break;
}
// 跳过标签文本(包含冒号、常见标签关键词等)
if (!nextValue.contains("") && !nextValue.contains(":") &&
!nextValue.contains("进出境关别") && !nextValue.contains("委托编号") && !nextValue.contains("NO") &&
!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("车型") && !nextValue.contains("车牌") && !nextValue.contains("柜号")) {
if (nextValue.contains("") || nextValue.equals("1")) {
headerInfo.setCustomsInspection(1);
} else if (nextValue.contains("") || nextValue.equals("0")) {
headerInfo.setCustomsInspection(0);
}
log.info("从表头第{}行读取到海关是否查验货物: {}", rowIdx + 1, nextValue);
found = true;
break;
}
}
}
}
// 如果没找到合适的值且未遇到下一个标签,尝试查找下一行的同一列
if (!found && !stopSearch) {
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("NO") &&
!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("车型") && !nextRowValue.contains("车牌") && !nextRowValue.contains("柜号")) {
if (nextRowValue.contains("") || nextRowValue.equals("1")) {
headerInfo.setCustomsInspection(1);
} else if (nextRowValue.contains("") || nextRowValue.equals("0")) {
headerInfo.setCustomsInspection(0);
}
log.info("从表头第{}行(下一行)读取到海关是否查验货物: {}", rowIdx + 2, nextRowValue);
found = true;
}
}
}
}
// 如果最终都没找到实际的值,不设置字段(保持为空)
if (!found && !stopSearch) {
log.warn("表头第{}行,标签'{}'在第{}列,找到的值是标签'{}',继续向后查找未找到实际值,海关是否查验货物字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, value);
}
}
log.info("从表头第{}行读取到海关是否查验货物: {}", rowIdx + 1, value);
} else if (labelValue.contains("是否需要报关")) {
if (value.contains("") || value.equals("1")) {
headerInfo.setNeedCustomsDeclaration(1);
@@ -449,28 +701,44 @@ public class StockInOrderApplicationService {
} else {
// 如果找到的值是标签,继续向后查找
boolean found = false;
boolean stopSearch = 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 (StringUtils.isNotBlank(nextValue)) {
// 检查是否遇到下一个标签(如"委托编号NO"、"下单日期"等),如果遇到则停止搜索
if (nextValue.contains("委托编号") || (nextValue.contains("NO") && 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("监管方式") || nextValue.contains("海关是否查验货物") || nextValue.contains("报关员")) {
// 遇到下一个标签,停止搜索
stopSearch = true;
log.warn("表头第{}行,标签'{}'在第{}列,向后搜索到第{}列时遇到下一个标签'{}',停止搜索,完成时间字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, searchColIdx + 1, nextValue);
break;
}
// 跳过标签文本(包含冒号、常见标签关键词等)
if (!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) {
// 如果没找到合适的值且未遇到下一个标签,尝试查找下一行的同一列
if (!found && !stopSearch) {
Row nextRow = sheet.getRow(rowIdx + 1);
if (nextRow != null) {
Cell nextRowCell = nextRow.getCell(colIdx);
@@ -486,10 +754,16 @@ public class StockInOrderApplicationService {
!nextRowValue.contains("报关员") && !nextRowValue.contains("生产商") && !nextRowValue.contains("承运方")) {
headerInfo.setCompletionTime(nextRowValue);
log.info("从表头第{}行(下一行)读取到完成时间: {}", rowIdx + 2, nextRowValue);
found = true;
}
}
}
}
// 如果最终都没找到实际的值,不设置字段(保持为空)
if (!found && !stopSearch) {
log.warn("表头第{}行,标签'{}'在第{}列,找到的值是标签'{}',继续向后查找未找到实际值,完成时间字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, value);
}
}
} else if (labelValue.contains("下单日期") && StringUtils.isBlank(headerInfo.getOrderDate())) {
// 过滤掉标签文本(包含冒号、常见标签关键词等)
@@ -506,28 +780,44 @@ public class StockInOrderApplicationService {
} else {
// 如果找到的值是标签,继续向后查找
boolean found = false;
boolean stopSearch = 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 (StringUtils.isNotBlank(nextValue)) {
// 检查是否遇到下一个标签(如"委托编号NO"、"起运/运抵国"等),如果遇到则停止搜索
if (nextValue.contains("委托编号") || (nextValue.contains("NO") && 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("监管方式") || nextValue.contains("海关是否查验货物") || nextValue.contains("报关员")) {
// 遇到下一个标签,停止搜索
stopSearch = true;
log.warn("表头第{}行,标签'{}'在第{}列,向后搜索到第{}列时遇到下一个标签'{}',停止搜索,下单日期字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, searchColIdx + 1, nextValue);
break;
}
// 跳过标签文本(包含冒号、常见标签关键词等)
if (!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) {
// 如果没找到合适的值且未遇到下一个标签,尝试查找下一行的同一列
if (!found && !stopSearch) {
Row nextRow = sheet.getRow(rowIdx + 1);
if (nextRow != null) {
Cell nextRowCell = nextRow.getCell(colIdx);
@@ -543,10 +833,16 @@ public class StockInOrderApplicationService {
!nextRowValue.contains("报关员") && !nextRowValue.contains("生产商") && !nextRowValue.contains("承运方")) {
headerInfo.setOrderDate(nextRowValue);
log.info("从表头第{}行(下一行)读取到下单日期: {}", rowIdx + 2, nextRowValue);
found = true;
}
}
}
}
// 如果最终都没找到实际的值,不设置字段(保持为空)
if (!found && !stopSearch) {
log.warn("表头第{}行,标签'{}'在第{}列,找到的值是标签'{}',继续向后查找未找到实际值,下单日期字段将保持为空",
rowIdx + 1, labelValue, colIdx + 1, value);
}
}
} else if (labelValue.contains("备注") && StringUtils.isBlank(headerInfo.getRemark())) {
headerInfo.setRemark(value);
@@ -559,7 +855,7 @@ public class StockInOrderApplicationService {
}
}
log.info("表头信息读取完成 - 委托编号NO: {}, 客户名称: {}, To: {}, 联系人: {}, Tel: {}, Fax: {}, 送货地址: {}, 起运/运抵国: {}, 车型及车牌: {}, 承运方: {}, 司机签名: {}, 入仓日期: {}, 申报地关区: {}, 生产商: {}, 报关员: {}, 完成时间: {}, 进出境关别: {}, 下单日期: {}, 备注: {}",
headerInfo.getConsignmentNo(), headerInfo.getCustomerName(), headerInfo.getTo(),
headerInfo.getConsignmentNo(), headerInfo.getShipperName(), headerInfo.getTo(),
headerInfo.getContactPerson(), headerInfo.getTel(), headerInfo.getFax(),
headerInfo.getDeliveryAddress(), headerInfo.getOriginDestinationCountry(),
headerInfo.getVehicleInfo(), headerInfo.getCarrier(), headerInfo.getDriverSignature(),
@@ -573,7 +869,7 @@ public class StockInOrderApplicationService {
// 为了兼容旧代码,保留这两个变量
String headerConsignmentNo = headerInfo.getConsignmentNo();
String headerCustomerName = headerInfo.getCustomerName();
String headerCustomerName = headerInfo.getShipperName();
// 先读取Excel第13行的列名,用于调试
try (InputStream isForDebug = file.getInputStream()) {
@@ -635,8 +931,8 @@ public class StockInOrderApplicationService {
row.setConsignmentNo(headerInfo.getConsignmentNo());
}
// 应用表头中的客户名称(表头有客户名称时,强制应用到所有明细行)
if (StringUtils.isNotBlank(headerInfo.getCustomerName())) {
row.setCustomerName(headerInfo.getCustomerName());
if (StringUtils.isNotBlank(headerInfo.getShipperName())) {
row.setShipperName(headerInfo.getShipperName());
}
// 应用其他表头字段(如果明细行为空,则使用表头值)
if (StringUtils.isBlank(row.getTo()) && StringUtils.isNotBlank(headerInfo.getTo())) {
@@ -739,13 +1035,13 @@ public class StockInOrderApplicationService {
warehouseId = associationWarehouseCacheDO.getWarehouseId();
// 客户名称应该从表头获取(优先使用表头,如果表头为空则使用明细行)
String customerName = StringUtils.isNotBlank(headerInfo.getCustomerName()) ? headerInfo.getCustomerName() : h.getCustomerName();
String customerName = StringUtils.isNotBlank(headerInfo.getShipperName()) ? headerInfo.getShipperName() : h.getShipperName();
if (StringUtils.isBlank(customerName)) {
throw new ServiceException("导入失败:客户名称不能为空(委托编号NO=" + h.getConsignmentNo() + ")。请确保Excel表头(第1-12行)中包含'客户名称'字段");
}
// 如果明细行的客户名称为空,使用表头的客户名称
if (StringUtils.isBlank(h.getCustomerName()) && StringUtils.isNotBlank(headerInfo.getCustomerName())) {
h.setCustomerName(headerInfo.getCustomerName());
if (StringUtils.isBlank(h.getShipperName()) && StringUtils.isNotBlank(headerInfo.getShipperName())) {
h.setShipperName(headerInfo.getShipperName());
}
StockInOrderDO order = new StockInOrderDO();
@@ -764,8 +1060,8 @@ public class StockInOrderApplicationService {
setWarehouseInfo(order);
// 货主ID不需要,直接设置为null,使用客户名称作为货主名称
order.setShipperId(null);
if (StringUtils.isNotBlank(h.getCustomerName())) {
order.setShipperName(h.getCustomerName());
if (StringUtils.isNotBlank(h.getShipperName())) {
order.setShipperName(h.getShipperName());
}
// order.setSupplierId(h.getSupplierId());
// order.setOrderTypeCode(h.getOrderTypeCode());
@@ -935,6 +1231,9 @@ public class StockInOrderApplicationService {
InMaterialDetailDO d = new InMaterialDetailDO();
d.setMaterialBaseInfoId(materialBaseInfoId);
// 设置商品名称和料号(从Excel读取)
d.setMaterialName(r.getMaterialName());
d.setMaterialCode(r.getMaterialCode());
d.setQuantity(quantity);
d.setSpecificationModel(r.getSpecificationModel());
d.setSkuCode(r.getSkuCode());
@@ -945,7 +1244,15 @@ public class StockInOrderApplicationService {
d.setBoxCount(r.getBoxCount());
d.setPieceCount(r.getPieceCount());
d.setDimensions(r.getDimensions());
d.setInboundQuantity(r.getInboundQuantity());
// 入库数量:优先使用入库数量,如果为空则使用仓库数量
BigDecimal inboundQuantity = r.getInboundQuantity();
if (inboundQuantity == null) {
inboundQuantity = r.getWarehouseQuantity();
if (inboundQuantity != null) {
log.info("入库数量为空,使用仓库数量作为入库数量: [{}]", inboundQuantity);
}
}
d.setInboundQuantity(inboundQuantity);
// 单位:优先使用"单位"字段,如果为空则使用"申报单位"
String unit = StringUtils.isNotBlank(r.getUnit()) ? r.getUnit() : null;
if (StringUtils.isBlank(unit) && StringUtils.isNotBlank(r.getDeclarationUnit())) {
@@ -216,6 +216,22 @@ public class ReceiptMaterialDetailPO extends BaseVOEntity {
@Excel(name = "是否生成上架单: 1-是 2-否")
private Integer genStockShelf;
@ApiModelProperty("总净重(KG)")
@Excel(name = "总净重(KG)")
private BigDecimal totalNetWeight;
@ApiModelProperty("总毛重(KG)")
@Excel(name = "总毛重(KG)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("总体积(CBM)")
@Excel(name = "总体积(CBM)")
private BigDecimal totalVolume;
@ApiModelProperty("总面积(SQM)")
@Excel(name = "总面积(SQM)")
private BigDecimal totalArea;
@ApiModelProperty("物料明细子集")
private List<ReceiptMaterialDetailPO> children;
@@ -24,6 +24,7 @@ import com.mhd.wms.domain.containerUsageRecord.repository.todo.ContainerUsageRec
import com.mhd.wms.domain.deliveTask.repository.facade.IDeliveTaskService;
import com.mhd.wms.domain.deliveTask.repository.todo.DeliveTaskDO;
import com.mhd.wms.domain.inMaterialDetail.repository.facade.IInMaterialDetailService;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetailSerialNumber.repository.facade.IInMaterialDetailSerialNumberService;
import com.mhd.wms.domain.inMaterialDetailSerialNumber.repository.po.InMaterialDetailSerialNumberPO;
import com.mhd.wms.domain.inMaterialDetailSerialNumber.repository.todo.InMaterialDetailSerialNumberDO;
@@ -703,6 +704,26 @@ public class StockReceiptOrderDomainService {
List<ReceiptMaterialDetailPO> receiptMaterialDetailPOS = receiptMaterialDetailService.queryList(receiptMaterialDetailDO);
//上架单明细集合
List<ShelfMaterialDetailDO> shelfMaterialDetailDOList = new ArrayList<>();
// 批量查询入库单明细,用于获取净重、毛重、体积、面积等字段
List<Long> inUniqueIds = receiptMaterialDetailPOS.stream()
.filter(r -> 2 == r.getGenStockShelf() && r.getInUniqueId() != null)
.map(ReceiptMaterialDetailPO::getInUniqueId)
.distinct()
.collect(Collectors.toList());
Map<Long, InMaterialDetailPO> inMaterialDetailMap = new HashMap<>();
if (!CollectionUtils.isEmpty(inUniqueIds)) {
// 使用 MyBatis-Plus 的 QueryWrapper 批量查询入库单明细
QueryWrapper<com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail> queryWrapper = new QueryWrapper<>();
queryWrapper.in("unique_id", inUniqueIds);
queryWrapper.eq("del_flag", 1);
List<com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail> inMaterialDetailList = iInMaterialDetailService.list(queryWrapper);
// 转换为 PO 对象
for (com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail inMaterialDetail : inMaterialDetailList) {
InMaterialDetailPO inMaterialDetailPO = new InMaterialDetailPO();
BeanUtils.copyProperties(inMaterialDetail, inMaterialDetailPO);
inMaterialDetailMap.put(inMaterialDetail.getUniqueId(), inMaterialDetailPO);
}
}
for (ReceiptMaterialDetailPO receiptMaterialDetailPO : receiptMaterialDetailPOS) {
if (2 == receiptMaterialDetailPO.getGenStockShelf()) {
ShelfMaterialDetailDO shelfMaterialDetailDO = new ShelfMaterialDetailDO();
@@ -710,6 +731,9 @@ public class StockReceiptOrderDomainService {
shelfMaterialDetailDO.setQuantity(receiptMaterialDetailPO.getReceiptQuantity());
shelfMaterialDetailDO.setInUniqueId(receiptMaterialDetailPO.getInUniqueId());
shelfMaterialDetailDO.setReceiptUniqueId(receiptMaterialDetailPO.getUniqueId());
// 从入库单明细中获取净重、毛重、体积、面积等字段
// 注意:由于 ShelfMaterialDetailDO 中没有这些字段,这些字段需要在查询时通过关联查询获取
// 或者需要先在上架单明细实体类中添加这些字段
shelfMaterialDetailDOList.add(shelfMaterialDetailDO);
receiptQuantity = receiptQuantity.add(receiptMaterialDetailPO.getReceiptQuantity());
}
@@ -68,7 +68,7 @@ public class StockInOrderImportRowDTO {
// 客户名称只在表头中明细行不需要此字段代码会从表头读取并应用到此字段
@Excel(name = "客户名称")
private String customerName;
private String shipperName;
@Excel(name = "承运商")
private String carrier;
@@ -56,11 +56,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateByName" column="update_by_name" />
<result property="delFlag" column="del_flag" />
<result property="genStockShelf" column="gen_stock_shelf" />
<result property="inUniqueId" column="in_unique_id" />
<result property="totalNetWeight" column="total_net_weight" />
<result property="totalGrossWeight" column="total_gross_weight" />
<result property="totalVolume" column="total_volume" />
<result property="totalArea" column="total_area" />
</resultMap>
<sql id="selectReceiptMaterialDetailPo">
select MATERIAL_DETAIL_ID, ORGANIZATION_ID, ORGANIZATION_NAME, TOP_ORGANIZATION_ID, UNIQUE_ID, RECEIPT_ORDER_NUMBER, MATERIAL_BASE_INFO_ID, MATERIAL_CODE, MATERIAL_NAME, BAR_CODE, QUANTITY, ALREADY_RECEIPT_QUANTITY, RECEIPT_QUANTITY, RECEIPT_STATUS, PACK_ID, PACK_CODE, PACK_NAME, PACK_DETAIL_ID, UNIT_CODE, UNIT_NAME, UNIT_NUMBER, MATERIAL_WAREHOUSE_CONTROL_ID, SERIAL_NUMBER_MANAGE, QUALITY_INSPECTION_MANAGE, QUALITY_INSPECTION_STAGE, QUALITY_INSPECTION_RULE, QUALITY_INSPECTION_RATIO, QUALITY_INSPECTION_TERM, QUALITY_INSPECTION_RESULTS, ALLOW_OVERCHARGE, OVERCHARGE_RATIO, BATCH_NUMBER, MATERIAL_STATUS_CODE, MATERIAL_STATUS_NAME, DISTRIBUTE_RULE_ID, DISTRIBUTE_RULE_CODE, DISTRIBUTE_RULE_NAME, CONTAINER_ID, CONTAINER_CODE, CONTAINER_TYPE, CONTAINER_TYPE_NAME, LEVEL, PARENT_UNIQUE_ID, IN_UNIQUE_ID, ALLOW_MODIFY, REMARK, CREATE_TIME, CREATE_BY, CREATE_BY_NAME, UPDATE_TIME, UPDATE_BY, UPDATE_BY_NAME, GEN_STOCK_SHELF, DEL_FLAG from RECEIPT_MATERIAL_DETAIL
select a.MATERIAL_DETAIL_ID, a.ORGANIZATION_ID, a.ORGANIZATION_NAME, a.TOP_ORGANIZATION_ID, a.UNIQUE_ID, a.RECEIPT_ORDER_NUMBER, a.MATERIAL_BASE_INFO_ID, a.MATERIAL_CODE, a.MATERIAL_NAME, a.BAR_CODE, a.QUANTITY, a.ALREADY_RECEIPT_QUANTITY, a.RECEIPT_QUANTITY, a.RECEIPT_STATUS, a.PACK_ID, a.PACK_CODE, a.PACK_NAME, a.PACK_DETAIL_ID, a.UNIT_CODE, a.UNIT_NAME, a.UNIT_NUMBER, a.MATERIAL_WAREHOUSE_CONTROL_ID, a.SERIAL_NUMBER_MANAGE, a.QUALITY_INSPECTION_MANAGE, a.QUALITY_INSPECTION_STAGE, a.QUALITY_INSPECTION_RULE, a.QUALITY_INSPECTION_RATIO, a.QUALITY_INSPECTION_TERM, a.QUALITY_INSPECTION_RESULTS, a.ALLOW_OVERCHARGE, a.OVERCHARGE_RATIO, a.BATCH_NUMBER, a.MATERIAL_STATUS_CODE, a.MATERIAL_STATUS_NAME, a.DISTRIBUTE_RULE_ID, a.DISTRIBUTE_RULE_CODE, a.DISTRIBUTE_RULE_NAME, a.CONTAINER_ID, a.CONTAINER_CODE, a.CONTAINER_TYPE, a.CONTAINER_TYPE_NAME, a.LEVEL, a.PARENT_UNIQUE_ID, a.IN_UNIQUE_ID, a.ALLOW_MODIFY, a.REMARK, a.CREATE_TIME, a.CREATE_BY, a.CREATE_BY_NAME, a.UPDATE_TIME, a.UPDATE_BY, a.UPDATE_BY_NAME, a.GEN_STOCK_SHELF, a.DEL_FLAG,
b.TOTAL_NET_WEIGHT, b.TOTAL_GROSS_WEIGHT, b.TOTAL_VOLUME, b.TOTAL_AREA
from RECEIPT_MATERIAL_DETAIL a
LEFT JOIN IN_MATERIAL_DETAIL b ON a.IN_UNIQUE_ID = b.UNIQUE_ID AND b.DEL_FLAG = 1
</sql>
<sql id="selectReceiptMaterialDetailPo1">
@@ -212,8 +220,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</if>
<choose>
<when test="delFlag != null"> and del_flag = #{delFlag} </when>
<otherwise> and del_flag = 1 </otherwise>
<when test="delFlag != null"> and a.del_flag = #{delFlag} </when>
<otherwise> and a.del_flag = 1 </otherwise>
</choose>
</where>
</sql>