no message
parent
eb29dc5ba5
commit
5972988f1f
|
|
@ -43,7 +43,6 @@ public class BatchProcessor {
|
|||
@Autowired
|
||||
private InventoryMapper inventoryMapper;
|
||||
|
||||
|
||||
@Autowired
|
||||
private BatchUtil batchUtil;
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Point> 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<ItemKey> itemKeys, Point station, String areaCode, String type) {
|
||||
if(AreaTypeEnum.CPCCQ.getValue().equals(areaCode)){
|
||||
if (AreaTypeEnum.CPCCQ.getValue().equals(areaCode)) {
|
||||
return allocateCpPoint(itemKeys, station, areaCode, type);
|
||||
}else{
|
||||
} else {
|
||||
return allocateMjPoint(itemKeys, station, areaCode, type);
|
||||
}
|
||||
}
|
||||
|
|
@ -215,7 +248,7 @@ public class ScanTrayProcessor {
|
|||
* @param type 业务类型
|
||||
* @return 目标库位
|
||||
*/
|
||||
private Point allocateCpPoint(List<ItemKey> itemKeys, Point station, String areaCode,String type){
|
||||
private Point allocateCpPoint(List<ItemKey> itemKeys, Point station, String areaCode, String type) {
|
||||
// 1. 获取可用库位
|
||||
List<Point> availablePoints = getAvailablePoints(itemKeys, areaCode, type);
|
||||
if (CollectionUtils.isEmpty(availablePoints)) {
|
||||
|
|
@ -271,7 +304,7 @@ public class ScanTrayProcessor {
|
|||
* @param type 业务类型
|
||||
* @return 目标库位
|
||||
*/
|
||||
private Point allocateMjPoint(List<ItemKey> itemKeys, Point station, String areaCode,String type){
|
||||
private Point allocateMjPoint(List<ItemKey> itemKeys, Point station, String areaCode, String type) {
|
||||
// 1. 获取可用库位
|
||||
List<Point> 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<Point> getMovePointsForInbound(Point currPoint) {
|
||||
List<Point> movePoints = new ArrayList<>();
|
||||
if (currPoint == null) {
|
||||
return movePoints;
|
||||
}
|
||||
|
||||
//当前巷道的库位数
|
||||
List<Point> 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<Point> leftPoints = calculateUsedPoints(points, 0, targetIndex);
|
||||
List<Point> 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<Point>
|
||||
*/
|
||||
private List<Point> calculateUsedPoints(List<Point> points, int start, int end) {
|
||||
List<Point> 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<Point> movePoints) {
|
||||
List<Task> moveList = new ArrayList<>();
|
||||
|
||||
//库存
|
||||
List<Long> pointIds = movePoints.stream().map(Point::getId).toList();
|
||||
List<Inventory> moveInventoryList = inventoryMapper.queryByPointIds(pointIds);
|
||||
|
||||
//物料
|
||||
List<Long> itemIds = moveInventoryList.stream().map(Inventory::getItemId).distinct().toList();
|
||||
Map<Long, Item> moveItemMap = itemService.queryByItemIdsToMap(itemIds);
|
||||
|
||||
//物料属性
|
||||
List<Long> itemKeyIds = moveInventoryList.stream().map(Inventory::getItemKeyId).distinct().toList();
|
||||
Map<Long, ItemKey> itemKeyMap = itemKeyService.queryByIdsToMap(itemKeyIds);
|
||||
List<ItemKey> itemKeyList = itemKeyMap.values().stream().toList();
|
||||
|
||||
//库位
|
||||
Map<Long, Point> fromPointMap = movePoints.stream().collect(Collectors.toMap(Point::getId, point -> point));
|
||||
|
||||
//容器
|
||||
List<Long> stockIds = moveInventoryList.stream().map(Inventory::getStockId).distinct().toList();
|
||||
Map<Long, Stock> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue