Merge remote-tracking branch 'origin/wms_dev' into wms_dev

This commit is contained in:
王奎兴
2026-02-02 13:42:13 +08:00
15 changed files with 967 additions and 21 deletions
@@ -5,11 +5,13 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.utils.bean.BeanUtils;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.UserServiceFeign;
import com.mhd.system.api.domain.BatchDetailFeignPO;
import com.mhd.system.api.domain.WarehouseFeignPO;
import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
@@ -20,14 +22,18 @@ import com.mhd.wms.domain.investigationManage.service.InvestigationManageDomainS
import com.mhd.wms.domain.investigetionManageDetail.repository.po.InvestigetionManageDetailPO;
import com.mhd.wms.domain.investigetionManageDetail.repository.todo.InvestigetionManageDetailDO;
import com.mhd.wms.domain.investigetionManageDetail.service.InvestigetionManageDetailDomainService;
import com.mhd.wms.domain.materialInventory.repository.mapper.MaterialInventoryMapper;
import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -48,6 +54,8 @@ public class InvestigationManageApplicationService {
private UserServiceFeign userServiceFeign;
@Autowired
private SystemServiceFeign systemServiceFeign;
@Autowired
private MaterialInventoryMapper materialInventoryMapper;
/**
@@ -94,10 +102,273 @@ public class InvestigationManageApplicationService {
}
/**
* 获取盘点管理详细信息
* 获取盘点管理详细信息(带批次属性)
*/
public InvestigationManagePO getInfo(Long investigationManageId) {
return investigationManageDomainService.getInfo(investigationManageId);
InvestigationManagePO investigationManagePO = investigationManageDomainService.getInfo(investigationManageId);
if (investigationManagePO == null || CollectionUtils.isEmpty(investigationManagePO.getInvestigetionManageDetailList())) {
return investigationManagePO;
}
List<InvestigetionManageDetailPO> detailList = investigationManagePO.getInvestigetionManageDetailList();
// 性能优化:批量获取批次属性,避免N+1查询问题
// 1. 收集所有唯一的materialBaseInfoId
Set<Long> materialBaseInfoIdSet = detailList.stream()
.map(InvestigetionManageDetailPO::getMaterialBaseInfoId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 2. 批量查询批次属性(使用Map缓存,避免重复查询相同的materialBaseInfoId
Map<Long, List<BatchDetailFeignPO>> batchDetailMap = new HashMap<>();
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
try {
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId);
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
List<BatchDetailFeignPO> batchDetailFeignPOList = JSON.parseArray(
JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
if (!CollectionUtils.isEmpty(batchDetailFeignPOList)) {
// 过滤isDisplay=1的属性
List<BatchDetailFeignPO> filteredList = batchDetailFeignPOList.stream()
.filter(batchDetail -> batchDetail.getIsDisplay() != null && batchDetail.getIsDisplay() == 1)
.collect(Collectors.toList());
batchDetailMap.put(materialBaseInfoId, filteredList);
}
}
} catch (Exception e) {
log.warn("获取物料批次属性失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
}
// 3. 为每个物料明细设置更多属性(从库存表中获取值)
setMaterialMoreDetailListFromInventory(detailList, batchDetailMap);
return investigationManagePO;
}
/**
* 为盘点物料明细设置更多属性(从库存表中获取值)
* @param investigetionManageDetailPOList 盘点物料明细列表
* @param batchDetailMap 批次属性Map
*/
private void setMaterialMoreDetailListFromInventory(List<InvestigetionManageDetailPO> investigetionManageDetailPOList,
Map<Long, List<BatchDetailFeignPO>> batchDetailMap) {
if (CollectionUtils.isEmpty(investigetionManageDetailPOList)) {
return;
}
investigetionManageDetailPOList.forEach(investigetionManageDetailPO -> {
Long materialBaseInfoId = investigetionManageDetailPO.getMaterialBaseInfoId();
Long materialInventoryId = investigetionManageDetailPO.getMaterialInventoryId();
// 创建新的materialMoreDetailList,只包含isDisplay=1的属性
List<MaterialMoreDetailPO> materialMoreDetailList = new ArrayList<>();
// 从库存表获取数据(包含批次属性字段)
MaterialInventoryPO materialInventoryPO = null;
if (materialInventoryId != null) {
materialInventoryPO = materialInventoryMapper.selectByIdWithBatchAttributes(materialInventoryId);
}
if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) {
List<BatchDetailFeignPO> batchDetailFeignPOList = batchDetailMap.get(materialBaseInfoId);
// 用于跟踪已添加到列表中的batchDetailId
Set<Long> addedBatchDetailIds = new HashSet<>();
for (BatchDetailFeignPO batchDetailFeignPO : batchDetailFeignPOList) {
MaterialMoreDetailPO materialMoreDetailPO = new MaterialMoreDetailPO();
materialMoreDetailPO.setBatchId(batchDetailFeignPO.getBatchId());
materialMoreDetailPO.setBatchDetailId(batchDetailFeignPO.getBatchDetailId());
materialMoreDetailPO.setBatchLabels(batchDetailFeignPO.getBatchLabels());
materialMoreDetailPO.setInputControl(batchDetailFeignPO.getInputControl());
materialMoreDetailPO.setAttributeFormat(batchDetailFeignPO.getAttributeFormat());
materialMoreDetailPO.setAttributeOption(batchDetailFeignPO.getAttributeOption());
materialMoreDetailPO.setRemark(batchDetailFeignPO.getRemark());
// 确保添加到列表中(使用batchDetailId来避免重复)
Long batchDetailId = batchDetailFeignPO.getBatchDetailId();
if (batchDetailId != null && !addedBatchDetailIds.contains(batchDetailId)) {
materialMoreDetailList.add(materialMoreDetailPO);
addedBatchDetailIds.add(batchDetailId);
}
// 根据fieldName或batchLabels从库存表中获取对应的字段值
if (materialInventoryPO != null) {
String fieldValue = null;
String usedFieldName = null;
// 优先使用fieldName(如果存在)
if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) {
usedFieldName = batchDetailFeignPO.getFieldName();
fieldValue = getFieldValueByFieldName(materialInventoryPO, usedFieldName);
log.info("批次属性 batchDetailId={}, fieldName={}, 从库存表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), usedFieldName, fieldValue);
}
// 如果fieldName为空,尝试根据batchLabels映射到字段名
else if (StringUtils.isNotBlank(batchDetailFeignPO.getBatchLabels())) {
String fieldNameByLabel = getFieldNameByBatchLabel(batchDetailFeignPO.getBatchLabels());
if (StringUtils.isNotBlank(fieldNameByLabel)) {
usedFieldName = fieldNameByLabel;
fieldValue = getFieldValueByFieldName(materialInventoryPO, usedFieldName);
log.info("批次属性 batchDetailId={}, batchLabels={}, 映射字段名={}, 从库存表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), batchDetailFeignPO.getBatchLabels(),
usedFieldName, fieldValue);
}
}
// 只有当获取到值时才更新attributeValue
if (fieldValue != null) {
materialMoreDetailPO.setAttributeValue(fieldValue);
log.info("设置更多属性:batchDetailId={}, batchLabels={}, attributeValue={}",
materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getBatchLabels(),
materialMoreDetailPO.getAttributeValue());
}
}
}
}
investigetionManageDetailPO.setMaterialMoreDetailList(materialMoreDetailList);
log.info("盘点物料明细 investigationManageDetailId={}, materialBaseInfoId={}, materialInventoryId={}, materialMoreDetailList大小={}",
investigetionManageDetailPO.getInvestigationManageDetailId(), investigetionManageDetailPO.getMaterialBaseInfoId(),
investigetionManageDetailPO.getMaterialInventoryId(),
materialMoreDetailList != null ? materialMoreDetailList.size() : 0);
});
}
/**
* 根据批次标签(batchLabels)映射到字段名
* @param batchLabel 批次标签
* @return 字段名,如果找不到映射则返回null
*/
private String getFieldNameByBatchLabel(String batchLabel) {
if (StringUtils.isBlank(batchLabel)) {
return null;
}
// 批次标签到字段名的映射关系
Map<String, String> labelToFieldNameMap = new HashMap<>();
labelToFieldNameMap.put("Invoice No.", "invoiceNo");
labelToFieldNameMap.put("Invoice No", "invoiceNo");
labelToFieldNameMap.put("发票号", "invoiceNo");
labelToFieldNameMap.put("Batch Ref NO's", "batchRefNo");
labelToFieldNameMap.put("Batch Ref NO", "batchRefNo");
labelToFieldNameMap.put("批次参考号", "batchRefNo");
labelToFieldNameMap.put("Sheet Ref NO's", "sheetRefNo");
labelToFieldNameMap.put("Sheet Ref NO", "sheetRefNo");
labelToFieldNameMap.put("单据参考号", "sheetRefNo");
labelToFieldNameMap.put("箱号/卡板号", "boxPalletNo");
labelToFieldNameMap.put("箱号", "boxPalletNo");
labelToFieldNameMap.put("卡板号", "boxPalletNo");
labelToFieldNameMap.put("生产日期", "productionDate");
labelToFieldNameMap.put("过期日期", "expiryDate");
labelToFieldNameMap.put("存货日期", "inventoryDate");
labelToFieldNameMap.put("扩展字段1", "extAttr1");
labelToFieldNameMap.put("扩展字段2", "extAttr2");
labelToFieldNameMap.put("扩展字段3", "extAttr3");
labelToFieldNameMap.put("扩展字段4", "extAttr4");
// 精确匹配
String fieldName = labelToFieldNameMap.get(batchLabel.trim());
if (StringUtils.isNotBlank(fieldName)) {
return fieldName;
}
// 模糊匹配(包含关系)
for (Map.Entry<String, String> entry : labelToFieldNameMap.entrySet()) {
if (batchLabel.contains(entry.getKey()) || entry.getKey().contains(batchLabel)) {
return entry.getValue();
}
}
return null;
}
/**
* 根据字段名从对象中获取字段值(使用反射)
* @param obj 对象
* @param fieldName 字段名
* @return 字段值(转换为字符串)
*/
private String getFieldValueByFieldName(Object obj, String fieldName) {
if (obj == null || StringUtils.isBlank(fieldName)) {
return null;
}
try {
// 兼容:如果传的是下划线命名(数据库列名风格),先转成驼峰字段名再取
String normalizedFieldName = fieldName;
if (normalizedFieldName.contains("_")) {
normalizedFieldName = snakeToCamel(normalizedFieldName);
}
// 获取对象的Class
Class<?> clazz = obj.getClass();
// 尝试获取字段(包括父类字段)
Field field = null;
Class<?> currentClass = clazz;
while (currentClass != null && field == null) {
try {
field = currentClass.getDeclaredField(normalizedFieldName);
} catch (NoSuchFieldException e) {
currentClass = currentClass.getSuperclass();
}
}
if (field == null) {
log.warn("字段不存在:{}(normalized{}),对象类型:{}", fieldName, normalizedFieldName, clazz.getName());
return null;
}
// 设置可访问
field.setAccessible(true);
// 获取字段值
Object value = field.get(obj);
// 转换为字符串
if (value == null) {
log.info("字段 {} 的值为 null,对象类型:{}", normalizedFieldName, clazz.getName());
return null;
}
String result;
// 处理日期类型字段
if (value instanceof Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
result = sdf.format((Date) value);
} else {
result = value.toString();
}
log.info("通过反射获取字段值成功,字段名:{}(原始:{}),值:{},对象类型:{}",
normalizedFieldName, fieldName, result, clazz.getName());
return result;
} catch (Exception e) {
log.warn("通过反射获取字段值失败,字段名:{},对象类型:{},错误:{}", fieldName, obj.getClass().getName(), e.getMessage());
return null;
}
}
private String snakeToCamel(String snake) {
if (StringUtils.isBlank(snake)) {
return null;
}
String s = snake.trim().toLowerCase();
StringBuilder sb = new StringBuilder();
boolean upperNext = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '_') {
upperNext = true;
continue;
}
if (upperNext) {
sb.append(Character.toUpperCase(c));
upperNext = false;
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
@@ -1,16 +1,29 @@
package com.mhd.wms.application.service.shiftMaterialDetail;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.mhd.common.core.utils.StringUtils;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.domain.BatchDetailFeignPO;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.materialInventory.entity.MaterialInventory;
import com.mhd.wms.domain.materialInventory.repository.mapper.MaterialInventoryMapper;
import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import com.mhd.wms.domain.shiftMaterialDetail.repository.po.ShiftMaterialDetailPO;
import com.mhd.wms.domain.shiftMaterialDetail.repository.todo.ShiftMaterialDetailDO;
import com.mhd.wms.domain.shiftMaterialDetail.service.ShiftMaterialDetailDomainService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
/**
* 移位物料明细ApplicationService
@@ -25,6 +38,8 @@ public class ShiftMaterialDetailApplicationService {
private ShiftMaterialDetailDomainService shiftMaterialDetailDomainService;
@Autowired
private SystemServiceFeign systemServiceFeign;
@Autowired
private MaterialInventoryMapper materialInventoryMapper;
/**
* 分页查询移位物料明细列表
@@ -92,4 +107,273 @@ public class ShiftMaterialDetailApplicationService {
return shiftMaterialDetailDomainService.getShiftMaterialDetail(shiftMaterialDetailDO);
}
/**
* 查询移位物料明细列表(带批次属性)
* 批次属性值从库存表中获取
*/
public List<ShiftMaterialDetailPO> queryListWithBatchAttributes(ShiftMaterialDetailDO shiftMaterialDetailDO) {
List<ShiftMaterialDetailPO> list = queryList(shiftMaterialDetailDO);
if (CollectionUtils.isEmpty(list)) {
return list;
}
// 性能优化:批量获取批次属性,避免N+1查询问题
// 1. 收集所有唯一的materialBaseInfoId
Set<Long> materialBaseInfoIdSet = list.stream()
.map(ShiftMaterialDetailPO::getMaterialBaseInfoId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 2. 批量查询批次属性(使用Map缓存,避免重复查询相同的materialBaseInfoId
Map<Long, List<BatchDetailFeignPO>> batchDetailMap = new HashMap<>();
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
try {
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId);
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
List<BatchDetailFeignPO> batchDetailFeignPOList = JSON.parseArray(
JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
if (!CollectionUtils.isEmpty(batchDetailFeignPOList)) {
// 过滤isDisplay=1的属性
List<BatchDetailFeignPO> filteredList = batchDetailFeignPOList.stream()
.filter(batchDetail -> batchDetail.getIsDisplay() != null && batchDetail.getIsDisplay() == 1)
.collect(Collectors.toList());
batchDetailMap.put(materialBaseInfoId, filteredList);
}
}
} catch (Exception e) {
log.warn("获取物料批次属性失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
}
// 3. 为每个物料明细设置更多属性(从库存表中获取值)
setMaterialMoreDetailListFromInventory(list, batchDetailMap);
return list;
}
/**
* 为移位物料明细设置更多属性(从库存表中获取值)
* @param shiftMaterialDetailPOList 移位物料明细列表
* @param batchDetailMap 批次属性Map
*/
private void setMaterialMoreDetailListFromInventory(List<ShiftMaterialDetailPO> shiftMaterialDetailPOList,
Map<Long, List<BatchDetailFeignPO>> batchDetailMap) {
if (CollectionUtils.isEmpty(shiftMaterialDetailPOList)) {
return;
}
shiftMaterialDetailPOList.forEach(shiftMaterialDetailPO -> {
Long materialBaseInfoId = shiftMaterialDetailPO.getMaterialBaseInfoId();
Long materialInventoryId = shiftMaterialDetailPO.getMaterialInventoryId();
// 创建新的materialMoreDetailList,只包含isDisplay=1的属性
List<MaterialMoreDetailPO> materialMoreDetailList = new ArrayList<>();
// 从库存表获取数据(包含批次属性字段)
MaterialInventoryPO materialInventoryPO = null;
if (materialInventoryId != null) {
materialInventoryPO = materialInventoryMapper.selectByIdWithBatchAttributes(materialInventoryId);
}
if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) {
List<BatchDetailFeignPO> batchDetailFeignPOList = batchDetailMap.get(materialBaseInfoId);
// 用于跟踪已添加到列表中的batchDetailId
Set<Long> addedBatchDetailIds = new HashSet<>();
for (BatchDetailFeignPO batchDetailFeignPO : batchDetailFeignPOList) {
MaterialMoreDetailPO materialMoreDetailPO = new MaterialMoreDetailPO();
materialMoreDetailPO.setBatchId(batchDetailFeignPO.getBatchId());
materialMoreDetailPO.setBatchDetailId(batchDetailFeignPO.getBatchDetailId());
materialMoreDetailPO.setBatchLabels(batchDetailFeignPO.getBatchLabels());
materialMoreDetailPO.setInputControl(batchDetailFeignPO.getInputControl());
materialMoreDetailPO.setAttributeFormat(batchDetailFeignPO.getAttributeFormat());
materialMoreDetailPO.setAttributeOption(batchDetailFeignPO.getAttributeOption());
materialMoreDetailPO.setRemark(batchDetailFeignPO.getRemark());
// 确保添加到列表中(使用batchDetailId来避免重复)
Long batchDetailId = batchDetailFeignPO.getBatchDetailId();
if (batchDetailId != null && !addedBatchDetailIds.contains(batchDetailId)) {
materialMoreDetailList.add(materialMoreDetailPO);
addedBatchDetailIds.add(batchDetailId);
}
// 根据fieldName或batchLabels从库存表中获取对应的字段值
if (materialInventoryPO != null) {
String fieldValue = null;
String usedFieldName = null;
// 优先使用fieldName(如果存在)
if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) {
usedFieldName = batchDetailFeignPO.getFieldName();
fieldValue = getFieldValueByFieldName(materialInventoryPO, usedFieldName);
log.info("批次属性 batchDetailId={}, fieldName={}, 从库存表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), usedFieldName, fieldValue);
}
// 如果fieldName为空,尝试根据batchLabels映射到字段名
else if (StringUtils.isNotBlank(batchDetailFeignPO.getBatchLabels())) {
String fieldNameByLabel = getFieldNameByBatchLabel(batchDetailFeignPO.getBatchLabels());
if (StringUtils.isNotBlank(fieldNameByLabel)) {
usedFieldName = fieldNameByLabel;
fieldValue = getFieldValueByFieldName(materialInventoryPO, usedFieldName);
log.info("批次属性 batchDetailId={}, batchLabels={}, 映射字段名={}, 从库存表获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), batchDetailFeignPO.getBatchLabels(),
usedFieldName, fieldValue);
}
}
// 只有当获取到值时才更新attributeValue
if (fieldValue != null) {
materialMoreDetailPO.setAttributeValue(fieldValue);
log.info("设置更多属性:batchDetailId={}, batchLabels={}, attributeValue={}",
materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getBatchLabels(),
materialMoreDetailPO.getAttributeValue());
}
}
}
}
shiftMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailList);
log.info("移位物料明细 uniqueId={}, materialBaseInfoId={}, materialInventoryId={}, materialMoreDetailList大小={}",
shiftMaterialDetailPO.getUniqueId(), shiftMaterialDetailPO.getMaterialBaseInfoId(),
shiftMaterialDetailPO.getMaterialInventoryId(),
materialMoreDetailList != null ? materialMoreDetailList.size() : 0);
});
}
/**
* 根据批次标签(batchLabels)映射到字段名
* @param batchLabel 批次标签
* @return 字段名,如果找不到映射则返回null
*/
private String getFieldNameByBatchLabel(String batchLabel) {
if (StringUtils.isBlank(batchLabel)) {
return null;
}
// 批次标签到字段名的映射关系
Map<String, String> labelToFieldNameMap = new HashMap<>();
labelToFieldNameMap.put("Invoice No.", "invoiceNo");
labelToFieldNameMap.put("Invoice No", "invoiceNo");
labelToFieldNameMap.put("发票号", "invoiceNo");
labelToFieldNameMap.put("Batch Ref NO's", "batchRefNo");
labelToFieldNameMap.put("Batch Ref NO", "batchRefNo");
labelToFieldNameMap.put("批次参考号", "batchRefNo");
labelToFieldNameMap.put("Sheet Ref NO's", "sheetRefNo");
labelToFieldNameMap.put("Sheet Ref NO", "sheetRefNo");
labelToFieldNameMap.put("单据参考号", "sheetRefNo");
labelToFieldNameMap.put("箱号/卡板号", "boxPalletNo");
labelToFieldNameMap.put("箱号", "boxPalletNo");
labelToFieldNameMap.put("卡板号", "boxPalletNo");
labelToFieldNameMap.put("生产日期", "productionDate");
labelToFieldNameMap.put("过期日期", "expiryDate");
labelToFieldNameMap.put("存货日期", "inventoryDate");
labelToFieldNameMap.put("扩展字段1", "extAttr1");
labelToFieldNameMap.put("扩展字段2", "extAttr2");
labelToFieldNameMap.put("扩展字段3", "extAttr3");
labelToFieldNameMap.put("扩展字段4", "extAttr4");
// 精确匹配
String fieldName = labelToFieldNameMap.get(batchLabel.trim());
if (StringUtils.isNotBlank(fieldName)) {
return fieldName;
}
// 模糊匹配(包含关系)
for (Map.Entry<String, String> entry : labelToFieldNameMap.entrySet()) {
if (batchLabel.contains(entry.getKey()) || entry.getKey().contains(batchLabel)) {
return entry.getValue();
}
}
return null;
}
/**
* 根据字段名从对象中获取字段值(使用反射)
* @param obj 对象
* @param fieldName 字段名
* @return 字段值(转换为字符串)
*/
private String getFieldValueByFieldName(Object obj, String fieldName) {
if (obj == null || StringUtils.isBlank(fieldName)) {
return null;
}
try {
// 兼容:如果传的是下划线命名(数据库列名风格),先转成驼峰字段名再取
String normalizedFieldName = fieldName;
if (normalizedFieldName.contains("_")) {
normalizedFieldName = snakeToCamel(normalizedFieldName);
}
// 获取对象的Class
Class<?> clazz = obj.getClass();
// 尝试获取字段(包括父类字段)
Field field = null;
Class<?> currentClass = clazz;
while (currentClass != null && field == null) {
try {
field = currentClass.getDeclaredField(normalizedFieldName);
} catch (NoSuchFieldException e) {
currentClass = currentClass.getSuperclass();
}
}
if (field == null) {
log.warn("字段不存在:{}(normalized{}),对象类型:{}", fieldName, normalizedFieldName, clazz.getName());
return null;
}
// 设置可访问
field.setAccessible(true);
// 获取字段值
Object value = field.get(obj);
// 转换为字符串
if (value == null) {
log.info("字段 {} 的值为 null,对象类型:{}", normalizedFieldName, clazz.getName());
return null;
}
String result;
// 处理日期类型字段
if (value instanceof Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
result = sdf.format((Date) value);
} else {
result = value.toString();
}
log.info("通过反射获取字段值成功,字段名:{}(原始:{}),值:{},对象类型:{}",
normalizedFieldName, fieldName, result, clazz.getName());
return result;
} catch (Exception e) {
log.warn("通过反射获取字段值失败,字段名:{},对象类型:{},错误:{}", fieldName, obj.getClass().getName(), e.getMessage());
return null;
}
}
private String snakeToCamel(String snake) {
if (StringUtils.isBlank(snake)) {
return null;
}
String s = snake.trim().toLowerCase();
StringBuilder sb = new StringBuilder();
boolean upperNext = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '_') {
upperNext = true;
continue;
}
if (upperNext) {
sb.append(Character.toUpperCase(c));
upperNext = false;
} else {
sb.append(c);
}
}
return sb.toString();
}
}
@@ -16,6 +16,7 @@ import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.UserServiceFeign;
import com.mhd.system.api.domain.BatchDetailFeignPO;
import com.mhd.system.api.domain.StorageLocationFeignPO;
import com.mhd.system.api.domain.SysDictData;
import com.mhd.system.api.domain.WarehouseFeignPO;
@@ -24,6 +25,7 @@ import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
import com.mhd.system.api.model.LoginUser;
import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO;
import com.mhd.wms.domain.materialInventory.service.MaterialInventoryDomainService;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import com.mhd.wms.domain.outMaterialDetail.repository.po.OutMaterialCheckPO;
import com.mhd.wms.domain.outMaterialDetail.repository.po.OutMaterialDetailPO;
import com.mhd.wms.domain.outMaterialDetail.repository.todo.OutMaterialDetailDO;
@@ -36,10 +38,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -121,11 +123,342 @@ public class StockOutOrderApplicationService {
}
/**
* 获取出库单详细信息
* 获取出库单详细信息(带批次属性)
*/
public StockOutOrderPO getInfoChildren(Long outOrderId)
{
return stockOutOrderDomainService.getInfoChildren(outOrderId);
StockOutOrderPO stockOutOrderPO = stockOutOrderDomainService.getInfoChildren(outOrderId);
if (stockOutOrderPO == null || CollectionUtils.isEmpty(stockOutOrderPO.getMaterialDetailList())) {
return stockOutOrderPO;
}
List<OutMaterialDetailPO> detailList = stockOutOrderPO.getMaterialDetailList();
// 性能优化:批量获取批次属性,避免N+1查询问题
// 1. 收集所有唯一的materialBaseInfoId
Set<Long> materialBaseInfoIdSet = detailList.stream()
.map(OutMaterialDetailPO::getMaterialBaseInfoId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 2. 批量查询批次属性(使用Map缓存,避免重复查询相同的materialBaseInfoId
Map<Long, List<BatchDetailFeignPO>> batchDetailMap = new HashMap<>();
for (Long materialBaseInfoId : materialBaseInfoIdSet) {
try {
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId);
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) {
List<BatchDetailFeignPO> batchDetailFeignPOList = JSON.parseArray(
JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
if (!CollectionUtils.isEmpty(batchDetailFeignPOList)) {
// 过滤isDisplay=1的属性
List<BatchDetailFeignPO> filteredList = batchDetailFeignPOList.stream()
.filter(batchDetail -> batchDetail.getIsDisplay() != null && batchDetail.getIsDisplay() == 1)
.collect(Collectors.toList());
batchDetailMap.put(materialBaseInfoId, filteredList);
}
}
} catch (Exception e) {
log.warn("获取物料批次属性失败,物料基础信息ID:{},错误:{}", materialBaseInfoId, e.getMessage());
}
}
// 3. 为每个物料明细设置更多属性(从物料明细表中获取值),递归处理所有层级
setMaterialMoreDetailListRecursively(detailList, batchDetailMap);
return stockOutOrderPO;
}
/**
* 递归为出库物料明细设置更多属性(从物料明细表中获取值)
* @param outMaterialDetailPOList 出库物料明细列表
* @param batchDetailMap 批次属性Map
*/
private void setMaterialMoreDetailListRecursively(List<OutMaterialDetailPO> outMaterialDetailPOList,
Map<Long, List<BatchDetailFeignPO>> batchDetailMap) {
if (CollectionUtils.isEmpty(outMaterialDetailPOList)) {
return;
}
outMaterialDetailPOList.forEach(outMaterialDetailPO -> {
Long materialBaseInfoId = outMaterialDetailPO.getMaterialBaseInfoId();
// 只保留isDisplay=1的批次属性(从batchDetailMap中获取,已经过滤过了)
// 创建新的materialMoreDetailList,只包含isDisplay=1的属性
List<MaterialMoreDetailPO> materialMoreDetailList = new ArrayList<>();
// 创建batchDetailId到MaterialMoreDetailPO的映射,用于快速查找已有的属性值
Map<Long, MaterialMoreDetailPO> batchDetailIdToMaterialMoreDetailMap = new HashMap<>();
List<MaterialMoreDetailPO> existingList = outMaterialDetailPO.getMaterialMoreDetailList();
if (!CollectionUtils.isEmpty(existingList)) {
for (MaterialMoreDetailPO existing : existingList) {
if (existing.getBatchDetailId() != null) {
batchDetailIdToMaterialMoreDetailMap.put(existing.getBatchDetailId(), existing);
}
}
}
if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) {
List<BatchDetailFeignPO> batchDetailFeignPOList = batchDetailMap.get(materialBaseInfoId);
// 用于跟踪已添加到列表中的batchDetailId
Set<Long> addedBatchDetailIds = new HashSet<>();
for (BatchDetailFeignPO batchDetailFeignPO : batchDetailFeignPOList) {
MaterialMoreDetailPO materialMoreDetailPO = batchDetailIdToMaterialMoreDetailMap.get(batchDetailFeignPO.getBatchDetailId());
// 如果不存在,创建新的
if (materialMoreDetailPO == null) {
materialMoreDetailPO = new MaterialMoreDetailPO();
materialMoreDetailPO.setBatchId(batchDetailFeignPO.getBatchId());
materialMoreDetailPO.setBatchDetailId(batchDetailFeignPO.getBatchDetailId());
materialMoreDetailPO.setBatchLabels(batchDetailFeignPO.getBatchLabels());
materialMoreDetailPO.setInputControl(batchDetailFeignPO.getInputControl());
materialMoreDetailPO.setAttributeFormat(batchDetailFeignPO.getAttributeFormat());
materialMoreDetailPO.setAttributeOption(batchDetailFeignPO.getAttributeOption());
materialMoreDetailPO.setRemark(batchDetailFeignPO.getRemark());
} else {
// 如果已存在,更新属性(保留已有的attributeValue
materialMoreDetailPO.setBatchId(batchDetailFeignPO.getBatchId());
materialMoreDetailPO.setBatchLabels(batchDetailFeignPO.getBatchLabels());
materialMoreDetailPO.setInputControl(batchDetailFeignPO.getInputControl());
materialMoreDetailPO.setAttributeFormat(batchDetailFeignPO.getAttributeFormat());
materialMoreDetailPO.setAttributeOption(batchDetailFeignPO.getAttributeOption());
materialMoreDetailPO.setRemark(batchDetailFeignPO.getRemark());
}
// 确保添加到列表中(使用batchDetailId来避免重复)
Long batchDetailId = batchDetailFeignPO.getBatchDetailId();
if (batchDetailId != null && !addedBatchDetailIds.contains(batchDetailId)) {
materialMoreDetailList.add(materialMoreDetailPO);
addedBatchDetailIds.add(batchDetailId);
}
// 根据fieldName或batchLabels从物料明细中获取对应的字段值
if (outMaterialDetailPO != null) {
String fieldValue = null;
String usedFieldName = null;
// 优先使用fieldName(如果存在)
if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) {
usedFieldName = batchDetailFeignPO.getFieldName();
fieldValue = getFieldValueByFieldName(outMaterialDetailPO, usedFieldName);
log.info("批次属性 batchDetailId={}, fieldName={}, 获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), usedFieldName, fieldValue);
}
// 如果fieldName为空,尝试根据batchLabels映射到字段名
else if (StringUtils.isNotBlank(batchDetailFeignPO.getBatchLabels())) {
String fieldNameByLabel = getFieldNameByBatchLabel(batchDetailFeignPO.getBatchLabels());
if (StringUtils.isNotBlank(fieldNameByLabel)) {
usedFieldName = fieldNameByLabel;
fieldValue = getFieldValueByFieldName(outMaterialDetailPO, usedFieldName);
log.info("批次属性 batchDetailId={}, batchLabels={}, 映射字段名={}, 获取到的值={}",
batchDetailFeignPO.getBatchDetailId(), batchDetailFeignPO.getBatchLabels(),
usedFieldName, fieldValue);
}
}
// 只有当获取到值时才更新attributeValue(避免覆盖已有的值)
if (fieldValue != null) {
materialMoreDetailPO.setAttributeValue(fieldValue);
log.info("设置更多属性:batchDetailId={}, batchLabels={}, attributeValue={}",
materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getBatchLabels(),
materialMoreDetailPO.getAttributeValue());
}
}
}
}
outMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailList);
log.info("出库物料明细 uniqueId={}, materialBaseInfoId={}, materialMoreDetailList大小={}",
outMaterialDetailPO.getUniqueId(), outMaterialDetailPO.getMaterialBaseInfoId(),
materialMoreDetailList != null ? materialMoreDetailList.size() : 0);
// 递归处理子集
if (!CollectionUtils.isEmpty(outMaterialDetailPO.getChildren())) {
setMaterialMoreDetailListRecursively(outMaterialDetailPO.getChildren(), batchDetailMap);
}
});
}
/**
* 根据批次标签(batchLabels)映射到字段名
* @param batchLabel 批次标签
* @return 字段名,如果找不到映射则返回null
*/
private String getFieldNameByBatchLabel(String batchLabel) {
if (StringUtils.isBlank(batchLabel)) {
return null;
}
// 批次标签到字段名的映射关系
Map<String, String> labelToFieldNameMap = new HashMap<>();
labelToFieldNameMap.put("Invoice No.", "invoiceNo");
labelToFieldNameMap.put("Invoice No", "invoiceNo");
labelToFieldNameMap.put("发票号", "invoiceNo");
labelToFieldNameMap.put("Batch Ref NO's", "batchRefNo");
labelToFieldNameMap.put("Batch Ref NO", "batchRefNo");
labelToFieldNameMap.put("批次参考号", "batchRefNo");
labelToFieldNameMap.put("Sheet Ref NO's", "sheetRefNo");
labelToFieldNameMap.put("Sheet Ref NO", "sheetRefNo");
labelToFieldNameMap.put("单据参考号", "sheetRefNo");
labelToFieldNameMap.put("箱号/卡板号", "boxPalletNo");
labelToFieldNameMap.put("箱号", "boxPalletNo");
labelToFieldNameMap.put("卡板号", "boxPalletNo");
labelToFieldNameMap.put("申报数量", "declareQuantity");
labelToFieldNameMap.put("申报单位", "declareUnit");
labelToFieldNameMap.put("原产国", "countryOfOrigin");
labelToFieldNameMap.put("币制", "currency");
labelToFieldNameMap.put("单位", "unit");
labelToFieldNameMap.put("", "liter");
labelToFieldNameMap.put("尺寸", "size");
labelToFieldNameMap.put("箱数", "caseCount");
labelToFieldNameMap.put("件数", "pieceCount");
labelToFieldNameMap.put("出库数量", "outboundQuantity");
labelToFieldNameMap.put("总净重", "totalNetWeight");
labelToFieldNameMap.put("总毛重", "totalGrossWeight");
labelToFieldNameMap.put("总体积", "totalVolume");
labelToFieldNameMap.put("总面积", "totalArea");
labelToFieldNameMap.put("总价", "totalAmount");
// 精确匹配
String fieldName = labelToFieldNameMap.get(batchLabel.trim());
if (StringUtils.isNotBlank(fieldName)) {
return fieldName;
}
// 模糊匹配(包含关系)
for (Map.Entry<String, String> entry : labelToFieldNameMap.entrySet()) {
if (batchLabel.contains(entry.getKey()) || entry.getKey().contains(batchLabel)) {
return entry.getValue();
}
}
// 如果找不到映射,尝试将批次标签转换为驼峰命名(简单处理)
return convertLabelToFieldName(batchLabel);
}
/**
* 将批次标签转换为字段名(驼峰命名)
* @param label 批次标签
* @return 字段名
*/
private String convertLabelToFieldName(String label) {
if (StringUtils.isBlank(label)) {
return null;
}
// 移除特殊字符,转换为小写,用空格或特殊字符分割
String cleaned = label.replaceAll("[^a-zA-Z0-9\\u4e00-\\u9fa5\\s]", " ")
.trim()
.toLowerCase();
// 如果是中文,无法自动转换,返回null
if (cleaned.matches(".*[\\u4e00-\\u9fa5].*")) {
return null;
}
// 将空格分割的单词转换为驼峰命名
String[] words = cleaned.split("\\s+");
if (words.length == 0) {
return null;
}
StringBuilder fieldName = new StringBuilder(words[0]);
for (int i = 1; i < words.length; i++) {
if (words[i].length() > 0) {
fieldName.append(words[i].substring(0, 1).toUpperCase())
.append(words[i].substring(1));
}
}
return fieldName.toString();
}
/**
* 根据字段名从对象中获取字段值(使用反射)
* @param obj 对象
* @param fieldName 字段名
* @return 字段值(转换为字符串)
*/
private String getFieldValueByFieldName(Object obj, String fieldName) {
if (obj == null || StringUtils.isBlank(fieldName)) {
return null;
}
try {
// 兼容:如果传的是下划线命名(数据库列名风格),先转成驼峰字段名再取
String normalizedFieldName = fieldName;
if (normalizedFieldName.contains("_")) {
normalizedFieldName = snakeToCamel(normalizedFieldName);
}
// 获取对象的Class
Class<?> clazz = obj.getClass();
// 尝试获取字段(包括父类字段)
Field field = null;
Class<?> currentClass = clazz;
while (currentClass != null && field == null) {
try {
field = currentClass.getDeclaredField(normalizedFieldName);
} catch (NoSuchFieldException e) {
currentClass = currentClass.getSuperclass();
}
}
if (field == null) {
log.warn("字段不存在:{}(normalized{}),对象类型:{}", fieldName, normalizedFieldName, clazz.getName());
return null;
}
// 设置可访问
field.setAccessible(true);
// 获取字段值
Object value = field.get(obj);
// 转换为字符串
if (value == null) {
log.info("字段 {} 的值为 null,对象类型:{}", normalizedFieldName, clazz.getName());
return null;
}
String result;
// 处理日期类型字段
if (value instanceof Date) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
result = sdf.format((Date) value);
} else {
result = value.toString();
}
log.info("通过反射获取字段值成功,字段名:{}(原始:{}),值:{},对象类型:{}",
normalizedFieldName, fieldName, result, clazz.getName());
return result;
} catch (Exception e) {
log.warn("通过反射获取字段值失败,字段名:{},对象类型:{},错误:{}", fieldName, obj.getClass().getName(), e.getMessage());
return null;
}
}
private String snakeToCamel(String snake) {
if (StringUtils.isBlank(snake)) {
return null;
}
String s = snake.trim().toLowerCase();
StringBuilder sb = new StringBuilder();
boolean upperNext = false;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '_') {
upperNext = true;
continue;
}
if (upperNext) {
sb.append(Character.toUpperCase(c));
upperNext = false;
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
@@ -1,12 +1,15 @@
package com.mhd.wms.domain.investigetionManageDetail.repository.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.mhd.common.core.annotation.Excel;
import com.mhd.common.core.web.domain.BaseVOEntity;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
@@ -204,5 +207,8 @@ public class InvestigetionManageDetailPO extends BaseVOEntity {
@Excel(name = "物料状态名称")
private String materialStatusName;
@ApiModelProperty("更多属性明细列表")
@TableField(exist = false)
private List<MaterialMoreDetailPO> materialMoreDetailList;
}
@@ -88,4 +88,11 @@ public interface MaterialInventoryMapper extends BaseMapper<MaterialInventory>
MaterialInventoryPO selectOneByWhere(MaterialInventoryDO materialInventoryDO);
List<MaterialInventoryPO> selectListByWhere(MaterialInventory materialInventory);
/**
* 根据库存ID查询库存信息(包含批次属性字段)
* @param materialInventoryId 库存ID
* @return 库存信息
*/
MaterialInventoryPO selectByIdWithBatchAttributes(@Param("materialInventoryId") Long materialInventoryId);
}
@@ -308,7 +308,7 @@ public class OutMaterialDetail extends BaseVOEntity {
*/
@ApiModelProperty("箱号/卡板号")
@Excel(name = "箱号/卡板号")
private String casePalletNo;
private String boxPalletNo;
/**
* 币制
@@ -1,8 +1,10 @@
package com.mhd.wms.domain.outMaterialDetail.repository.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.mhd.common.core.annotation.Excel;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import com.mhd.wms.domain.stockOutOrder.repository.todo.StockOutOrderBaseDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -315,7 +317,7 @@ public class OutMaterialDetailPO extends StockOutOrderBaseDO {
*/
@ApiModelProperty("箱号/卡板号")
@Excel(name = "箱号/卡板号")
private String casePalletNo;
private String boxPalletNo;
/**
* 币制
@@ -392,4 +394,8 @@ public class OutMaterialDetailPO extends StockOutOrderBaseDO {
@ApiModelProperty("单位")
@Excel(name = "单位")
private String unit;
@ApiModelProperty("更多属性明细列表")
@TableField(exist = false)
private List<MaterialMoreDetailPO> materialMoreDetailList;
}
@@ -323,7 +323,7 @@ public class OutMaterialDetailDO extends BaseVOEntity {
*/
@ApiModelProperty("箱号/卡板号")
@Excel(name = "箱号/卡板号")
private String casePalletNo;
private String boxPalletNo;
/**
* 币制
@@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.mhd.common.core.annotation.Excel;
import com.mhd.common.core.web.domain.BaseVOEntity;
import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO;
import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.po.OutMaterialDetailSerialNumberPO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -250,5 +251,8 @@ public class ShiftMaterialDetailPO extends BaseVOEntity {
@ApiModelProperty("序列号")
private List<OutMaterialDetailSerialNumberPO> materialDetailSerialNumberList;
@ApiModelProperty("更多属性明细列表")
@TableField(exist = false)
private List<MaterialMoreDetailPO> materialMoreDetailList;
}
@@ -196,10 +196,10 @@ public class ExcelParseService {
if (StringUtils.isEmpty(stockOutOrder.getCarrier())) errorMsg.append("承运商不能为空; ");
if (StringUtils.isEmpty(stockOutOrder.getTransportModeCode())) errorMsg.append("运输方式不能为空; ");
if (StringUtils.isEmpty(stockOutOrder.getSupervisionModeCode())) errorMsg.append("监督方式不能为空; ");
if (StringUtils.isEmpty(stockOutOrder.getContainerNo())) errorMsg.append("柜号不能为空; ");
// if (StringUtils.isEmpty(stockOutOrder.getContainerNo())) errorMsg.append("柜号不能为空; ");
if (StringUtils.isEmpty(stockOutOrder.getDepartureArrivalCountry())) errorMsg.append("出发/到达国家不能为空; ");
if (StringUtils.isEmpty(stockOutOrder.getManufacturer())) errorMsg.append("制造商不能为空; ");
if (ObjectUtil.isEmpty(stockOutOrder.getOutboundDate())) errorMsg.append("出仓日期不能为空; ");
// if (ObjectUtil.isEmpty(stockOutOrder.getOutboundDate())) errorMsg.append("出仓日期不能为空; ");
if (StringUtils.isEmpty(stockOutOrder.getContactPerson())) errorMsg.append("联系人不能为空; ");
if (StringUtils.isEmpty(stockOutOrder.getTel())) errorMsg.append("Tel不能为空; ");
if (StringUtils.isEmpty(stockOutOrder.getFax())) errorMsg.append("Fax不能为空; ");
@@ -71,7 +71,7 @@ public class ItemListener extends AnalysisEventListener<Map<Integer, Object>> {
item.setSheetRefNo(getStringValue(rowData[18]));
item.setCountryOfOrigin(getStringValue(rowData[19]));
item.setCasePalletNo(getStringValue(rowData[20]));
item.setBoxPalletNo(getStringValue(rowData[20]));
item.setTotalAmount(parseBigDecimal(rowData[21]));
item.setCurrency(getStringValue(rowData[22]));
item.setRemark(getStringValue(rowData[23]));
@@ -325,7 +325,7 @@ public class OutMaterialDetailDTO extends BaseVOEntity {
*/
@ApiModelProperty("箱号/卡板号")
@Excel(name = "箱号/卡板号")
private String casePalletNo;
private String boxPalletNo;
/**
* 币制
@@ -92,7 +92,8 @@ public class ShiftMaterialDetailApi extends BaseController {
throw new ServiceException("请输入移位单号");
}
startPage();
List<ShiftMaterialDetailPO> list = shiftMaterialDetailApplicationService.queryList(shiftMaterialDetailDO);
// 使用带批次属性的查询方法,批次属性值从库存表中获取
List<ShiftMaterialDetailPO> list = shiftMaterialDetailApplicationService.queryListWithBatchAttributes(shiftMaterialDetailDO);
return getDataTable(list);
}
@@ -63,7 +63,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="batchRefNo" column="BATCH_REF_NO" />
<result property="sheetRefNo" column="SHEET_REF_NO" />
<result property="countryOfOrigin" column="COUNTRY_OF_ORIGIN" />
<result property="casePalletNo" column="CASE_PALLET_NO" />
<result property="boxPalletNo" column="BOX_PALLET_NO" />
<result property="currency" column="CURRENCY" />
<result property="declareQuantity" column="DECLARE_QUANTITY" />
<result property="caseCount" column="CASE_COUNT" />
@@ -98,7 +98,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
a.BATCH_REF_NO,
a.SHEET_REF_NO,
a.COUNTRY_OF_ORIGIN,
a.CASE_PALLET_NO,
a.BOX_PALLET_NO,
a.CURRENCY,
a.DECLARE_QUANTITY,
a.CASE_COUNT,
@@ -44,6 +44,21 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateByName" column="update_by_name" />
<result property="delFlag" column="del_flag" />
<result property="isAble" column="is_able" />
<result property="unit" column="unit" />
<result property="netWeight" column="net_weight" />
<result property="grossWeight" column="gross_weight" />
<result property="volume" column="volume" />
<result property="area" column="area" />
<result property="extAttr1" column="ext_attr_1" />
<result property="extAttr2" column="ext_attr_2" />
<result property="extAttr3" column="ext_attr_3" />
<result property="extAttr4" column="ext_attr_4" />
<result property="productionDate" column="production_date" />
<result property="expiryDate" column="expiry_date" />
<result property="inventoryDate" column="inventory_date" />
<result property="batchRefNo" column="batch_ref_no" />
<result property="sheetRefNo" column="sheet_ref_no" />
<result property="boxPalletNo" column="box_pallet_no" />
</resultMap>
@@ -718,4 +733,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND a.BATCH_REF_NO = #{batchRefNo}
</if>
</select>
<!-- 根据库存ID查询库存信息(包含批次属性字段) -->
<select id="selectByIdWithBatchAttributes" parameterType="java.lang.Long" resultMap="MaterialInventoryResult">
SELECT
material_inventory_id, organization_id, organization_name, top_organization_id,
material_base_info_id, shipper_id, shipper_code, shipper_name, material_detail_id,
warehouse_id, warehouse_code, warehouse_name,
storage_section_id, storage_code, storage_name, storage_location_id, storage_location_code, storage_location_name,
batch_number, material_status_code, material_status_name,
container_id, container_code, container_type, container_type_name,
inventory_quantity, allocation_quantity, freeze_quantity, remark, is_able, unit,
net_weight, gross_weight, volume, area,
ext_attr_1, ext_attr_2, ext_attr_3, ext_attr_4,
production_date, expiry_date, inventory_date,
batch_ref_no, sheet_ref_no, box_pallet_no,
create_time, create_by, create_by_name, update_time, update_by, update_by_name, del_flag
FROM material_inventory
WHERE material_inventory_id = #{materialInventoryId} AND del_flag = 1
</select>
</mapper>