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 974eeeb99..5f8bed0bd 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 @@ -267,9 +267,14 @@ public class ShiftManageApplicationService { /** * 物料移位(PDA),与收货、上架一致:支持 getInfoByApp 的 parent_copy 结构及分批移位 + * 按单移位:PDA 仅传 shiftManageId、updateTime 时,自动从库中带出该单下所有待移位明细,默认 shiftQuantity=quantity */ public Boolean appMoveFromShiftManage(ShiftManageDO shiftManageDO){ List shiftMaterialDetailDOList = shiftManageDO.getShiftMaterialDetailList(); + if (CollectionUtils.isEmpty(shiftMaterialDetailDOList)) { + fillShiftMaterialDetailFromDb(shiftManageDO); + shiftMaterialDetailDOList = shiftManageDO.getShiftMaterialDetailList(); + } boolean firstItemHadChildrenBefore = !CollectionUtils.isEmpty(shiftMaterialDetailDOList) && !CollectionUtils.isEmpty(shiftMaterialDetailDOList.get(0).getChildren()); // PDA 平铺结构转父子结构(与收货、上架一致) @@ -366,6 +371,38 @@ public class ShiftManageApplicationService { shiftManageDO.setShiftMaterialDetailList(newList); } + /** + * 按单移位:PDA 未传 shiftMaterialDetailList 时,从库中带出该移位单下所有待移位明细,默认 shiftQuantity=quantity + */ + private void fillShiftMaterialDetailFromDb(ShiftManageDO shiftManageDO) { + ShiftManagePO shiftManagePO = shiftManageDomainService.getInfoByApp(shiftManageDO.getShiftManageId()); + if (shiftManagePO == null || CollectionUtils.isEmpty(shiftManagePO.getShiftMaterialDetailList())) { + throw new ServiceException("移位单不存在或无待移位明细"); + } + List doList = new ArrayList<>(); + for (ShiftMaterialDetailPO po : shiftManagePO.getShiftMaterialDetailList()) { + ShiftMaterialDetailDO dto = poToDoForShift(po); + dto.setShiftQuantity(dto.getQuantity() != null ? dto.getQuantity() : BigDecimal.ZERO); + doList.add(dto); + } + shiftManageDO.setShiftMaterialDetailList(doList); + } + + private ShiftMaterialDetailDO poToDoForShift(ShiftMaterialDetailPO po) { + ShiftMaterialDetailDO dto = new ShiftMaterialDetailDO(); + BeanUtils.copyProperties(po, dto); + if (!CollectionUtils.isEmpty(po.getChildren())) { + List childDoList = new ArrayList<>(); + for (ShiftMaterialDetailPO childPo : po.getChildren()) { + ShiftMaterialDetailDO childDo = poToDoForShift(childPo); + childDo.setShiftQuantity(childDo.getQuantity() != null ? childDo.getQuantity() : BigDecimal.ZERO); + childDoList.add(childDo); + } + dto.setChildren(childDoList); + } + return dto; + } + /** * 移位时:将 children 中第一条(parent_copy)的值赋给主项,并删除第一条;与收货 assignFirstChildToParentAndRemove 一致。 * getInfoByApp 有子项时会将 parent_copy 作为 children 第一条,PDA 提交时需将其值回填主项并移除。 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 8ee893f56..068f9d9c1 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 @@ -384,6 +384,22 @@ public class StockReceiptOrderApplicationService { return sum; } + /** + * 第一次收货:主项无子项时,收货数量默认等于计划数量,供 PDA 表单默认展示 + */ + private void fillFirstReceiptQuantityDefault(List receiptMaterialDetailPOList) { + if (CollectionUtils.isEmpty(receiptMaterialDetailPOList)) { + return; + } + for (ReceiptMaterialDetailPO parent : receiptMaterialDetailPOList) { + if (CollectionUtils.isEmpty(parent.getChildren())) { + if (parent.getQuantity() != null && (parent.getReceiptQuantity() == null || parent.getReceiptQuantity().compareTo(BigDecimal.ZERO) == 0)) { + parent.setReceiptQuantity(parent.getQuantity()); + } + } + } + } + /** * 扁平化明细:主行保留自身 receiptQuantity,alreadyReceiptQuantity 汇总主行+所有子项;保留父子结构,子项作为 children 展示 * @param receiptMaterialDetailPOList 物料明细列表(树形,level 1 父级含 children) @@ -959,6 +975,8 @@ public class StockReceiptOrderApplicationService { // 物料条码为空时取物料维护的条码信息第一行的 barCode Map materialBarCodeMap = buildMaterialBarCodeMap(materialBaseInfoIdSet); fillBarCodeFromMaterialBarCodeRecursively(materialDetailList, materialBarCodeMap); + // 第一次收货:主项无子项时,收货数量默认等于计划数量 + fillFirstReceiptQuantityDefault(materialDetailList); // PDA 端与 PC 端一致:主行收货数量取第一条子项,已收货数量汇总所有子项 flattenMaterialDetailList(materialDetailList); clearChildQuantityRecursively(materialDetailList); 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 f00256c9d..2685051f2 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 @@ -286,6 +286,9 @@ public class StockShelfOrderApplicationService { // 4.4 为每个明细行填充物料单位、包装和条码信息 fillMaterialDetailInfoRecursively(shelfMaterialDetailPOList, materialBaseInfoMap, materialBarCodeMap, packDetailMap); + // 第一次上架:主项无子项时,上架数量默认等于收货数量(quantity 由上架单生成时取自收货数量),供 PDA 表单默认展示 + fillFirstShelvesQuantityDefault(shelfMaterialDetailPOList); + stockShelfOrderPO.setMaterialDetailList(shelfMaterialDetailPOList); log.info("返回上架单信息,shelfOrderId={}, materialDetailList大小={}", stockShelfOrderPO.getShelfOrderId(), @@ -961,6 +964,22 @@ public class StockShelfOrderApplicationService { }); } + /** + * 第一次上架:主项无子项时,上架数量默认等于收货数量(quantity 由上架单生成时取自 receipt_quantity),供 PDA 表单默认展示 + */ + private void fillFirstShelvesQuantityDefault(List shelfMaterialDetailPOList) { + if (CollectionUtils.isEmpty(shelfMaterialDetailPOList)) { + return; + } + for (ShelfMaterialDetailPO parent : shelfMaterialDetailPOList) { + if (CollectionUtils.isEmpty(parent.getChildren())) { + if (parent.getQuantity() != null && (parent.getShelvesQuantity() == null || parent.getShelvesQuantity().compareTo(BigDecimal.ZERO) == 0)) { + parent.setShelvesQuantity(parent.getQuantity()); + } + } + } + } + /** * 根据批次标签(batchLabels)映射到字段名 * @param batchLabel 批次标签 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 2b81e2753..e0b40ef2f 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 @@ -3,6 +3,7 @@ package com.mhd.wms.domain.stockOutTaskOrder.service; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.mhd.common.core.exception.ServiceException; @@ -37,6 +38,7 @@ import com.mhd.wms.domain.stockOutTaskOrder.repository.po.StockOutTaskOrderPO; import com.mhd.wms.domain.stockOutTaskOrder.repository.po.TaskMaterialPO; import com.mhd.wms.domain.stockOutTaskOrder.repository.po.TaskStoragePO; import com.mhd.wms.domain.stockOutTaskOrder.repository.todo.StockOutTaskOrderDO; +import com.mhd.wms.domain.taskPickingMaterialDetail.entity.TaskPickingMaterialDetail; import com.mhd.wms.domain.taskPickingMaterialDetail.repository.facade.ITaskPickingMaterialDetailService; import com.mhd.wms.domain.taskPickingMaterialDetail.repository.po.TaskPickingMaterialDetailPO; import com.mhd.wms.domain.taskPickingMaterialDetail.repository.todo.TaskPickingMaterialDetailDO; @@ -96,9 +98,64 @@ public class StockOutTaskOrderDomainService { /** * 分页查询拣货作业单列表 + * 列表返回前补充拣货进度:materialQuantity=拣货明细种类数,pickingMaterialQuantity=已完成种类数,用于显示 已完成数/总数 */ public List queryList(StockOutTaskOrderDO stockOutTaskOrderDO) { - return stockOutTaskOrderService.queryList(stockOutTaskOrderDO); + List list = stockOutTaskOrderService.queryList(stockOutTaskOrderDO); + if (CollectionUtil.isEmpty(list)) { + return list; + } + enrichListWithPickingProgress(list); + return list; + } + + /** + * 为拣货作业单列表补充拣货进度(materialQuantity、pickingMaterialQuantity) + */ + private void enrichListWithPickingProgress(List list) { + List taskNumberList = list.stream() + .map(StockOutTaskOrderPO::getTaskNumber) + .filter(taskNumber -> taskNumber != null && !taskNumber.isEmpty()) + .distinct() + .collect(Collectors.toList()); + if (CollectionUtil.isEmpty(taskNumberList)) { + return; + } + List detailList = taskPickingMaterialDetailService.list( + new LambdaQueryWrapper() + .in(TaskPickingMaterialDetail::getTaskNumber, taskNumberList)); + if (CollectionUtils.isEmpty(detailList)) { + return; + } + // 按 task_number -> material_base_info_id 分组,汇总 quantity、pickingQuantity + Map>> taskToMaterialMap = detailList.stream() + .collect(Collectors.groupingBy(TaskPickingMaterialDetail::getTaskNumber, + Collectors.groupingBy(TaskPickingMaterialDetail::getMaterialBaseInfoId))); + for (StockOutTaskOrderPO po : list) { + String taskNumber = po.getTaskNumber(); + if (taskNumber == null) { + continue; + } + Map> materialMap = taskToMaterialMap.get(taskNumber); + if (materialMap == null || materialMap.isEmpty()) { + continue; + } + int totalMaterialQuantity = materialMap.size(); + int completedMaterialQuantity = 0; + for (List materialDetails : materialMap.values()) { + BigDecimal quantity = BigDecimal.ZERO; + BigDecimal pickingQuantity = BigDecimal.ZERO; + for (TaskPickingMaterialDetail d : materialDetails) { + quantity = quantity.add(d.getQuantity() != null ? d.getQuantity() : BigDecimal.ZERO); + pickingQuantity = pickingQuantity.add(d.getPickingQuantity() != null ? d.getPickingQuantity() : BigDecimal.ZERO); + } + if (pickingQuantity.compareTo(quantity) >= 0 && quantity.compareTo(BigDecimal.ZERO) > 0) { + completedMaterialQuantity++; + } + } + po.setMaterialQuantity(totalMaterialQuantity); + po.setPickingMaterialQuantity(completedMaterialQuantity); + } } @@ -160,6 +217,8 @@ public class StockOutTaskOrderDomainService { totalPickingMaterialQuantity += 1; } } + // 拣货进度:已完成数/拣货明细总数(按物料分组) + stockOutTaskOrderPO.setMaterialQuantity(taskPickingMaterialDetailPOMap.size()); stockOutTaskOrderPO.setPickingMaterialQuantity(totalPickingMaterialQuantity); stockOutTaskOrderPO.setMaterialDetailList(taskPickingMaterialDetailPOList); return stockOutTaskOrderPO; @@ -180,22 +239,39 @@ public class StockOutTaskOrderDomainService { // .collect(Collectors.groupingBy(OutMaterialDetailSerialNumberPO::getMaterialDetailUniqueId)); List taskPickingMaterialDetailPOList = taskPickingMaterialDetailService.queryList(taskPickingMaterialDetailDO); Map> taskPickingMaterialDetailPOMap = taskPickingMaterialDetailPOList.stream().collect(Collectors.groupingBy(TaskPickingMaterialDetailPO::getStorageLocationId)); - int totalPickingMaterialQuantity = 0;//拣货单按库位分组 统计已拣货进度 + int totalPickingMaterialQuantity = 0;//拣货单按库位分组 统计已拣货进度(含已完成的库位) + int totalStorageCount = taskPickingMaterialDetailPOMap.size(); List taskStoragePOList = new ArrayList<>(); for (Map.Entry> map : taskPickingMaterialDetailPOMap.entrySet()){ - List taskPickingMaterialDetailPOListByMaterial = map.getValue(); - if (CollectionUtil.isEmpty(taskPickingMaterialDetailPOListByMaterial)){ + List taskPickingMaterialDetailPOListByStorage = map.getValue(); + if (CollectionUtil.isEmpty(taskPickingMaterialDetailPOListByStorage)){ + continue; + } + BigDecimal quantityAll = BigDecimal.ZERO; + BigDecimal pickingQuantityAll = BigDecimal.ZERO; + for (TaskPickingMaterialDetailPO d : taskPickingMaterialDetailPOListByStorage) { + quantityAll = quantityAll.add(d.getQuantity() != null ? d.getQuantity() : BigDecimal.ZERO); + pickingQuantityAll = pickingQuantityAll.add(d.getPickingQuantity() != null ? d.getPickingQuantity() : BigDecimal.ZERO); + } + 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(taskPickingMaterialDetailPOListByMaterial.get(0), taskStoragePO); + BeanUtils.copyProperties(incompleteList.get(0), taskStoragePO); BigDecimal quantity = BigDecimal.ZERO; BigDecimal pickingQuantity = BigDecimal.ZERO; BigDecimal waitPickingQuantity = BigDecimal.ZERO; - for (TaskPickingMaterialDetailPO taskPickingMaterialDetailPO : taskPickingMaterialDetailPOListByMaterial) { + for (TaskPickingMaterialDetailPO taskPickingMaterialDetailPO : incompleteList) { quantity = quantity.add(taskPickingMaterialDetailPO.getQuantity()); - pickingQuantity = pickingQuantity.add(taskPickingMaterialDetailPO.getPickingQuantity()); - waitPickingQuantity = waitPickingQuantity.add(taskPickingMaterialDetailPO.getWaitPickingQuantity()); + pickingQuantity = pickingQuantity.add(taskPickingMaterialDetailPO.getPickingQuantity() != null ? taskPickingMaterialDetailPO.getPickingQuantity() : BigDecimal.ZERO); + waitPickingQuantity = waitPickingQuantity.add(taskPickingMaterialDetailPO.getWaitPickingQuantity() != null ? taskPickingMaterialDetailPO.getWaitPickingQuantity() : BigDecimal.ZERO); } taskStoragePO.setQuantity(quantity); taskStoragePO.setPickingQuantity(pickingQuantity); @@ -203,12 +279,11 @@ public class StockOutTaskOrderDomainService { //判断拣货数量是否等于计划数量 Integer pickingStatus = judgePickingQuantity(pickingQuantity, quantity); taskStoragePO.setPickingStatus(pickingStatus); - taskStoragePO.setTaskPickingMaterialDetailList(taskPickingMaterialDetailPOListByMaterial); + taskStoragePO.setTaskPickingMaterialDetailList(incompleteList); taskStoragePOList.add(taskStoragePO); - if (pickingStatus > 2){ - totalPickingMaterialQuantity += 1; - } } + // 拣货进度:已完成数/拣货明细总数(按库位分组,几种库位就几种明细) + stockOutTaskOrderPO.setMaterialQuantity(totalStorageCount); stockOutTaskOrderPO.setPickingMaterialQuantity(totalPickingMaterialQuantity); stockOutTaskOrderPO.setTaskStorageList(taskStoragePOList); return stockOutTaskOrderPO; @@ -252,6 +327,8 @@ public class StockOutTaskOrderDomainService { totalPickingMaterialQuantity += 1; } } + // 拣货进度:已完成数/拣货明细总数(按物料分组,几种物料就几种明细) + stockOutTaskOrderPO.setMaterialQuantity(taskMaterialPOList.size()); stockOutTaskOrderPO.setPickingMaterialQuantity(totalPickingMaterialQuantity); stockOutTaskOrderPO.setTaskMaterialList(taskMaterialPOList); return stockOutTaskOrderPO;