PDA入库[收货,上架修改]

This commit is contained in:
秦鸿展
2026-03-14 10:09:23 +08:00
parent 51a7501da6
commit 4aa41a0366
4 changed files with 163 additions and 12 deletions
@@ -267,9 +267,14 @@ public class ShiftManageApplicationService {
/**
* 物料移位(PDA),与收货、上架一致:支持 getInfoByApp 的 parent_copy 结构及分批移位
* 按单移位:PDA 仅传 shiftManageId、updateTime 时,自动从库中带出该单下所有待移位明细,默认 shiftQuantity=quantity
*/
public Boolean appMoveFromShiftManage(ShiftManageDO shiftManageDO){
List<ShiftMaterialDetailDO> 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<ShiftMaterialDetailDO> 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<ShiftMaterialDetailDO> 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 提交时需将其值回填主项并移除。
@@ -384,6 +384,22 @@ public class StockReceiptOrderApplicationService {
return sum;
}
/**
* 第一次收货:主项无子项时,收货数量默认等于计划数量,供 PDA 表单默认展示
*/
private void fillFirstReceiptQuantityDefault(List<ReceiptMaterialDetailPO> 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());
}
}
}
}
/**
* 扁平化明细:主行保留自身 receiptQuantityalreadyReceiptQuantity 汇总主行+所有子项;保留父子结构,子项作为 children 展示
* @param receiptMaterialDetailPOList 物料明细列表(树形,level 1 父级含 children
@@ -959,6 +975,8 @@ public class StockReceiptOrderApplicationService {
// 物料条码为空时取物料维护的条码信息第一行的 barCode
Map<Long, String> materialBarCodeMap = buildMaterialBarCodeMap(materialBaseInfoIdSet);
fillBarCodeFromMaterialBarCodeRecursively(materialDetailList, materialBarCodeMap);
// 第一次收货:主项无子项时,收货数量默认等于计划数量
fillFirstReceiptQuantityDefault(materialDetailList);
// PDA 端与 PC 端一致:主行收货数量取第一条子项,已收货数量汇总所有子项
flattenMaterialDetailList(materialDetailList);
clearChildQuantityRecursively(materialDetailList);
@@ -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<ShelfMaterialDetailPO> 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 批次标签
@@ -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<StockOutTaskOrderPO> queryList(StockOutTaskOrderDO stockOutTaskOrderDO) {
return stockOutTaskOrderService.queryList(stockOutTaskOrderDO);
List<StockOutTaskOrderPO> list = stockOutTaskOrderService.queryList(stockOutTaskOrderDO);
if (CollectionUtil.isEmpty(list)) {
return list;
}
enrichListWithPickingProgress(list);
return list;
}
/**
* 为拣货作业单列表补充拣货进度materialQuantitypickingMaterialQuantity
*/
private void enrichListWithPickingProgress(List<StockOutTaskOrderPO> list) {
List<String> taskNumberList = list.stream()
.map(StockOutTaskOrderPO::getTaskNumber)
.filter(taskNumber -> taskNumber != null && !taskNumber.isEmpty())
.distinct()
.collect(Collectors.toList());
if (CollectionUtil.isEmpty(taskNumberList)) {
return;
}
List<TaskPickingMaterialDetail> detailList = taskPickingMaterialDetailService.list(
new LambdaQueryWrapper<TaskPickingMaterialDetail>()
.in(TaskPickingMaterialDetail::getTaskNumber, taskNumberList));
if (CollectionUtils.isEmpty(detailList)) {
return;
}
// task_number -> material_base_info_id 分组汇总 quantitypickingQuantity
Map<String, Map<Long, List<TaskPickingMaterialDetail>>> 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<Long, List<TaskPickingMaterialDetail>> materialMap = taskToMaterialMap.get(taskNumber);
if (materialMap == null || materialMap.isEmpty()) {
continue;
}
int totalMaterialQuantity = materialMap.size();
int completedMaterialQuantity = 0;
for (List<TaskPickingMaterialDetail> 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<TaskPickingMaterialDetailPO> taskPickingMaterialDetailPOList = taskPickingMaterialDetailService.queryList(taskPickingMaterialDetailDO);
Map<Long, List<TaskPickingMaterialDetailPO>> taskPickingMaterialDetailPOMap = taskPickingMaterialDetailPOList.stream().collect(Collectors.groupingBy(TaskPickingMaterialDetailPO::getStorageLocationId));
int totalPickingMaterialQuantity = 0;//拣货单按库位分组 统计已拣货进度
int totalPickingMaterialQuantity = 0;//拣货单按库位分组 统计已拣货进度含已完成的库位
int totalStorageCount = taskPickingMaterialDetailPOMap.size();
List<TaskStoragePO> taskStoragePOList = new ArrayList<>();
for (Map.Entry<Long, List<TaskPickingMaterialDetailPO>> map : taskPickingMaterialDetailPOMap.entrySet()){
List<TaskPickingMaterialDetailPO> taskPickingMaterialDetailPOListByMaterial = map.getValue();
if (CollectionUtil.isEmpty(taskPickingMaterialDetailPOListByMaterial)){
List<TaskPickingMaterialDetailPO> 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<TaskPickingMaterialDetailPO> 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;