批次规则bug修改
This commit is contained in:
+33
@@ -10,6 +10,8 @@ import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
|
||||
/**
|
||||
@@ -348,4 +350,35 @@ public class InMaterialDetailPO extends StockInOrderBasePO {
|
||||
@Excel(name = "总价")
|
||||
private BigDecimal totalPrice;
|
||||
|
||||
@ApiModelProperty("生产日期")
|
||||
@Excel(name = "生产日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date productionDate;
|
||||
|
||||
@ApiModelProperty("过期日期")
|
||||
@Excel(name = "过期日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date expiryDate;
|
||||
|
||||
@ApiModelProperty("存货日期")
|
||||
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date inventoryDate;
|
||||
|
||||
@ApiModelProperty("扩展属性1")
|
||||
@Excel(name = "扩展属性1")
|
||||
private String extAttr1;
|
||||
|
||||
@ApiModelProperty("扩展属性2")
|
||||
@Excel(name = "扩展属性2")
|
||||
private String extAttr2;
|
||||
|
||||
@ApiModelProperty("扩展属性3")
|
||||
@Excel(name = "扩展属性3")
|
||||
private String extAttr3;
|
||||
|
||||
@ApiModelProperty("扩展属性4")
|
||||
@Excel(name = "扩展属性4")
|
||||
private String extAttr4;
|
||||
|
||||
}
|
||||
|
||||
+68
@@ -214,5 +214,73 @@ public class ReceiptMaterialDetail extends BaseVOEntity {
|
||||
@Excel(name = "备注")
|
||||
private String remark;
|
||||
|
||||
@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("Invoice No.")
|
||||
@Excel(name = "Invoice No.")
|
||||
private String invoiceNo;
|
||||
|
||||
@ApiModelProperty("Batch Ref NO's")
|
||||
@Excel(name = "Batch Ref NO's")
|
||||
private String batchRefNo;
|
||||
|
||||
@ApiModelProperty("Sheet Ref NO's")
|
||||
@Excel(name = "Sheet Ref NO's")
|
||||
private String sheetRefNo;
|
||||
|
||||
@ApiModelProperty("箱号/卡板号")
|
||||
@Excel(name = "箱号/卡板号")
|
||||
private String boxPalletNo;
|
||||
|
||||
@ApiModelProperty("申报数量")
|
||||
@Excel(name = "申报数量")
|
||||
private BigDecimal declaredQuantity;
|
||||
|
||||
@ApiModelProperty("申报单位")
|
||||
@Excel(name = "申报单位")
|
||||
private String declarationUnit;
|
||||
|
||||
@ApiModelProperty("原产国")
|
||||
@Excel(name = "原产国")
|
||||
private String originCountry;
|
||||
|
||||
@ApiModelProperty("币制")
|
||||
@Excel(name = "币制")
|
||||
private String currency;
|
||||
|
||||
@ApiModelProperty("单位")
|
||||
@Excel(name = "单位")
|
||||
private String unit;
|
||||
|
||||
@ApiModelProperty("升")
|
||||
@Excel(name = "升")
|
||||
private BigDecimal liter;
|
||||
|
||||
@ApiModelProperty("尺寸")
|
||||
@Excel(name = "尺寸")
|
||||
private String dimensions;
|
||||
|
||||
@ApiModelProperty("箱数")
|
||||
@Excel(name = "箱数")
|
||||
private BigDecimal boxCount;
|
||||
|
||||
@ApiModelProperty("件数")
|
||||
@Excel(name = "件数")
|
||||
private BigDecimal pieceCount;
|
||||
|
||||
|
||||
}
|
||||
|
||||
+158
-31
@@ -13,6 +13,7 @@ import com.mhd.common.core.utils.uuid.IdGenerator;
|
||||
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.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
|
||||
@@ -43,11 +44,15 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import com.mhd.common.core.utils.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -56,6 +61,7 @@ import java.util.stream.Collectors;
|
||||
* @author gen
|
||||
* @date 2024-06-17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetailMapper, ReceiptMaterialDetail> implements IReceiptMaterialDetailService{
|
||||
@Autowired
|
||||
@@ -291,7 +297,7 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
|
||||
if (!CollectionUtils.isEmpty(materialDetailSerialNumberList)){
|
||||
inMaterialDetailSerialNumberService.saveBatch(materialDetailSerialNumberList);
|
||||
}
|
||||
//从materialMoreDetailList中根据attributeOption提取字段值并更新入库单明细
|
||||
//从materialMoreDetailList中提取字段值并更新入库单明细(优先使用batchDetailId->fieldName映射,兼容attributeOption)
|
||||
updateInMaterialDetailFromAttributeOption(receiptMaterialDetailDOList);
|
||||
}
|
||||
|
||||
@@ -306,64 +312,185 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
|
||||
if (CollectionUtils.isEmpty(receiptMaterialDetailDOList)) {
|
||||
return;
|
||||
}
|
||||
// 缓存:materialBaseInfoId -> (batchDetailId -> fieldName)
|
||||
Map<Long, Map<Long, String>> batchFieldNameCache = new HashMap<>();
|
||||
updateInMaterialDetailFromAttributeOption(receiptMaterialDetailDOList, batchFieldNameCache);
|
||||
}
|
||||
|
||||
private void updateInMaterialDetailFromAttributeOption(List<ReceiptMaterialDetailDO> receiptMaterialDetailDOList,
|
||||
Map<Long, Map<Long, String>> batchFieldNameCache) {
|
||||
if (CollectionUtils.isEmpty(receiptMaterialDetailDOList)) {
|
||||
return;
|
||||
}
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
for (ReceiptMaterialDetailDO receiptMaterialDetailDO : receiptMaterialDetailDOList) {
|
||||
Long inUniqueId = receiptMaterialDetailDO.getInUniqueId();
|
||||
if (inUniqueId == null) {
|
||||
// 处理子项
|
||||
List<ReceiptMaterialDetailDO> children = receiptMaterialDetailDO.getChildren();
|
||||
if (!CollectionUtils.isEmpty(children)) {
|
||||
updateInMaterialDetailFromAttributeOption(children, batchFieldNameCache);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
List<MaterialMoreDetailDO> materialMoreDetailList = receiptMaterialDetailDO.getMaterialMoreDetailList();
|
||||
if (CollectionUtils.isEmpty(materialMoreDetailList)) {
|
||||
// 处理子项
|
||||
List<ReceiptMaterialDetailDO> children = receiptMaterialDetailDO.getChildren();
|
||||
if (!CollectionUtils.isEmpty(children)) {
|
||||
updateInMaterialDetailFromAttributeOption(children, batchFieldNameCache);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 构建UpdateWrapper
|
||||
|
||||
// 构建UpdateWrapper(用列名动态set)
|
||||
UpdateWrapper<InMaterialDetail> updateWrapper = new UpdateWrapper<>();
|
||||
updateWrapper.lambda().eq(InMaterialDetail::getUniqueId, inUniqueId);
|
||||
updateWrapper.eq("unique_id", inUniqueId);
|
||||
boolean hasUpdate = false;
|
||||
|
||||
// 遍历materialMoreDetailList,根据attributeOption映射到对应字段
|
||||
|
||||
// 构建 batchDetailId -> fieldName 映射(按物料维度缓存)
|
||||
Map<Long, String> batchDetailIdToFieldName = null;
|
||||
Long materialBaseInfoId = receiptMaterialDetailDO.getMaterialBaseInfoId();
|
||||
if (materialBaseInfoId != null) {
|
||||
batchDetailIdToFieldName = batchFieldNameCache.get(materialBaseInfoId);
|
||||
if (batchDetailIdToFieldName == null) {
|
||||
batchDetailIdToFieldName = loadBatchDetailIdToFieldName(materialBaseInfoId);
|
||||
batchFieldNameCache.put(materialBaseInfoId, batchDetailIdToFieldName);
|
||||
}
|
||||
}
|
||||
|
||||
for (MaterialMoreDetailDO materialMoreDetail : materialMoreDetailList) {
|
||||
String attributeOption = materialMoreDetail.getAttributeOption();
|
||||
String attributeValue = materialMoreDetail.getAttributeValue();
|
||||
|
||||
// 如果attributeValue为空,跳过
|
||||
if (attributeValue == null || attributeValue.trim().isEmpty()) {
|
||||
if (StringUtils.isBlank(attributeValue)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 根据attributeOption映射到入库单明细表的字段
|
||||
if ("InvoiceNo".equalsIgnoreCase(attributeOption)) {
|
||||
updateWrapper.lambda().set(InMaterialDetail::getInvoiceNo, attributeValue);
|
||||
hasUpdate = true;
|
||||
} else if ("BatchRefNo".equalsIgnoreCase(attributeOption)) {
|
||||
updateWrapper.lambda().set(InMaterialDetail::getBatchRefNo, attributeValue);
|
||||
hasUpdate = true;
|
||||
} else if ("SheetRefNo".equalsIgnoreCase(attributeOption)) {
|
||||
updateWrapper.lambda().set(InMaterialDetail::getSheetRefNo, attributeValue);
|
||||
hasUpdate = true;
|
||||
} else if ("BoxPalletNo".equalsIgnoreCase(attributeOption)) {
|
||||
updateWrapper.lambda().set(InMaterialDetail::getBoxPalletNo, attributeValue);
|
||||
hasUpdate = true;
|
||||
|
||||
String fieldName = null;
|
||||
Long batchDetailId = materialMoreDetail.getBatchDetailId();
|
||||
if (batchDetailId != null && batchDetailIdToFieldName != null) {
|
||||
fieldName = batchDetailIdToFieldName.get(batchDetailId);
|
||||
}
|
||||
|
||||
// 兼容旧逻辑:fieldName取不到时用attributeOption(例如 InvoiceNo -> invoiceNo)
|
||||
if (StringUtils.isBlank(fieldName)) {
|
||||
String attributeOption = materialMoreDetail.getAttributeOption();
|
||||
fieldName = lowerFirst(attributeOption);
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(fieldName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// camelCase -> snake_case 列名
|
||||
String columnName = camelToSnake(fieldName);
|
||||
if (StringUtils.isBlank(columnName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 数字字段尝试转BigDecimal,其它按String
|
||||
Object val = coerceInMaterialDetailValue(fieldName, attributeValue);
|
||||
updateWrapper.set(columnName, val);
|
||||
hasUpdate = true;
|
||||
}
|
||||
|
||||
// 如果有字段需要更新,则执行更新
|
||||
|
||||
if (hasUpdate) {
|
||||
updateWrapper.lambda()
|
||||
.set(InMaterialDetail::getUpdateBy, loginUser.getUserid())
|
||||
.set(InMaterialDetail::getUpdateByName, loginUser.getUsername())
|
||||
.set(InMaterialDetail::getUpdateTime, new Date());
|
||||
updateWrapper
|
||||
.set("update_by", loginUser.getUserid())
|
||||
.set("update_by_name", loginUser.getUsername())
|
||||
.set("update_time", new Date());
|
||||
iInMaterialDetailService.update(updateWrapper);
|
||||
}
|
||||
|
||||
|
||||
// 处理子项
|
||||
List<ReceiptMaterialDetailDO> children = receiptMaterialDetailDO.getChildren();
|
||||
if (!CollectionUtils.isEmpty(children)) {
|
||||
updateInMaterialDetailFromAttributeOption(children);
|
||||
updateInMaterialDetailFromAttributeOption(children, batchFieldNameCache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Long, String> loadBatchDetailIdToFieldName(Long materialBaseInfoId) {
|
||||
Map<Long, String> result = new HashMap<>();
|
||||
try {
|
||||
AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId);
|
||||
if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) {
|
||||
return result;
|
||||
}
|
||||
List<BatchDetailFeignPO> list = JSON.parseArray(JSON.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
return result;
|
||||
}
|
||||
for (BatchDetailFeignPO po : list) {
|
||||
if (po.getBatchDetailId() == null) {
|
||||
continue;
|
||||
}
|
||||
String fieldName = po.getFieldName();
|
||||
if (StringUtils.isBlank(fieldName)) {
|
||||
// 兼容:fieldName为空时尝试用attributeOption
|
||||
fieldName = lowerFirst(po.getAttributeOption());
|
||||
}
|
||||
if (StringUtils.isNotBlank(fieldName)) {
|
||||
result.put(po.getBatchDetailId(), fieldName);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("加载批次属性fieldName失败,materialBaseInfoId:{},错误:{}", materialBaseInfoId, e.getMessage());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String lowerFirst(String s) {
|
||||
if (StringUtils.isBlank(s)) {
|
||||
return null;
|
||||
}
|
||||
if (s.length() == 1) {
|
||||
return s.toLowerCase();
|
||||
}
|
||||
return s.substring(0, 1).toLowerCase() + s.substring(1);
|
||||
}
|
||||
|
||||
private String camelToSnake(String camel) {
|
||||
if (StringUtils.isBlank(camel)) {
|
||||
return null;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < camel.length(); i++) {
|
||||
char c = camel.charAt(i);
|
||||
if (Character.isUpperCase(c)) {
|
||||
if (i > 0) {
|
||||
sb.append('_');
|
||||
}
|
||||
sb.append(Character.toLowerCase(c));
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private Object coerceInMaterialDetailValue(String fieldName, String raw) {
|
||||
if (raw == null) {
|
||||
return null;
|
||||
}
|
||||
// 这些字段在库里通常是NUMBER
|
||||
if ("liter".equals(fieldName)
|
||||
|| "declaredQuantity".equals(fieldName)
|
||||
|| "boxCount".equals(fieldName)
|
||||
|| "pieceCount".equals(fieldName)
|
||||
|| "totalNetWeight".equals(fieldName)
|
||||
|| "totalGrossWeight".equals(fieldName)
|
||||
|| "totalVolume".equals(fieldName)
|
||||
|| "totalArea".equals(fieldName)) {
|
||||
try {
|
||||
return new BigDecimal(raw.trim());
|
||||
} catch (Exception ignored) {
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 从入库单明细表中获取InvoiceNo、BatchRefNo、SheetRefNo、BoxPalletNo字段的值并填充到materialMoreDetailList的attributeValue中
|
||||
* @author Auto
|
||||
|
||||
+33
@@ -12,6 +12,8 @@ import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
|
||||
/**
|
||||
@@ -252,6 +254,37 @@ public class ReceiptMaterialDetailPO extends BaseVOEntity {
|
||||
@Excel(name = "箱号/卡板号")
|
||||
private String boxPalletNo;
|
||||
|
||||
@ApiModelProperty("生产日期")
|
||||
@Excel(name = "生产日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date productionDate;
|
||||
|
||||
@ApiModelProperty("过期日期")
|
||||
@Excel(name = "过期日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date expiryDate;
|
||||
|
||||
@ApiModelProperty("存货日期")
|
||||
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date inventoryDate;
|
||||
|
||||
@ApiModelProperty("扩展属性1")
|
||||
@Excel(name = "扩展属性1")
|
||||
private String extAttr1;
|
||||
|
||||
@ApiModelProperty("扩展属性2")
|
||||
@Excel(name = "扩展属性2")
|
||||
private String extAttr2;
|
||||
|
||||
@ApiModelProperty("扩展属性3")
|
||||
@Excel(name = "扩展属性3")
|
||||
private String extAttr3;
|
||||
|
||||
@ApiModelProperty("扩展属性4")
|
||||
@Excel(name = "扩展属性4")
|
||||
private String extAttr4;
|
||||
|
||||
@ApiModelProperty("物料明细子集")
|
||||
private List<ReceiptMaterialDetailPO> children;
|
||||
|
||||
|
||||
+65
@@ -11,6 +11,8 @@ import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
|
||||
/**
|
||||
@@ -218,6 +220,69 @@ public class ReceiptMaterialDetailDO 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("Invoice No.")
|
||||
@Excel(name = "Invoice No.")
|
||||
private String invoiceNo;
|
||||
|
||||
@ApiModelProperty("Batch Ref NO's")
|
||||
@Excel(name = "Batch Ref NO's")
|
||||
private String batchRefNo;
|
||||
|
||||
@ApiModelProperty("Sheet Ref NO's")
|
||||
@Excel(name = "Sheet Ref NO's")
|
||||
private String sheetRefNo;
|
||||
|
||||
@ApiModelProperty("箱号/卡板号")
|
||||
@Excel(name = "箱号/卡板号")
|
||||
private String boxPalletNo;
|
||||
|
||||
@ApiModelProperty("生产日期")
|
||||
@Excel(name = "生产日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date productionDate;
|
||||
|
||||
@ApiModelProperty("过期日期")
|
||||
@Excel(name = "过期日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date expiryDate;
|
||||
|
||||
@ApiModelProperty("存货日期")
|
||||
@Excel(name = "存货日期", width = 30, dateFormat = "yyyy-MM-dd")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date inventoryDate;
|
||||
|
||||
@ApiModelProperty("扩展属性1")
|
||||
@Excel(name = "扩展属性1")
|
||||
private String extAttr1;
|
||||
|
||||
@ApiModelProperty("扩展属性2")
|
||||
@Excel(name = "扩展属性2")
|
||||
private String extAttr2;
|
||||
|
||||
@ApiModelProperty("扩展属性3")
|
||||
@Excel(name = "扩展属性3")
|
||||
private String extAttr3;
|
||||
|
||||
@ApiModelProperty("扩展属性4")
|
||||
@Excel(name = "扩展属性4")
|
||||
private String extAttr4;
|
||||
|
||||
@ApiModelProperty(name = "组织ID集合")
|
||||
private List<Long> organizationIdList;
|
||||
|
||||
|
||||
+198
@@ -40,6 +40,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -297,6 +298,11 @@ public class StockInOrderDomainService {
|
||||
ReceiptMaterialDetailDO receiptMaterialDetailDO = new ReceiptMaterialDetailDO();
|
||||
BeanUtils.copyProperties(inMaterialDetailPO, receiptMaterialDetailDO);
|
||||
receiptMaterialDetailDO.setInUniqueId(inMaterialDetailPO.getUniqueId());
|
||||
|
||||
// 复制特定字段:生产日期、过期日期、存货日期、批次参考号、单据参考号、箱号/卡板号、扩展属性1-4
|
||||
// 这些字段可能使用驼峰命名或下划线命名,使用反射获取和设置
|
||||
copySpecialFields(inMaterialDetailPO, receiptMaterialDetailDO);
|
||||
|
||||
receiptMaterialDetailDOList.add(receiptMaterialDetailDO);
|
||||
});
|
||||
stockReceiptOrderDO.setMaterialDetailList(receiptMaterialDetailDOList);
|
||||
@@ -452,4 +458,196 @@ public class StockInOrderDomainService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 复制特定字段从入库单明细到收货明细
|
||||
* 包括:生产日期、过期日期、存货日期、批次参考号、单据参考号、箱号/卡板号、扩展属性1-4
|
||||
* @author gen
|
||||
* @date 2026/1/29
|
||||
* @param source 源对象(InMaterialDetailPO)
|
||||
* @param target 目标对象(ReceiptMaterialDetailDO)
|
||||
*/
|
||||
private void copySpecialFields(InMaterialDetailPO source, ReceiptMaterialDetailDO target) {
|
||||
if (source == null || target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 字段映射:源字段名 -> 目标字段名(支持驼峰和下划线两种命名方式)
|
||||
Map<String, String> fieldMappings = new HashMap<>();
|
||||
fieldMappings.put("productionDate", "productionDate");
|
||||
fieldMappings.put("production_date", "productionDate");
|
||||
fieldMappings.put("expiryDate", "expiryDate");
|
||||
fieldMappings.put("expiry_date", "expiryDate");
|
||||
fieldMappings.put("inventoryDate", "inventoryDate");
|
||||
fieldMappings.put("inventory_date", "inventoryDate");
|
||||
fieldMappings.put("batchRefNo", "batchRefNo");
|
||||
fieldMappings.put("batch_ref_no", "batchRefNo");
|
||||
fieldMappings.put("sheetRefNo", "sheetRefNo");
|
||||
fieldMappings.put("sheet_ref_no", "sheetRefNo");
|
||||
fieldMappings.put("boxPalletNo", "boxPalletNo");
|
||||
fieldMappings.put("box_pallet_no", "boxPalletNo");
|
||||
fieldMappings.put("extAttr1", "extAttr1");
|
||||
fieldMappings.put("ext_attr_1", "extAttr1");
|
||||
fieldMappings.put("extAttr2", "extAttr2");
|
||||
fieldMappings.put("ext_attr_2", "extAttr2");
|
||||
fieldMappings.put("extAttr3", "extAttr3");
|
||||
fieldMappings.put("ext_attr_3", "extAttr3");
|
||||
fieldMappings.put("extAttr4", "extAttr4");
|
||||
fieldMappings.put("ext_attr_4", "extAttr4");
|
||||
|
||||
// 使用反射复制字段值
|
||||
for (Map.Entry<String, String> entry : fieldMappings.entrySet()) {
|
||||
String sourceFieldName = entry.getKey();
|
||||
String targetFieldName = entry.getValue();
|
||||
|
||||
// 尝试从源对象获取字段值(支持驼峰和下划线命名)
|
||||
Object value = getFieldValue(source, sourceFieldName);
|
||||
if (value != null) {
|
||||
// 设置到目标对象(使用驼峰命名)
|
||||
setFieldValue(target, targetFieldName, value);
|
||||
log.info("复制字段成功:{} -> {},值:{}", sourceFieldName, targetFieldName, value);
|
||||
} else {
|
||||
log.debug("源对象字段 {} 的值为 null,跳过复制", sourceFieldName);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("复制特定字段时发生异常,源对象:{},目标对象:{},错误:{}",
|
||||
source.getClass().getSimpleName(), target.getClass().getSimpleName(), e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 使用反射获取字段值(支持驼峰和下划线命名)
|
||||
*/
|
||||
private Object getFieldValue(Object obj, String fieldName) {
|
||||
if (obj == null || StringUtils.isBlank(fieldName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> clazz = obj.getClass();
|
||||
Field field = null;
|
||||
|
||||
// 先尝试直接获取字段(驼峰命名)
|
||||
try {
|
||||
field = clazz.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// 如果失败,尝试转换为驼峰命名(如果是下划线命名)
|
||||
if (fieldName.contains("_")) {
|
||||
String camelCaseName = snakeToCamel(fieldName);
|
||||
try {
|
||||
field = clazz.getDeclaredField(camelCaseName);
|
||||
} catch (NoSuchFieldException ex) {
|
||||
// 继续查找父类
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果当前类找不到,查找父类
|
||||
if (field == null) {
|
||||
Class<?> currentClass = clazz.getSuperclass();
|
||||
while (currentClass != null && field == null) {
|
||||
try {
|
||||
field = currentClass.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
if (fieldName.contains("_")) {
|
||||
String camelCaseName = snakeToCamel(fieldName);
|
||||
try {
|
||||
field = currentClass.getDeclaredField(camelCaseName);
|
||||
} catch (NoSuchFieldException ex) {
|
||||
// 继续查找父类
|
||||
}
|
||||
}
|
||||
}
|
||||
currentClass = currentClass.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
if (field != null) {
|
||||
field.setAccessible(true);
|
||||
return field.get(obj);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("获取字段值失败,对象:{},字段名:{},错误:{}",
|
||||
obj.getClass().getSimpleName(), fieldName, e.getMessage());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 使用反射设置字段值
|
||||
*/
|
||||
private void setFieldValue(Object obj, String fieldName, Object value) {
|
||||
if (obj == null || StringUtils.isBlank(fieldName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Class<?> clazz = obj.getClass();
|
||||
Field field = null;
|
||||
|
||||
// 先尝试直接获取字段(驼峰命名)
|
||||
try {
|
||||
field = clazz.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException e) {
|
||||
// 如果失败,查找父类
|
||||
Class<?> currentClass = clazz.getSuperclass();
|
||||
while (currentClass != null && field == null) {
|
||||
try {
|
||||
field = currentClass.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException ex) {
|
||||
// 继续查找父类
|
||||
}
|
||||
currentClass = currentClass.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
if (field != null) {
|
||||
field.setAccessible(true);
|
||||
// 类型转换:如果值类型不匹配,尝试转换
|
||||
Class<?> fieldType = field.getType();
|
||||
if (value != null && !fieldType.isAssignableFrom(value.getClass())) {
|
||||
// 尝试类型转换
|
||||
if (fieldType == Date.class && value instanceof String) {
|
||||
// 字符串转日期(简单处理,实际可能需要更复杂的解析)
|
||||
value = null; // 暂时不转换,避免解析错误
|
||||
} else if (fieldType == String.class) {
|
||||
value = String.valueOf(value);
|
||||
}
|
||||
}
|
||||
if (value != null && fieldType.isAssignableFrom(value.getClass())) {
|
||||
field.set(obj, value);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("设置字段值失败,对象:{},字段名:{},值:{},错误:{}",
|
||||
obj.getClass().getSimpleName(), fieldName, value, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 下划线命名转驼峰命名
|
||||
*/
|
||||
private String snakeToCamel(String snakeCase) {
|
||||
if (StringUtils.isBlank(snakeCase)) {
|
||||
return snakeCase;
|
||||
}
|
||||
|
||||
String[] parts = snakeCase.split("_");
|
||||
if (parts.length == 0) {
|
||||
return snakeCase;
|
||||
}
|
||||
|
||||
StringBuilder camelCase = new StringBuilder(parts[0].toLowerCase());
|
||||
for (int i = 1; i < parts.length; i++) {
|
||||
if (parts[i].length() > 0) {
|
||||
camelCase.append(parts[i].substring(0, 1).toUpperCase())
|
||||
.append(parts[i].substring(1).toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
return camelCase.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user