Merge branch 'dev_qinhongzhanWMS' into wms_dev
This commit is contained in:
+280
-29
@@ -33,7 +33,10 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -203,43 +206,121 @@ public class StockInOrderApplicationService {
|
||||
if (labelCell != null) {
|
||||
String labelValue = getCellValueAsString(labelCell);
|
||||
if (StringUtils.isNotBlank(labelValue)) {
|
||||
// 尝试下一个单元格作为值
|
||||
Cell valueCell = row.getCell(colIdx + 1);
|
||||
// 调试日志:打印所有非空单元格内容
|
||||
log.info("表头第{}行第{}列: {}", rowIdx + 1, colIdx + 1, labelValue);
|
||||
String value = null;
|
||||
if (valueCell != null) {
|
||||
value = getCellValueAsString(valueCell);
|
||||
}
|
||||
|
||||
// 如果当前单元格包含冒号,尝试从同一单元格提取值
|
||||
if (StringUtils.isBlank(value) && labelValue.contains(":")) {
|
||||
// 先尝试从同一单元格提取值(如果包含冒号)
|
||||
String extractedFromSameCell = null;
|
||||
if (labelValue.contains(":")) {
|
||||
String[] parts = labelValue.split(":", 2);
|
||||
if (parts.length > 1) {
|
||||
value = parts[1].trim();
|
||||
extractedFromSameCell = parts[1].trim();
|
||||
}
|
||||
}
|
||||
|
||||
// 跳过空单元格,查找下一个非空单元格作为值(最多向后查找10列)
|
||||
String nextCellValue = null;
|
||||
for (int searchColIdx = colIdx + 1; searchColIdx < colIdx + 10 && searchColIdx < row.getPhysicalNumberOfCells(); searchColIdx++) {
|
||||
Cell valueCell = row.getCell(searchColIdx);
|
||||
if (valueCell != null) {
|
||||
String cellValue = getCellValueAsString(valueCell);
|
||||
if (StringUtils.isNotBlank(cellValue)) {
|
||||
nextCellValue = cellValue;
|
||||
log.info("表头第{}行,标签'{}'在第{}列,找到值'{}'在第{}列", rowIdx + 1, labelValue, colIdx + 1, nextCellValue, searchColIdx + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 优先使用下一个非空单元格的值(如果存在且不为空)
|
||||
// 如果下一个单元格为空,且同一单元格有冒号后的值,则使用冒号后的值
|
||||
// 但如果冒号后的值是选项列表(如"3T、5T、8T、10T"),则应该使用下一个单元格的值
|
||||
if (StringUtils.isNotBlank(nextCellValue)) {
|
||||
// 如果冒号后的值是选项列表(包含顿号、逗号等),优先使用下一个单元格的值
|
||||
if (extractedFromSameCell != null && (extractedFromSameCell.contains("、") || extractedFromSameCell.contains(","))) {
|
||||
value = nextCellValue;
|
||||
} else {
|
||||
// 否则优先使用下一个单元格的值
|
||||
value = nextCellValue;
|
||||
}
|
||||
} else if (StringUtils.isNotBlank(extractedFromSameCell)) {
|
||||
// 如果下一个单元格为空,使用同一单元格冒号后的值
|
||||
value = extractedFromSameCell;
|
||||
}
|
||||
|
||||
// 根据标签匹配字段
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
// 委托编号NO(支持"委托编号NO"、"委托编号"等格式)
|
||||
if (labelValue.contains("委托编号") && StringUtils.isBlank(headerInfo.getConsignmentNo())) {
|
||||
if (!value.contains("委托编号") && !value.contains("NO")) {
|
||||
// 排除标签本身和包含"NO"的标签文本
|
||||
if (!value.contains("委托编号") && !value.contains("NO") && !value.equals("委托编号NO") && !value.equals("委托编号")) {
|
||||
headerInfo.setConsignmentNo(value);
|
||||
log.info("从表头第{}行读取到委托编号NO: {}", rowIdx + 1, value);
|
||||
}
|
||||
} else if (labelValue.contains("客户名称") && StringUtils.isBlank(headerInfo.getCustomerName())) {
|
||||
if (!value.contains("客户")) {
|
||||
}
|
||||
// 客户名称
|
||||
else if (labelValue.contains("客户名称") && StringUtils.isBlank(headerInfo.getCustomerName())) {
|
||||
if (!value.contains("客户") && !value.equals("客户名称")) {
|
||||
headerInfo.setCustomerName(value);
|
||||
log.info("从表头第{}行读取到客户名称: {}", rowIdx + 1, value);
|
||||
}
|
||||
} else if (labelValue.contains("To") && StringUtils.isBlank(headerInfo.getTo())) {
|
||||
headerInfo.setTo(value);
|
||||
log.info("从表头第{}行读取到To: {}", rowIdx + 1, value);
|
||||
}
|
||||
// To(需要精确匹配,避免误匹配)
|
||||
else if ((labelValue.equals("To") || labelValue.equals("To:") || labelValue.equals("To:") || labelValue.startsWith("To:") || labelValue.startsWith("To:")) && StringUtils.isBlank(headerInfo.getTo())) {
|
||||
// 如果值是"To"或"To:",说明可能是标签本身,继续查找下一个值
|
||||
if (value.equals("To") || value.equals("To:") || value.equals("To:")) {
|
||||
// 继续向后查找,跳过标签(包含冒号的文本)
|
||||
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);
|
||||
// 跳过标签文本(包含冒号、等于"To"等,以及常见的标签关键词)
|
||||
if (StringUtils.isNotBlank(nextValue) &&
|
||||
!nextValue.equals("To") && !nextValue.equals("To:") && !nextValue.equals("To:") &&
|
||||
!nextValue.contains(":") && !nextValue.contains(":") &&
|
||||
!nextValue.contains("联系人") && !nextValue.contains("Tel") && !nextValue.contains("Fax") &&
|
||||
!nextValue.contains("客户") && !nextValue.contains("地址") && !nextValue.contains("日期") &&
|
||||
!nextValue.contains("方式") && !nextValue.contains("关区") && !nextValue.contains("关别")) {
|
||||
headerInfo.setTo(nextValue);
|
||||
log.info("从表头第{}行读取到To: {}", 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.equals("To") && !nextRowValue.equals("To:") && !nextRowValue.equals("To:")) {
|
||||
headerInfo.setTo(nextRowValue);
|
||||
log.info("从表头第{}行(下一行)读取到To: {}", rowIdx + 2, nextRowValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!value.contains(":") && !value.contains(":") &&
|
||||
!value.contains("联系人") && !value.contains("Tel") && !value.contains("Fax") &&
|
||||
!value.contains("客户") && !value.contains("地址") && !value.contains("日期") &&
|
||||
!value.contains("方式") && !value.contains("关区") && !value.contains("关别")) {
|
||||
// 值不是标签(不包含冒号和常见标签关键词),可以使用
|
||||
headerInfo.setTo(value);
|
||||
log.info("从表头第{}行读取到To: {}", rowIdx + 1, value);
|
||||
}
|
||||
} else if (labelValue.contains("联系人") && StringUtils.isBlank(headerInfo.getContactPerson())) {
|
||||
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);
|
||||
} else if (labelValue.contains("承运方") || labelValue.contains("承运商") && StringUtils.isBlank(headerInfo.getCarrier())) {
|
||||
} else if ((labelValue.contains("承运方") || labelValue.contains("承运商")) && StringUtils.isBlank(headerInfo.getCarrier())) {
|
||||
headerInfo.setCarrier(value);
|
||||
log.info("从表头第{}行读取到承运方: {}", rowIdx + 1, value);
|
||||
} else if (labelValue.contains("Tel") && StringUtils.isBlank(headerInfo.getTel())) {
|
||||
@@ -269,7 +350,7 @@ public class StockInOrderApplicationService {
|
||||
} else if (labelValue.contains("进出境关别") && StringUtils.isBlank(headerInfo.getEntryExitCustoms())) {
|
||||
headerInfo.setEntryExitCustoms(value);
|
||||
log.info("从表头第{}行读取到进出境关别: {}", rowIdx + 1, value);
|
||||
} else if (labelValue.contains("起运") || labelValue.contains("运抵国") && StringUtils.isBlank(headerInfo.getOriginDestinationCountry())) {
|
||||
} else if ((labelValue.contains("起运") || labelValue.contains("运抵国")) && StringUtils.isBlank(headerInfo.getOriginDestinationCountry())) {
|
||||
headerInfo.setOriginDestinationCountry(value);
|
||||
log.info("从表头第{}行读取到起运/运抵国(地区): {}", rowIdx + 1, value);
|
||||
} else if (labelValue.contains("柜号") && StringUtils.isBlank(headerInfo.getContainerNo())) {
|
||||
@@ -318,7 +399,14 @@ public class StockInOrderApplicationService {
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("表头信息读取完成 - 委托编号NO: {}, 客户名称: {}", headerInfo.getConsignmentNo(), headerInfo.getCustomerName());
|
||||
log.info("表头信息读取完成 - 委托编号NO: {}, 客户名称: {}, To: {}, 联系人: {}, Tel: {}, Fax: {}, 送货地址: {}, 起运/运抵国: {}, 车型及车牌: {}, 承运方: {}, 司机签名: {}, 入仓日期: {}, 申报地关区: {}, 生产商: {}, 报关员: {}, 完成时间: {}, 进出境关别: {}, 下单日期: {}, 备注: {}",
|
||||
headerInfo.getConsignmentNo(), headerInfo.getCustomerName(), headerInfo.getTo(),
|
||||
headerInfo.getContactPerson(), headerInfo.getTel(), headerInfo.getFax(),
|
||||
headerInfo.getDeliveryAddress(), headerInfo.getOriginDestinationCountry(),
|
||||
headerInfo.getVehicleInfo(), headerInfo.getCarrier(), headerInfo.getDriverSignature(),
|
||||
headerInfo.getWarehouseDate(), headerInfo.getDeclarationArea(), headerInfo.getManufacturer(),
|
||||
headerInfo.getCustomsBrokerInfo(), headerInfo.getCompletionTime(), headerInfo.getEntryExitCustoms(),
|
||||
headerInfo.getOrderDate(), headerInfo.getRemark());
|
||||
} catch (Exception e) {
|
||||
log.error("读取Excel表头信息失败", e);
|
||||
// 不抛出异常,继续尝试从明细行读取
|
||||
@@ -328,11 +416,49 @@ public class StockInOrderApplicationService {
|
||||
String headerConsignmentNo = headerInfo.getConsignmentNo();
|
||||
String headerCustomerName = headerInfo.getCustomerName();
|
||||
|
||||
// 先读取Excel第13行的列名,用于调试
|
||||
try (InputStream isForDebug = file.getInputStream()) {
|
||||
Workbook wbDebug = WorkbookFactory.create(isForDebug);
|
||||
Sheet sheetDebug = wbDebug.getSheetAt(0);
|
||||
Row headerRow = sheetDebug.getRow(detailTitleRowIndex);
|
||||
if (headerRow != null) {
|
||||
log.info("Excel第{}行(明细表列名行)的列名:", detailTitleRowIndex + 1);
|
||||
for (int colIdx = 0; colIdx < headerRow.getPhysicalNumberOfCells(); colIdx++) {
|
||||
Cell cell = headerRow.getCell(colIdx);
|
||||
if (cell != null) {
|
||||
String colName = getCellValueAsString(cell);
|
||||
if (StringUtils.isNotBlank(colName)) {
|
||||
// 打印列名及其长度、字符编码等信息,便于排查
|
||||
log.info(" 第{}列: [{}] (长度: {}, 包含换行: {}, 包含空格: {})",
|
||||
colIdx + 1, colName, colName.length(),
|
||||
colName.contains("\n"), colName.contains(" "));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("读取Excel列名失败,继续导入", e);
|
||||
}
|
||||
|
||||
ExcelUtil<StockInOrderImportRowDTO> util = new ExcelUtil<>(StockInOrderImportRowDTO.class);
|
||||
// 从第13行(索引12)读取明细数据
|
||||
List<StockInOrderImportRowDTO> rows = null;
|
||||
try {
|
||||
rows = util.importExcel(is, detailTitleRowIndex);
|
||||
log.info("成功读取 {} 行明细数据", rows != null ? rows.size() : 0);
|
||||
// 调试:打印第一行数据的关键字段
|
||||
if (rows != null && !rows.isEmpty()) {
|
||||
StockInOrderImportRowDTO firstRow = rows.get(0);
|
||||
log.info("第一行明细数据 - 规格型号: [{}], SKU码: [{}], 升: [{}], 箱数: [{}], 尺寸: [{}], 仓库数量: [{}], 入库数量: [{}], 单位: [{}], 总净重: [{}], 总净重2: [{}], 总毛重: [{}], 总毛重2: [{}], 总体积: [{}], 总体积2: [{}], 总面积: [{}], 总面积2: [{}], 原产国: [{}], 币制: [{}]",
|
||||
firstRow.getSpecificationModel(), firstRow.getSkuCode(), firstRow.getLiter(),
|
||||
firstRow.getBoxCount(), firstRow.getDimensions(), firstRow.getWarehouseQuantity(),
|
||||
firstRow.getInboundQuantity(), firstRow.getUnit(),
|
||||
firstRow.getTotalNetWeight(), firstRow.getTotalNetWeight2(),
|
||||
firstRow.getTotalGrossWeight(), firstRow.getTotalGrossWeight2(),
|
||||
firstRow.getTotalVolume(), firstRow.getTotalVolume2(),
|
||||
firstRow.getTotalArea(), firstRow.getTotalArea2(),
|
||||
firstRow.getOriginCountry(), firstRow.getCurrency());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("读取Excel明细数据失败", e);
|
||||
throw new ServiceException("读取Excel明细数据失败:" + e.getMessage() + "。请检查Excel第13行是否为明细表列名,第14行开始是否为数据行");
|
||||
@@ -411,6 +537,9 @@ public class StockInOrderApplicationService {
|
||||
if (row.getNeedTransport() == null && headerInfo.getNeedTransport() != null) {
|
||||
row.setNeedTransport(headerInfo.getNeedTransport());
|
||||
}
|
||||
if (StringUtils.isBlank(row.getWarehouseDate()) && StringUtils.isNotBlank(headerInfo.getWarehouseDate())) {
|
||||
row.setWarehouseDate(headerInfo.getWarehouseDate());
|
||||
}
|
||||
if (StringUtils.isBlank(row.getCompletionTime()) && StringUtils.isNotBlank(headerInfo.getCompletionTime())) {
|
||||
row.setCompletionTime(headerInfo.getCompletionTime());
|
||||
}
|
||||
@@ -467,9 +596,13 @@ public class StockInOrderApplicationService {
|
||||
order.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||
order.setCreateBy(loginUser.getUserid());
|
||||
order.setCreateByName(loginUser.getUsername());
|
||||
// 设置创建时间为当前时间
|
||||
order.setCreateTime(new Date());
|
||||
|
||||
// 必填/基础字段
|
||||
order.setWarehouseId(warehouseId);
|
||||
// 设置仓库完整信息(warehouseCode 和 warehouseName)
|
||||
setWarehouseInfo(order);
|
||||
// 货主ID不需要,直接设置为null,使用客户名称作为货主名称
|
||||
order.setShipperId(null);
|
||||
if (StringUtils.isNotBlank(h.getCustomerName())) {
|
||||
@@ -517,6 +650,34 @@ public class StockInOrderApplicationService {
|
||||
} else {
|
||||
order.setNeedTransport(needTransport);
|
||||
}
|
||||
|
||||
// 日期字段(优先使用表头字段,如果表头为空则使用明细行字段)
|
||||
String warehouseDateStr = StringUtils.isNotBlank(headerInfo.getWarehouseDate()) ? headerInfo.getWarehouseDate() : h.getWarehouseDate();
|
||||
if (StringUtils.isNotBlank(warehouseDateStr)) {
|
||||
Date warehouseDate = parseDateString(warehouseDateStr);
|
||||
if (warehouseDate != null) {
|
||||
order.setWarehouseDate(warehouseDate);
|
||||
log.info("设置入仓日期: {}", warehouseDate);
|
||||
}
|
||||
}
|
||||
|
||||
String completionTimeStr = StringUtils.isNotBlank(headerInfo.getCompletionTime()) ? headerInfo.getCompletionTime() : h.getCompletionTime();
|
||||
if (StringUtils.isNotBlank(completionTimeStr)) {
|
||||
Date completionTime = parseDateString(completionTimeStr);
|
||||
if (completionTime != null) {
|
||||
order.setCompletionTime(completionTime);
|
||||
log.info("设置完成时间: {}", completionTime);
|
||||
}
|
||||
}
|
||||
|
||||
String orderDateStr = StringUtils.isNotBlank(headerInfo.getOrderDate()) ? headerInfo.getOrderDate() : h.getOrderDate();
|
||||
if (StringUtils.isNotBlank(orderDateStr)) {
|
||||
Date orderDate = parseDateString(orderDateStr);
|
||||
if (orderDate != null) {
|
||||
order.setOrderDate(orderDate);
|
||||
log.info("设置下单日期: {}", orderDate);
|
||||
}
|
||||
}
|
||||
|
||||
// 明细
|
||||
List<InMaterialDetailDO> details = new ArrayList<>();
|
||||
@@ -575,10 +736,13 @@ public class StockInOrderApplicationService {
|
||||
r.getMaterialCode(), r.getSkuCode(), r.getMaterialName());
|
||||
}
|
||||
|
||||
// 使用仓库数量
|
||||
// 使用仓库数量或入库数量(优先使用仓库数量,如果为空则使用入库数量)
|
||||
BigDecimal quantity = r.getWarehouseQuantity();
|
||||
if (quantity == null) {
|
||||
throw new ServiceException("导入失败:仓库数量不能为空(委托编号NO=" + h.getConsignmentNo() + ",物料基础信息ID=" + materialBaseInfoId + ")");
|
||||
quantity = r.getInboundQuantity();
|
||||
}
|
||||
if (quantity == null) {
|
||||
throw new ServiceException("导入失败:仓库数量或入库数量不能为空(委托编号NO=" + h.getConsignmentNo() + ",物料基础信息ID=" + materialBaseInfoId + ")");
|
||||
}
|
||||
|
||||
InMaterialDetailDO d = new InMaterialDetailDO();
|
||||
@@ -593,12 +757,22 @@ public class StockInOrderApplicationService {
|
||||
d.setBoxCount(r.getBoxCount());
|
||||
d.setPieceCount(r.getPieceCount());
|
||||
d.setDimensions(r.getDimensions());
|
||||
d.setOutboundQuantity(r.getOutboundQuantity());
|
||||
d.setUnit(r.getUnit());
|
||||
d.setTotalNetWeight(r.getTotalNetWeight());
|
||||
d.setTotalGrossWeight(r.getTotalGrossWeight());
|
||||
d.setTotalVolume(r.getTotalVolume());
|
||||
d.setTotalArea(r.getTotalArea());
|
||||
d.setInboundQuantity(r.getInboundQuantity());
|
||||
// 单位:优先使用"单位"字段,如果为空则使用"申报单位"
|
||||
String unit = StringUtils.isNotBlank(r.getUnit()) ? r.getUnit() : null;
|
||||
if (StringUtils.isBlank(unit) && StringUtils.isNotBlank(r.getDeclarationUnit())) {
|
||||
unit = r.getDeclarationUnit();
|
||||
log.info("单位字段为空,使用申报单位: {}", unit);
|
||||
}
|
||||
d.setUnit(unit);
|
||||
// 总净重:优先使用主字段,如果为空则使用备用字段
|
||||
d.setTotalNetWeight(r.getTotalNetWeight() != null ? r.getTotalNetWeight() : r.getTotalNetWeight2());
|
||||
// 总毛重:优先使用主字段,如果为空则使用备用字段
|
||||
d.setTotalGrossWeight(r.getTotalGrossWeight() != null ? r.getTotalGrossWeight() : r.getTotalGrossWeight2());
|
||||
// 总体积:优先使用主字段,如果为空则使用备用字段
|
||||
d.setTotalVolume(r.getTotalVolume() != null ? r.getTotalVolume() : r.getTotalVolume2());
|
||||
// 总面积:优先使用主字段,如果为空则使用备用字段
|
||||
d.setTotalArea(r.getTotalArea() != null ? r.getTotalArea() : r.getTotalArea2());
|
||||
d.setBatchRefNo(r.getBatchRefNo());
|
||||
d.setSheetRefNo(r.getSheetRefNo());
|
||||
d.setOriginCountry(r.getOriginCountry());
|
||||
@@ -621,6 +795,59 @@ public class StockInOrderApplicationService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析日期字符串为Date对象
|
||||
* 支持多种日期格式:yyyy-MM-dd, yyyy/MM/dd, yyyy年MM月dd日, Date.toString()格式等
|
||||
*/
|
||||
private Date parseDateString(String dateStr) {
|
||||
if (StringUtils.isBlank(dateStr)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 如果已经是Date.toString()格式(如 "Sun Feb 01 00:00:00 CST 2026"),尝试直接解析
|
||||
if (dateStr.contains("CST") || dateStr.contains("GMT") || dateStr.contains("UTC")) {
|
||||
try {
|
||||
// 尝试解析标准Date.toString()格式
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", java.util.Locale.ENGLISH);
|
||||
return sdf.parse(dateStr);
|
||||
} catch (ParseException e) {
|
||||
log.warn("无法解析日期格式: {}", dateStr);
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试多种日期格式
|
||||
String[] datePatterns = {
|
||||
"yyyy-MM-dd",
|
||||
"yyyy/MM/dd",
|
||||
"yyyy.MM.dd",
|
||||
"yyyy年MM月dd日",
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
"yyyy/MM/dd HH:mm:ss",
|
||||
"yyyy-MM-dd HH:mm",
|
||||
"yyyy/MM/dd HH:mm"
|
||||
};
|
||||
|
||||
for (String pattern : datePatterns) {
|
||||
try {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
|
||||
sdf.setLenient(false);
|
||||
return sdf.parse(dateStr.trim());
|
||||
} catch (ParseException e) {
|
||||
// 继续尝试下一个格式
|
||||
}
|
||||
}
|
||||
|
||||
// 如果所有格式都失败,记录警告
|
||||
log.warn("无法解析日期字符串: {},尝试使用DateUtils.parseDate", dateStr);
|
||||
try {
|
||||
// 使用DateUtils的parseDate方法(支持多种格式)
|
||||
return com.mhd.common.core.utils.DateUtils.parseDate(dateStr);
|
||||
} catch (Exception e) {
|
||||
log.error("解析日期失败: {}", dateStr, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Excel单元格的字符串值
|
||||
*/
|
||||
@@ -633,7 +860,16 @@ public class StockInOrderApplicationService {
|
||||
return cell.getStringCellValue();
|
||||
case NUMERIC:
|
||||
if (DateUtil.isCellDateFormatted(cell)) {
|
||||
return cell.getDateCellValue().toString();
|
||||
// 日期类型单元格,格式化为 yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss
|
||||
Date dateValue = cell.getDateCellValue();
|
||||
SimpleDateFormat sdf;
|
||||
// 检查是否包含时间部分
|
||||
if (dateValue.getHours() == 0 && dateValue.getMinutes() == 0 && dateValue.getSeconds() == 0) {
|
||||
sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
} else {
|
||||
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
}
|
||||
return sdf.format(dateValue);
|
||||
} else {
|
||||
double numericValue = cell.getNumericCellValue();
|
||||
if (numericValue == (long) numericValue) {
|
||||
@@ -658,11 +894,26 @@ public class StockInOrderApplicationService {
|
||||
* @param stockInOrderDO
|
||||
*/
|
||||
private void setWarehouseInfo(StockInOrderDO stockInOrderDO) {
|
||||
if (stockInOrderDO.getWarehouseId() == null) {
|
||||
throw new ServiceException("仓库ID不能为空");
|
||||
}
|
||||
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockInOrderDO.getWarehouseId());
|
||||
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
|
||||
throw new ServiceException("获取仓库信息失败");
|
||||
if (ajaxResult == null) {
|
||||
throw new ServiceException("获取仓库信息失败:返回结果为空,仓库ID:" + stockInOrderDO.getWarehouseId());
|
||||
}
|
||||
Object codeObj = ajaxResult.get("code");
|
||||
if (codeObj == null || !"200".equals(String.valueOf(codeObj))) {
|
||||
String errorMsg = ajaxResult.get("msg") != null ? String.valueOf(ajaxResult.get("msg")) : "未知错误";
|
||||
throw new ServiceException("获取仓库信息失败,仓库ID:" + stockInOrderDO.getWarehouseId() + ",错误信息:" + errorMsg);
|
||||
}
|
||||
Object dataObj = ajaxResult.get("data");
|
||||
if (dataObj == null) {
|
||||
throw new ServiceException("获取仓库信息失败:返回数据为空,仓库ID:" + stockInOrderDO.getWarehouseId());
|
||||
}
|
||||
WarehouseFeignPO warehouseFeignPO = JSON.parseObject(JSONObject.toJSONString(dataObj), WarehouseFeignPO.class);
|
||||
if (warehouseFeignPO == null) {
|
||||
throw new ServiceException("获取仓库信息失败:数据解析失败,仓库ID:" + stockInOrderDO.getWarehouseId());
|
||||
}
|
||||
WarehouseFeignPO warehouseFeignPO = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
|
||||
stockInOrderDO.setWarehouseCode(warehouseFeignPO.getWarehouseCode());
|
||||
stockInOrderDO.setWarehouseName(warehouseFeignPO.getWarehouseName());
|
||||
}
|
||||
|
||||
@@ -313,6 +313,10 @@ public class InMaterialDetail extends BaseVOEntity {
|
||||
@Excel(name = "件数")
|
||||
private BigDecimal pieceCount;
|
||||
|
||||
@ApiModelProperty("入库数量(输入大于等于0的数字,可以为小数)")
|
||||
@Excel(name = "入库数量")
|
||||
private BigDecimal inboundQuantity;
|
||||
|
||||
@ApiModelProperty("出库数量")
|
||||
@Excel(name = "出库数量")
|
||||
private BigDecimal outboundQuantity;
|
||||
|
||||
+3
-3
@@ -324,9 +324,9 @@ public class InMaterialDetailPO extends StockInOrderBasePO {
|
||||
@Excel(name = "件数")
|
||||
private BigDecimal pieceCount;
|
||||
|
||||
@ApiModelProperty("出库数量")
|
||||
@Excel(name = "出库数量")
|
||||
private BigDecimal outboundQuantity;
|
||||
@ApiModelProperty("入库数量")
|
||||
@Excel(name = "入库数量")
|
||||
private BigDecimal inboundQuantity;
|
||||
|
||||
@ApiModelProperty("总净重(KG)")
|
||||
@Excel(name = "总净重(KG)")
|
||||
|
||||
+3
-3
@@ -320,9 +320,9 @@ public class InMaterialDetailDO extends StockInOrderBaseDO {
|
||||
@Excel(name = "件数")
|
||||
private BigDecimal pieceCount;
|
||||
|
||||
@ApiModelProperty("出库数量(输入大于等于0的数字,可以为小数)")
|
||||
@Excel(name = "出库数量")
|
||||
private BigDecimal outboundQuantity;
|
||||
@ApiModelProperty("入库数量(输入大于等于0的数字,可以为小数)")
|
||||
@Excel(name = "ruku数量")
|
||||
private BigDecimal inboundQuantity;
|
||||
|
||||
@ApiModelProperty("总净重(KG)(输入大于等于0的数字,可以为小数)")
|
||||
@Excel(name = "总净重(KG)")
|
||||
|
||||
+21
-5
@@ -122,6 +122,10 @@ public class StockInOrderImportRowDTO {
|
||||
|
||||
@Excel(name = "仓库数量")
|
||||
private BigDecimal warehouseQuantity;
|
||||
|
||||
// 支持"入库数量"列名(与"仓库数量"映射到同一个字段)
|
||||
@Excel(name = "入库数量")
|
||||
private BigDecimal inboundQuantity;
|
||||
|
||||
@Excel(name = "规格型号/ITEM")
|
||||
private String specificationModel;
|
||||
@@ -153,21 +157,33 @@ public class StockInOrderImportRowDTO {
|
||||
// @Excel(name = "出库数量")
|
||||
private BigDecimal outboundQuantity;
|
||||
|
||||
// 模板中没有此字段,注释掉
|
||||
// @Excel(name = "单位")
|
||||
@Excel(name = "单位")
|
||||
private String unit;
|
||||
|
||||
// 支持多种列名格式(处理换行符、空格、括号等)
|
||||
@Excel(name = "总净重(KG)")
|
||||
private BigDecimal totalNetWeight;
|
||||
|
||||
|
||||
@Excel(name = "总净重\n(KG)")
|
||||
private BigDecimal totalNetWeight2;
|
||||
|
||||
@Excel(name = "总毛重(KG)")
|
||||
private BigDecimal totalGrossWeight;
|
||||
|
||||
|
||||
@Excel(name = "总毛重 (KG)")
|
||||
private BigDecimal totalGrossWeight2;
|
||||
|
||||
@Excel(name = "总体积(CBM)")
|
||||
private BigDecimal totalVolume;
|
||||
|
||||
|
||||
@Excel(name = "总体积\n(CBM)")
|
||||
private BigDecimal totalVolume2;
|
||||
|
||||
@Excel(name = "总面积(SQM)")
|
||||
private BigDecimal totalArea;
|
||||
|
||||
@Excel(name = "总面积(SQM)")
|
||||
private BigDecimal totalArea2;
|
||||
|
||||
@Excel(name = "Batch Ref NO's")
|
||||
private String batchRefNo;
|
||||
|
||||
@@ -67,7 +67,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="declaredQuantity" column="DECLARED_QUANTITY" />
|
||||
<result property="boxCount" column="BOX_COUNT" />
|
||||
<result property="pieceCount" column="PIECE_COUNT" />
|
||||
<result property="outboundQuantity" column="OUTBOUND_QUANTITY" />
|
||||
<result property="inboundQuantity" column="INBOUND_QUANTITY" />
|
||||
<result property="totalNetWeight" column="TOTAL_NET_WEIGHT" />
|
||||
<result property="totalGrossWeight" column="TOTAL_GROSS_WEIGHT" />
|
||||
<result property="totalVolume" column="TOTAL_VOLUME" />
|
||||
@@ -90,7 +90,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
a.warehouse_id, a.warehouse_code, a.warehouse_name, a.storage_section_id, a.storage_code, a.storage_name, a.storage_location_id, a.storage_location_code, a.storage_location_name,
|
||||
a.level, a.parent_unique_id, a.remark, a.create_time, a.create_by,a.create_by_name, a.update_time, a.update_by, a.update_by_name, a.del_flag, a.over_stock_id, a.over_stock_status, a.over_stock_type,
|
||||
a.SPECIFICATION_MODEL, a.SKU_CODE, a.INVOICE_NO, a.LITER, a.DIMENSIONS, a.DECLARATION_UNIT, a.BATCH_REF_NO, a.SHEET_REF_NO,
|
||||
a.ORIGIN_COUNTRY, a.BOX_PALLET_NO, a.CURRENCY, a.UNIT, a.DECLARED_QUANTITY, a.BOX_COUNT, a.PIECE_COUNT, a.OUTBOUND_QUANTITY,
|
||||
a.ORIGIN_COUNTRY, a.BOX_PALLET_NO, a.CURRENCY, a.UNIT, a.DECLARED_QUANTITY, a.BOX_COUNT, a.PIECE_COUNT, a.INBOUND_QUANTITY,
|
||||
a.TOTAL_NET_WEIGHT, a.TOTAL_GROSS_WEIGHT, a.TOTAL_VOLUME, a.TOTAL_AREA, a.TOTAL_PRICE
|
||||
,CASE
|
||||
WHEN (a.quantity - a.receipt_quantity) < 0 THEN 0
|
||||
|
||||
@@ -376,6 +376,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<where>
|
||||
<include refid="selectStockInOrderPo1"/>
|
||||
</where>
|
||||
ORDER BY a.create_time DESC
|
||||
ORDER BY a.create_time IS NULL, a.create_time DESC
|
||||
</select>
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user