From 5972988f1f9397753059c689771a12c5910e9cd8 Mon Sep 17 00:00:00 2001 From: "HUOJIN\\92525" <925259474@qq.com> Date: Thu, 29 Jan 2026 22:55:58 +0800 Subject: [PATCH] no message --- .../service/processor/BatchProcessor.java | 1 - .../service/processor/ScanTrayProcessor.java | 186 ++++++++++++++++-- 2 files changed, 172 insertions(+), 15 deletions(-) diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/processor/BatchProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/processor/BatchProcessor.java index 29ec83d..c27289d 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/processor/BatchProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/base/service/processor/BatchProcessor.java @@ -43,7 +43,6 @@ public class BatchProcessor { @Autowired private InventoryMapper inventoryMapper; - @Autowired private BatchUtil batchUtil; diff --git a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/processor/ScanTrayProcessor.java b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/processor/ScanTrayProcessor.java index 57003a1..57656b5 100644 --- a/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/processor/ScanTrayProcessor.java +++ b/cpte-boot-module/cpte-module-wms/src/main/java/org/cpte/modules/conveyorLine/service/processor/ScanTrayProcessor.java @@ -3,16 +3,15 @@ package org.cpte.modules.conveyorLine.service.processor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; +import org.cpte.modules.agvTask.mapper.AgvTaskMapper; import org.cpte.modules.agvTask.service.IAgvTaskService; -import org.cpte.modules.base.entity.Item; -import org.cpte.modules.base.entity.ItemKey; -import org.cpte.modules.base.entity.Point; -import org.cpte.modules.base.entity.Stock; -import org.cpte.modules.base.mapper.ItemKeyMapper; -import org.cpte.modules.base.mapper.ItemMapper; -import org.cpte.modules.base.mapper.PointMapper; -import org.cpte.modules.base.mapper.StockMapper; +import org.cpte.modules.base.entity.*; +import org.cpte.modules.base.mapper.*; +import org.cpte.modules.base.service.IItemKeyService; +import org.cpte.modules.base.service.IItemService; import org.cpte.modules.base.service.IPointService; +import org.cpte.modules.base.service.IStockService; +import org.cpte.modules.constant.GeneralConstant; import org.cpte.modules.constant.enums.*; import org.cpte.modules.conveyorLine.request.ScanTrayRequest; import org.cpte.modules.conveyorLine.vo.PointScore; @@ -24,6 +23,10 @@ import org.cpte.modules.receive.entity.Asn; import org.cpte.modules.receive.entity.AsnDetail; import org.cpte.modules.receive.mapper.AsnDetailMapper; import org.cpte.modules.receive.mapper.AsnMapper; +import org.cpte.modules.serialNumber.MoveSerialNumberRule; +import org.cpte.modules.shipping.entity.Task; +import org.cpte.modules.shipping.service.ITaskService; +import org.cpte.modules.utils.BatchUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -38,6 +41,9 @@ import java.util.stream.Stream; @Slf4j public class ScanTrayProcessor { + @Autowired + private AreaMapper areaMapper; + @Autowired private ItemMapper itemMapper; @@ -56,15 +62,36 @@ public class ScanTrayProcessor { @Autowired private ItemKeyMapper itemKeyMapper; + @Autowired + private AgvTaskMapper agvTaskMapper; + @Autowired private InventoryMapper inventoryMapper; @Autowired private IPointService pointService; + @Autowired + private IStockService stockService; + + @Autowired + private IItemService itemService; + + @Autowired + private IItemKeyService itemKeyService; + + @Autowired + private ITaskService taskService; + @Autowired private IAgvTaskService agvTaskService; + @Autowired + private MoveSerialNumberRule moveSerialNumberRule; + + @Autowired + private BatchUtil batchUtil; + /** * 扫描托盘 * @@ -82,7 +109,13 @@ public class ScanTrayProcessor { String areaCode = getAreaCode(data.getAsn().getOrderType()); Point dstPoint = allocatePoint(data.getItemKeys(), data.getStation(), areaCode, BusinessTypeEnum.INBOUND.getValue()); - // 5.生成TES任务 + //5.判断当前分配的库位是否需要移位 + List movePoints = getMovePointsForInbound(dstPoint); + if (CollectionUtils.isNotEmpty(movePoints)) { + buildMoveTask(movePoints); + } + + // 6.生成TES任务 agvTaskService.processAgvTask(data, dstPoint); } @@ -199,9 +232,9 @@ public class ScanTrayProcessor { * @return 目标库位 */ public Point allocatePoint(List itemKeys, Point station, String areaCode, String type) { - if(AreaTypeEnum.CPCCQ.getValue().equals(areaCode)){ - return allocateCpPoint(itemKeys, station, areaCode, type); - }else{ + if (AreaTypeEnum.CPCCQ.getValue().equals(areaCode)) { + return allocateCpPoint(itemKeys, station, areaCode, type); + } else { return allocateMjPoint(itemKeys, station, areaCode, type); } } @@ -215,7 +248,7 @@ public class ScanTrayProcessor { * @param type 业务类型 * @return 目标库位 */ - private Point allocateCpPoint(List itemKeys, Point station, String areaCode,String type){ + private Point allocateCpPoint(List itemKeys, Point station, String areaCode, String type) { // 1. 获取可用库位 List availablePoints = getAvailablePoints(itemKeys, areaCode, type); if (CollectionUtils.isEmpty(availablePoints)) { @@ -271,7 +304,7 @@ public class ScanTrayProcessor { * @param type 业务类型 * @return 目标库位 */ - private Point allocateMjPoint(List itemKeys, Point station, String areaCode,String type){ + private Point allocateMjPoint(List itemKeys, Point station, String areaCode, String type) { // 1. 获取可用库位 List availablePoints = getAvailablePoints(itemKeys, areaCode, type); if (CollectionUtils.isEmpty(availablePoints)) { @@ -607,4 +640,129 @@ public class ScanTrayProcessor { return pointList.stream().collect(Collectors.groupingBy(Point::getColNum, Collectors.counting())); } + /** + * 处理入库移位逻辑,返回需要移位的库位列表 + * + * @param currPoint 目标库位 + * @return 可移动的库位列表 + */ + private List getMovePointsForInbound(Point currPoint) { + List movePoints = new ArrayList<>(); + if (currPoint == null) { + return movePoints; + } + + //当前巷道的库位数 + List points = pointMapper.findByColAndLayer(currPoint.getColNum(), currPoint.getLayerNum()); + if (CollectionUtils.isEmpty(points)) { + return movePoints; + } + + //将入库目标库位的行号转换为索引 + int targetIndex = Integer.parseInt(currPoint.getRowNum()) - 1; + if (currPoint.getIzDoubleLane().equals(1)) { + List leftPoints = calculateUsedPoints(points, 0, targetIndex); + List rightPoints = calculateUsedPoints(points, targetIndex + 1, points.size()); + // 选择占用数较少的一侧 + if (leftPoints.size() <= rightPoints.size()) { + // 从左侧入库,需要移除左侧所有占用库位 + movePoints = leftPoints; + } else { + // 从右侧入库,需要移除右侧所有占用库位 + movePoints = rightPoints; + } + }else{ + // 单通道入库:检查目标库位前方的占用情况 + movePoints = calculateUsedPoints(points, 0, targetIndex); + } + + return movePoints; + } + + /** + * 巷道库位使用情况 + * + * @param points 当前巷道所有库位 + * @param start 巷道起始库位 + * @param end 巷道结束库位 + * @return List + */ + private List calculateUsedPoints(List points, int start, int end) { + List usedPoints = new ArrayList<>(); + + if (CollectionUtils.isEmpty(points)) { + return usedPoints; + } + + for (int i = start; i < end && i < points.size(); i++) { + Point point = points.get(i); + if (point != null && point.getStatus().equals(CommonStatusEnum.USED.getValue())) { + usedPoints.add(point); + } + } + return usedPoints; + } + + /** + * 构建移库任务 + * + * @param movePoints 移库目标库位 + */ + public void buildMoveTask(List movePoints) { + List moveList = new ArrayList<>(); + + //库存 + List pointIds = movePoints.stream().map(Point::getId).toList(); + List moveInventoryList = inventoryMapper.queryByPointIds(pointIds); + + //物料 + List itemIds = moveInventoryList.stream().map(Inventory::getItemId).distinct().toList(); + Map moveItemMap = itemService.queryByItemIdsToMap(itemIds); + + //物料属性 + List itemKeyIds = moveInventoryList.stream().map(Inventory::getItemKeyId).distinct().toList(); + Map itemKeyMap = itemKeyService.queryByIdsToMap(itemKeyIds); + List itemKeyList = itemKeyMap.values().stream().toList(); + + //库位 + Map fromPointMap = movePoints.stream().collect(Collectors.toMap(Point::getId, point -> point)); + + //容器 + List stockIds = moveInventoryList.stream().map(Inventory::getStockId).distinct().toList(); + Map stockMap = stockService.queryByStockIdsToMap(stockIds); + + for (Inventory inv : moveInventoryList) { + try { + //如果移位库位已有出库任务则不需要生成移位任务 + Stock stock = stockMap.get(inv.getStockId()); + if (agvTaskMapper.existsByStockCode(stock.getStockCode(), AgvVendorEnum.TES.getValue()) != null) { + continue; + } + Item moveItem = moveItemMap.get(inv.getItemId()); + Point fromPoint = fromPointMap.get(inv.getPointId()); + + Area area = areaMapper.selectById(fromPoint.getAreaId()); + String areaCode = area.getAreaCode(); + + String taskNo = moveSerialNumberRule.generateSerialNumber(GeneralConstant.MOVE_ORDER_NO); + //根据算法找到最优的目标库位 + Point toPoint = allocatePoint(itemKeyList, fromPoint, areaCode, BusinessTypeEnum.MOVE.getValue()); + Task moveTask = taskService.bulidTask(taskNo, TaskTypeEnum.MOVE.getValue(), moveItem, fromPoint, toPoint, stock, null, null, inv.getItemKeyId(), inv.getId(), inv.getQuantity(), 0); + moveList.add(moveTask); + pointService.bindPoint(toPoint); + inv.setStatus(InventoryStatusEnum.MOVE.getValue()); + log.info("生成移位任务:{}- 容器:{} - 库位:{} - 库存数量:{}", taskNo, stock.getStockCode(), fromPoint.getPointCode(), inv.getQuantity()); + } catch (Exception e) { + throw e; + } + } + if (CollectionUtils.isNotEmpty(moveInventoryList)) { + inventoryMapper.updateById(moveInventoryList); + } + if (CollectionUtils.isNotEmpty(moveList)) { + batchUtil.saveBatchTask(moveList); + } + } + + }