Merge branch 'dev_qinhongzhanWMS' into wms_dev

This commit is contained in:
秦鸿展
2026-01-24 15:46:31 +08:00
7 changed files with 314 additions and 43 deletions
@@ -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;
@@ -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)")
@@ -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)")
@@ -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) &lt; 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>