From 6db8a47b4cbf2d988dbbfd0b3245f37e3598d23f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=A6=E9=B8=BF=E5=B1=95?= <18031053041@163.com> Date: Fri, 13 Mar 2026 19:46:06 +0800 Subject: [PATCH] =?UTF-8?q?PDA=E5=AE=B9=E5=99=A8=E7=A7=BB=E4=BD=8D?= =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MaterialInventoryApplicationService.java | 257 +++++++++++++++++- .../ShiftManageApplicationService.java | 109 +++++++- .../po/MaterialInventoryQueryListPO.java | 46 ++++ .../todo/MaterialInventoryQueryListDO.java | 3 + .../service/ShiftManageDomainService.java | 41 ++- .../persistence/ShiftMaterialDetailImpl.java | 128 +++++++-- .../po/ShiftMoveMaterialQuantityPO.java | 11 + .../MaterialInventoryQueryListDTO.java | 4 + .../shiftManage/ShiftManageAppApi.java | 8 +- .../MaterialInventoryMapper.xml | 52 +++- 10 files changed, 604 insertions(+), 55 deletions(-) diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java index 1051f5495..bc08e5096 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/materialInventory/MaterialInventoryApplicationService.java @@ -3,6 +3,7 @@ package com.mhd.wms.application.service.materialInventory; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson2.JSONObject; import com.alibaba.nacos.common.utils.CollectionUtils; +import com.mhd.common.core.utils.bean.BeanUtils; import com.mhd.common.core.utils.StringUtils; import com.mhd.common.core.web.domain.AjaxResult; import com.mhd.common.security.utils.SecurityUtils; @@ -458,6 +459,260 @@ public class MaterialInventoryApplicationService { materialInventoryQueryListDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId()); } } - return materialInventoryDomainService.materialQueryList(materialInventoryQueryListDO); + List list = materialInventoryDomainService.materialQueryList(materialInventoryQueryListDO); + // 批次属性填充,与按单移位一致 + fillMaterialMoreDetailForInventoryQueryList(list); + // 主项子项结构,与移位详情 getInfoByApp 一致,每条主项下含一条 parent_copy 子项 + buildParentChildForInventoryQueryList(list); + return list; + } + + /** + * 将库存查询列表转为主项子项结构,与移位详情一致,供 PDA 表单复用 + */ + private void buildParentChildForInventoryQueryList(List list) { + if (CollectionUtils.isEmpty(list)) return; + for (MaterialInventoryQueryListPO parent : list) { + Long uid = parent.getMaterialInventoryId(); + parent.setLevel(1); + parent.setUniqueId(uid); + parent.setParentUniqueId(null); + MaterialInventoryQueryListPO child = new MaterialInventoryQueryListPO(); + BeanUtils.copyProperties(parent, child, "children"); + child.setLevel(2); + child.setUniqueId(uid); + child.setParentUniqueId(uid); + child.setChildren(null); + BigDecimal qty = parent.getShiftQuantity() != null ? parent.getShiftQuantity() : parent.getAllocationQuantity(); + if (qty == null) qty = BigDecimal.ONE; + if (parent.getNetWeight() != null) child.setTotalNetWeight(parent.getNetWeight().multiply(qty)); + if (parent.getGrossWeight() != null) child.setTotalGrossWeight(parent.getGrossWeight().multiply(qty)); + if (parent.getVolume() != null) child.setTotalVolume(parent.getVolume().multiply(qty)); + if (parent.getArea() != null) child.setTotalArea(parent.getArea().multiply(qty)); + parent.setTotalNetWeight(child.getTotalNetWeight()); + parent.setTotalGrossWeight(child.getTotalGrossWeight()); + parent.setTotalVolume(child.getTotalVolume()); + parent.setTotalArea(child.getTotalArea()); + List children = new ArrayList<>(); + children.add(child); + parent.setChildren(children); + } + } + + /** + * 根据 materialInventoryId 获取单条库存(含批次属性、shiftQuantity),供移位表单预填,内部使用 + */ + public MaterialInventoryQueryListPO getInventoryForShiftForm(Long materialInventoryId) { + if (materialInventoryId == null) return null; + MaterialInventoryQueryListDO do_ = new MaterialInventoryQueryListDO(); + do_.setMaterialInventoryId(materialInventoryId); + do_.setQueryType(0); + List list = materialQueryList(do_); + return CollectionUtils.isEmpty(list) ? null : list.get(0); + } + + /** + * 库存查询列表批次属性填充,与按单移位 fillMaterialMoreDetailForShiftDetail 一致 + */ + private void fillMaterialMoreDetailForInventoryQueryList(List list) { + if (CollectionUtils.isEmpty(list)) { + return; + } + Set materialBaseInfoIdSet = list.stream() + .map(MaterialInventoryQueryListPO::getMaterialBaseInfoId) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + Map> batchDetailMap = new HashMap<>(); + for (Long materialBaseInfoId : materialBaseInfoIdSet) { + try { + AjaxResult ajaxResult = systemServiceFeign.getBatchDetailListByMaterialBaseInfoId(materialBaseInfoId); + if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code")))) { + List batchList = JSON.parseArray( + JSONObject.toJSONString(ajaxResult.get("data")), BatchDetailFeignPO.class); + if (!CollectionUtils.isEmpty(batchList)) { + batchDetailMap.put(materialBaseInfoId, batchList); + } + } + } catch (Exception e) { + log.warn("获取物料批次属性失败,materialBaseInfoId={}, error={}", materialBaseInfoId, e.getMessage()); + } + } + list.forEach(po -> { + fillMaterialMoreDetailForInventoryQueryPO(po, batchDetailMap); + // 移位数量供 PDA 底部表单区显示,库存查询时等于可用数量 + po.setShiftQuantity(po.getAllocationQuantity()); + }); + } + + private void fillMaterialMoreDetailForInventoryQueryPO(MaterialInventoryQueryListPO po, + Map> batchDetailMap) { + if (po == null || po.getMaterialBaseInfoId() == null) { + po.setMaterialMoreDetailList(new ArrayList<>()); + return; + } + List materialMoreDetailList = new ArrayList<>(); + List batchList = batchDetailMap.get(po.getMaterialBaseInfoId()); + if (!CollectionUtils.isEmpty(batchList)) { + materialMoreDetailList = filterAndConvertToMaterialMoreDetail(batchList); + } + // 与按单移位一致:净重、毛重、体积、面积、移位数量不放在上面 materialMoreDetailList,由 PO 顶层字段在底部表单区(移入数量、移入库位、容器旁)显示 + materialMoreDetailList = excludeWeightVolumeAreaShiftFromList(materialMoreDetailList); + fillAttributeValueFromInventoryQueryPO(po, materialMoreDetailList); + List filtered = materialMoreDetailList.stream() + .filter(m -> m.getAttributeValue() != null && !m.getAttributeValue().trim().isEmpty()) + .collect(Collectors.toList()); + po.setMaterialMoreDetailList(filtered); + } + + /** 净重、毛重、体积、面积、移位数量在底部表单区显示,从上面 materialMoreDetailList 中排除,与按单移位一致 */ + private static final String[] WEIGHT_VOLUME_AREA_SHIFT_LABELS = { + "净重(KG)", "净重", "总净重", + "毛重(KG)", "毛重", "总毛重", + "体积(CBM)", "体积", "总体积", + "面积(SQM)", "面积", "总面积", + "移位数量", "可移位数量" + }; + + private List excludeWeightVolumeAreaShiftFromList(List list) { + if (CollectionUtils.isEmpty(list)) { + return list; + } + return list.stream() + .filter(m -> { + String label = m.getBatchLabels(); + if (label == null) return true; + for (String exclude : WEIGHT_VOLUME_AREA_SHIFT_LABELS) { + if (exclude.equals(label.trim())) return false; + } + return true; + }) + .collect(Collectors.toList()); + } + + private List filterAndConvertToMaterialMoreDetail(List batchList) { + List result = new ArrayList<>(); + if (CollectionUtils.isEmpty(batchList)) { + return result; + } + for (BatchDetailFeignPO po : batchList) { + if (po.getIsDisplay() == null || po.getIsDisplay() != 1) { + continue; + } + MaterialMoreDetailPO mpo = new MaterialMoreDetailPO(); + mpo.setBatchId(po.getBatchId()); + mpo.setBatchDetailId(po.getBatchDetailId()); + mpo.setBatchLabels(po.getBatchLabels()); + mpo.setInputControl(po.getInputControl()); + mpo.setAttributeFormat(po.getAttributeFormat()); + mpo.setAttributeOption(po.getAttributeOption()); + result.add(mpo); + } + return result; + } + + private void fillAttributeValueFromInventoryQueryPO(MaterialInventoryQueryListPO po, + List materialMoreDetailList) { + if (CollectionUtils.isEmpty(materialMoreDetailList)) { + return; + } + for (MaterialMoreDetailPO materialMoreDetail : materialMoreDetailList) { + if (materialMoreDetail.getAttributeValue() != null && !materialMoreDetail.getAttributeValue().trim().isEmpty()) { + continue; + } + String batchLabels = materialMoreDetail.getBatchLabels(); + String attributeOption = materialMoreDetail.getAttributeOption(); + String refVal = null; + if (StringUtils.isNotBlank(batchLabels)) { + switch (batchLabels.trim()) { + case "Invoice No.": + case "Invoice No": + case "发票号": + refVal = po.getExtAttr1(); + break; + case "Batch Ref NO's": + case "Batch Ref NO": + case "批次参考号": + refVal = po.getBatchRefNo(); + break; + case "Sheet Ref NO's": + case "Sheet Ref NO": + case "单据参考号": + refVal = po.getSheetRefNo(); + break; + case "箱号/卡板号": + case "箱号": + case "卡板号": + refVal = po.getBoxPalletNo(); + break; + case "扩展字段1": + case "扩展属性1": + refVal = po.getExtAttr1(); + break; + case "扩展字段2": + case "扩展属性2": + refVal = po.getExtAttr2(); + break; + case "扩展字段3": + case "扩展属性3": + refVal = po.getExtAttr3() != null ? new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(po.getExtAttr3()) : null; + break; + case "扩展字段4": + case "扩展属性4": + refVal = po.getExtAttr4() != null ? new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(po.getExtAttr4()) : null; + break; + case "生产日期": + refVal = po.getProductionDate() != null ? new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(po.getProductionDate()) : null; + break; + case "过期日期": + refVal = po.getExpiryDate() != null ? new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(po.getExpiryDate()) : null; + break; + case "存货日期": + refVal = po.getInventoryDate() != null ? new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(po.getInventoryDate()) : null; + break; + case "批次号": + refVal = po.getBatchNumber(); + break; + case "总净重": + case "净重(KG)": + case "净重": + refVal = po.getNetWeight() != null ? po.getNetWeight().toString() : null; + break; + case "总毛重": + case "毛重(KG)": + case "毛重": + refVal = po.getGrossWeight() != null ? po.getGrossWeight().toString() : null; + break; + case "总体积": + case "体积(CBM)": + case "体积": + refVal = po.getVolume() != null ? po.getVolume().toString() : null; + break; + case "总面积": + case "面积(SQM)": + case "面积": + refVal = po.getArea() != null ? po.getArea().toString() : null; + break; + default: + if ("InvoiceNo".equalsIgnoreCase(attributeOption)) refVal = po.getExtAttr1(); + else if ("BatchRefNo".equalsIgnoreCase(attributeOption)) refVal = po.getBatchRefNo(); + else if ("SheetRefNo".equalsIgnoreCase(attributeOption)) refVal = po.getSheetRefNo(); + else if ("BoxPalletNo".equalsIgnoreCase(attributeOption)) refVal = po.getBoxPalletNo(); + else if ("ProductionDate".equalsIgnoreCase(attributeOption) && po.getProductionDate() != null) + refVal = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(po.getProductionDate()); + else if ("ExpiryDate".equalsIgnoreCase(attributeOption) && po.getExpiryDate() != null) + refVal = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(po.getExpiryDate()); + else if ("InventoryDate".equalsIgnoreCase(attributeOption) && po.getInventoryDate() != null) + refVal = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(po.getInventoryDate()); + else if ("NetWeight".equalsIgnoreCase(attributeOption) && po.getNetWeight() != null) refVal = po.getNetWeight().toString(); + else if ("GrossWeight".equalsIgnoreCase(attributeOption) && po.getGrossWeight() != null) refVal = po.getGrossWeight().toString(); + else if ("Volume".equalsIgnoreCase(attributeOption) && po.getVolume() != null) refVal = po.getVolume().toString(); + else if ("Area".equalsIgnoreCase(attributeOption) && po.getArea() != null) refVal = po.getArea().toString(); + break; + } + } + if (refVal != null) { + materialMoreDetail.setAttributeValue(refVal); + } + } } } diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftManage/ShiftManageApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftManage/ShiftManageApplicationService.java index 6c1019965..974eeeb99 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftManage/ShiftManageApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftManage/ShiftManageApplicationService.java @@ -19,6 +19,8 @@ import com.mhd.system.api.domain.WarehouseFeignPO; 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.application.service.materialInventory.MaterialInventoryApplicationService; +import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryQueryListPO; import com.mhd.wms.domain.shiftManage.repository.po.ShiftManagePO; import com.mhd.wms.domain.shiftManage.repository.todo.ContainerShiftDO; import com.mhd.wms.domain.shiftManage.repository.todo.ShiftManageDO; @@ -53,6 +55,8 @@ public class ShiftManageApplicationService { @Autowired private ShiftMaterialDetailDomainService shiftMaterialDetailDomainService; @Autowired + private MaterialInventoryApplicationService materialInventoryApplicationService; + @Autowired private IdGenerator idGenerator; @Autowired @@ -123,14 +127,86 @@ public class ShiftManageApplicationService { } /** - * @description app 获取移位详情 - * @author ZhouGY - * @date 2024/7/30 14:20 - * @param ShiftManageId - * @return ShiftManagePO + * app 获取移位详情。支持两种入参:按单移位传 shiftManageId,从库存/容器移位传 materialInventoryId,返回结构一致 */ - public ShiftManagePO getInfoByApp(Long ShiftManageId) { - return shiftManageDomainService.getInfoByApp(ShiftManageId); + public ShiftManagePO getInfoByApp(Long shiftManageId, Long materialInventoryId) { + if (materialInventoryId != null && shiftManageId == null) { + return getInfoByInventory(materialInventoryId); + } + if (shiftManageId == null) return null; + return shiftManageDomainService.getInfoByApp(shiftManageId); + } + + /** 从库存构建与 getInfoByApp 一致的 ShiftManagePO 结构,供容器移位/库存进入复用 */ + private ShiftManagePO getInfoByInventory(Long materialInventoryId) { + MaterialInventoryQueryListPO inv = materialInventoryApplicationService.getInventoryForShiftForm(materialInventoryId); + if (inv == null) return null; + ShiftManagePO po = new ShiftManagePO(); + po.setShiftManageId(null); + po.setShiftNumber(null); + po.setWarehouseId(inv.getWarehouseId()); + po.setWarehouseCode(inv.getWarehouseCode()); + po.setWarehouseName(inv.getWarehouseName()); + po.setOrganizationId(inv.getOrganizationId()); + po.setOrganizationName(inv.getOrganizationName()); + po.setTopOrganizationId(inv.getTopOrganizationId()); + ShiftMaterialDetailPO parent = buildShiftDetailFromInventory(inv, 1, null); + ShiftMaterialDetailPO child = buildShiftDetailFromInventory(inv, 2, parent.getUniqueId()); + child.setMaterialDetailSerialNumberList(new ArrayList<>()); + List children = new ArrayList<>(); + children.add(child); + parent.setChildren(children); + List shiftMaterialDetailList = new ArrayList<>(); + shiftMaterialDetailList.add(parent); + po.setShiftMaterialDetailList(shiftMaterialDetailList); + return po; + } + + private ShiftMaterialDetailPO buildShiftDetailFromInventory(MaterialInventoryQueryListPO inv, int level, Long parentUniqueId) { + ShiftMaterialDetailPO d = new ShiftMaterialDetailPO(); + d.setUniqueId(idGenerator.snowflakeId(SnowFlakeConstants.wmsId)); + d.setMaterialInventoryId(inv.getMaterialInventoryId()); + d.setMaterialBaseInfoId(inv.getMaterialBaseInfoId()); + d.setMaterialCode(inv.getMaterialCode()); + d.setMaterialName(inv.getMaterialName()); + d.setBarCode(inv.getBarCode()); + d.setQuantity(inv.getAllocationQuantity()); + d.setShiftQuantity(inv.getShiftQuantity() != null ? inv.getShiftQuantity() : inv.getAllocationQuantity()); + d.setInventoryQuantity(inv.getInventoryQuantity()); + d.setOldWarehouseId(inv.getWarehouseId()); + d.setOldWarehouseCode(inv.getWarehouseCode()); + d.setOldWarehouseName(inv.getWarehouseName()); + d.setOldStorageSectionId(inv.getStorageSectionId()); + d.setOldStorageCode(inv.getStorageCode()); + d.setOldStorageName(inv.getStorageName()); + d.setOldStorageLocationId(inv.getStorageLocationId()); + d.setOldStorageLocationCode(inv.getStorageLocationCode()); + d.setOldStorageLocationName(inv.getStorageLocationName()); + d.setNewStorageLocationId(inv.getNewStorageLocationId()); + d.setNewStorageLocationCode(inv.getNewStorageLocationCode()); + d.setNewStorageLocationName(inv.getNewStorageLocationName()); + d.setContainerId(inv.getContainerId()); + d.setContainerCode(inv.getContainerCode()); + d.setContainerType(inv.getContainerType()); + d.setContainerTypeName(inv.getContainerTypeName()); + d.setBatchNumber(inv.getBatchNumber()); + d.setMaterialStatusCode(inv.getMaterialStatusCode()); + d.setMaterialStatusName(inv.getMaterialStatusName()); + d.setUnitCode(inv.getUnit()); + d.setUnitName(inv.getUnitName()); + d.setNetWeight(inv.getNetWeight()); + d.setGrossWeight(inv.getGrossWeight()); + d.setVolume(inv.getVolume()); + d.setArea(inv.getArea()); + BigDecimal qty = d.getShiftQuantity() != null ? d.getShiftQuantity() : BigDecimal.ONE; + if (inv.getNetWeight() != null) d.setTotalNetWeight(inv.getNetWeight().multiply(qty)); + if (inv.getGrossWeight() != null) d.setTotalGrossWeight(inv.getGrossWeight().multiply(qty)); + if (inv.getVolume() != null) d.setTotalVolume(inv.getVolume().multiply(qty)); + if (inv.getArea() != null) d.setTotalArea(inv.getArea().multiply(qty)); + d.setLevel(level); + d.setParentUniqueId(parentUniqueId); + d.setMaterialMoreDetailList(inv.getMaterialMoreDetailList() != null ? inv.getMaterialMoreDetailList() : new ArrayList<>()); + return d; } @@ -602,15 +678,18 @@ public class ShiftManageApplicationService { shiftMoveMaterialQuantityPO.setNewStorageLocationCode(storageLocationFeignPO.getStorageLocationCode()); shiftMoveMaterialQuantityPO.setNewStorageLocationName(storageLocationFeignPO.getStorageLocationName()); - //获取容器详情 - AjaxResult ajaxResult = systemServiceFeign.getContainerInfoByContainerId(shiftMoveMaterialQuantityPO.getContainerId()); - if(!"200".equals(String.valueOf(ajaxResult.get("code")))){ - throw new ServiceException("获取容器信息失败"); + // 有容器id时获取容器详情,无容器时跳过(有容器或批次号其一即可提交) + Long containerId = shiftMoveMaterialQuantityPO.getContainerId(); + if (containerId != null && containerId > 0) { + AjaxResult ajaxResult = systemServiceFeign.getContainerInfoByContainerId(containerId); + if(!"200".equals(String.valueOf(ajaxResult.get("code")))){ + throw new ServiceException("获取容器信息失败"); + } + ContainerFeignPO containerFeignPO = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), ContainerFeignPO.class); + shiftMoveMaterialQuantityPO.setContainerCode(containerFeignPO.getContainerCode()); + shiftMoveMaterialQuantityPO.setContainerType(containerFeignPO.getContainerType()); + shiftMoveMaterialQuantityPO.setContainerTypeName(containerFeignPO.getContainerTypeName()); } - ContainerFeignPO containerFeignPO = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), ContainerFeignPO.class); - shiftMoveMaterialQuantityPO.setContainerCode(containerFeignPO.getContainerCode()); - shiftMoveMaterialQuantityPO.setContainerType(containerFeignPO.getContainerType()); - shiftMoveMaterialQuantityPO.setContainerTypeName(containerFeignPO.getContainerTypeName()); }); } } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/po/MaterialInventoryQueryListPO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/po/MaterialInventoryQueryListPO.java index 5e6debb3f..9db299f10 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/po/MaterialInventoryQueryListPO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/po/MaterialInventoryQueryListPO.java @@ -3,6 +3,7 @@ package com.mhd.wms.domain.materialInventory.repository.po; import com.fasterxml.jackson.annotation.JsonFormat; import com.mhd.common.core.annotation.Excel; import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBasePO; +import com.mhd.wms.domain.materialMoreDetail.repository.po.MaterialMoreDetailPO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -10,6 +11,7 @@ import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; import java.util.Date; +import java.util.List; /** @@ -103,6 +105,15 @@ public class MaterialInventoryQueryListPO extends MaterialBasePO { @Excel(name = "库位名称") private String storageLocationName; + @ApiModelProperty("移入库位id,供 PDA 底部表单区填写") + private Long newStorageLocationId; + + @ApiModelProperty("移入库位编码,供 PDA 底部表单区填写") + private String newStorageLocationCode; + + @ApiModelProperty("移入库位名称,供 PDA 底部表单区显示") + private String newStorageLocationName; + @ApiModelProperty("批次号") @Excel(name = "批次号") private String batchNumber; @@ -139,6 +150,10 @@ public class MaterialInventoryQueryListPO extends MaterialBasePO { @Excel(name = "可用数量") private BigDecimal allocationQuantity; + @ApiModelProperty("移位数量,供 PDA 底部表单区显示,库存查询时等于可用数量") + @Excel(name = "移位数量") + private BigDecimal shiftQuantity; + @ApiModelProperty("冻结数量") @Excel(name = "冻结数量") private BigDecimal freezeQuantity; @@ -156,6 +171,10 @@ public class MaterialInventoryQueryListPO extends MaterialBasePO { @Excel(name = "单位") private String unit; + @ApiModelProperty("单位名称") + @Excel(name = "单位名称") + private String unitName; + @ApiModelProperty("净重(KG)") @Excel(name = "净重(KG)") private BigDecimal netWeight; @@ -222,4 +241,31 @@ public class MaterialInventoryQueryListPO extends MaterialBasePO { @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") @Excel(name = "ExtAttr4", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") private Date extAttr4; + + @ApiModelProperty("批次属性列表,与按单移位一致") + private List materialMoreDetailList; + + @ApiModelProperty("层级深度,与移位详情一致:1-主项 2-子项") + private Integer level; + + @ApiModelProperty("业务唯一id,与移位详情一致") + private Long uniqueId; + + @ApiModelProperty("父级唯一Id,子项时使用") + private Long parentUniqueId; + + @ApiModelProperty("子项列表,与移位详情一致,主项下含一条 parent_copy 子项") + private List children; + + @ApiModelProperty("总净重(KG),PDA 表单区显示") + private BigDecimal totalNetWeight; + + @ApiModelProperty("总毛重(KG),PDA 表单区显示") + private BigDecimal totalGrossWeight; + + @ApiModelProperty("总体积(CBM),PDA 表单区显示") + private BigDecimal totalVolume; + + @ApiModelProperty("总面积(SQM),PDA 表单区显示") + private BigDecimal totalArea; } \ No newline at end of file diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/todo/MaterialInventoryQueryListDO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/todo/MaterialInventoryQueryListDO.java index cf7517ffe..772bb83fd 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/todo/MaterialInventoryQueryListDO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/materialInventory/repository/todo/MaterialInventoryQueryListDO.java @@ -172,6 +172,9 @@ public class MaterialInventoryQueryListDO extends MaterialBaseDO { @Excel(name = "物料/库位信息") private String storageInfo; + @ApiModelProperty("容器号或批次号,输入后同时按容器号、批次号模糊匹配") + @Excel(name = "容器号或批次号") + private String containerOrBatch; @ApiModelProperty("单位") @Excel(name = "单位") diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/shiftManage/service/ShiftManageDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/shiftManage/service/ShiftManageDomainService.java index 5aeeb156e..8aec71ccc 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/shiftManage/service/ShiftManageDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/shiftManage/service/ShiftManageDomainService.java @@ -22,6 +22,7 @@ import com.mhd.common.core.web.domain.AjaxResult; import com.mhd.common.core.utils.StringUtils; import com.mhd.system.api.SystemServiceFeign; import com.mhd.system.api.domain.BatchDetailFeignPO; +import com.mhd.system.api.domain.StorageLocationFeignPO; import com.mhd.wms.domain.materialInventory.entity.MaterialInventory; import com.mhd.wms.domain.materialInventory.repository.facade.IMaterialInventoryService; import com.mhd.wms.domain.materialInventory.repository.todo.MaterialInventoryDO; @@ -107,6 +108,8 @@ public class ShiftManageDomainService { fillMaterialMoreDetailForShiftDetail(shiftMaterialDetailPO); // 填充 totalNetWeight 等,供 PDA 表单区(移入数量、移入库位、容器旁)显示 fillTotalWeightVolumeArea(shiftMaterialDetailPO); + // 填充移入库位名称,供 PDA 底部表单区显示 + fillNewStorageLocationName(shiftMaterialDetailPO); List shiftMaterialDetailPOChildrenNowList = new ArrayList<>(); ShiftMaterialDetailPO shiftMaterialDetailPOChildrenNow = new ShiftMaterialDetailPO(); BeanUtils.copyProperties(shiftMaterialDetailPO, shiftMaterialDetailPOChildrenNow, "children"); @@ -119,12 +122,14 @@ public class ShiftManageDomainService { // 子项副本同步批次属性 shiftMaterialDetailPOChildrenNow.setMaterialMoreDetailList(shiftMaterialDetailPO.getMaterialMoreDetailList()); fillTotalWeightVolumeArea(shiftMaterialDetailPOChildrenNow); + fillNewStorageLocationName(shiftMaterialDetailPOChildrenNow); shiftMaterialDetailPOChildrenNowList.add(shiftMaterialDetailPOChildrenNow); //子集 List shiftMaterialDetailPOChildrenList = shiftMaterialDetailPO.getChildren(); shiftMaterialDetailPOChildrenList.forEach(receiptMaterialDetailPOChildren -> { fillMaterialMoreDetailForShiftDetail(receiptMaterialDetailPOChildren); fillTotalWeightVolumeArea(receiptMaterialDetailPOChildren); + fillNewStorageLocationName(receiptMaterialDetailPOChildren); List materialDetailSerialNumberChildrenList = inMaterialDetailSerialNumberMap.get(shiftMaterialDetailPO.getUniqueId()); if (!CollectionUtils.isEmpty(materialDetailSerialNumberChildrenList)){ receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(materialDetailSerialNumberChildrenList); @@ -214,6 +219,30 @@ public class ShiftManageDomainService { } } + /** + * 填充移入库位名称,供 PDA 底部表单区显示。当 newStorageLocationId 有值但 newStorageLocationName 为空时,从系统服务获取 + */ + private void fillNewStorageLocationName(ShiftMaterialDetailPO shiftMaterialDetailPO) { + if (shiftMaterialDetailPO == null || shiftMaterialDetailPO.getNewStorageLocationId() == null) { + return; + } + if (StringUtils.isNotBlank(shiftMaterialDetailPO.getNewStorageLocationName())) { + return; + } + try { + AjaxResult result = systemServiceFeign.getStorageLocationInfoByStorageLocationId(shiftMaterialDetailPO.getNewStorageLocationId()); + if (result != null && "200".equals(String.valueOf(result.get("code"))) && result.get("data") != null) { + StorageLocationFeignPO po = JSON.parseObject(JSONObject.toJSONString(result.get("data")), StorageLocationFeignPO.class); + if (po != null) { + shiftMaterialDetailPO.setNewStorageLocationCode(po.getStorageLocationCode()); + shiftMaterialDetailPO.setNewStorageLocationName(po.getStorageLocationName()); + } + } + } catch (Exception e) { + log.warn("获取移入库位信息失败, newStorageLocationId={}", shiftMaterialDetailPO.getNewStorageLocationId(), e); + } + } + /** 净重、毛重、体积、面积在移位上面区域不展示,从 materialMoreDetailList 中排除 */ private static final String[] WEIGHT_VOLUME_AREA_LABELS = { "净重(KG)", "净重", "总净重", @@ -704,10 +733,20 @@ public class ShiftManageDomainService { ShiftMaterialDetailDO shiftMaterialDetailDO = new ShiftMaterialDetailDO(); shiftMaterialDetailDO.setShiftNumber(shiftManagePO.getShiftNumber()); List shiftMaterialDetailPOList = shiftMaterialDetailService.queryList(shiftMaterialDetailDO); + // 有子项时仅用子项(level=2)生成追溯,避免主项+子项重复统计;无子项时用全部 + List toUseList = shiftMaterialDetailPOList.stream() + .filter(p -> p.getLevel() != null && p.getLevel() == 2) + .collect(Collectors.toList()); + if (toUseList.isEmpty()) { + toUseList = shiftMaterialDetailPOList; + } //生成追溯记录 List inventoryStandingDetailDOList = new ArrayList<>(); LoginUser loginUser = SecurityUtils.getLoginUser(); - for (ShiftMaterialDetailPO shiftMaterialDetailPO : shiftMaterialDetailPOList){ + for (ShiftMaterialDetailPO shiftMaterialDetailPO : toUseList){ + if (shiftMaterialDetailPO.getShiftQuantity() == null || shiftMaterialDetailPO.getShiftQuantity().compareTo(BigDecimal.ZERO) <= 0) { + continue; + } InventoryStandingDetailDO inventoryStandingDetailDO = new InventoryStandingDetailDO(); inventoryStandingDetailDO.setOrganizationId(shiftManagePO.getOrganizationId()); inventoryStandingDetailDO.setOrganizationName(shiftManagePO.getOrganizationName()); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/shiftMaterialDetail/repository/persistence/ShiftMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/shiftMaterialDetail/repository/persistence/ShiftMaterialDetailImpl.java index cf3988e0c..e052574a6 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/shiftMaterialDetail/repository/persistence/ShiftMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/shiftMaterialDetail/repository/persistence/ShiftMaterialDetailImpl.java @@ -213,11 +213,11 @@ public class ShiftMaterialDetailImpl extends ServiceImpl 主项列表,每个主项含 children 子项 */ @Override @Transactional(rollbackFor = Exception.class) @@ -227,40 +227,114 @@ public class ShiftMaterialDetailImpl extends ServiceImpl materialInventoryNowList = new ArrayList<>(); List shiftMaterialDetailDOList = new ArrayList<>(); for (ContainerShiftDO containerShiftDO : containerShiftDOList){ - BigDecimal shiftQuantity = BigDecimal.ZERO; List shiftMoveMaterialQuantityList = containerShiftDO.getChildren(); if (CollectionUtils.isEmpty(shiftMoveMaterialQuantityList)){ - //没有移位 跳过 continue; } - //原库位 + // 先累加有效移位数量及用户填写的净重、毛重、体积、面积 + BigDecimal totalShiftQuantity = BigDecimal.ZERO; + BigDecimal totalNetWeight = BigDecimal.ZERO; + BigDecimal totalGrossWeight = BigDecimal.ZERO; + BigDecimal totalVolume = BigDecimal.ZERO; + BigDecimal totalArea = BigDecimal.ZERO; + for (ShiftMoveMaterialQuantityPO c : shiftMoveMaterialQuantityList) { + if (c.getShiftQuantity() != null && c.getShiftQuantity().compareTo(BigDecimal.ZERO) > 0) { + totalShiftQuantity = totalShiftQuantity.add(c.getShiftQuantity()); + if (c.getNetWeight() != null) totalNetWeight = totalNetWeight.add(c.getNetWeight()); + if (c.getGrossWeight() != null) totalGrossWeight = totalGrossWeight.add(c.getGrossWeight()); + if (c.getVolume() != null) totalVolume = totalVolume.add(c.getVolume()); + if (c.getArea() != null) totalArea = totalArea.add(c.getArea()); + } + } + if (totalShiftQuantity.compareTo(BigDecimal.ZERO) <= 0){ + continue; + } + // 原库位校验 MaterialInventory materialInventoryOldDb = materialInventoryMapper.selectById(containerShiftDO.getMaterialInventoryId()); if (ObjectUtil.isNull(materialInventoryOldDb)){ throw new ServiceException("原库位【" + containerShiftDO.getContainerTypeName() + "】不存在,不能进行移位"); } - if (materialInventoryOldDb.getInventoryQuantity().compareTo(shiftQuantity) < 0){ + if (materialInventoryOldDb.getInventoryQuantity().compareTo(totalShiftQuantity) < 0){ throw new ServiceException("容器【" + containerShiftDO.getContainerTypeName() + "】下的物料库存不足,不能进行移位"); } + // 主项(参考按单移位),主项 newStorageLocationId 取第一个子项,供 insert 时 setWarehouseInfo 使用 + ShiftMoveMaterialQuantityPO firstChild = shiftMoveMaterialQuantityList.stream() + .filter(c -> c.getShiftQuantity() != null && c.getShiftQuantity().compareTo(BigDecimal.ZERO) > 0) + .findFirst().orElse(null); + ShiftMaterialDetailDO parentDO = new ShiftMaterialDetailDO(); + parentDO.setMaterialInventoryId(containerShiftDO.getMaterialInventoryId()); + parentDO.setMaterialBaseInfoId(containerShiftDO.getMaterialBaseInfoId()); + parentDO.setQuantity(totalShiftQuantity); + parentDO.setLevel(1); + if (firstChild != null) { + parentDO.setNewStorageLocationId(firstChild.getNewStorageLocationId()); + parentDO.setNewStorageSectionId(firstChild.getNewStorageSectionId()); + parentDO.setNewStorageCode(firstChild.getNewStorageCode()); + parentDO.setNewStorageName(firstChild.getNewStorageName()); + parentDO.setNewStorageLocationCode(firstChild.getNewStorageLocationCode()); + parentDO.setNewStorageLocationName(firstChild.getNewStorageLocationName()); + } + List children = new ArrayList<>(); + // 原库位减少,净重毛重体积面积:优先用用户填写汇总,无则按原库存比例计算 MaterialInventoryDO materialInventoryDOOld = new MaterialInventoryDO(); materialInventoryDOOld.setMaterialInventoryId(containerShiftDO.getMaterialInventoryId()); - materialInventoryDOOld.setInventoryQuantity(shiftQuantity); - materialInventoryDOOld.setAllocationQuantity(shiftQuantity); + materialInventoryDOOld.setInventoryQuantity(totalShiftQuantity); + materialInventoryDOOld.setAllocationQuantity(totalShiftQuantity); + if (totalNetWeight.compareTo(BigDecimal.ZERO) > 0) { + materialInventoryDOOld.setNetWeight(totalNetWeight); + } + if (totalGrossWeight.compareTo(BigDecimal.ZERO) > 0) { + materialInventoryDOOld.setGrossWeight(totalGrossWeight); + } + if (totalVolume.compareTo(BigDecimal.ZERO) > 0) { + materialInventoryDOOld.setVolume(totalVolume); + } + if (totalArea.compareTo(BigDecimal.ZERO) > 0) { + materialInventoryDOOld.setArea(totalArea); + } + if (materialInventoryDOOld.getNetWeight() == null && materialInventoryDOOld.getGrossWeight() == null + && materialInventoryDOOld.getVolume() == null && materialInventoryDOOld.getArea() == null) { + BigDecimal oldQty = materialInventoryOldDb.getInventoryQuantity(); + if (oldQty != null && oldQty.compareTo(BigDecimal.ZERO) > 0) { + BigDecimal ratio = totalShiftQuantity.divide(oldQty, 10, java.math.RoundingMode.HALF_UP); + if (materialInventoryOldDb.getNetWeight() != null) materialInventoryDOOld.setNetWeight(materialInventoryOldDb.getNetWeight().multiply(ratio)); + if (materialInventoryOldDb.getGrossWeight() != null) materialInventoryDOOld.setGrossWeight(materialInventoryOldDb.getGrossWeight().multiply(ratio)); + if (materialInventoryOldDb.getVolume() != null) materialInventoryDOOld.setVolume(materialInventoryOldDb.getVolume().multiply(ratio)); + if (materialInventoryOldDb.getArea() != null) materialInventoryDOOld.setArea(materialInventoryOldDb.getArea().multiply(ratio)); + } + } materialInventoryOldList.add(materialInventoryDOOld); for (ShiftMoveMaterialQuantityPO shiftMoveMaterialQuantityPO : shiftMoveMaterialQuantityList) { if (ObjectUtil.isNull(shiftMoveMaterialQuantityPO.getShiftQuantity()) || shiftMoveMaterialQuantityPO.getShiftQuantity().compareTo(BigDecimal.ZERO) == 0){ - //没有移位 跳过 continue; } - //新库位 + // 子项(参考按单移位) + ShiftMaterialDetailDO childDO = new ShiftMaterialDetailDO(); + childDO.setMaterialInventoryId(null); + childDO.setQuantity(shiftMoveMaterialQuantityPO.getShiftQuantity()); + childDO.setShiftQuantity(shiftMoveMaterialQuantityPO.getShiftQuantity()); + childDO.setNewStorageLocationId(shiftMoveMaterialQuantityPO.getNewStorageLocationId()); + childDO.setNewStorageSectionId(shiftMoveMaterialQuantityPO.getNewStorageSectionId()); + childDO.setNewStorageCode(shiftMoveMaterialQuantityPO.getNewStorageCode()); + childDO.setNewStorageName(shiftMoveMaterialQuantityPO.getNewStorageName()); + childDO.setNewStorageLocationCode(shiftMoveMaterialQuantityPO.getNewStorageLocationCode()); + childDO.setNewStorageLocationName(shiftMoveMaterialQuantityPO.getNewStorageLocationName()); + childDO.setContainerId(shiftMoveMaterialQuantityPO.getContainerId()); + childDO.setContainerCode(shiftMoveMaterialQuantityPO.getContainerCode()); + childDO.setContainerType(shiftMoveMaterialQuantityPO.getContainerType()); + childDO.setContainerTypeName(shiftMoveMaterialQuantityPO.getContainerTypeName()); + childDO.setLevel(2); + children.add(childDO); + // 新库位增加 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(MaterialInventory::getWarehouseId, SystemServiceCacheUtil.getAssociationWarehouseCache(SecurityUtils.getLoginUser().getUserid()).getWarehouseId()); // 仓库 - queryWrapper.eq(MaterialInventory::getStorageSectionId, shiftMoveMaterialQuantityPO.getNewStorageSectionId()); // 库区 - queryWrapper.eq(MaterialInventory::getStorageLocationId, shiftMoveMaterialQuantityPO.getNewStorageLocationId()); // 库位 - queryWrapper.eq(MaterialInventory::getMaterialBaseInfoId, containerShiftDO.getMaterialBaseInfoId()); // 物料基础信息id - queryWrapper.eq(MaterialInventory::getBatchNumber, containerShiftDO.getBatchNumber()); // 批次号 - queryWrapper.eq(MaterialInventory::getMaterialStatusCode, containerShiftDO.getMaterialStatusCode()); // 物料状态 + queryWrapper.eq(MaterialInventory::getWarehouseId, SystemServiceCacheUtil.getAssociationWarehouseCache(SecurityUtils.getLoginUser().getUserid()).getWarehouseId()); + queryWrapper.eq(MaterialInventory::getStorageSectionId, shiftMoveMaterialQuantityPO.getNewStorageSectionId()); + queryWrapper.eq(MaterialInventory::getStorageLocationId, shiftMoveMaterialQuantityPO.getNewStorageLocationId()); + queryWrapper.eq(MaterialInventory::getMaterialBaseInfoId, containerShiftDO.getMaterialBaseInfoId()); + queryWrapper.eq(MaterialInventory::getBatchNumber, containerShiftDO.getBatchNumber()); + queryWrapper.eq(MaterialInventory::getMaterialStatusCode, containerShiftDO.getMaterialStatusCode()); if (!ObjectUtil.isNull(shiftMoveMaterialQuantityPO.getContainerId())){ - queryWrapper.eq(MaterialInventory::getContainerId,shiftMoveMaterialQuantityPO.getContainerId()); + queryWrapper.eq(MaterialInventory::getContainerId, shiftMoveMaterialQuantityPO.getContainerId()); } MaterialInventory materialInventoryDb = materialInventoryMapper.selectOne(queryWrapper); if (ObjectUtil.isNull(materialInventoryDb)){ @@ -278,6 +352,10 @@ public class ShiftMaterialDetailImpl extends ServiceImpl + + and a.material_inventory_id = #{materialInventoryId} + and a.organization_id = #{organizationId} @@ -130,9 +133,23 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and a.material_detail_id, = #{materialDetailId} - - and a.batch_number = #{batchNumber} - + + + + and (a.container_code like concat('%', #{containerOrBatch}, '%') or a.batch_number like concat('%', #{containerOrBatch}, '%')) + + + and (a.batch_number like concat('%', #{batchNumber}, '%') or a.container_code like concat('%', #{containerCode}, '%')) + + + + and a.batch_number like concat('%', #{batchNumber}, '%') + + + and a.container_code like concat('%', #{containerCode}, '%') + + + and a.material_status_code like concat('%', #{materialStatusCode}, '%') @@ -142,9 +159,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and a.container_id = #{containerId} - - and a.container_code like concat('%', #{containerCode}, '%') - and a.container_type like concat('%', #{containerType}, '%') @@ -256,6 +270,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + @@ -270,8 +285,33 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + + + + + + + + + + + + + + + + + + + + + +