diff --git a/mhd-common/mhd-common-security/src/main/java/com/mhd/common/security/config/WebMvcConfig.java b/mhd-common/mhd-common-security/src/main/java/com/mhd/common/security/config/WebMvcConfig.java index 7d5df991e..4ab2622d9 100644 --- a/mhd-common/mhd-common-security/src/main/java/com/mhd/common/security/config/WebMvcConfig.java +++ b/mhd-common/mhd-common-security/src/main/java/com/mhd/common/security/config/WebMvcConfig.java @@ -13,7 +13,7 @@ public class WebMvcConfig implements WebMvcConfigurer { /** * 不需要拦截地址 */ - public static final String[] excludeUrls = {"/login", "/loginApi","/dingloginApi", "/logout", "/refresh", "/basicApi/findAgreement","/approvalDocumentApi/dingdingHuiDiao"}; + public static final String[] excludeUrls = {"/login", "/loginApi","/dingloginApi", "/logout", "/refresh", "/basicApi/findAgreement","/approvalDocumentApi/dingdingHuiDiao","/materialInventoryApi/listAll"}; @Override public void addInterceptors(InterceptorRegistry registry) { diff --git a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java index 3613e9493..2aa409f4e 100644 --- a/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java +++ b/mhd-modules/mhd-system/src/main/java/com/mhd/basic/application/service/Lease/LeaseApplicationService.java @@ -439,7 +439,7 @@ public class LeaseApplicationService { warehouseOccupancyRate.setEntireLeaseArea(entireLeaseArea); warehouseOccupancyRate.setFractionalLeaseArea(fractionalLeaseArea); warehouseOccupancyRate.setTotalArea(finalTotalArea); - BigDecimal dailyRentalRate = entireLeaseArea.add(fractionalLeaseArea).divide(finalTotalArea, 2, BigDecimal.ROUND_HALF_UP); + BigDecimal dailyRentalRate = entireLeaseArea.add(fractionalLeaseArea).divide(finalTotalArea, 4, BigDecimal.ROUND_HALF_UP); warehouseOccupancyRate.setDailyRentalRate(dailyRentalRate); warehouseOccupancyRatesList.add(warehouseOccupancyRate); }); diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/handoverTaskOrder/HandoverTaskOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/handoverTaskOrder/HandoverTaskOrderApplicationService.java index 5ee9f3ca8..c64618805 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/handoverTaskOrder/HandoverTaskOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/handoverTaskOrder/HandoverTaskOrderApplicationService.java @@ -151,6 +151,27 @@ public class HandoverTaskOrderApplicationService { return handoverTaskOrderDomainService.getInfo(outTaskOrderId); } + /** + * 按作业单号获取交接作业单详细信息(PDA 端) + * 用于下发任务(taskType=7)中 trackingNumber 对应交接作业单的 taskNumber + * + * @param taskNumber 作业单号 + * @return 交接作业单详情,含物料明细(与 getInfo 逻辑一致) + */ + public HandoverTaskOrderPO getInfoByTaskNumber(String taskNumber) { + if (taskNumber == null || taskNumber.trim().isEmpty()) { + return null; + } + HandoverTaskOrder handoverTaskOrder = handoverTaskOrderService.getOne( + new LambdaQueryWrapper() + .eq(HandoverTaskOrder::getTaskNumber, taskNumber.trim()) + .eq(HandoverTaskOrder::getDelFlag, 1)); + if (handoverTaskOrder == null) { + return null; + } + return handoverTaskOrderDomainService.getInfo(handoverTaskOrder.getHandoverTaskOrderId()); + } + /** * 分配月台 */ diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/receiptMaterialDetail/ReceiptMaterialDetailApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/receiptMaterialDetail/ReceiptMaterialDetailApplicationService.java index c157e39d5..725672b37 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/receiptMaterialDetail/ReceiptMaterialDetailApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/receiptMaterialDetail/ReceiptMaterialDetailApplicationService.java @@ -27,7 +27,6 @@ public class ReceiptMaterialDetailApplicationService { /** * 分页查询物料明细列表 */ - public List queryList(ReceiptMaterialDetailDO receiptMaterialDetailDO) { LoginUser loginUser = SecurityUtils.getLoginUser(); if (loginUser != null){ 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 d47fcf3a6..feafe4655 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 @@ -741,8 +741,44 @@ public class ShiftManageApplicationService { if (CollectionUtils.isEmpty(shiftMoveMaterialQuantityList)){ continue; } + // 兼容:容器移位通常只有一个目标库位 + // 1) 若子项未传 newStorageLocationId,优先从父级复制(PDA 可能把目标放在父级) + Long parentTargetId = containerShiftDO.getNewStorageLocationId(); + if (parentTargetId != null && parentTargetId > 0) { + shiftMoveMaterialQuantityList.forEach(c -> { + if (c.getNewStorageLocationId() == null || c.getNewStorageLocationId() <= 0) { + c.setNewStorageLocationId(parentTargetId); + c.setNewStorageSectionId(containerShiftDO.getNewStorageSectionId()); + c.setNewStorageCode(containerShiftDO.getNewStorageCode()); + c.setNewStorageName(containerShiftDO.getNewStorageName()); + c.setNewStorageLocationCode(containerShiftDO.getNewStorageLocationCode()); + c.setNewStorageLocationName(containerShiftDO.getNewStorageLocationName()); + } + }); + } + // 2) 若部分子项仍未传,从同组第一个有值的子项复制 + ShiftMoveMaterialQuantityPO firstWithTarget = shiftMoveMaterialQuantityList.stream() + .filter(c -> c.getNewStorageLocationId() != null && c.getNewStorageLocationId() > 0) + .findFirst().orElse(null); + if (firstWithTarget != null) { + shiftMoveMaterialQuantityList.forEach(c -> { + if (c.getNewStorageLocationId() == null || c.getNewStorageLocationId() <= 0) { + c.setNewStorageLocationId(firstWithTarget.getNewStorageLocationId()); + c.setNewStorageSectionId(firstWithTarget.getNewStorageSectionId()); + c.setNewStorageCode(firstWithTarget.getNewStorageCode()); + c.setNewStorageName(firstWithTarget.getNewStorageName()); + c.setNewStorageLocationCode(firstWithTarget.getNewStorageLocationCode()); + c.setNewStorageLocationName(firstWithTarget.getNewStorageLocationName()); + } + }); + } shiftMoveMaterialQuantityList.forEach(shiftMoveMaterialQuantityPO -> { - AjaxResult storageLocationResult = systemServiceFeign.getStorageLocationInfoByStorageLocationId(shiftMoveMaterialQuantityPO.getNewStorageLocationId()); + Long newStorageLocationId = shiftMoveMaterialQuantityPO.getNewStorageLocationId(); + if (newStorageLocationId == null || newStorageLocationId <= 0) { + log.warn("容器移位缺少目标库位。父级newStorageLocationId={}, 请求体={}", containerShiftDO.getNewStorageLocationId(), JSON.toJSONString(containerShiftDOList)); + throw new ServiceException("目标库位不能为空,请选择目标库位"); + } + AjaxResult storageLocationResult = systemServiceFeign.getStorageLocationInfoByStorageLocationId(newStorageLocationId); if(!"200".equals(String.valueOf(storageLocationResult.get("code")))){ throw new ServiceException("获取上架库位信息失败"); } diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftMaterialDetail/ShiftMaterialDetailApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftMaterialDetail/ShiftMaterialDetailApplicationService.java index 08f0fae37..986834e2a 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftMaterialDetail/ShiftMaterialDetailApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/shiftMaterialDetail/ShiftMaterialDetailApplicationService.java @@ -7,7 +7,12 @@ 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.domain.PackDetailFeignPO; import com.mhd.system.api.model.LoginUser; +import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService; +import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO; +import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo; +import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService; 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; @@ -41,6 +46,9 @@ public class ShiftMaterialDetailApplicationService { @Autowired private MaterialInventoryMapper materialInventoryMapper; + @Autowired + private IMaterialBarCodeService materialBarCodeService; + /** * 分页查询移位物料明细列表 */ @@ -203,6 +211,21 @@ public class ShiftMaterialDetailApplicationService { MaterialInventoryPO materialInventoryPO = null; if (materialInventoryId != null) { materialInventoryPO = materialInventoryMapper.selectByIdWithBatchAttributes(materialInventoryId); + + + List materialBarCodePOList = materialBarCodeService.getInfoByMaterialBaseInfoIds(materialBaseInfoId); + if (materialBarCodePOList != null && !materialBarCodePOList.isEmpty()) { + Map collect = materialBarCodePOList.stream() + .collect(Collectors.toMap( + MaterialBarCodePO::getMaterialBaseInfoId, + po -> po, + (existing, replacement) -> existing + )); + MaterialBarCodePO materialBarCodePO = collect.get(shiftMaterialDetailPO.getMaterialBaseInfoId()); + if (materialBarCodePO != null && materialBarCodePO.getBarCode() != null) { + shiftMaterialDetailPO.setBarCode(materialBarCodePO.getBarCode()); + } + } } if (materialBaseInfoId != null && batchDetailMap.containsKey(materialBaseInfoId)) { diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java index 175acfb0f..c746d8c57 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java @@ -19,6 +19,7 @@ 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.inMaterialDetail.repository.todo.InMaterialDetailDO; +import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo; import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService; import com.mhd.wms.domain.materialBaseInfo.repository.po.MaterialBaseInfoPO; import com.mhd.wms.domain.materialBaseInfo.repository.todo.MaterialBaseInfoDO; @@ -1336,8 +1337,14 @@ public class StockInOrderApplicationService { InMaterialDetailDO d = new InMaterialDetailDO(); d.setMaterialBaseInfoId(materialBaseInfoId); - // 设置商品名称和料号(从Excel读取) - d.setMaterialName(r.getMaterialName()); + if (materialBaseInfoId != null){ + //从数据库获取名称 + MaterialBaseInfo materialBaseInfo = materialBaseInfoService.getById(materialBaseInfoId); + d.setMaterialName(materialBaseInfo.getMaterialName()); + }else { + // 设置商品名称和料号(从Excel读取) + d.setMaterialName(r.getMaterialName()); + } // 如果料号为空但物料ID有值,根据物料ID查询并补充料号 String materialCode = r.getMaterialCode(); if (StringUtils.isBlank(materialCode) && materialBaseInfoId != null) { diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java index f52ad744f..b3bf9bde4 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutOrder/StockOutOrderApplicationService.java @@ -36,6 +36,8 @@ 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; import com.mhd.wms.domain.outMaterialDetail.service.OutMaterialDetailDomainService; +import com.mhd.wms.domain.pickingMaterialDetail.repository.facade.IPickingMaterialDetailService; +import com.mhd.wms.domain.pickingMaterialDetail.repository.po.PickingMaterialDetailPO; import com.mhd.wms.domain.stockOutOrder.entity.StockOutOrder; import com.mhd.wms.domain.stockOutOrder.repository.facade.IStockOutOrderService; import com.mhd.wms.domain.stockOutOrder.repository.po.StockOutOrderPO; @@ -80,6 +82,8 @@ public class StockOutOrderApplicationService { private IStockOutOrderService stockOutOrderService; @Autowired private IOutMaterialDetailService outMaterialDetailService; + @Autowired + private IPickingMaterialDetailService pickingMaterialDetailService; /** @@ -147,12 +151,35 @@ public class StockOutOrderApplicationService { List stockOutOrderPOS = stockOutOrderDomainService.queryList(stockOutOrderDO); for (StockOutOrderPO stockOutOrderPO : stockOutOrderPOS) { StockOutOrderPO stockOutOrderPO1 = stockOutOrderDomainService.getInfoChildren(stockOutOrderPO.getOutOrderId()); - List materialDetailList = stockOutOrderPO1.getMaterialDetailList(); - BigDecimal reduce = materialDetailList.stream().map(OutMaterialDetailPO::getOutboundQuantity).reduce(BigDecimal.ZERO, BigDecimal::add); + List materialDetailList = stockOutOrderPO1 != null ? stockOutOrderPO1.getMaterialDetailList() : null; + if (materialDetailList == null) { + materialDetailList = Collections.emptyList(); + } + BigDecimal reduce = materialDetailList.stream().map(OutMaterialDetailPO::getOutboundQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); stockOutOrderPO.setTotalOutboundQuantity(reduce); - stockOutOrderPO.setAllocationQuantity(stockOutOrderPO1.getAllocationQuantity()); - stockOutOrderPO.setPickingQuantity(stockOutOrderPO1.getPickingQuantity()); - stockOutOrderPO.setCheckQuantity(stockOutOrderPO1.getCheckQuantity()); + stockOutOrderPO.setAllocationQuantity(stockOutOrderPO1 != null ? stockOutOrderPO1.getAllocationQuantity() : null); + String outOrderNumber = stockOutOrderPO.getOutOrderNumber(); + // PDA复核物料总数量:使用实际下发时的拣货完成数量(picking_material_detail),拣货多少显示多少 + // PDA端物料总数量取quantity字段、复核总数量取checkQuantity字段,需同时设置quantity和pickingQuantity + BigDecimal actualPickingQty = pickingMaterialDetailService.sumPickingQuantityByOutOrderNumber(outOrderNumber); + BigDecimal displayPickingQty = actualPickingQty.compareTo(BigDecimal.ZERO) > 0 ? actualPickingQty : (stockOutOrderPO1 != null ? stockOutOrderPO1.getPickingQuantity() : BigDecimal.ZERO); + stockOutOrderPO.setPickingQuantity(displayPickingQty); + stockOutOrderPO.setQuantity(displayPickingQty); + // 物料种类:优先从picking_material_detail统计,为0时从out_material_detail按料号去重 + Integer materialTypeCount = pickingMaterialDetailService.countMaterialTypesByOutOrderNumber(outOrderNumber); + if (materialTypeCount != null && materialTypeCount > 0) { + stockOutOrderPO.setMaterialQuantity(materialTypeCount); + } else { + long count = materialDetailList.stream() + .map(d -> d.getMaterialBaseInfoId() != null ? String.valueOf(d.getMaterialBaseInfoId()) : d.getMaterialCode()) + .filter(Objects::nonNull) + .distinct() + .count(); + stockOutOrderPO.setMaterialQuantity((int) count); + } + // 复核总数量:从out_material_detail汇总check_quantity + BigDecimal checkSum = materialDetailList.stream().map(OutMaterialDetailPO::getCheckQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); + stockOutOrderPO.setCheckQuantity(checkSum); } return stockOutOrderPOS; } @@ -243,9 +270,46 @@ public class StockOutOrderApplicationService { // 4. 为每个物料明细设置分配按钮显示类型,递归处理所有层级 setAllocationButtonTypeRecursively(detailList); + // 5. 出库交接场景(已出库/已复核):过滤 pickingQuantity 为 0 的明细,与交接详情一致 + if (stockOutOrderPO.getStatus() != null && (stockOutOrderPO.getStatus() == 9 || stockOutOrderPO.getStatus() == 12)) { + filterMaterialDetailByPickingQuantity(detailList, stockOutOrderPO.getReview(), stockOutOrderPO.getOutOrderNumber()); + } + return stockOutOrderPO; } + /** + * 出库交接场景:递归过滤 pickingQuantity 为 0 的明细(与交接详情一致) + * @param detailList 物料明细树 + * @param review 是否需要复核 1-是 2-否 + * @param outOrderNumber 出库单号(review=1 时用于 picking_material_detail 查询) + */ + private void filterMaterialDetailByPickingQuantity(List detailList, Integer review, String outOrderNumber) { + if (CollectionUtils.isEmpty(detailList)) { + return; + } + for (int i = detailList.size() - 1; i >= 0; i--) { + OutMaterialDetailPO d = detailList.get(i); + List children = d.getChildren(); + if (!CollectionUtils.isEmpty(children)) { + filterMaterialDetailByPickingQuantity(children, review, outOrderNumber); + } + BigDecimal pickQty; + if (Integer.valueOf(1).equals(review) && d.getUniqueId() != null) { + PickingMaterialDetailPO pickingSummary = pickingMaterialDetailService.queryTotalsByOutNumberAndBaseId(d.getUniqueId()); + pickQty = (pickingSummary != null && pickingSummary.getPickingQuantity() != null) ? pickingSummary.getPickingQuantity() : BigDecimal.ZERO; + } else { + pickQty = d.getPickingQuantity() != null ? d.getPickingQuantity() : BigDecimal.ZERO; + } + if (pickQty.compareTo(BigDecimal.ZERO) <= 0) { + detailList.remove(i); + } else if (Integer.valueOf(1).equals(review) && d.getUniqueId() != null) { + // 需要复核时:用 picking_material_detail 的拣货数量覆盖展示,保证已拣货数量正确 + d.setPickingQuantity(pickQty); + } + } + } + /** * 递归为出库物料明细设置更多属性 * 如果已分配库存(materialInventoryId不为空),则从库存表中获取批次属性值 diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutTaskOrder/StockOutTaskOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutTaskOrder/StockOutTaskOrderApplicationService.java index f4b420b41..26a264f2f 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutTaskOrder/StockOutTaskOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockOutTaskOrder/StockOutTaskOrderApplicationService.java @@ -232,6 +232,11 @@ public class StockOutTaskOrderApplicationService { TaskPickingMaterialDetailDO returnTaskPickingMaterialDetailDO = new TaskPickingMaterialDetailDO(); BeanUtils.copyProperties(taskPickingMaterialDetailPO, returnTaskPickingMaterialDetailDO); returnTaskPickingMaterialDetailDO.setActualQuantity(taskPickingMaterialDetailDO.getActualQuantity()); + // PDA 提交的净重、毛重、体积、面积需传递到拣货更新逻辑,否则会丢失 + returnTaskPickingMaterialDetailDO.setTotalNetWeight(taskPickingMaterialDetailDO.getTotalNetWeight()); + returnTaskPickingMaterialDetailDO.setTotalGrossWeight(taskPickingMaterialDetailDO.getTotalGrossWeight()); + returnTaskPickingMaterialDetailDO.setTotalVolume(taskPickingMaterialDetailDO.getTotalVolume()); + returnTaskPickingMaterialDetailDO.setTotalArea(taskPickingMaterialDetailDO.getTotalArea()); //是否开启了序列号管理 if (taskPickingMaterialDetailPO.getSerialNumberManage() == 1){ if (CollectionUtils.isEmpty(taskPickingMaterialDetailDO.getMaterialDetailSerialNumberList())){ diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java index daad3e047..ceeaaf8b4 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockReceiptOrder/StockReceiptOrderApplicationService.java @@ -540,23 +540,23 @@ public class StockReceiptOrderApplicationService { } // 只有当获取到值时才更新attributeValue(避免覆盖已有的值) if (fieldValue != null) { - // 扩展属性1-4:优先使用 material_more_detail 的值(按 material_detail_unique_id 存储,每个明细独立) - // 避免从 ReceiptMaterialDetailPO 反射取值(主项/子项可能共用 in_unique_id,导致取到同一 in_material_detail 的错误值) + // 子项(level=2)与主项共用 in_unique_id,ReceiptMaterialDetailPO 反射取值会得到 in_material_detail 的值,覆盖子项真实数据 + // 故 batch_ref_no、invoice_no、sheet_ref_no、box_pallet_no、ext_attr 等均优先用 material_more_detail + boolean isChild = receiptMaterialDetailPO.getLevel() != null && receiptMaterialDetailPO.getLevel() == 2; boolean isExtAttr = usedFieldName != null && ( "ext_attr_1".equalsIgnoreCase(usedFieldName) || "extAttr1".equals(usedFieldName) || "ext_attr_2".equalsIgnoreCase(usedFieldName) || "extAttr2".equals(usedFieldName) || "ext_attr_3".equalsIgnoreCase(usedFieldName) || "extAttr3".equals(usedFieldName) || "ext_attr_4".equalsIgnoreCase(usedFieldName) || "extAttr4".equals(usedFieldName)); - if (isExtAttr) { - // 扩展属性:优先从 material_more_detail 表查询(按 material_detail_unique_id + batch_detail_id) + boolean preferMaterialMoreDetail = isExtAttr || isChild; + if (preferMaterialMoreDetail) { String attrFromDb = getExtAttrFromMaterialMoreDetail(receiptMaterialDetailPO.getUniqueId(), batchDetailFeignPO.getBatchDetailId()); if (StringUtils.isNotBlank(attrFromDb)) { materialMoreDetailPO.setAttributeValue(attrFromDb); - log.debug("扩展属性 batchDetailId={}, 使用 material_more_detail 的值={}", + log.debug("批次属性 batchDetailId={}, 使用 material_more_detail 的值={}", materialMoreDetailPO.getBatchDetailId(), attrFromDb); } else if (StringUtils.isNotBlank(materialMoreDetailPO.getAttributeValue())) { - // 已有值(来自 queryListChildren 的 merge)则保留 - log.debug("扩展属性 batchDetailId={}, 保留已有值={}", + log.debug("批次属性 batchDetailId={}, 保留已有值={}", materialMoreDetailPO.getBatchDetailId(), materialMoreDetailPO.getAttributeValue()); } else { materialMoreDetailPO.setAttributeValue(fieldValue); diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java index 6354c87f5..054cbb62f 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockShelfOrder/StockShelfOrderApplicationService.java @@ -186,26 +186,36 @@ public class StockShelfOrderApplicationService { } /** - * 获取上架单详细信息 + * 获取上架单详细信息(PC端:不添加 parent_copy,收货无子项时上架也不显示子项) */ - public StockShelfOrderPO getInfo(Long shelfOrderId) - { + public StockShelfOrderPO getInfo(Long shelfOrderId) { + return getInfo(shelfOrderId, false); + } + + /** + * 获取上架单详细信息 + * @param shelfOrderId 上架单ID + * @param addParentCopyWhenNoChildren 主项无子项时是否添加 parent_copy:true-PDA 详情页从 children 读取数据需要;false-PC 端收货无子项时上架不显示虚拟子项 + */ + public StockShelfOrderPO getInfo(Long shelfOrderId, boolean addParentCopyWhenNoChildren) { StockShelfOrderPO stockShelfOrderPO = stockShelfOrderDomainService.getInfo(shelfOrderId); ShelfMaterialDetailDO shelfMaterialDetailDO = new ShelfMaterialDetailDO(); shelfMaterialDetailDO.setShelfOrderNumber(stockShelfOrderPO.getShelfOrderNumber()); List shelfMaterialDetailPOList = shelfMaterialDetailDomainService.queryListChildren(shelfMaterialDetailDO); - // 主项无子项时:添加 parent_copy 到 children,供详情页展示(详情页从 children 读取数据) - for (ShelfMaterialDetailPO parent : shelfMaterialDetailPOList) { - if (CollectionUtils.isEmpty(parent.getChildren())) { - ShelfMaterialDetailPO parentCopy = new ShelfMaterialDetailPO(); - BeanUtils.copyProperties(parent, parentCopy, "children"); - parentCopy.setLevel(2); - parentCopy.setParentUniqueId(parent.getUniqueId()); - parentCopy.setQuantity(null); - parentCopy.setChildren(new ArrayList<>()); - List children = new ArrayList<>(); - children.add(parentCopy); - parent.setChildren(children); + // PDA:主项无子项时添加 parent_copy 到 children,供详情页展示(详情页从 children 读取数据);PC:不添加,避免收货无子项时上架显示虚拟子项 + if (addParentCopyWhenNoChildren) { + for (ShelfMaterialDetailPO parent : shelfMaterialDetailPOList) { + if (CollectionUtils.isEmpty(parent.getChildren())) { + ShelfMaterialDetailPO parentCopy = new ShelfMaterialDetailPO(); + BeanUtils.copyProperties(parent, parentCopy, "children"); + parentCopy.setLevel(2); + parentCopy.setParentUniqueId(parent.getUniqueId()); + parentCopy.setQuantity(null); + parentCopy.setChildren(new ArrayList<>()); + List children = new ArrayList<>(); + children.add(parentCopy); + parent.setChildren(children); + } } } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/deliveTask/repository/persistence/DeliveTaskImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/deliveTask/repository/persistence/DeliveTaskImpl.java index 13589daad..d5a07e167 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/deliveTask/repository/persistence/DeliveTaskImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/deliveTask/repository/persistence/DeliveTaskImpl.java @@ -21,6 +21,7 @@ import com.mhd.wms.domain.handoverTaskOrder.entity.HandoverTaskOrder; import com.mhd.wms.domain.handoverTaskOrder.repository.facade.IHandoverTaskOrderService; import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail; import com.mhd.wms.domain.outMaterialDetail.repository.facade.IOutMaterialDetailService; +import com.mhd.wms.domain.pickingMaterialDetail.repository.mapper.PickingMaterialDetailMapper; import com.mhd.wms.domain.pickingOrder.repository.facade.IPickingOrderService; import com.mhd.wms.domain.pickingOrder.repository.po.PickingOrderPO; import com.mhd.wms.domain.pickingOrder.repository.todo.PickingOrderDO; @@ -42,7 +43,9 @@ import javax.annotation.Resource; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * 下发任务Service业务层处理 @@ -79,6 +82,9 @@ public class DeliveTaskImpl extends ServiceImpl im @Autowired private IOutMaterialDetailService outMaterialDetailService; + @Autowired + private PickingMaterialDetailMapper pickingMaterialDetailMapper; + /** * 查询下发任务列表 */ @@ -119,25 +125,7 @@ public class DeliveTaskImpl extends ServiceImpl im } deliveTaskPO.setHandoverStatus(handoverTaskOrder.getStatus());//交接状态: 1-未交接 2-已交接,与PC端保持一致 String orderNumber = handoverTaskOrder.getOrderNumber();//出库单号 - PickingOrderDTO pickingOrderDTO = new PickingOrderDTO(); - pickingOrderDTO.setOrderNumber(orderNumber); - PickingOrderDO pickingOrderDO = pickingOrderAssembler.toDO(pickingOrderDTO); - List pickingList = pickingOrderService.queryList(pickingOrderDO); - if (!pickingList.isEmpty()) { - PickingOrderPO pickingOrderPOS = pickingList.get(0); - BigDecimal pickingQuantity = pickingOrderPOS.getPickingQuantity();//已拣货数量 - deliveTaskPO.setPickingQuantity(pickingQuantity); - } - // 物料种类数:从出库明细按料号去重统计 - long materialQuantity = outMaterialDetailService.list(new LambdaQueryWrapper() - .eq(OutMaterialDetail::getOutOrderNumber, orderNumber)) - .stream() - .map(d -> d.getMaterialCode() != null && !d.getMaterialCode().isEmpty() ? d.getMaterialCode() : d.getMaterialNo()) - .filter(c -> c != null && !c.isEmpty()) - .distinct() - .count(); - deliveTaskPO.setMaterialQuantity((int) materialQuantity); - // 已复核数量、出库单信息:直接从出库单获取(getCheckInfo仅支持复核中状态会抛异常) + // 已复核数量、出库单信息:直接从出库单获取(需在物料统计前获取,用于判断是否需要复核) StockOutOrder stockOutOrder = stockOutOrderService.getOne(new LambdaQueryWrapper() .eq(StockOutOrder::getOutOrderNumber, orderNumber)); if (stockOutOrder != null) { @@ -146,7 +134,48 @@ public class DeliveTaskImpl extends ServiceImpl im deliveTaskPO.setShipperName(stockOutOrder.getShipperName()); deliveTaskPO.setCarrier(stockOutOrder.getCarrier()); deliveTaskPO.setCheckQuantity(stockOutOrder.getCheckQuantity());//已复核数量 + // 已拣货数量:需要复核时用 picking_material_detail 汇总(与交接详情一致),否则用 picking_order + BigDecimal pickingQuantity; + if (Integer.valueOf(1).equals(stockOutOrder.getReview())) { + pickingQuantity = pickingMaterialDetailMapper.sumPickingQuantityByOutOrderNumber(orderNumber); + } else { + PickingOrderDTO pickingOrderDTO = new PickingOrderDTO(); + pickingOrderDTO.setOrderNumber(orderNumber); + List pickingList = pickingOrderService.queryList(pickingOrderAssembler.toDO(pickingOrderDTO)); + pickingQuantity = pickingList.isEmpty() ? BigDecimal.ZERO : (pickingList.get(0).getPickingQuantity() != null ? pickingList.get(0).getPickingQuantity() : BigDecimal.ZERO); + } + deliveTaskPO.setPickingQuantity(pickingQuantity != null ? pickingQuantity : BigDecimal.ZERO); + } else { + // 无出库单时仍从拣货单取已拣货数量 + PickingOrderDTO pickingOrderDTO = new PickingOrderDTO(); + pickingOrderDTO.setOrderNumber(orderNumber); + List pickingList = pickingOrderService.queryList(pickingOrderAssembler.toDO(pickingOrderDTO)); + BigDecimal pickingQuantity = pickingList.isEmpty() ? BigDecimal.ZERO : (pickingList.get(0).getPickingQuantity() != null ? pickingList.get(0).getPickingQuantity() : BigDecimal.ZERO); + deliveTaskPO.setPickingQuantity(pickingQuantity); } + // 物料种类数:从出库明细按料号去重统计,pickingQuantity 为 0 的过滤掉(与交接详情一致) + List omdList = outMaterialDetailService.list(new LambdaQueryWrapper() + .eq(OutMaterialDetail::getOutOrderNumber, orderNumber) + .eq(OutMaterialDetail::getDelFlag, 1)); + Set outUniqueIdsWithPicking = null; + if (stockOutOrder != null && Integer.valueOf(1).equals(stockOutOrder.getReview())) { + List ids = pickingMaterialDetailMapper.selectOutUniqueIdsWithPickingByOutOrderNumber(orderNumber); + outUniqueIdsWithPicking = ids != null ? new HashSet<>(ids) : new HashSet<>(); + } + final Set pickingIds = outUniqueIdsWithPicking; + long materialQuantity = omdList.stream() + .filter(d -> { + if (pickingIds != null) { + return pickingIds.contains(d.getUniqueId()); + } + BigDecimal pq = d.getPickingQuantity(); + return pq != null && pq.compareTo(BigDecimal.ZERO) > 0; + }) + .map(d -> d.getMaterialCode() != null && !d.getMaterialCode().isEmpty() ? d.getMaterialCode() : d.getMaterialNo()) + .filter(c -> c != null && !c.isEmpty()) + .distinct() + .count(); + deliveTaskPO.setMaterialQuantity((int) materialQuantity); } } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/deliveTask/repository/todo/DeliveTaskDO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/deliveTask/repository/todo/DeliveTaskDO.java index 8da01aba6..9e2aac9ec 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/deliveTask/repository/todo/DeliveTaskDO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/deliveTask/repository/todo/DeliveTaskDO.java @@ -115,4 +115,7 @@ public class DeliveTaskDO extends BaseVOEntity { @ApiModelProperty("查询类型 1-指派给我的 2-任务") @Excel(name = "查询类型 1-指派给我的 2-任务") private Long tabType; + + @ApiModelProperty("交接查询类型(taskType=7时生效): 1-列表(未交接) 2-历史(已交接),不传默认1") + private Integer handoverQueryType; } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/differentManage/repository/persistence/DifferentManageImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/differentManage/repository/persistence/DifferentManageImpl.java index be3f7fb15..2bfae323a 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/differentManage/repository/persistence/DifferentManageImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/differentManage/repository/persistence/DifferentManageImpl.java @@ -187,10 +187,17 @@ public class DifferentManageImpl extends ServiceImpl investigetionManageDetailList = differentManageDO.getInvestigetionManageDetailList(); investigetionManageDetailList.forEach(e->{ MaterialInventory materialInventory = new MaterialInventory(); - if (e.getInvestigationStatus() != 3){ // 库存更新 +// if (e.getInvestigationStatus() != 3){ // 库存更新 materialInventory = materialInventoryMapper.selectById(e.getMaterialInventoryId()); materialInventory.setInventoryQuantity(e.getInvestigationQuantity()); + if (e.getInvestigationResult() == 1){ + materialInventory.setAllocationQuantity(materialInventory.getAllocationQuantity().add(e.getDifferentQuantity())); + } else if (e.getInvestigationResult() == 2) { + materialInventory.setAllocationQuantity(materialInventory.getAllocationQuantity().subtract(e.getDifferentQuantity())); + }else { + materialInventory.setAllocationQuantity(materialInventory.getAllocationQuantity() == null ? BigDecimal.ZERO : materialInventory.getAllocationQuantity()); } +// } InventoryAdjustmentRecord(e); materialInventoryMapper.updateMaterial(JSONUtil.toBean(JSONUtil.toJsonStr(materialInventory), MaterialInventoryDO.class)); }); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/handoverTaskOrder/service/HandoverTaskOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/handoverTaskOrder/service/HandoverTaskOrderDomainService.java index 185ac586b..66f8801f9 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/handoverTaskOrder/service/HandoverTaskOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/handoverTaskOrder/service/HandoverTaskOrderDomainService.java @@ -17,10 +17,14 @@ import com.mhd.wms.domain.handoverTaskOrder.repository.po.HandoverTaskOrderPO; import com.mhd.wms.domain.handoverTaskOrder.repository.todo.HandoverTaskOrderDO; import com.mhd.wms.domain.inventoryAdjustmentRecord.entity.InventoryAdjustmentRecord; import com.mhd.wms.domain.inventoryAdjustmentRecord.repository.mapper.InventoryAdjustmentRecordMapper; +import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService; +import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO; import com.mhd.wms.domain.materialInventory.entity.MaterialInventory; import com.mhd.wms.domain.materialInventory.repository.mapper.MaterialInventoryMapper; import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail; import com.mhd.wms.domain.outMaterialDetail.repository.mapper.OutMaterialDetailMapper; +import com.mhd.wms.domain.pickingMaterialDetail.repository.mapper.PickingMaterialDetailMapper; +import com.mhd.wms.domain.pickingMaterialDetail.repository.po.PickingMaterialDetailPO; import com.mhd.wms.domain.taskHandoverMaterialDetail.repository.po.TaskHandoverMaterialDetailPO; import com.mhd.wms.domain.shiftManage.repository.po.ShiftManagePO; import com.mhd.wms.domain.shiftManage.repository.todo.ShiftManageDO; @@ -37,6 +41,7 @@ import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -61,6 +66,10 @@ public class HandoverTaskOrderDomainService { private StockOutOrderMapper stockOutOrderMapper; @Autowired private IDeliveTaskService deliveTaskService; + @Autowired + private PickingMaterialDetailMapper pickingMaterialDetailMapper; + @Autowired + private IMaterialBarCodeService materialBarCodeService; /** @@ -95,7 +104,8 @@ public class HandoverTaskOrderDomainService { /** * 获取交接作业单详细信息 - * 物料明细根据复核单(out_material_detail)数据生成,数量使用复核数量(check_quantity),不需要复核时使用拣货数量(picking_quantity) + * 需要复核时:仅从复核单取明细(picking_material_detail 有拣货的 out_unique_id + check_quantity>0),复核几条生成几条 + * 不需要复核时:从出库单取 picking_quantity>0 的明细 */ public HandoverTaskOrderPO getInfo(Long outTaskOrderId) { @@ -103,15 +113,53 @@ public class HandoverTaskOrderDomainService { if (handoverTaskOrderPO == null) { return null; } - // 根据复核单数据生成物料明细:按出库单号查询 out_material_detail,使用复核数量 String orderNumber = handoverTaskOrderPO.getOrderNumber(); if (orderNumber != null && !orderNumber.trim().isEmpty()) { - List outMaterialDetailList = outMaterialDetailMapper.selectList( - new QueryWrapper().lambda() - .eq(OutMaterialDetail::getOutOrderNumber, orderNumber) - .eq(OutMaterialDetail::getDelFlag, 1)); + StockOutOrder stockOutOrder = stockOutOrderMapper.selectOne(new QueryWrapper().lambda() + .eq(StockOutOrder::getOutOrderNumber, orderNumber) + .eq(StockOutOrder::getDelFlag, 1)); + Integer review = stockOutOrder != null ? stockOutOrder.getReview() : null; + // 需要复核时:仅限复核单上的明细(picking_material_detail 有拣货的 unique_id) + java.util.Set outUniqueIdsWithPicking = null; + if (Integer.valueOf(1).equals(review)) { + List ids = pickingMaterialDetailMapper.selectOutUniqueIdsWithPickingByOutOrderNumber(orderNumber); + outUniqueIdsWithPicking = ids != null ? new java.util.HashSet<>(ids) : java.util.Collections.emptySet(); + } + // 需要复核时:与复核单一致,仅取 level=1 父级(复核单只展示父级,子级挂在父级下) + LambdaQueryWrapper omdQuery = new QueryWrapper().lambda() + .eq(OutMaterialDetail::getOutOrderNumber, orderNumber) + .eq(OutMaterialDetail::getDelFlag, 1); + if (Integer.valueOf(1).equals(review)) { + omdQuery.eq(OutMaterialDetail::getLevel, 1); + } + List outMaterialDetailList = outMaterialDetailMapper.selectList(omdQuery); List materialDetailList = new ArrayList<>(); for (OutMaterialDetail omd : outMaterialDetailList) { + BigDecimal handoverQuantity; + BigDecimal pickQty; + if (Integer.valueOf(1).equals(review)) { + // 仅包含复核单上的明细(有拣货)且已复核的 + if (outUniqueIdsWithPicking != null && !outUniqueIdsWithPicking.contains(omd.getUniqueId())) { + continue; + } + if (omd.getCheckQuantity() == null || omd.getCheckQuantity().compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + // pickingQuantity 为 0 的过滤掉:从 picking_material_detail 取拣货数量 + PickingMaterialDetailPO pickingSummary = pickingMaterialDetailMapper.queryTotalsByOutNumberAndBaseId(omd.getUniqueId()); + pickQty = (pickingSummary != null && pickingSummary.getPickingQuantity() != null) ? pickingSummary.getPickingQuantity() : BigDecimal.ZERO; + if (pickQty.compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + handoverQuantity = omd.getCheckQuantity(); + } else { + BigDecimal qty = omd.getPickingQuantity() != null ? omd.getPickingQuantity() : omd.getQuantity(); + if (qty == null || qty.compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + pickQty = qty; + handoverQuantity = qty; + } TaskHandoverMaterialDetailPO detail = new TaskHandoverMaterialDetailPO(); detail.setMaterialDetailId(omd.getMaterialDetailId()); detail.setUniqueId(omd.getUniqueId()); @@ -126,12 +174,7 @@ public class HandoverTaskOrderDomainService { detail.setWeightLimit(omd.getWeightLimit()); detail.setVolumeLimit(omd.getVolumeLimit()); detail.setQuantity(omd.getQuantity()); - detail.setPickingQuantity(omd.getPickingQuantity()); - // 物料明细数量:优先使用复核数量(复核单数据),不需要复核时使用拣货数量 - BigDecimal handoverQuantity = omd.getCheckQuantity(); - if (handoverQuantity == null || handoverQuantity.compareTo(BigDecimal.ZERO) <= 0) { - handoverQuantity = omd.getPickingQuantity() != null ? omd.getPickingQuantity() : omd.getQuantity(); - } + detail.setPickingQuantity(pickQty); detail.setCheckQuantity(handoverQuantity); detail.setPackId(omd.getPackId()); detail.setPackCode(omd.getPackCode()); @@ -257,14 +300,26 @@ public class HandoverTaskOrderDomainService { String orderNumber = handoverTaskOrder.getOrderNumber(); StockOutOrder stockOutOrder = stockOutOrderMapper.selectOne(new QueryWrapper().lambda() .eq(StockOutOrder::getOutOrderNumber, orderNumber)); + if (stockOutOrder == null) { + continue; + } //完成交接状态改为已出库 stockOutOrder.setStatus(9); stockOutOrderMapper.updateById(stockOutOrder); List outMaterialDetailList = outMaterialDetailMapper.selectList(new QueryWrapper().lambda() - .eq(OutMaterialDetail::getOutOrderNumber, orderNumber)); + .eq(OutMaterialDetail::getOutOrderNumber, orderNumber) + .eq(OutMaterialDetail::getDelFlag, 1)); + Integer review = stockOutOrder != null ? stockOutOrder.getReview() : null; for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) { Long materialInventoryId = outMaterialDetail.getMaterialInventoryId(); - BigDecimal checkQuantity = outMaterialDetail.getCheckQuantity(); + // 复核什么扣减什么:需要复核用check_quantity,不需要复核用picking_quantity + BigDecimal effectiveQuantity = Integer.valueOf(1).equals(review) + ? outMaterialDetail.getCheckQuantity() + : (outMaterialDetail.getPickingQuantity() != null ? outMaterialDetail.getPickingQuantity() : outMaterialDetail.getQuantity()); + if (materialInventoryId == null || effectiveQuantity == null || effectiveQuantity.compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + BigDecimal checkQuantity = effectiveQuantity; BigDecimal checkArea = outMaterialDetail.getCheckArea(); BigDecimal checkVolume = outMaterialDetail.getCheckVolume(); BigDecimal checkGrossWeight = outMaterialDetail.getCheckGrossWeight(); @@ -284,13 +339,17 @@ public class HandoverTaskOrderDomainService { //库存数量 BigDecimal oldInventoryQuantity = materialInventoryPO.getInventoryQuantity(); oldInventoryQuantity = oldInventoryQuantity != null ? oldInventoryQuantity : BigDecimal.ZERO; - //冻结数量 + //可用数量 + BigDecimal oldAllocationQuantity = materialInventoryPO.getAllocationQuantity(); + oldAllocationQuantity = oldAllocationQuantity != null ? oldAllocationQuantity : BigDecimal.ZERO; + //冻结数量(出库交接不变动冻结数量) BigDecimal oldFreezeQuantity = materialInventoryPO.getFreezeQuantity(); oldFreezeQuantity = oldFreezeQuantity != null ? oldFreezeQuantity : BigDecimal.ZERO; - //分配后库存数量 + //扣减后库存数量 BigDecimal newInventoryQuantity = oldInventoryQuantity.subtract(checkQuantity); - //分配后冻结数量 - BigDecimal newFreezeQuantity = oldFreezeQuantity.subtract(checkQuantity); + //扣减后可用数量 + BigDecimal newAllocationQuantity = oldAllocationQuantity.subtract(checkQuantity); + BigDecimal newFreezeQuantity = oldFreezeQuantity; @@ -311,6 +370,7 @@ public class HandoverTaskOrderDomainService { BigDecimal newNetWeight = oldNetWeight.subtract(checkNetWeight); materialInventoryPO.setInventoryQuantity(newInventoryQuantity); + materialInventoryPO.setAllocationQuantity(newAllocationQuantity); materialInventoryPO.setFreezeQuantity(newFreezeQuantity); materialInventoryPO.setArea(newArea); materialInventoryPO.setVolume(newVolume); @@ -334,6 +394,9 @@ public class HandoverTaskOrderDomainService { inventoryAdjustmentRecord.setMaterialCode(outMaterialDetail.getMaterialNo()); inventoryAdjustmentRecord.setMaterialName(outMaterialDetail.getCommodityName()); inventoryAdjustmentRecord.setBarCode(outMaterialDetail.getBarCode()); + if (inventoryAdjustmentRecord.getBarCode().equals("")){ + getBarCode(materialInventoryPO, inventoryAdjustmentRecord); + } inventoryAdjustmentRecord.setMaterialBaseInfoId(outMaterialDetail.getMaterialBaseInfoId()); inventoryAdjustmentRecord.setAdjustType(1L); inventoryAdjustmentRecord.setOrganizationId(stockOutOrder.getOrganizationId()); @@ -357,8 +420,8 @@ public class HandoverTaskOrderDomainService { UserPo userPo = loginUser.getUserPo(); if (userPo != null) inventoryAdjustmentRecord.setCreateByName(userPo.getUserName()); inventoryAdjustmentRecord.setCreateTime(new Date()); - inventoryAdjustmentRecord.setAllocationAfterQuantity(materialInventoryPO.getAllocationQuantity()); - inventoryAdjustmentRecord.setAllocationBeforeQuantity(materialInventoryPO.getAllocationQuantity()); + inventoryAdjustmentRecord.setAllocationBeforeQuantity(oldAllocationQuantity); + inventoryAdjustmentRecord.setAllocationAfterQuantity(newAllocationQuantity); inventoryAdjustmentRecord.setFreezeBeforeQuantity(oldFreezeQuantity); inventoryAdjustmentRecord.setFreezeAfterQuantity(newFreezeQuantity); inventoryAdjustmentRecord.setInventoryBeforeQuantity(oldInventoryQuantity); @@ -381,6 +444,23 @@ public class HandoverTaskOrderDomainService { } + private void getBarCode(MaterialInventory materialInventoryPO, InventoryAdjustmentRecord inventoryAdjustmentRecord) { + List materialBarCodePOList = materialBarCodeService.getInfoByMaterialBaseInfoIds(materialInventoryPO.getMaterialBaseInfoId()); + if (materialBarCodePOList != null && !materialBarCodePOList.isEmpty()) { + Map collect = materialBarCodePOList.stream() + .collect(Collectors.toMap( + MaterialBarCodePO::getMaterialBaseInfoId, + po -> po, + (existing, replacement) -> existing + )); + MaterialBarCodePO materialBarCodePO = collect.get(materialInventoryPO.getMaterialBaseInfoId()); + if (materialBarCodePO != null && materialBarCodePO.getBarCode() != null) { + inventoryAdjustmentRecord.setBarCode(materialBarCodePO.getBarCode()); + } + } + } + + /** * @description 任务下发 */ @@ -448,4 +528,4 @@ public class HandoverTaskOrderDomainService { -} \ No newline at end of file +} diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/persistence/OutMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/persistence/OutMaterialDetailImpl.java index 24f29b343..026231beb 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/persistence/OutMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/outMaterialDetail/repository/persistence/OutMaterialDetailImpl.java @@ -15,6 +15,8 @@ import com.mhd.common.security.utils.SecurityUtils; import com.mhd.system.api.model.LoginUser; import com.mhd.wms.domain.inventoryAdjustmentRecord.entity.InventoryAdjustmentRecord; import com.mhd.wms.domain.inventoryAdjustmentRecord.repository.mapper.InventoryAdjustmentRecordMapper; +import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService; +import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO; import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo; import com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper; import com.mhd.wms.domain.materialInventory.entity.MaterialInventory; @@ -31,6 +33,7 @@ import com.mhd.wms.domain.outMaterialDetail.repository.todo.OutMaterialDetailDO; import com.mhd.wms.domain.outMaterialDetailSerialNumber.entity.OutMaterialDetailSerialNumber; import com.mhd.wms.domain.outMaterialDetailSerialNumber.repository.facade.IOutMaterialDetailSerialNumberService; import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO; +import com.mhd.wms.domain.pickingMaterialDetail.repository.facade.IPickingMaterialDetailService; import com.mhd.wms.domain.pickingMaterialDetail.entity.PickingMaterialDetail; import com.mhd.wms.domain.stockOutOrder.entity.StockOutOrder; import com.mhd.wms.domain.stockOutOrder.repository.mapper.StockOutOrderMapper; @@ -72,6 +75,10 @@ public class OutMaterialDetailImpl extends ServiceImpl().lambda().eq(StockOutOrder::getOutOrderNumber, outOrderNumber)); for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) { BigDecimal nowAllocationQuantity = outMaterialDetail.getNowAllocationQuantity(); - if (nowAllocationQuantity == null && nowAllocationQuantity.compareTo(BigDecimal.ZERO) <= 0) { + if (nowAllocationQuantity == null || nowAllocationQuantity.compareTo(BigDecimal.ZERO) <= 0) { continue; } Long materialInventoryId = outMaterialDetail.getMaterialInventoryId(); @@ -473,6 +482,9 @@ public class OutMaterialDetailImpl extends ServiceImpl materialBarCodePOList = materialBarCodeService.getInfoByMaterialBaseInfoIds(materialInventoryPO.getMaterialBaseInfoId()); + if (materialBarCodePOList != null && !materialBarCodePOList.isEmpty()) { + Map collect = materialBarCodePOList.stream() + .collect(Collectors.toMap( + MaterialBarCodePO::getMaterialBaseInfoId, + po -> po, + (existing, replacement) -> existing + )); + MaterialBarCodePO materialBarCodePO = collect.get(materialInventoryPO.getMaterialBaseInfoId()); + if (materialBarCodePO != null && materialBarCodePO.getBarCode() != null) { + inventoryAdjustmentRecord.setBarCode(materialBarCodePO.getBarCode()); + } + } + } + public synchronized void childrenxgkc(List outMaterialDetailList,String outOrderNumber,LoginUser loginUser) { StockOutOrder stockOutOrder = stockOutOrderMapper.selectOne(new QueryWrapper().lambda().eq(StockOutOrder::getOutOrderNumber, outOrderNumber)); for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) { BigDecimal nowAllocationQuantity = outMaterialDetail.getNowAllocationQuantity(); - if (nowAllocationQuantity == null && nowAllocationQuantity.compareTo(BigDecimal.ZERO) <= 0) { + if (nowAllocationQuantity == null || nowAllocationQuantity.compareTo(BigDecimal.ZERO) <= 0) { continue; } Long materialInventoryId = outMaterialDetail.getMaterialInventoryId(); @@ -564,6 +592,9 @@ public class OutMaterialDetailImpl extends ServiceImpl outOrderAbnormalList = new ArrayList<>(); for (OutMaterialDetail outMaterialDetail : outMaterialDetailList){ //复核 - if (outMaterialDetail.getCheckQuantity().compareTo(outMaterialDetail.getQuantity()) != 0){ + if (outMaterialDetail.getCheckQuantity().compareTo(outMaterialDetail.getAllocationQuantity()) != 0){ //判断是否存在异常 根据设置的是否允许超收 取值动态赋值 先默认写死 收货异常 OutOrderAbnormal outOrderAbnormal = new OutOrderAbnormal(); //赋值基础数据 BeanUtils.copyProperties(OutOrderAbnormalBaseDO, outOrderAbnormal); //赋值物料信息 BeanUtils.copyProperties(outMaterialDetail, outOrderAbnormal, IgnoreNullUtil.getNullPropertyNames(outMaterialDetail)); - outOrderAbnormal.setAbnormalNumber(OrderSequence.getOrderCode("FSYC")); + outOrderAbnormal.setAbnormalNumber(OrderSequence.getOrderCode("FHYC")); outOrderAbnormal.setAbnormalType(2);//复核异常 outOrderAbnormal.setActualQuantity(outMaterialDetail.getCheckQuantity()); + outOrderAbnormal.setQuantity(outMaterialDetail.getAllocationQuantity()); if (outMaterialDetail.getCheckQuantity().compareTo(outMaterialDetail.getPickingQuantity()) > 0){ //复核数量大于拣货数量 outOrderAbnormal.setAbnormalReason("复核数量大于拣货数量"); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/repository/facade/IPickingMaterialDetailService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/repository/facade/IPickingMaterialDetailService.java index adf4361c3..95becdcce 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/repository/facade/IPickingMaterialDetailService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/pickingMaterialDetail/repository/facade/IPickingMaterialDetailService.java @@ -9,6 +9,7 @@ import com.mhd.wms.domain.pickingOrder.repository.po.PickingOrderPO; import com.mhd.wms.domain.pickingOrder.repository.todo.PickingOrderDO; import org.apache.ibatis.annotations.Param; +import java.math.BigDecimal; import java.util.List; /** @@ -26,6 +27,16 @@ public interface IPickingMaterialDetailService extends IService selectOutUniqueIdsWithPickingByOutOrderNumber(@Param("outOrderNumber") String outOrderNumber); + /** * @description 根据拣货单增加拣货数量 * @author ZhouGY @@ -33,4 +49,21 @@ public interface PickingMaterialDetailMapper extends BaseMapper().lambda() .eq(StockOutOrder::getOutOrderNumber, pickingOrderPODb.getOrderNumber())); - if (pickingQuantity.compareTo(stockOutOrderDb.getQuantity()) >= 0){ + // 与下发拣货数量比较:只下发部分时用拣货计划数量,否则用出库单总数量 + List allPickingOrders = pickingOrderService.list(new QueryWrapper().lambda() + .eq(PickingOrder::getDelFlag, 1) + .eq(PickingOrder::getOrderNumber, pickingOrderPODb.getOrderNumber())); + BigDecimal totalPickingPlanQuantity = allPickingOrders.stream() + .map(PickingOrder::getQuantity).filter(java.util.Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal thresholdQuantity = (totalPickingPlanQuantity != null && totalPickingPlanQuantity.compareTo(BigDecimal.ZERO) > 0) + ? totalPickingPlanQuantity : (stockOutOrderDb.getQuantity() != null ? stockOutOrderDb.getQuantity() : BigDecimal.ZERO); + // 所有拣货单都已完成(status=3)时直接视为拣货完成,不依赖数量比较 + boolean allPickingOrdersDone = allPickingOrders.stream().allMatch(o -> o.getStatus() != null && o.getStatus() == 3); + if (allPickingOrdersDone || pickingQuantity.compareTo(thresholdQuantity) >= 0){ status = 7; if (pickingOrderPODb.getReview() == 2){ status = 9; @@ -619,6 +629,8 @@ public class PickingOrderDomainService { .set(PickingOrder::getUpdateByName, loginUser.getUsername()) .set(PickingOrder::getUpdateTime, new Date()) .eq(PickingOrder::getPickingOrderId, pickingOrderDO.getPickingOrderId())); + // 同步内存状态,确保后续 updateStockOutOrder 查DB时该单已是 status=3 + pickingOrderPO.setStatus(3); if (pickingOrderPO.getType() == 2){ //将分配数量分给子单 pickingMaterialDetailService.waveAssignUpdate(pickingOrderPO.getOrderNumber(), 2); @@ -633,6 +645,20 @@ public class PickingOrderDomainService { outOrderAbnormalService.genOutOrderAbnormal(outOrderAbnormalBaseDO, 1); //更新出库单状态 updateStockOutOrder(pickingOrderPO); + // 点击完成拣货时,不管数量多少,强制将出库单状态推进到拣货完成(7)或已出库(9) + if (1 == pickingOrderPO.getType()) { + StockOutOrder forceUpdate = new StockOutOrder(); + forceUpdate.setOutOrderNumber(pickingOrderPO.getOrderNumber()); + int forceStatus = (pickingOrderPO.getReview() != null && pickingOrderPO.getReview() == 2) ? 9 : 7; + forceUpdate.setStatus(forceStatus); + forceUpdate.setUpdateBy(loginUser.getUserid()); + forceUpdate.setUpdateByName(loginUser.getUsername()); + forceUpdate.setUpdateTime(new Date()); + stockOutOrderService.update(forceUpdate, new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper().lambda().eq(StockOutOrder::getOutOrderNumber, pickingOrderPO.getOrderNumber())); + if (pickingOrderPO.getReview() != null && pickingOrderPO.getReview() == 2) { + genHandoverTaskOrder(pickingOrderPO); + } + } //同步BMS结算系统,生成业务单据 //这里只有不需要复核的时候才推送,需要复核的在复核流程推送 if(stockOutOrder.getReview()==2){ @@ -803,4 +829,4 @@ public class PickingOrderDomainService { } deliveTaskService.batchInsert(deliveTaskDOList); } -} \ No newline at end of file +} diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/receiptMaterialDetail/repository/persistence/ReceiptMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/receiptMaterialDetail/repository/persistence/ReceiptMaterialDetailImpl.java index f74ef0c0a..9c459570e 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/receiptMaterialDetail/repository/persistence/ReceiptMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/receiptMaterialDetail/repository/persistence/ReceiptMaterialDetailImpl.java @@ -615,6 +615,7 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl queryWrapper = new QueryWrapper<>(); queryWrapper.eq("unique_id", receiptMaterialDetailPO.getInUniqueId()); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/repository/persistence/ShelfMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/repository/persistence/ShelfMaterialDetailImpl.java index 9a68fb0ad..b51e059e5 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/repository/persistence/ShelfMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/shelfMaterialDetail/repository/persistence/ShelfMaterialDetailImpl.java @@ -87,9 +87,18 @@ public class ShelfMaterialDetailImpl extends ServiceImpl shelfParentIds = shelfMaterialDetailPOList.stream() + .filter(po -> po.getUniqueId() != null) + .map(ShelfMaterialDetailPO::getUniqueId) + .collect(Collectors.toSet()); List receiptMaterialDetailPOParentList = shelfMaterialDetailPOList - .stream().filter(e -> 1 == e.getLevel()).collect(Collectors.toList()); + .stream().filter(e -> e.getLevel() != null && ( + 1 == e.getLevel() + || (2 == e.getLevel() && (e.getParentUniqueId() == null || Long.valueOf(0).equals(e.getParentUniqueId()))) + || (2 == e.getLevel() && e.getParentUniqueId() != null && !shelfParentIds.contains(e.getParentUniqueId())) + )).collect(Collectors.toList()); // 递归查询子集 for(ShelfMaterialDetailPO materialDetailPO : receiptMaterialDetailPOParentList){ List children = getChildren(materialDetailPO.getUniqueId(), shelfMaterialDetailPOList, 2); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/shiftManage/repository/todo/ContainerShiftDO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/shiftManage/repository/todo/ContainerShiftDO.java index 30876baea..cc818451a 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/shiftManage/repository/todo/ContainerShiftDO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/shiftManage/repository/todo/ContainerShiftDO.java @@ -63,6 +63,19 @@ public class ContainerShiftDO implements Serializable { @Excel(name = "库位名称") private String storageLocationName; + @ApiModelProperty("目标库区id(容器移位时 PDA 可能放在父级)") + private Long newStorageSectionId; + @ApiModelProperty("目标库区编码") + private String newStorageCode; + @ApiModelProperty("目标库区名称") + private String newStorageName; + @ApiModelProperty("目标库位id(容器移位时 PDA 可能放在父级)") + private Long newStorageLocationId; + @ApiModelProperty("目标库位编码") + private String newStorageLocationCode; + @ApiModelProperty("目标库位名称") + private String newStorageLocationName; + @ApiModelProperty("批次号") @Excel(name = "批次号") private String batchNumber; 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 f24ee0b24..39b22396d 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 @@ -570,7 +570,7 @@ public class ShiftManageDomainService { } /** - * @description app 容器移位 + * @description app 容器移位(PDA 端直接调用 PC 端移位流程:insert + finishShiftByPC) * @author ZhouGY * @date 2024/7/30 14:24 * @param containerShiftDOList @@ -580,7 +580,11 @@ public class ShiftManageDomainService { public Boolean appMoveContainShift(List containerShiftDOList){ LoginUser loginUser = SecurityUtils.getLoginUser(); String shiftNumber = OrderSequence.getOrderCode("YW"); - List shiftMaterialDetailDOList = shiftMaterialDetailService.appMoveContainShift(containerShiftDOList, shiftNumber); + // 仅构建移位明细结构,不执行库存变更(库存变更由 PC finishShiftByPC 统一处理) + List shiftMaterialDetailDOList = shiftMaterialDetailService.buildShiftMaterialDetailListFromContainerShift(containerShiftDOList); + if (CollectionUtils.isEmpty(shiftMaterialDetailDOList)) { + throw new ServiceException("容器移位明细不能为空"); + } ShiftManageDO shiftManageDO = new ShiftManageDO(); AssociationWarehouseCacheDO associationWarehouseCacheDO = SystemServiceCacheUtil.getAssociationWarehouseCache(loginUser.getUserid()); shiftManageDO.setWarehouseId(associationWarehouseCacheDO.getWarehouseId()); @@ -588,7 +592,7 @@ public class ShiftManageDomainService { shiftManageDO.setWarehouseName(associationWarehouseCacheDO.getWarehouseName()); shiftManageDO.setShiftNumber(shiftNumber); shiftManageDO.setRemark("容器移位生成"); - shiftManageDO.setShiftStatus(4);//默认以为完成 + shiftManageDO.setShiftStatus(1);// 先创建为已创建状态,由 finishShiftByPC 完成 shiftManageDO.setAuditStatus(3); shiftManageDO.setAuditBy(loginUser.getUserid()); shiftManageDO.setAuditByName(loginUser.getUsername()); @@ -601,12 +605,22 @@ public class ShiftManageDomainService { shiftManageDO.setQuantity(quantity); shiftManageDO.setShiftQuantity(quantity); shiftManageDO.setShiftMaterialDetailList(shiftMaterialDetailDOList); - //新增移位单 + // 1. 新增移位单(PC insert) insert(shiftManageDO); - //生成移位追溯记录 + // 2. 获取新创建的移位单 ShiftManagePO shiftManagePO = shiftManageService.getInfoByShiftNumber(shiftManageDO.getShiftNumber()); - genInventoryStandingDetail(shiftManagePO); - return true; + if (shiftManagePO == null) { + throw new ServiceException("容器移位单创建失败"); + } + // 3. 调用 PC 完成移位(库存变更、库存调整记录、移位追溯由 finishShiftByPC 统一处理) + ShiftManageDO finishShiftDO = new ShiftManageDO(); + finishShiftDO.setShiftManageId(shiftManagePO.getShiftManageId()); + ShiftMaterialDetailDO queryDO = new ShiftMaterialDetailDO(); + queryDO.setShiftNumber(shiftNumber); + List shiftMaterialDetailPOList = shiftMaterialDetailService.queryListChildren(queryDO); + List finishDetailList = shiftMaterialDetailPOList.stream().map(po -> convertShiftDetailPOToDO(po)).collect(Collectors.toList()); + finishShiftDO.setShiftMaterialDetailList(finishDetailList); + return finishShiftByPC(finishShiftDO); } /** @@ -660,7 +674,14 @@ public class ShiftManageDomainService { shiftManage.setShiftQuantity(shiftManageDO.getShiftQuantity()); shiftManage.setShiftMaterialQuantity(shiftManageDO.getShiftMaterialQuantity()); int shiftStatus = 3; - if(shiftManageDO.getShiftQuantity().compareTo(shiftManagePO.getQuantity()) >= 0){ + // 多条物料时,需要查询所有明细,判断是否全部已完成移位(shiftQuantity >= quantity),才能置为已完成 + ShiftMaterialDetailDO queryDetailDO = new ShiftMaterialDetailDO(); + queryDetailDO.setShiftNumber(shiftManagePO.getShiftNumber()); + List allDetails = shiftMaterialDetailService.queryList(queryDetailDO); + boolean allDone = !allDetails.isEmpty() && allDetails.stream().allMatch(d -> + d.getShiftQuantity() != null && d.getQuantity() != null + && d.getShiftQuantity().compareTo(d.getQuantity()) >= 0); + if (allDone) { shiftStatus = 4; } shiftManage.setShiftStatus(shiftStatus); @@ -691,31 +712,46 @@ public class ShiftManageDomainService { ShiftMaterialDetailDO shiftMaterialDetailDO = new ShiftMaterialDetailDO(); shiftMaterialDetailDO.setShiftNumber(shiftNumber); List shiftMaterialDetailPOList = shiftMaterialDetailService.queryListChildren(shiftMaterialDetailDO); - // 避免 NPE:getMaterialMoreDetailList 可能为 null;同一 shift 下 shiftNumber 重复需合并 - Map> MaterialMoreDetailMap = shiftMaterialDetailList.stream() - .filter(d -> d.getShiftNumber() != null) - .collect(Collectors.toMap( - ShiftMaterialDetailDO::getShiftNumber, - d -> d.getMaterialMoreDetailList() != null ? d.getMaterialMoreDetailList() : new ArrayList<>(), - (a, b) -> a - )); + // key by uniqueId so each detail maps to its own materialMoreDetailList + Map> materialMoreDetailMap = new java.util.HashMap<>(); + for (ShiftMaterialDetailDO d : shiftMaterialDetailList) { + if (d.getUniqueId() != null) { + materialMoreDetailMap.put(d.getUniqueId(), + d.getMaterialMoreDetailList() != null ? d.getMaterialMoreDetailList() : new ArrayList<>()); + } + if (!CollectionUtils.isEmpty(d.getChildren())) { + for (ShiftMaterialDetailDO child : d.getChildren()) { + if (child.getUniqueId() != null) { + materialMoreDetailMap.put(child.getUniqueId(), + child.getMaterialMoreDetailList() != null ? child.getMaterialMoreDetailList() + : (d.getMaterialMoreDetailList() != null ? d.getMaterialMoreDetailList() : new ArrayList<>())); + } + } + } + } for (ShiftMaterialDetailPO shiftMaterialDetailPO : shiftMaterialDetailPOList){ MaterialInventory materialInventoryOldDb = materialInventoryService.getById(shiftMaterialDetailPO.getMaterialInventoryId()); - BigDecimal shiftQuantity = shiftMaterialDetailPO.getShiftQuantity(); - //构建新物料库存信息 - shiftMaterialDetailPO.setMaterialMoreDetailList(MaterialMoreDetailMap.get(shiftMaterialDetailPO.getShiftNumber())); -// shiftMaterialDetailPO.setNetWeight(materialInventoryOldDb.getNetWeight()); -// shiftMaterialDetailPO.setGrossWeight(materialInventoryOldDb.getGrossWeight()); -// shiftMaterialDetailPO.setVolume(materialInventoryOldDb.getVolume()); -// shiftMaterialDetailPO.setArea(materialInventoryOldDb.getArea()); -// shiftMaterialDetailPO.setMaterialInventoryId(materialInventoryOldDb.getMaterialInventoryId()); - materialInventoryNowList.add(genMaterialInventory(shiftMaterialDetailPO)); List shiftMaterialDetailPOChildrenList = shiftMaterialDetailPO.getChildren(); - for (ShiftMaterialDetailPO shiftMaterialDetailPOChildren : shiftMaterialDetailPOChildrenList){ - shiftQuantity = shiftQuantity.add(shiftMaterialDetailPOChildren.getShiftQuantity()); - //构建新物料库存信息 - materialInventoryNowList.add(genMaterialInventory(shiftMaterialDetailPOChildren)); - }; + boolean hasChildren = !CollectionUtils.isEmpty(shiftMaterialDetailPOChildrenList); + BigDecimal shiftQuantity; + if (hasChildren) { + shiftQuantity = shiftMaterialDetailPOChildrenList.stream() + .map(c -> c.getShiftQuantity() != null ? c.getShiftQuantity() : BigDecimal.ZERO) + .reduce(BigDecimal.ZERO, BigDecimal::add); + shiftMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailMap.get(shiftMaterialDetailPO.getUniqueId())); + for (ShiftMaterialDetailPO shiftMaterialDetailPOChildren : shiftMaterialDetailPOChildrenList) { + List childMoreDetail = materialMoreDetailMap.get(shiftMaterialDetailPOChildren.getUniqueId()); + if (childMoreDetail == null) { + childMoreDetail = materialMoreDetailMap.get(shiftMaterialDetailPO.getUniqueId()); + } + shiftMaterialDetailPOChildren.setMaterialMoreDetailList(childMoreDetail); + materialInventoryNowList.add(genMaterialInventory(shiftMaterialDetailPOChildren)); + } + } else { + shiftQuantity = shiftMaterialDetailPO.getShiftQuantity() != null ? shiftMaterialDetailPO.getShiftQuantity() : BigDecimal.ZERO; + shiftMaterialDetailPO.setMaterialMoreDetailList(materialMoreDetailMap.get(shiftMaterialDetailPO.getUniqueId())); + materialInventoryNowList.add(genMaterialInventory(shiftMaterialDetailPO)); + } if (materialInventoryOldDb.getInventoryQuantity().compareTo(shiftQuantity) < 0){ throw new ServiceException("物料原库位下的物料库存不足,不能进行移位"); } @@ -850,6 +886,9 @@ public class ShiftManageDomainService { } private void BatchAttributeAssignment(List materialMoreDetailList, MaterialInventoryDO materialInventoryDONow) { + if (CollectionUtils.isEmpty(materialMoreDetailList)) { + return; + } for (MaterialMoreDetailPO materialMoreDetailPO : materialMoreDetailList) { if (materialMoreDetailPO == null || materialMoreDetailPO.getBatchLabels() == null) { continue; @@ -886,12 +925,41 @@ public class ShiftManageDomainService { } } - public Date stringToDate(String dateStr) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - try { - return sdf.parse(dateStr); - } catch (ParseException e) { - throw new RuntimeException(e); + public Date stringToDate(String dateStr) { + if (dateStr == null || dateStr.trim().isEmpty()) { + return null; } + // 去除首尾空格 + dateStr = dateStr.trim(); + // 定义可能的格式 + String[] patterns = { + "yyyy-MM-dd HH:mm:ss", // 完整时间 + "yyyy-MM-dd HH:mm", // 到分钟 + "yyyy-MM-dd", // 只有日期 (报错的这个) + "yyyy/MM/dd HH:mm:ss", + "yyyy/MM/dd" + }; + for (String pattern : patterns) { + try { + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + // 设置严格解析,避免将 2026-03-0112:00:00 这种错误数据解析成功 + sdf.setLenient(false); + return sdf.parse(dateStr); + } catch (ParseException e) { + } + } + throw new RuntimeException("无法解析的日期格式: " + dateStr + ",支持格式:yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss"); + } + + /** PO 转 DO,含 children 递归转换 */ + private ShiftMaterialDetailDO convertShiftDetailPOToDO(ShiftMaterialDetailPO po) { + ShiftMaterialDetailDO d = new ShiftMaterialDetailDO(); + BeanUtils.copyProperties(po, d, "children"); + if (!CollectionUtils.isEmpty(po.getChildren())) { + List childList = po.getChildren().stream() + .map(this::convertShiftDetailPOToDO).collect(Collectors.toList()); + d.setChildren(childList); + } + return d; } } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/shiftMaterialDetail/repository/facade/IShiftMaterialDetailService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/shiftMaterialDetail/repository/facade/IShiftMaterialDetailService.java index 7fcb83295..7acd7960e 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/shiftMaterialDetail/repository/facade/IShiftMaterialDetailService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/shiftMaterialDetail/repository/facade/IShiftMaterialDetailService.java @@ -81,6 +81,13 @@ public interface IShiftMaterialDetailService extends IService appMoveContainShift(List containerShiftDOList, String shiftNumber); + /** + * 容器移位:仅构建移位明细结构(供 PDA 调用 PC 移位流程使用,不执行库存变更) + * @param containerShiftDOList 容器移位明细 + * @return 移位物料明细列表(主项含 children 子项) + */ + public List buildShiftMaterialDetailListFromContainerShift(List containerShiftDOList); + /** * @description 批量修改物料信息 * @author ZhouGY 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 27b1e5aae..8c807f43d 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 @@ -408,6 +408,62 @@ public class ShiftMaterialDetailImpl extends ServiceImpl buildShiftMaterialDetailListFromContainerShift(List containerShiftDOList) { + List shiftMaterialDetailDOList = new ArrayList<>(); + for (ContainerShiftDO containerShiftDO : containerShiftDOList){ + List shiftMoveMaterialQuantityList = containerShiftDO.getChildren(); + if (CollectionUtils.isEmpty(shiftMoveMaterialQuantityList)) continue; + BigDecimal totalShiftQuantity = BigDecimal.ZERO; + for (ShiftMoveMaterialQuantityPO c : shiftMoveMaterialQuantityList) { + if (c.getShiftQuantity() != null && c.getShiftQuantity().compareTo(BigDecimal.ZERO) > 0) { + totalShiftQuantity = totalShiftQuantity.add(c.getShiftQuantity()); + } + } + 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(totalShiftQuantity) < 0){ + throw new ServiceException("容器【" + containerShiftDO.getContainerTypeName() + "】下的物料库存不足,不能进行移位"); + } + // 容器移位只生成扁平明细(每条目标一条记录),不生成父项,避免 insert 时父+子两条记录、updateMaterialInventory 重复计算 + for (ShiftMoveMaterialQuantityPO shiftMoveMaterialQuantityPO : shiftMoveMaterialQuantityList) { + if (ObjectUtil.isNull(shiftMoveMaterialQuantityPO.getShiftQuantity()) || shiftMoveMaterialQuantityPO.getShiftQuantity().compareTo(BigDecimal.ZERO) == 0){ + continue; + } + ShiftMaterialDetailDO detailDO = new ShiftMaterialDetailDO(); + detailDO.setMaterialInventoryId(containerShiftDO.getMaterialInventoryId()); + detailDO.setMaterialBaseInfoId(containerShiftDO.getMaterialBaseInfoId()); + detailDO.setQuantity(shiftMoveMaterialQuantityPO.getShiftQuantity()); + detailDO.setShiftQuantity(shiftMoveMaterialQuantityPO.getShiftQuantity()); + detailDO.setNewStorageLocationId(shiftMoveMaterialQuantityPO.getNewStorageLocationId()); + detailDO.setNewStorageSectionId(shiftMoveMaterialQuantityPO.getNewStorageSectionId()); + detailDO.setNewStorageCode(shiftMoveMaterialQuantityPO.getNewStorageCode()); + detailDO.setNewStorageName(shiftMoveMaterialQuantityPO.getNewStorageName()); + detailDO.setNewStorageLocationCode(shiftMoveMaterialQuantityPO.getNewStorageLocationCode()); + detailDO.setNewStorageLocationName(shiftMoveMaterialQuantityPO.getNewStorageLocationName()); + detailDO.setContainerId(shiftMoveMaterialQuantityPO.getContainerId()); + detailDO.setContainerCode(shiftMoveMaterialQuantityPO.getContainerCode()); + detailDO.setContainerType(shiftMoveMaterialQuantityPO.getContainerType()); + detailDO.setContainerTypeName(shiftMoveMaterialQuantityPO.getContainerTypeName()); + detailDO.setLevel(1); + detailDO.setChildren(null); + if (shiftMoveMaterialQuantityPO.getNetWeight() != null) detailDO.setNetWeight(shiftMoveMaterialQuantityPO.getNetWeight()); + if (shiftMoveMaterialQuantityPO.getGrossWeight() != null) detailDO.setGrossWeight(shiftMoveMaterialQuantityPO.getGrossWeight()); + if (shiftMoveMaterialQuantityPO.getVolume() != null) detailDO.setVolume(shiftMoveMaterialQuantityPO.getVolume()); + if (shiftMoveMaterialQuantityPO.getArea() != null) detailDO.setArea(shiftMoveMaterialQuantityPO.getArea()); + shiftMaterialDetailDOList.add(detailDO); + } + } + return shiftMaterialDetailDOList; + } + /** * 容器移位生成库存调整记录:原库位减少记录 + 各目标库位增加记录 */ @@ -416,9 +472,9 @@ public class ShiftMaterialDetailImpl extends ServiceImpl shiftMoveMaterialQuantityList, String shiftNumber) { LoginUser loginUser = SecurityUtils.getLoginUser(); MaterialBaseInfoPO materialBaseInfo = materialBaseInfoService.getInfo(containerShiftDO.getMaterialBaseInfoId()); - String materialCode = materialBaseInfo != null ? materialBaseInfo.getMaterialCode() : ""; - String materialName = materialBaseInfo != null ? materialBaseInfo.getMaterialName() : ""; - String barCode = materialBaseInfo != null ? materialBaseInfo.getBarCode() : ""; + String materialCode = materialBaseInfo != null && materialBaseInfo.getMaterialCode() != null ? materialBaseInfo.getMaterialCode() : ""; + String materialName = materialBaseInfo != null && materialBaseInfo.getMaterialName() != null ? materialBaseInfo.getMaterialName() : ""; + String barCode = materialBaseInfo != null && materialBaseInfo.getBarCode() != null ? materialBaseInfo.getBarCode() : ""; BigDecimal oldQty = materialInventoryOldDb.getInventoryQuantity() != null ? materialInventoryOldDb.getInventoryQuantity() : BigDecimal.ZERO; BigDecimal oldAlloc = materialInventoryOldDb.getAllocationQuantity() != null ? materialInventoryOldDb.getAllocationQuantity() : BigDecimal.ZERO; BigDecimal newQty = oldQty.subtract(totalShiftQuantity).max(BigDecimal.ZERO); @@ -442,13 +498,15 @@ public class ShiftMaterialDetailImpl extends ServiceImpl qw = new LambdaQueryWrapper<>(); + qw.eq(MaterialInventory::getWarehouseId, shiftMaterialDetailDO.getNewWarehouseId()); + qw.eq(MaterialInventory::getStorageSectionId, shiftMaterialDetailDO.getNewStorageSectionId()); + qw.eq(MaterialInventory::getStorageLocationId, shiftMaterialDetailDO.getNewStorageLocationId()); + qw.eq(MaterialInventory::getMaterialBaseInfoId, shiftMaterialDetailDO.getMaterialBaseInfoId()); + qw.eq(MaterialInventory::getBatchNumber, shiftMaterialDetailDO.getBatchNumber() != null ? shiftMaterialDetailDO.getBatchNumber() : ""); + qw.eq(MaterialInventory::getMaterialStatusCode, shiftMaterialDetailDO.getMaterialStatusCode() != null ? shiftMaterialDetailDO.getMaterialStatusCode() : ""); + if (ObjectUtil.isNotNull(shiftMaterialDetailDO.getContainerId()) && shiftMaterialDetailDO.getContainerId() != 0) { + qw.eq(MaterialInventory::getContainerId, shiftMaterialDetailDO.getContainerId()); + } else { + qw.and(w -> w.isNull(MaterialInventory::getContainerId).or().eq(MaterialInventory::getContainerId, 0)); + } + try { + return materialInventoryService.getOne(qw); + } catch (Exception e) { + return null; + } } /** diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/service/StockOutOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/service/StockOutOrderDomainService.java index 80401d977..41928f335 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/service/StockOutOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutOrder/service/StockOutOrderDomainService.java @@ -23,6 +23,8 @@ import com.mhd.wms.domain.handoverTaskOrder.repository.todo.HandoverTaskOrderDO; import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO; import com.mhd.wms.domain.inventoryStandingDetail.repository.facade.IInventoryStandingDetailService; import com.mhd.wms.domain.inventoryStandingDetail.repository.todo.InventoryStandingDetailDO; +import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService; +import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO; import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo; import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService; import com.mhd.wms.domain.materialBaseInfo.repository.mapper.MaterialBaseInfoMapper; @@ -498,9 +500,29 @@ public class StockOutOrderDomainService { } /** - * 获取出库单详细信息 + * 获取出库单详细信息(PDA复核管理查询详情) + * 复核场景下与PC端getCheckInfo保持一致,返回拣货下发时的完整数据(树形结构、拣货汇总、批次属性等) */ public StockOutOrderPO getInfoByApp(Long outOrderId) { + StockOutOrder stockOutOrder = stockOutOrderService.getById(outOrderId); + if (stockOutOrder == null) { + throw new ServiceException("出库单不存在"); + } + // 复核场景:与PC端getCheckInfo保持一致,返回拣货下发的完整数据(含历史记录 status=9 已出库,与列表详情一致) + if (stockOutOrder.getReview() != null && stockOutOrder.getReview() == 1 + && stockOutOrder.getStatus() != null && (stockOutOrder.getStatus() == 7 || stockOutOrder.getStatus() == 8 || stockOutOrder.getStatus() == 9)) { + StockOutOrderDO stockOutOrderDO = new StockOutOrderDO(); + stockOutOrderDO.setOutOrderNumber(stockOutOrder.getOutOrderNumber()); + StockOutOrderPO stockOutOrderPO = getCheckInfo(stockOutOrderDO); + // PDA端需扁平化树形结构,与PC端展开后的展示条数一致(父项+子项全部展开为独立行) + List flattenedList = flattenMaterialDetailTree(stockOutOrderPO.getMaterialDetailList()); + stockOutOrderPO.setMaterialDetailList(flattenedList); + if (stockOutOrderPO.getOutMaterialCheckPO() != null) { + stockOutOrderPO.getOutMaterialCheckPO().setCount(flattenedList.size()); + } + return stockOutOrderPO; + } + // 非复核场景:保持原有逻辑 StockOutOrderPO stockOutOrderPO = stockOutOrderService.getInfo(outOrderId); OutMaterialDetailDO outMaterialDetailDO = new OutMaterialDetailDO(); outMaterialDetailDO.setOutOrderNumber(stockOutOrderPO.getOutOrderNumber()); @@ -734,6 +756,9 @@ public class StockOutOrderDomainService { .in(StockOutOrder::getOutOrderId, outOrderIds)); } + @Autowired + private IMaterialBarCodeService materialBarCodeService; + /** * 获取出库单复核详细信息 */ @@ -756,6 +781,21 @@ public class StockOutOrderDomainService { OutMaterialDetailDO outMaterialDetailDO = new OutMaterialDetailDO(); outMaterialDetailDO.setOutOrderNumber(stockOutOrderPO.getOutOrderNumber()); List outMaterialDetailPOList = outMaterialDetailService.queryListChildren(outMaterialDetailDO); + for (OutMaterialDetailPO outMaterialDetailPO : outMaterialDetailPOList) {//获取物料条形码 + List materialBarCodePOList = materialBarCodeService.getInfoByMaterialBaseInfoIds(outMaterialDetailPO.getMaterialBaseInfoId()); + if (materialBarCodePOList != null && !materialBarCodePOList.isEmpty()) { + Map collect = materialBarCodePOList.stream() + .collect(Collectors.toMap( + MaterialBarCodePO::getMaterialBaseInfoId, + po -> po, + (existing, replacement) -> existing + )); + MaterialBarCodePO materialBarCodePO = collect.get(outMaterialDetailPO.getMaterialBaseInfoId()); + if (materialBarCodePO != null && materialBarCodePO.getBarCode() != null) { + outMaterialDetailPO.setBarCode(materialBarCodePO.getBarCode()); + } + } + } for (OutMaterialDetailPO outMaterialDetailPO : outMaterialDetailPOList) { outMaterialDetailPO.setMaterialCode(outMaterialDetailPO.getMaterialNo()); outMaterialDetailPO.setMaterialName(outMaterialDetailPO.getCommodityName()); @@ -770,7 +810,21 @@ public class StockOutOrderDomainService { outMaterialDetailPO.setCheckVolume(pickingMaterialDetailPO.getTotalVolume()); outMaterialDetailPO.setCheckNetWeight(pickingMaterialDetailPO.getTotalNetWeight()); outMaterialDetailPO.setCheckGrossWeight(pickingMaterialDetailPO.getTotalGrossWeight()); - outMaterialDetailPO.setWaitCheckQuantity(outMaterialDetailPO.getPickingQuantity()); + // 拣货数量:优先 picking_material_detail,否则 out_material_detail + BigDecimal pickQty = (pickingMaterialDetailPO.getPickingQuantity() != null && pickingMaterialDetailPO.getPickingQuantity().compareTo(BigDecimal.ZERO) > 0) + ? pickingMaterialDetailPO.getPickingQuantity() : outMaterialDetailPO.getPickingQuantity(); + BigDecimal checkQty = outMaterialDetailPO.getCheckQuantity() != null ? outMaterialDetailPO.getCheckQuantity() : BigDecimal.ZERO; + // 待复核数量 = 拣货数量 - 已复核数量(复核提交后应减少) + BigDecimal waitQty = (pickQty != null ? pickQty : BigDecimal.ZERO).subtract(checkQty); + if (waitQty.compareTo(BigDecimal.ZERO) < 0) { + waitQty = BigDecimal.ZERO; + } + outMaterialDetailPO.setWaitCheckQuantity(waitQty); + // quantity=PC下发时的拣货数量,actualQuantity默认=待复核数量 + if (pickQty != null) { + outMaterialDetailPO.setQuantity(pickQty); + } + outMaterialDetailPO.setActualQuantity(waitQty); } List children = outMaterialDetailPO.getChildren(); if (!CollectionUtils.isEmpty(children)) { @@ -788,7 +842,21 @@ public class StockOutOrderDomainService { outMaterialDetailPOChild.setCheckVolume(pickingMaterialDetailPO1.getTotalVolume()); outMaterialDetailPOChild.setCheckNetWeight(pickingMaterialDetailPO1.getTotalNetWeight()); outMaterialDetailPOChild.setCheckGrossWeight(pickingMaterialDetailPO1.getTotalGrossWeight()); - outMaterialDetailPOChild.setWaitCheckQuantity(outMaterialDetailPOChild.getPickingQuantity()); + // 拣货数量:优先 picking_material_detail,否则 out_material_detail + BigDecimal pickQtyChild = (pickingMaterialDetailPO1.getPickingQuantity() != null && pickingMaterialDetailPO1.getPickingQuantity().compareTo(BigDecimal.ZERO) > 0) + ? pickingMaterialDetailPO1.getPickingQuantity() : outMaterialDetailPOChild.getPickingQuantity(); + BigDecimal checkQtyChild = outMaterialDetailPOChild.getCheckQuantity() != null ? outMaterialDetailPOChild.getCheckQuantity() : BigDecimal.ZERO; + // 待复核数量 = 拣货数量 - 已复核数量(复核提交后应减少) + BigDecimal waitQtyChild = (pickQtyChild != null ? pickQtyChild : BigDecimal.ZERO).subtract(checkQtyChild); + if (waitQtyChild.compareTo(BigDecimal.ZERO) < 0) { + waitQtyChild = BigDecimal.ZERO; + } + outMaterialDetailPOChild.setWaitCheckQuantity(waitQtyChild); + // quantity=PC下发时的拣货数量,actualQuantity默认=待复核数量 + if (pickQtyChild != null) { + outMaterialDetailPOChild.setQuantity(pickQtyChild); + } + outMaterialDetailPOChild.setActualQuantity(waitQtyChild); } } } @@ -801,8 +869,10 @@ public class StockOutOrderDomainService { for (OutMaterialDetailPO outMaterialDetailPO : outMaterialDetailPOList){ weightLimit = weightLimit.add(outMaterialDetailPO.getWeightLimit()); volumeLimit = volumeLimit.add(outMaterialDetailPO.getVolumeLimit()); - wantNumber = wantNumber.add(outMaterialDetailPO.getPickingQuantity()); - alreadyNumber = alreadyNumber.add(outMaterialDetailPO.getCheckQuantity()); + // wantNumber=拣货数量总和,alreadyNumber=已复核总和,notHaveNumber=剩余待复核 + BigDecimal pickQty = (outMaterialDetailPO.getQuantity() != null ? outMaterialDetailPO.getQuantity() : outMaterialDetailPO.getPickingQuantity()); + wantNumber = wantNumber.add(pickQty != null ? pickQty : BigDecimal.ZERO); + alreadyNumber = alreadyNumber.add(outMaterialDetailPO.getCheckQuantity() != null ? outMaterialDetailPO.getCheckQuantity() : BigDecimal.ZERO); } OutMaterialCheckPO outMaterialCheckPO = new OutMaterialCheckPO(); outMaterialCheckPO.setCount(outMaterialDetailPOList.size()); @@ -843,12 +913,37 @@ public class StockOutOrderDomainService { // 3. 为每个物料明细设置更多属性(从库存表中获取值) setMaterialMoreDetailListFromInventory(materialDetailList, batchDetailMap); - materialDetailList.removeIf(detail -> detail.getPickingQuantity() != null && detail.getPickingQuantity().compareTo(BigDecimal.ONE) < 0); + // 过滤无拣货数量的明细:pickingQuantity 或 waitCheckQuantity 任一 >= 1 则保留(waitCheckQuantity 来自 picking_material_detail 已拣货数量) + materialDetailList.removeIf(detail -> { + BigDecimal pickQty = detail.getPickingQuantity() != null ? detail.getPickingQuantity() : BigDecimal.ZERO; + BigDecimal waitQty = detail.getWaitCheckQuantity() != null ? detail.getWaitCheckQuantity() : BigDecimal.ZERO; + return pickQty.compareTo(BigDecimal.ONE) < 0 && waitQty.compareTo(BigDecimal.ONE) < 0; + }); stockOutOrderPO.setMaterialDetailList(materialDetailList); return stockOutOrderPO; } + /** + * 将物料明细树形结构扁平化,PDA端展示与PC端条数一致(父项+子项全部展开为独立行) + */ + private List flattenMaterialDetailTree(List treeList) { + if (CollectionUtils.isEmpty(treeList)) { + return new ArrayList<>(); + } + List result = new ArrayList<>(); + for (OutMaterialDetailPO item : treeList) { + result.add(item); + List children = item.getChildren(); + if (!CollectionUtils.isEmpty(children)) { + List flattenedChildren = flattenMaterialDetailTree(children); + result.addAll(flattenedChildren); + item.setChildren(null); + } + } + return result; + } + /** * 为物料库存设置更多属性(从库存表中获取值) * @param materialDetailList 物料库存列表 diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutTaskOrder/service/StockOutTaskOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutTaskOrder/service/StockOutTaskOrderDomainService.java index 2b39251c6..4f3fdaa07 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutTaskOrder/service/StockOutTaskOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockOutTaskOrder/service/StockOutTaskOrderDomainService.java @@ -24,6 +24,8 @@ import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail; import com.mhd.wms.domain.outMaterialDetail.repository.mapper.OutMaterialDetailMapper; import com.mhd.wms.domain.outOrderAbnormal.repository.facade.IOutOrderAbnormalService; import com.mhd.wms.domain.outOrderAbnormal.repository.todo.OutOrderAbnormalBaseDO; +import com.mhd.wms.domain.pickingMaterialDetail.entity.PickingMaterialDetail; +import com.mhd.wms.domain.pickingMaterialDetail.repository.facade.IPickingMaterialDetailService; import com.mhd.wms.domain.pickingOrder.entity.PickingOrder; import com.mhd.wms.domain.pickingOrder.repository.facade.IPickingOrderService; import com.mhd.wms.domain.pickingOrder.repository.po.PickingOrderPO; @@ -75,6 +77,8 @@ public class StockOutTaskOrderDomainService { @Autowired private IPickingOrderService pickingOrderService; @Autowired + private IPickingMaterialDetailService pickingMaterialDetailService; + @Autowired private IStockOutOrderService stockOutOrderService; @Autowired private IWaveOutOrderService waveOutOrderService; @@ -256,19 +260,12 @@ public class StockOutTaskOrderDomainService { if (quantityAll.compareTo(BigDecimal.ZERO) > 0 && pickingQuantityAll.compareTo(quantityAll) >= 0){ totalPickingMaterialQuantity += 1; } - // 过滤掉已拣货完成的明细,只展示待拣货的 - List incompleteList = taskPickingMaterialDetailPOListByStorage.stream() - .filter(d -> d.getQuantity() != null && (d.getPickingQuantity() == null || d.getPickingQuantity().compareTo(d.getQuantity()) < 0)) - .collect(Collectors.toList()); - if (CollectionUtil.isEmpty(incompleteList)){ - continue; - } TaskStoragePO taskStoragePO = new TaskStoragePO(); - BeanUtils.copyProperties(incompleteList.get(0), taskStoragePO); + BeanUtils.copyProperties(taskPickingMaterialDetailPOListByStorage.get(0), taskStoragePO); BigDecimal quantity = BigDecimal.ZERO; BigDecimal pickingQuantity = BigDecimal.ZERO; BigDecimal waitPickingQuantity = BigDecimal.ZERO; - for (TaskPickingMaterialDetailPO taskPickingMaterialDetailPO : incompleteList) { + for (TaskPickingMaterialDetailPO taskPickingMaterialDetailPO : taskPickingMaterialDetailPOListByStorage) { quantity = quantity.add(taskPickingMaterialDetailPO.getQuantity()); pickingQuantity = pickingQuantity.add(taskPickingMaterialDetailPO.getPickingQuantity() != null ? taskPickingMaterialDetailPO.getPickingQuantity() : BigDecimal.ZERO); waitPickingQuantity = waitPickingQuantity.add(taskPickingMaterialDetailPO.getWaitPickingQuantity() != null ? taskPickingMaterialDetailPO.getWaitPickingQuantity() : BigDecimal.ZERO); @@ -280,12 +277,12 @@ public class StockOutTaskOrderDomainService { Integer pickingStatus = judgePickingQuantity(pickingQuantity, quantity); taskStoragePO.setPickingStatus(pickingStatus); // actualQuantity 为输入框字段,默认等于待拣货数量,供 PDA 表单默认展示 - for (TaskPickingMaterialDetailPO d : incompleteList) { + for (TaskPickingMaterialDetailPO d : taskPickingMaterialDetailPOListByStorage) { if (d.getWaitPickingQuantity() != null) { d.setActualQuantity(d.getWaitPickingQuantity()); } } - taskStoragePO.setTaskPickingMaterialDetailList(incompleteList); + taskStoragePO.setTaskPickingMaterialDetailList(taskPickingMaterialDetailPOListByStorage); taskStoragePOList.add(taskStoragePO); } // 拣货进度:已完成数/拣货明细总数(按库位分组,几种库位就几种明细) @@ -371,8 +368,7 @@ public class StockOutTaskOrderDomainService { } stockOutTaskOrderDO.setTaskNumber(stockOutTaskOrderPODb.getTaskNumber()); StockOutTaskOrderPO stockOutTaskOrderPO = taskPickingMaterialDetailService.batchPickingUpdate(stockOutTaskOrderDO); - //修改库存 - updateMaterialInventory(stockOutTaskOrderDO); + // 拣货阶段不扣减库存,库存在出库交接完成时统一扣减(completeHandover -> xgkc) //设置拣货单拣货需要更新的数据数据 updateStockOutTaskOrder(stockOutTaskOrderPO, stockOutTaskOrderPODb, 2); return true; @@ -519,8 +515,10 @@ public class StockOutTaskOrderDomainService { @Transactional(rollbackFor = Exception.class) public Boolean updateStockOutOrder(PickingOrderPO pickingOrderPODb) { LoginUser loginUser = SecurityUtils.getLoginUser(); + // 与 PickingOrderDomainService 一致:只统计已拣货(status=3)的拣货单数量,确保完成拣货后出库单状态正确更新 List pickingOrderList = pickingOrderService.list(new QueryWrapper().lambda() .eq(PickingOrder::getDelFlag, 1) + .eq(PickingOrder::getStatus, 3) .eq(PickingOrder::getOrderNumber, pickingOrderPODb.getOrderNumber())); BigDecimal pickingQuantity = pickingOrderList.stream().map(PickingOrder::getPickingQuantity).reduce(BigDecimal.ZERO, BigDecimal::add); if (1 == pickingOrderPODb.getType()){ @@ -529,17 +527,44 @@ public class StockOutTaskOrderDomainService { StockOutOrder stockOutOrderDb = stockOutOrderService.getOne(new QueryWrapper().lambda() .eq(StockOutOrder::getDelFlag, 1) .eq(StockOutOrder::getOutOrderNumber, pickingOrderPODb.getOrderNumber())); - if (pickingQuantity.compareTo(stockOutOrderDb.getQuantity()) >= 0){ + // 与下发拣货数量比较:只下发部分时用分配数量/拣货计划数量,否则用出库单总数量 + List allPickingOrders = pickingOrderService.list(new QueryWrapper().lambda() + .eq(PickingOrder::getDelFlag, 1) + .eq(PickingOrder::getOrderNumber, pickingOrderPODb.getOrderNumber())); + BigDecimal totalPickingPlanQuantity = allPickingOrders.stream() + .map(PickingOrder::getQuantity).filter(java.util.Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal thresholdQuantity = (totalPickingPlanQuantity != null && totalPickingPlanQuantity.compareTo(BigDecimal.ZERO) > 0) + ? totalPickingPlanQuantity : (stockOutOrderDb.getQuantity() != null ? stockOutOrderDb.getQuantity() : BigDecimal.ZERO); + if (pickingQuantity.compareTo(thresholdQuantity) >= 0){ status = 7; if (pickingOrderPODb.getReview() == 2){ status = 9; genStockInOrder(stockOutOrderDb); } } + // 根据拣货单明细更新出库单物料明细的拣货数量(与 PickingOrderDomainService 一致) + for (PickingOrder pickingOrder : pickingOrderList) { + List list = pickingMaterialDetailService.list(new QueryWrapper().lambda() + .eq(PickingMaterialDetail::getPickingOrderNumber, pickingOrder.getPickingOrderNumber())); + for (PickingMaterialDetail pickingMaterialDetail : list) { + OutMaterialDetail outMaterialDetail = outMaterialDetailMapper.selectOne(new QueryWrapper().lambda() + .eq(OutMaterialDetail::getUniqueId, pickingMaterialDetail.getOutUniqueId()) + .eq(OutMaterialDetail::getDelFlag, 1)); + if (outMaterialDetail != null) { + outMaterialDetail.setPickingQuantity(pickingMaterialDetail.getPickingQuantity()); + outMaterialDetail.setTotalNetWeight(pickingMaterialDetail.getTotalNetWeight()); + outMaterialDetail.setTotalGrossWeight(pickingMaterialDetail.getTotalGrossWeight()); + outMaterialDetail.setTotalVolume(pickingMaterialDetail.getTotalVolume()); + outMaterialDetail.setTotalArea(pickingMaterialDetail.getTotalArea()); + outMaterialDetailMapper.updateById(outMaterialDetail); + } + } + } StockOutOrder stockOutOrder = new StockOutOrder(); stockOutOrder.setOutOrderNumber(pickingOrderPODb.getOrderNumber()); //1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 stockOutOrder.setStatus(status); + stockOutOrder.setPickingQuantity(pickingQuantity); stockOutOrder.setUpdateBy(loginUser.getUserid()); stockOutOrder.setUpdateByName(loginUser.getUsername()); stockOutOrder.setUpdateTime(new Date()); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/service/StockReceiptOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/service/StockReceiptOrderDomainService.java index c682234e2..24df63599 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/service/StockReceiptOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockReceiptOrder/service/StockReceiptOrderDomainService.java @@ -228,7 +228,7 @@ public class StockReceiptOrderDomainService { receiptMaterialDetailPOChildren.setQuantity(null); }); } else { - // 主项无子项时:添加 parent_copy 到 children,供详情页展示(详情页从 children 读取数据) + // 主项无子项时:添加 parent_copy 到 children,与上架一致,供 PDA 详情页从 children 读取数据展示(PDA 端与上架共用同一展示逻辑) if (CollectionUtils.isEmpty(receiptMaterialDetailPO.getMaterialMoreDetailList())) { receiptMaterialDetailPO.setMaterialMoreDetailList(getMaterialMoreDetail(receiptMaterialDetailPO)); } @@ -238,11 +238,6 @@ public class StockReceiptOrderDomainService { parentCopy.setParentUniqueId(receiptMaterialDetailPO.getUniqueId()); parentCopy.setQuantity(null); parentCopy.setChildren(new ArrayList<>()); - if (CollectionUtils.isEmpty(parentCopy.getMaterialMoreDetailList())) { - parentCopy.setMaterialMoreDetailList(receiptMaterialDetailPO.getMaterialMoreDetailList()); - } - List serialList = inMaterialDetailSerialNumberMap.get(receiptMaterialDetailPO.getUniqueId()); - parentCopy.setMaterialDetailSerialNumberList(serialList != null ? serialList : new ArrayList<>()); receiptMaterialDetailPOChildrenList = new ArrayList<>(); receiptMaterialDetailPOChildrenList.add(parentCopy); } diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockShelfOrder/service/StockShelfOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockShelfOrder/service/StockShelfOrderDomainService.java index 75f8e1dfa..3badbb476 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockShelfOrder/service/StockShelfOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockShelfOrder/service/StockShelfOrderDomainService.java @@ -33,6 +33,8 @@ import com.mhd.wms.domain.inMaterialDetailSerialNumber.repository.todo.InMateria import com.mhd.wms.domain.inOrderAbnormal.repository.facade.IInOrderAbnormalService; import com.mhd.wms.domain.inOrderAbnormal.repository.todo.InOrderAbnormalBaseDO; import com.mhd.wms.domain.inventoryAdjustmentRecord.entity.InventoryAdjustmentRecord; +import com.mhd.wms.domain.materialBarCode.repository.facade.IMaterialBarCodeService; +import com.mhd.wms.domain.materialBarCode.repository.po.MaterialBarCodePO; import com.mhd.wms.domain.inventoryAdjustmentRecord.repository.mapper.InventoryAdjustmentRecordMapper; import com.mhd.wms.domain.inventoryStandingDetail.repository.facade.IInventoryStandingDetailService; import com.mhd.wms.domain.inventoryStandingDetail.repository.todo.InventoryStandingDetailDO; @@ -118,6 +120,8 @@ public class StockShelfOrderDomainService { @Autowired private MaterialInventoryMapper materialInventoryMapper; @Autowired + private IMaterialBarCodeService materialBarCodeService; + @Autowired private IMaterialGoodsRuleService materialGoodsRuleService; @Autowired private InventoryAdjustmentRecordMapper inventoryAdjustmentRecordMapper; @@ -235,28 +239,19 @@ public class StockShelfOrderDomainService { MaterialMoreDetailDO materialMoreDetailDO = new MaterialMoreDetailDO(); materialMoreDetailDO.setOrderNumber(stockShelfOrderPO.getShelfOrderNumber()); shelfMaterialDetailPOList.forEach(shelfMaterialDetailPO -> { - List shelfMaterialDetailPOChildrenNowList = new ArrayList<>(); - ShelfMaterialDetailPO shelfMaterialDetailPOChildrenNow = new ShelfMaterialDetailPO(); - BeanUtils.copyProperties(shelfMaterialDetailPO, shelfMaterialDetailPOChildrenNow, "children"); - List materialDetailSerialNumberList = inMaterialDetailSerialNumberMap.get(shelfMaterialDetailPO.getUniqueId()); - if (!CollectionUtils.isEmpty(materialDetailSerialNumberList)){ - shelfMaterialDetailPOChildrenNow.setMaterialDetailSerialNumberList(materialDetailSerialNumberList); - }else { - shelfMaterialDetailPOChildrenNow.setMaterialDetailSerialNumberList(new ArrayList<>()); - } - shelfMaterialDetailPOChildrenNowList.add(shelfMaterialDetailPOChildrenNow); - //子集 + // 不添加 parent_copy,避免 PDA 端重复显示两条记录;主项自身已有全部数据,详情页可直接从主项读取 List shelfMaterialDetailPOChildrenList = shelfMaterialDetailPO.getChildren(); - shelfMaterialDetailPOChildrenList.forEach(receiptMaterialDetailPOChildren -> { - List materialDetailSerialNumberChildrenList = inMaterialDetailSerialNumberMap.get(shelfMaterialDetailPO.getUniqueId()); - if (!CollectionUtils.isEmpty(materialDetailSerialNumberChildrenList)){ - receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(materialDetailSerialNumberChildrenList); - }else { - receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(new ArrayList<>()); - } - }); - shelfMaterialDetailPOChildrenNowList.addAll(shelfMaterialDetailPOChildrenList); - shelfMaterialDetailPO.setChildren(shelfMaterialDetailPOChildrenNowList); + if (!CollectionUtils.isEmpty(shelfMaterialDetailPOChildrenList)) { + shelfMaterialDetailPOChildrenList.forEach(receiptMaterialDetailPOChildren -> { + List materialDetailSerialNumberChildrenList = inMaterialDetailSerialNumberMap.get(shelfMaterialDetailPO.getUniqueId()); + if (!CollectionUtils.isEmpty(materialDetailSerialNumberChildrenList)){ + receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(materialDetailSerialNumberChildrenList); + }else { + receiptMaterialDetailPOChildren.setMaterialDetailSerialNumberList(new ArrayList<>()); + } + }); + } + shelfMaterialDetailPO.setChildren(shelfMaterialDetailPOChildrenList != null ? shelfMaterialDetailPOChildrenList : new ArrayList<>()); }); stockShelfOrderPO.setMaterialDetailList(shelfMaterialDetailPOList); return stockShelfOrderPO; @@ -727,7 +722,26 @@ public class StockShelfOrderDomainService { inventoryAdjustmentRecord.setMaterialBaseInfoId(materialInventory.getMaterialBaseInfoId()); inventoryAdjustmentRecord.setMaterialCode(shelfMaterialDetail.getMaterialCode()); inventoryAdjustmentRecord.setMaterialName(shelfMaterialDetail.getMaterialName()); - inventoryAdjustmentRecord.setBarCode(shelfMaterialDetail.getBarCode()); + // 条码优先取上架明细上的条码;如果为空,则根据物料基础信息ID从物料条码表中获取(单位代码为EA的条码) + String shelfBarCode = shelfMaterialDetail.getBarCode(); + if (StringUtils.isBlank(shelfBarCode) && shelfMaterialDetail.getMaterialBaseInfoId() != null) { + try { + java.util.List barCodeList = materialBarCodeService.getInfoByMaterialBaseInfoIds(shelfMaterialDetail.getMaterialBaseInfoId()); + if (barCodeList != null && !barCodeList.isEmpty()) { + // 优先选择单位代码为EA的条码,若不存在则取第一条 + MaterialBarCodePO eaBarCode = barCodeList.stream() + .filter(po -> "EA".equals(po.getUnitCode())) + .findFirst() + .orElse(barCodeList.get(0)); + if (eaBarCode != null && StringUtils.isNotBlank(eaBarCode.getBarCode())) { + shelfBarCode = eaBarCode.getBarCode(); + } + } + } catch (Exception e) { + log.warn("根据物料基础信息ID获取条码失败,materialBaseInfoId={},错误:{}", shelfMaterialDetail.getMaterialBaseInfoId(), e.getMessage()); + } + } + inventoryAdjustmentRecord.setBarCode(shelfBarCode); inventoryAdjustmentRecord.setMaterialBaseInfoId(shelfMaterialDetail.getMaterialBaseInfoId()); inventoryAdjustmentRecord.setOrganizationId(stockReceiptOrderDO.getOrganizationId()); inventoryAdjustmentRecord.setOrganizationName(stockReceiptOrderDO.getOrganizationName()); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/persistence/TaskPickingMaterialDetailImpl.java b/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/persistence/TaskPickingMaterialDetailImpl.java index 17c3c253f..45b6415ea 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/persistence/TaskPickingMaterialDetailImpl.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/persistence/TaskPickingMaterialDetailImpl.java @@ -160,12 +160,37 @@ public class TaskPickingMaterialDetailImpl extends ServiceImpl pickingUniqueId.equals(p.getUniqueId())).findFirst().orElse(null); + if (existing != null) { + existing.setPickingQuantity((existing.getPickingQuantity() != null ? existing.getPickingQuantity() : BigDecimal.ZERO).add(qty)); + // 净重、毛重、体积、面积:拣货填写值直接覆盖,不累加 + if (taskPickingMaterialDetailDO.getTotalNetWeight() != null) { + existing.setTotalNetWeight(taskPickingMaterialDetailDO.getTotalNetWeight()); + } + if (taskPickingMaterialDetailDO.getTotalGrossWeight() != null) { + existing.setTotalGrossWeight(taskPickingMaterialDetailDO.getTotalGrossWeight()); + } + if (taskPickingMaterialDetailDO.getTotalVolume() != null) { + existing.setTotalVolume(taskPickingMaterialDetailDO.getTotalVolume()); + } + if (taskPickingMaterialDetailDO.getTotalArea() != null) { + existing.setTotalArea(taskPickingMaterialDetailDO.getTotalArea()); + } + } else { + PickingMaterialDetailDO pickingMaterialDetailDO = new PickingMaterialDetailDO(); + pickingMaterialDetailDO.setUniqueId(pickingUniqueId); + pickingMaterialDetailDO.setPickingQuantity(qty); + pickingMaterialDetailDO.setTotalNetWeight(taskPickingMaterialDetailDO.getTotalNetWeight()); + pickingMaterialDetailDO.setTotalGrossWeight(taskPickingMaterialDetailDO.getTotalGrossWeight()); + pickingMaterialDetailDO.setTotalVolume(taskPickingMaterialDetailDO.getTotalVolume()); + pickingMaterialDetailDO.setTotalArea(taskPickingMaterialDetailDO.getTotalArea()); + pickingMaterialDetailList.add(pickingMaterialDetailDO); + } + totalPickingQuantity = totalPickingQuantity.add(qty); } //保存物料明细信息 saveOrUpdateBatch(taskPickingMaterialDetailList); diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/todo/TaskPickingMaterialDetailDO.java b/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/todo/TaskPickingMaterialDetailDO.java index c00697173..20092288b 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/todo/TaskPickingMaterialDetailDO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/taskPickingMaterialDetail/repository/todo/TaskPickingMaterialDetailDO.java @@ -207,4 +207,20 @@ public class TaskPickingMaterialDetailDO extends BaseVOEntity { @ApiModelProperty("序列号") private List materialDetailSerialNumberList; + + @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; } diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/deliveTask/DeliveTaskDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/deliveTask/DeliveTaskDTO.java index 8f39e5d31..40cacf6bd 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/deliveTask/DeliveTaskDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/deliveTask/DeliveTaskDTO.java @@ -115,4 +115,7 @@ public class DeliveTaskDTO extends BaseVOEntity { @ApiModelProperty("查询类型 1-指派给我的 2-任务") @Excel(name = "查询类型 1-指派给我的 2-任务") private Long tabType; + + @ApiModelProperty("交接查询类型(taskType=7时生效): 1-列表(未交接) 2-历史(已交接),不传默认1") + private Integer handoverQueryType; } diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/inventoryAdjustmentRecord/InventoryAdjustmentRecordDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/inventoryAdjustmentRecord/InventoryAdjustmentRecordDTO.java index cb4d3b8ac..f9ff15d67 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/inventoryAdjustmentRecord/InventoryAdjustmentRecordDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/inventoryAdjustmentRecord/InventoryAdjustmentRecordDTO.java @@ -157,6 +157,11 @@ public class InventoryAdjustmentRecordDTO extends BaseVOEntity { @Excel(name = "调整后冻结数量") private BigDecimal freezeAfterQuantity; + @ApiModelProperty("调整动作") + private String adjustAction; + + @ApiModelProperty("关联单号") + private String relateNo; @ApiModelProperty(name = "组织ID集合") private List organizationIdList; diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/LongFromStringDeserializer.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/LongFromStringDeserializer.java new file mode 100644 index 000000000..ca7ef7a5e --- /dev/null +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/LongFromStringDeserializer.java @@ -0,0 +1,31 @@ +package com.mhd.wms.interfaces.dto.receiptMaterialDetail; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; + +/** + * Long 反序列化器:支持从字符串或数字解析,避免 JavaScript 大整数精度丢失。 + * 前端应始终以字符串形式传递 uniqueId、parentUniqueId、inUniqueId 等大 Long 字段。 + */ +public class LongFromStringDeserializer extends JsonDeserializer { + + @Override + public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + JsonNode node = p.readValueAsTree(); + if (node == null || node.isNull()) { + return null; + } + if (node.isTextual()) { + String s = node.asText(); + return s == null || s.isEmpty() ? null : Long.parseLong(s.trim()); + } + if (node.isNumber()) { + return node.asLong(); + } + return null; + } +} diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/ReceiptMaterialDetailDTO.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/ReceiptMaterialDetailDTO.java index 639ba47f1..883f03844 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/ReceiptMaterialDetailDTO.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/dto/receiptMaterialDetail/ReceiptMaterialDetailDTO.java @@ -1,5 +1,6 @@ package com.mhd.wms.interfaces.dto.receiptMaterialDetail; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.mhd.common.core.annotation.Excel; @@ -41,6 +42,7 @@ public class ReceiptMaterialDetailDTO extends BaseVOEntity { @ApiModelProperty("业务唯一id") @Excel(name = "业务唯一id") @JsonSerialize(using = ToStringSerializer.class) + @JsonDeserialize(using = LongFromStringDeserializer.class) private Long uniqueId; @ApiModelProperty("收货单号") @@ -194,11 +196,13 @@ public class ReceiptMaterialDetailDTO extends BaseVOEntity { @ApiModelProperty("父级唯一Id") @Excel(name = "父级唯一Id") @JsonSerialize(using = ToStringSerializer.class) + @JsonDeserialize(using = LongFromStringDeserializer.class) private Long parentUniqueId; @ApiModelProperty("入库单物料明细id") @Excel(name = "入库单物料明细id") @JsonSerialize(using = ToStringSerializer.class) + @JsonDeserialize(using = LongFromStringDeserializer.class) private Long inUniqueId; @ApiModelProperty("备注") diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java index 3dd66441b..5b110472b 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/materialInventory/MaterialInventoryApi.java @@ -81,36 +81,36 @@ public class MaterialInventoryApi extends BaseController { List list = materialInventoryApplicationService.queryListWithBatchAttributes(materialInventoryDO); TableDataInfo tableDataInfo = getDataTable(list); // 如果查询结果为空,抛出异常提示用户该物料在库存中不存在 - if (tableDataInfo.getTotal() == 0) { - StringBuilder errorMsg = new StringBuilder("该物料在库存中不存在"); - // 如果有物料信息,添加到提示中 - if (StringUtils.isNotBlank(materialInventoryDTO.getMaterialName())) { - errorMsg.append(",物料名称:").append(materialInventoryDTO.getMaterialName()); - } else if (StringUtils.isNotBlank(materialInventoryDTO.getMaterialCode())) { - errorMsg.append(",物料编码:").append(materialInventoryDTO.getMaterialCode()); - } else if (StringUtils.isNotBlank(materialInventoryDTO.getBarCode())) { - errorMsg.append(",物料条码:").append(materialInventoryDTO.getBarCode()); - } - // 如果有货主信息,添加到提示中(优先显示查询到的货主名称,否则显示客户名称) - if (StringUtils.isNotBlank(shipperName)) { - errorMsg.append(",货主:").append(shipperName); - } else if (StringUtils.isNotBlank(customerName)) { - errorMsg.append(",货主:").append(customerName); - } - // 如果有批次参考号,添加到提示中 - if (StringUtils.isNotBlank(materialInventoryDTO.getBatchRefNo())) { - errorMsg.append(",Batch Ref NO's:").append(materialInventoryDTO.getBatchRefNo()); - } - // 如果有单据参考号,添加到提示中 - if (StringUtils.isNotBlank(materialInventoryDTO.getSheetRefNo())) { - errorMsg.append(",Sheet Ref NO's:").append(materialInventoryDTO.getSheetRefNo()); - } - // 如果有箱号/卡板号,添加到提示中 - if (StringUtils.isNotBlank(materialInventoryDTO.getBoxPalletNo())) { - errorMsg.append(",箱号/卡板号:").append(materialInventoryDTO.getBoxPalletNo()); - } - throw new ServiceException(errorMsg.toString()); - } +// if (tableDataInfo.getTotal() == 0) { +// StringBuilder errorMsg = new StringBuilder("该物料在库存中不存在"); +// // 如果有物料信息,添加到提示中 +// if (StringUtils.isNotBlank(materialInventoryDTO.getMaterialName())) { +// errorMsg.append(",物料名称:").append(materialInventoryDTO.getMaterialName()); +// } else if (StringUtils.isNotBlank(materialInventoryDTO.getMaterialCode())) { +// errorMsg.append(",物料编码:").append(materialInventoryDTO.getMaterialCode()); +// } else if (StringUtils.isNotBlank(materialInventoryDTO.getBarCode())) { +// errorMsg.append(",物料条码:").append(materialInventoryDTO.getBarCode()); +// } +// // 如果有货主信息,添加到提示中(优先显示查询到的货主名称,否则显示客户名称) +// if (StringUtils.isNotBlank(shipperName)) { +// errorMsg.append(",货主:").append(shipperName); +// } else if (StringUtils.isNotBlank(customerName)) { +// errorMsg.append(",货主:").append(customerName); +// } +// // 如果有批次参考号,添加到提示中 +// if (StringUtils.isNotBlank(materialInventoryDTO.getBatchRefNo())) { +// errorMsg.append(",Batch Ref NO's:").append(materialInventoryDTO.getBatchRefNo()); +// } +// // 如果有单据参考号,添加到提示中 +// if (StringUtils.isNotBlank(materialInventoryDTO.getSheetRefNo())) { +// errorMsg.append(",Sheet Ref NO's:").append(materialInventoryDTO.getSheetRefNo()); +// } +// // 如果有箱号/卡板号,添加到提示中 +// if (StringUtils.isNotBlank(materialInventoryDTO.getBoxPalletNo())) { +// errorMsg.append(",箱号/卡板号:").append(materialInventoryDTO.getBoxPalletNo()); +// } +// throw new ServiceException(errorMsg.toString()); +// } return tableDataInfo; } diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockShelfOrder/StockShelfOrderApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockShelfOrder/StockShelfOrderApi.java index 457490cca..3ca941c78 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockShelfOrder/StockShelfOrderApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockShelfOrder/StockShelfOrderApi.java @@ -55,13 +55,13 @@ public class StockShelfOrderApi extends BaseController { } /** - * 获取上架单详细信息 + * 获取上架单详细信息(PC 不添加 parent_copy,避免只上架一条时显示虚拟子项) */ @ApiOperation("获取上架单") @GetMapping(value = "/getInfo/{shelfOrderId}") public AjaxResult getInfo(@PathVariable("shelfOrderId") Long shelfOrderId) { - return AjaxResult.success(stockShelfOrderApplicationService.getInfo(shelfOrderId)); + return AjaxResult.success(stockShelfOrderApplicationService.getInfo(shelfOrderId, false)); } @ApiOperation("任务下发") diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApp/stockShelfOrder/StockShelfOrderAppApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApp/stockShelfOrder/StockShelfOrderAppApi.java index 9099cd451..4f82c804c 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApp/stockShelfOrder/StockShelfOrderAppApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApp/stockShelfOrder/StockShelfOrderAppApi.java @@ -47,13 +47,13 @@ public class StockShelfOrderAppApi extends BaseController { } /** - * 获取上架单详细信息 + * 获取上架单详细信息(PDA:主项无子项时添加 parent_copy,供详情页从 children 读取数据) */ @ApiOperation("获取上架单") @GetMapping(value = "/getInfo") public AjaxResult getInfo(Long shelfOrderId) { - return AjaxResult.success(stockShelfOrderApplicationService.getInfo(shelfOrderId)); + return AjaxResult.success(stockShelfOrderApplicationService.getInfo(shelfOrderId, true)); } diff --git a/mhd_wms/src/main/resources/mapper/deliveTask/DeliveTaskMapper.xml b/mhd_wms/src/main/resources/mapper/deliveTask/DeliveTaskMapper.xml index 729830731..196979e7f 100644 --- a/mhd_wms/src/main/resources/mapper/deliveTask/DeliveTaskMapper.xml +++ b/mhd_wms/src/main/resources/mapper/deliveTask/DeliveTaskMapper.xml @@ -91,6 +91,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and task_type = #{taskType} + + + and EXISTS (SELECT 1 FROM handover_task_order hto WHERE hto.task_number = delive_task.tracking_number AND hto.del_flag = 1 AND hto.status = 1) + + + and EXISTS (SELECT 1 FROM handover_task_order hto WHERE hto.task_number = delive_task.tracking_number AND hto.del_flag = 1 AND hto.status = 2) + and task_status = #{taskStatus} @@ -158,6 +165,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and task_type = #{taskType} + + + and EXISTS (SELECT 1 FROM handover_task_order hto WHERE hto.task_number = delive_task.tracking_number AND hto.del_flag = 1 AND hto.status = 1) + + + and EXISTS (SELECT 1 FROM handover_task_order hto WHERE hto.task_number = delive_task.tracking_number AND hto.del_flag = 1 AND hto.status = 2) + and task_status = #{taskStatus} diff --git a/mhd_wms/src/main/resources/mapper/inventoryAdjustmentRecord/InventoryAdjustmentRecordMapper.xml b/mhd_wms/src/main/resources/mapper/inventoryAdjustmentRecord/InventoryAdjustmentRecordMapper.xml index a1c7454d0..0917626e5 100644 --- a/mhd_wms/src/main/resources/mapper/inventoryAdjustmentRecord/InventoryAdjustmentRecordMapper.xml +++ b/mhd_wms/src/main/resources/mapper/inventoryAdjustmentRecord/InventoryAdjustmentRecordMapper.xml @@ -101,6 +101,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" and a.material_code = #{materialCode} + + and a.adjust_action = #{adjustAction} + + + and a.relate_no = #{relateNo} + and a.material_name like concat('%', #{materialName}, '%') diff --git a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml index 77d072eb7..300a084d7 100644 --- a/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml +++ b/mhd_wms/src/main/resources/mapper/materialInventory/MaterialInventoryMapper.xml @@ -550,7 +550,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND d.del_flag = 1 LEFT JOIN stock_in_order e ON d.in_order_number = e.in_order_number WHERE - c.del_flag = 1 and d.STATUS = 3 and e.STATUS in (3,4) + c.del_flag = 1 and d.STATUS = 3 AND e.warehouse_id = a.warehouse_id AND (a.shipper_id IS NULL OR e.shipper_id = a.shipper_id) AND c.material_base_info_id = a.material_base_info_id diff --git a/mhd_wms/src/main/resources/mapper/pickingMaterialDetail/PickingMaterialDetailMapper.xml b/mhd_wms/src/main/resources/mapper/pickingMaterialDetail/PickingMaterialDetailMapper.xml index 6ac504b8c..ad2e8b8e4 100644 --- a/mhd_wms/src/main/resources/mapper/pickingMaterialDetail/PickingMaterialDetailMapper.xml +++ b/mhd_wms/src/main/resources/mapper/pickingMaterialDetail/PickingMaterialDetailMapper.xml @@ -191,11 +191,42 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + + + @@ -206,6 +237,27 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" WHEN #{item.uniqueId} THEN LEAST(picking_quantity + #{item.pickingQuantity}, quantity) + + + + WHEN #{item.uniqueId} THEN IFNULL(#{item.totalNetWeight}, total_net_weight) + + + + + WHEN #{item.uniqueId} THEN IFNULL(#{item.totalGrossWeight}, total_gross_weight) + + + + + WHEN #{item.uniqueId} THEN IFNULL(#{item.totalVolume}, total_volume) + + + + + WHEN #{item.uniqueId} THEN IFNULL(#{item.totalArea}, total_area) + + update_by = #{updateBy}, update_by_name = #{updateByName}, update_time = #{updateTime} @@ -216,4 +268,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{item.uniqueId} + + + + UPDATE picking_material_detail SET total_net_weight = 0, total_gross_weight = 0, total_volume = 0, total_area = 0 + WHERE out_unique_id = #{outUniqueId} AND del_flag = 1 + + + + UPDATE picking_material_detail pmd + INNER JOIN (SELECT unique_id FROM picking_material_detail WHERE out_unique_id = #{outUniqueId} AND del_flag = 1 ORDER BY unique_id LIMIT 1) first_row ON pmd.unique_id = first_row.unique_id + SET pmd.total_net_weight = #{totalNetWeight}, pmd.total_gross_weight = #{totalGrossWeight}, pmd.total_volume = #{totalVolume}, pmd.total_area = #{totalArea}, + pmd.update_by = #{updateBy}, pmd.update_by_name = #{updateByName}, pmd.update_time = #{updateTime} + WHERE pmd.out_unique_id = #{outUniqueId} AND pmd.del_flag = 1 + \ No newline at end of file diff --git a/mhd_wms/src/main/resources/mapper/pickingOrder/PickingOrderMapper.xml b/mhd_wms/src/main/resources/mapper/pickingOrder/PickingOrderMapper.xml index a57fadf4d..4f52d88ce 100644 --- a/mhd_wms/src/main/resources/mapper/pickingOrder/PickingOrderMapper.xml +++ b/mhd_wms/src/main/resources/mapper/pickingOrder/PickingOrderMapper.xml @@ -32,7 +32,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" a.picking_order_id, a.organization_id, a.organization_name, a.top_organization_id, a.order_number, a.picking_order_number, a.status, a.type, a.warehouse_id, a.warehouse_code, a.warehouse_name, a.shipper_id, a.shipper_name, a.quantity, a.weight_limit, a.volume_limit, a.material_quantity, - a.picking_quantity, a.picking_material_quantity, a.abnormal, a.task_distribution, a.remark, a.create_time, a.create_by, a.create_by_name, a.update_time, + IFNULL((SELECT SUM(b.picking_quantity) FROM picking_material_detail b WHERE b.picking_order_number = a.picking_order_number AND b.del_flag = 1), 0) AS picking_quantity, + a.picking_material_quantity, a.abnormal, a.task_distribution, a.remark, a.create_time, a.create_by, a.create_by_name, a.update_time, a.update_by, a.update_by_name, a.del_flag diff --git a/mhd_wms/src/main/resources/mapper/shiftMaterialDetail/ShiftMaterialDetailMapper.xml b/mhd_wms/src/main/resources/mapper/shiftMaterialDetail/ShiftMaterialDetailMapper.xml index d9221f19d..64a3036b4 100644 --- a/mhd_wms/src/main/resources/mapper/shiftMaterialDetail/ShiftMaterialDetailMapper.xml +++ b/mhd_wms/src/main/resources/mapper/shiftMaterialDetail/ShiftMaterialDetailMapper.xml @@ -6,6 +6,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" +