diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/statementStatistics/StatementStatisticsService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/statementStatistics/StatementStatisticsService.java index 9df75d74b..438aa2af5 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/statementStatistics/StatementStatisticsService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/statementStatistics/StatementStatisticsService.java @@ -1,11 +1,16 @@ package com.mhd.wms.application.service.statementStatistics; +import com.mhd.common.core.utils.StringUtils; import com.mhd.common.security.utils.SecurityUtils; +import com.mhd.system.api.domain.BatchDetailFeignPO; import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO; import com.mhd.system.api.domain.cache.SystemServiceCacheUtil; import com.mhd.system.api.model.LoginUser; import com.mhd.wms.domain.inventoryStandingDetail.service.InventoryStandingDetailDomainService; +import com.mhd.wms.domain.materialInventory.repository.mapper.MaterialInventoryMapper; +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.statementStatistics.po.ImmediateInventoryPO; import com.mhd.wms.domain.statementStatistics.po.WarehousingReportPO; import com.mhd.wms.domain.statementStatistics.todo.ImmediateInventoryDO; @@ -13,8 +18,11 @@ import com.mhd.wms.domain.statementStatistics.todo.WarehousingReportDO; 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.*; /** * 报表管理ApplicationService @@ -29,6 +37,8 @@ public class StatementStatisticsService { private MaterialInventoryDomainService materialInventoryDomainService; @Autowired private InventoryStandingDetailDomainService inventoryStandingDetailDomainService; + @Autowired + private MaterialInventoryMapper materialInventoryMapper; /** * 分页查询即时库存列表 @@ -67,7 +77,233 @@ public class StatementStatisticsService { } } } - return materialInventoryDomainService.queryImmediateInventoryList(immediateInventoryDO); + List immediateInventoryPOS = materialInventoryDomainService.queryImmediateInventoryList(immediateInventoryDO); + + + return immediateInventoryPOS; + } + + /** + * 为物料库存设置更多属性(从库存表中获取值) + * @param materialInventoryPOList 物料库存列表 + * @param batchDetailMap 批次属性Map + */ + private void setMaterialMoreDetailListFromInventory(List materialInventoryPOList, + Map> batchDetailMap) { + if (CollectionUtils.isEmpty(materialInventoryPOList)) { + return; + } + + materialInventoryPOList.forEach(materialInventoryPO -> { + Long materialBaseInfoId = materialInventoryPO.getMaterialBaseInfoId(); + Long materialInventoryId = materialInventoryPO.getMaterialInventoryId(); + + // 创建新的materialMoreDetailList,只包含isDisplay=1的属性 + List materialMoreDetailList = new ArrayList<>(); + + // 从库存表获取数据(包含批次属性字段) + MaterialInventoryPO inventoryPO = null; + if (materialInventoryId != null) { + inventoryPO = materialInventoryMapper.selectByIdWithBatchAttributes(materialInventoryId); + } + + if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) { + List batchDetailFeignPOList = batchDetailMap.get(materialBaseInfoId); + // 用于跟踪已添加到列表中的batchDetailId + Set 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 (inventoryPO != null) { + String fieldValue = null; + String usedFieldName = null; + // 优先使用fieldName(如果存在) + if (StringUtils.isNotBlank(batchDetailFeignPO.getFieldName())) { + usedFieldName = batchDetailFeignPO.getFieldName(); + fieldValue = getFieldValueByFieldName(inventoryPO, 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(inventoryPO, 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()); + } + } + } + } + materialInventoryPO.setMaterialMoreDetailList(materialMoreDetailList); + log.info("物料库存 materialInventoryId={}, materialBaseInfoId={}, materialMoreDetailList大小={}", + materialInventoryPO.getMaterialInventoryId(), materialInventoryPO.getMaterialBaseInfoId(), + materialMoreDetailList != null ? materialMoreDetailList.size() : 0); + }); + } + + /** + * 根据字段名从对象中获取字段值(使用反射) + * @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(); + } + + /** + * 根据批次标签(batchLabels)映射到字段名 + * @param batchLabel 批次标签 + * @return 字段名,如果找不到映射则返回null + */ + private String getFieldNameByBatchLabel(String batchLabel) { + if (StringUtils.isBlank(batchLabel)) { + return null; + } + + // 批次标签到字段名的映射关系 + Map 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 entry : labelToFieldNameMap.entrySet()) { + if (batchLabel.contains(entry.getKey()) || entry.getKey().contains(batchLabel)) { + return entry.getValue(); + } + } + + return null; } /** @@ -121,4 +357,4 @@ public class StatementStatisticsService { } -} +} \ No newline at end of file diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/statementStatistics/po/ImmediateInventoryPO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/statementStatistics/po/ImmediateInventoryPO.java index 724d4c5bc..205eb5638 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/statementStatistics/po/ImmediateInventoryPO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/statementStatistics/po/ImmediateInventoryPO.java @@ -1,14 +1,24 @@ package com.mhd.wms.domain.statementStatistics.po; +import com.fasterxml.jackson.annotation.JsonFormat; import com.mhd.common.core.annotation.Excel; +import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO; import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; +import java.util.Date; +import java.util.List; @Data public class ImmediateInventoryPO { + @ApiModelProperty("物料库存id") + private Long materialInventoryId; + + @ApiModelProperty("物料基础信息id") + private Long materialBaseInfoId; @ApiModelProperty("仓库名称") @Excel(name = "仓库名称") @@ -61,5 +71,49 @@ public class ImmediateInventoryPO { @Excel(name = "复核数量") private BigDecimal checkQuantity; + //批次属性字段 + @ApiModelProperty("Batch Ref NO's") + private String batchRefNo; + + @ApiModelProperty("Sheet Ref NO's") + private String sheetRefNo; + + @ApiModelProperty("箱号/卡板号") + private String boxPalletNo; + + @ApiModelProperty("扩展字段1") + private String extAttr1; + + @ApiModelProperty("扩展字段2") + private String extAttr2; + + @ApiModelProperty("生产日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date productionDate; + + @ApiModelProperty("过期日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date expiryDate; + + @ApiModelProperty("存货日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date inventoryDate; + + @ApiModelProperty("ExtAttr3") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date extAttr3; + + @ApiModelProperty("ExtAttr4") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date extAttr4; + + @ApiModelProperty("物料更多属性列表(批次属性)") + private List materialMoreDetailList; + } \ No newline at end of file diff --git a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml index 186d60013..4bd32dca3 100644 --- a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml +++ b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml @@ -347,6 +347,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + + + + + + + + +