Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
+37
@@ -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 提交时需将其值回填主项并移除。
|
||||
|
||||
+18
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 扁平化明细:主行保留自身 receiptQuantity,alreadyReceiptQuantity 汇总主行+所有子项;保留父子结构,子项作为 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);
|
||||
|
||||
+19
@@ -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 批次标签
|
||||
|
||||
+89
-12
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为拣货作业单列表补充拣货进度(materialQuantity、pickingMaterialQuantity)
|
||||
*/
|
||||
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 分组,汇总 quantity、pickingQuantity
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user