no message
parent
3559b73ee1
commit
e4733b37de
|
|
@ -4,14 +4,14 @@
|
|||
<select id="queryByLastEndCode" resultType="org.cpte.modules.agvTask.entity.AgvTask">
|
||||
(SELECT * FROM data_agv_task
|
||||
WHERE start_code = #{endCode}
|
||||
AND type IN ('INBOUND','OUTBOUND')
|
||||
AND type = 'INBOUND'
|
||||
AND agv_vendor = 'TES'
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 1)
|
||||
UNION ALL
|
||||
(SELECT * FROM data_agv_task
|
||||
WHERE end_code = #{endCode}
|
||||
AND type IN ('INBOUND','OUTBOUND')
|
||||
AND type ='OUTBOUND'
|
||||
AND agv_vendor = 'TES'
|
||||
ORDER BY create_time DESC
|
||||
LIMIT 1)
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ public interface PointMapper extends BaseMapper<Point> {
|
|||
List<Point> findPointsWithSkuBatchPo(@Param("itemKeyIds") List<Long> itemKeyIds, @Param("areaCode") String areaCode);
|
||||
|
||||
// 查询同一巷道占用数量
|
||||
@Select("SELECT COUNT(id) FROM base_point WHERE col_num = #{colNum} AND layer_num = #{layerNum} AND status = 1")
|
||||
int countOccupiedInSameColumn(@Param("colNum") String colNum, @Param("layerNum") String layerNum);
|
||||
@Select("select * from base_point p join base_area a on a.id=p.area_id where a.area_code = #{areaCode} and `status`=1 ")
|
||||
List<Point> countOccupiedInSameColumn(@Param("areaCode") String areaCode);
|
||||
|
||||
@Select("SELECT * FROM base_point WHERE col_num = #{colNum} AND layer_num = #{layerNum} ORDER BY row_num ASC")
|
||||
List<Point> findByColAndLayer(@Param("colNum") String colNum, @Param("layerNum") String layerNum);
|
||||
|
|
|
|||
|
|
@ -15,10 +15,14 @@ import org.cpte.modules.conveyorLine.service.processor.ScanTrayProcessor;
|
|||
import org.cpte.modules.shipping.entity.Task;
|
||||
import org.cpte.modules.shipping.mapper.TaskMapper;
|
||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||
import org.jeecg.common.util.RedisUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
|
|
@ -33,9 +37,14 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
|
|||
@Autowired
|
||||
private ScanTrayProcessor scanTrayProcessor;
|
||||
|
||||
@Autowired
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Autowired
|
||||
private RedisDistributedLockUtil redissonLock;
|
||||
|
||||
private static final String CONVEYOR_LINE_KEY = "CONVEYOR_LINE_KEY";
|
||||
|
||||
@Override
|
||||
public void scanTray(ScanTrayRequest scanTrayRequest) {
|
||||
String lockKey = "scanTray:" + scanTrayRequest.getContent().getSignal().getBarCode();
|
||||
|
|
@ -59,48 +68,136 @@ public class IConveyorLineServiceImpl implements IConveyorLineService {
|
|||
|
||||
@Override
|
||||
public JSONObject showConveyorLine(String conveyorLine) {
|
||||
JSONObject jsonObject = initJsonObject();
|
||||
jsonObject.put("endCode", conveyorLine);
|
||||
|
||||
//工作站
|
||||
Area area = areaMapper.queryByPointCode(conveyorLine);
|
||||
if (area == null) {
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
// 设置任务类型
|
||||
String taskType = BusinessTypeEnum.OUTBOUND.getDesc();
|
||||
if (AreaTypeEnum.RK_DOCK.getValue().equals(area.getAreaCode())) {
|
||||
taskType = BusinessTypeEnum.INBOUND.getDesc();
|
||||
}
|
||||
jsonObject.put("taskType", taskType);
|
||||
|
||||
//获取工作站的最新任务
|
||||
AgvTask agvTask = agvTaskMapper.queryByLastEndCode(conveyorLine);
|
||||
if (agvTask == null) {
|
||||
jsonObject.put("description", "无出库任务");
|
||||
if (AreaTypeEnum.RK_DOCK.getValue().equals(area.getAreaCode())) {
|
||||
jsonObject.put("description", "无入库任务");
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
// 设置公共字段
|
||||
setCommonFields(jsonObject, agvTask);
|
||||
|
||||
// 根据区域类型处理不同逻辑
|
||||
if (AreaTypeEnum.RK_DOCK.getValue().equals(area.getAreaCode())) {
|
||||
handleInboundTask(jsonObject, agvTask);
|
||||
if (AgvStatusEnum.COMPLETED.getValue().equals(agvTask.getStatus())) {
|
||||
Object dateObj = redisUtil.get(CONVEYOR_LINE_KEY);
|
||||
if (dateObj != null) {
|
||||
String description = "工作站无入库任务";
|
||||
return cleanJsonObject(conveyorLine,description);
|
||||
} else {
|
||||
redisUtil.set(CONVEYOR_LINE_KEY, agvTask.getId());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
handleOutboundTask(jsonObject, agvTask);
|
||||
}
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化JSON对象
|
||||
*/
|
||||
private JSONObject initJsonObject() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("stockCode", "");
|
||||
jsonObject.put("taskType", "");
|
||||
jsonObject.put("endCode", "");
|
||||
jsonObject.put("izAll", "");
|
||||
jsonObject.put("description", "");
|
||||
String description;
|
||||
//工作站库区
|
||||
Area area = areaMapper.queryByPointCode(conveyorLine);
|
||||
if(area==null){
|
||||
return jsonObject;
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
if(AreaTypeEnum.RK_DOCK.getValue().equals(area.getAreaCode())){
|
||||
|
||||
}else{
|
||||
|
||||
}
|
||||
AgvTask agvTask = agvTaskMapper.queryByLastEndCode(conveyorLine);
|
||||
if (agvTask == null) {
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
if(BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())){
|
||||
//先查询扫描成功的日志并返回成功描述信息,如果没有则返回扫描异常信息
|
||||
}
|
||||
|
||||
String stockCode = agvTask.getCarrierCode();
|
||||
String taskType = BusinessTypeEnum.getDescByValue(agvTask.getType());
|
||||
String endCode = agvTask.getEndCode();
|
||||
String izAll = agvTask.getIzAll() == 1 ? "拆托" : "整托";
|
||||
description = izAll.equals("拆托")
|
||||
? "请人工将托盘【" + stockCode + "】叉走,避免任务拥堵"
|
||||
: "请等待AGV将托盘【" + stockCode + "】叉走";
|
||||
|
||||
jsonObject.put("stockCode", stockCode);
|
||||
jsonObject.put("taskType", taskType);
|
||||
jsonObject.put("endCode", endCode);
|
||||
jsonObject.put("izAll", izAll);
|
||||
private JSONObject cleanJsonObject(String conveyorLine, String description) {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("stockCode", "");
|
||||
jsonObject.put("taskType", "");
|
||||
jsonObject.put("endCode", conveyorLine);
|
||||
jsonObject.put("izAll", "");
|
||||
jsonObject.put("description", description);
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置公共字段
|
||||
*/
|
||||
private void setCommonFields(JSONObject jsonObject, AgvTask agvTask) {
|
||||
jsonObject.put("stockCode", agvTask.getCarrierCode());
|
||||
jsonObject.put("izAll", agvTask.getIzAll() == 1 ? "拆托" : "整托");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理入库任务
|
||||
*/
|
||||
private void handleInboundTask(JSONObject jsonObject, AgvTask agvTask) {
|
||||
String description = getInboundDescription(agvTask);
|
||||
|
||||
jsonObject.put("description", description);
|
||||
}
|
||||
|
||||
private void updateAgvTaskId(AgvTask agvTask) {
|
||||
redisUtil.set(CONVEYOR_LINE_KEY, agvTask.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据状态获取入库描述
|
||||
*/
|
||||
private String getInboundDescription(AgvTask agvTask) {
|
||||
String carrierCode = agvTask.getCarrierCode();
|
||||
|
||||
Map<Integer, String> statusDescriptionMap = new HashMap<>();
|
||||
statusDescriptionMap.put(AgvStatusEnum.CREATED.getValue(),
|
||||
"托盘异常:" + agvTask.getResMessage());
|
||||
statusDescriptionMap.put(AgvStatusEnum.EXECUTING.getValue(),
|
||||
"托盘检测成功,入库中");
|
||||
statusDescriptionMap.put(AgvStatusEnum.COMPLETED.getValue(),
|
||||
"托盘入库完成");
|
||||
statusDescriptionMap.put(AgvStatusEnum.CANCELLED.getValue(),
|
||||
"托盘入库已取消或已失败,人工确认");
|
||||
|
||||
//成功更新缓存
|
||||
if (AgvStatusEnum.COMPLETED.getValue().equals(agvTask.getStatus())) {
|
||||
updateAgvTaskId(agvTask);
|
||||
}
|
||||
|
||||
return statusDescriptionMap.getOrDefault(agvTask.getStatus(),
|
||||
"【" + carrierCode + "】托盘状态未知");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理出库任务
|
||||
*/
|
||||
private void handleOutboundTask(JSONObject jsonObject, AgvTask agvTask) {
|
||||
String stockCode = agvTask.getCarrierCode();
|
||||
String izAll = agvTask.getIzAll() == 1 ? "拆托" : "整托";
|
||||
|
||||
String description = izAll.equals("拆托")
|
||||
? "请人工将托盘叉走,避免任务拥堵"
|
||||
: "请等待AGV将托盘叉走";
|
||||
|
||||
jsonObject.put("description", description);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -208,6 +208,9 @@ public class ScanTrayProcessor {
|
|||
//根据巷道分组,得到每个巷道有多个库位,<巷道编号,库位个数>
|
||||
Map<String, Long> colMap = getColMap(areaCode);
|
||||
|
||||
//获取每个巷道已占用的库位
|
||||
Map<String, Long> colUsedMap = getColUsedMap(areaCode);
|
||||
|
||||
//根据layerNum层来分组
|
||||
Map<String, List<Point>> layerMap = availablePoints.stream().collect(Collectors.groupingBy(Point::getLayerNum));
|
||||
|
||||
|
|
@ -216,15 +219,15 @@ public class ScanTrayProcessor {
|
|||
|
||||
//移位选择最优库位
|
||||
if (type.equals(BusinessTypeEnum.MOVE.getValue())) {
|
||||
firstScoredPoints = selectBestPointForMove(station, itemKeys,colMap,layerMap);
|
||||
firstScoredPoints = selectBestPointForMove(station, itemKeys, colMap, layerMap, colUsedMap);
|
||||
} else {
|
||||
//计算第一层的库位分数
|
||||
Station firstStation = new Station(station.getPositionX(), station.getPositionY());
|
||||
firstScoredPoints = selectBestPointForStorage(firstStation, itemKeys, CommonStatusEnum.ONE.getValue(), colMap, layerMap);
|
||||
firstScoredPoints = selectBestPointForStorage(firstStation, itemKeys, CommonStatusEnum.ONE.getValue(), colMap, layerMap, colUsedMap);
|
||||
|
||||
//计算第二层的库位分数
|
||||
Station secondStation = new Station(station.getPositionTwoX(), station.getPositionTwoY());
|
||||
secondScoredPoints= selectBestPointForStorage(secondStation, itemKeys, CommonStatusEnum.TWO.getValue(), colMap, layerMap);
|
||||
secondScoredPoints = selectBestPointForStorage(secondStation, itemKeys, CommonStatusEnum.TWO.getValue(), colMap, layerMap, colUsedMap);
|
||||
}
|
||||
|
||||
//合并获取最优库位
|
||||
|
|
@ -265,7 +268,7 @@ public class ScanTrayProcessor {
|
|||
/**
|
||||
* 移位选择最优库位评分
|
||||
*/
|
||||
private List<PointScore> selectBestPointForMove(Point station, List<ItemKey> itemKeys, Map<String, Long> colMap, Map<String, List<Point>> layerMap) {
|
||||
private List<PointScore> selectBestPointForMove(Point station, List<ItemKey> itemKeys, Map<String, Long> colMap, Map<String, List<Point>> layerMap, Map<String, Long> colUsedMap) {
|
||||
|
||||
//当前库位的层数
|
||||
String layerNum = station.getLayerNum();
|
||||
|
|
@ -277,7 +280,7 @@ public class ScanTrayProcessor {
|
|||
currentLayerPoints = currentLayerPoints.stream().filter(point -> !point.getColNum().equals(station.getColNum())).toList();
|
||||
if (CollectionUtils.isNotEmpty(currentLayerPoints)) {
|
||||
return currentLayerPoints.stream()
|
||||
.map(point -> clusterPointScore(point, currentStation, itemKeys, colMap))
|
||||
.map(point -> clusterPointScore(point, currentStation, itemKeys, colMap, colUsedMap))
|
||||
.toList();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
|
|
@ -286,11 +289,11 @@ public class ScanTrayProcessor {
|
|||
/**
|
||||
* 入库选择最优库位评分
|
||||
*/
|
||||
private List<PointScore> selectBestPointForStorage(Station station, List<ItemKey> itemKeys, Integer layerNum, Map<String, Long> colMap, Map<String, List<Point>> layerMap) {
|
||||
private List<PointScore> selectBestPointForStorage(Station station, List<ItemKey> itemKeys, Integer layerNum, Map<String, Long> colMap, Map<String, List<Point>> layerMap, Map<String, Long> colUsedMap) {
|
||||
List<Point> currLayerPoints = layerMap.get(String.valueOf(layerNum));
|
||||
if (CollectionUtils.isNotEmpty(currLayerPoints)) {
|
||||
return currLayerPoints.stream()
|
||||
.map(point -> clusterPointScore(point, station, itemKeys, colMap))
|
||||
.map(point -> clusterPointScore(point, station, itemKeys, colMap, colUsedMap))
|
||||
.toList();
|
||||
}
|
||||
return new ArrayList<>();
|
||||
|
|
@ -300,26 +303,26 @@ public class ScanTrayProcessor {
|
|||
/**
|
||||
* 库位评分计算
|
||||
*/
|
||||
private PointScore clusterPointScore(Point point, Station station, List<ItemKey> itemKeys, Map<String, Long> colMap) {
|
||||
private PointScore clusterPointScore(Point point, Station station, List<ItemKey> itemKeys, Map<String, Long> colMap, Map<String, Long> colUsedMap) {
|
||||
double totalScore;
|
||||
|
||||
// 1. 距离评分 - 考虑从入库口到库位的距离
|
||||
double distanceScore = calculateClusterDistanceCost(point, station) * 0.3;// 权重30%
|
||||
double distanceScore = calculateClusterDistanceCost(point, station) * 0.45;// 权重30%
|
||||
|
||||
// 2. 通道深度策略评分 - 新增核心策略
|
||||
double channelDepthScore = calculateChannelDepthScore(point, colMap) * 0.25; // 权重25%
|
||||
double channelDepthScore = calculateChannelDepthScore(point, colMap) * 0.20; // 权重20%
|
||||
|
||||
// 3. 通道类型评分 - 双通道优先
|
||||
double channelScore = calculateChannelScore(point) * 0.2; // 权重20%
|
||||
double channelScore = calculateChannelScore(point) * 0.25; // 权重25%
|
||||
|
||||
// 4. 均衡评分 - 避免热点区域
|
||||
// double balanceScore = calculateBalanceScore(point) * 0.1; // 权重10%
|
||||
double balanceScore = calculateBalanceScore(point, colMap, colUsedMap) * 0.10; // 权重20%
|
||||
|
||||
// 5. 物料聚集潜力评分 - 新增
|
||||
// double clusterPotentialScore = calculateClusterPotentialScore(point, itemKeys) * 0.2; // 权重20%
|
||||
|
||||
totalScore = distanceScore + channelDepthScore + channelScore;
|
||||
log.info("【{}】库位总分:{} - 距离评分: {} - 通道深度策略评分: {} - 通道类型评分: {} - 均衡评分: {} - 物料聚集评分: {}", point.getPointCode(), totalScore, distanceScore, channelDepthScore, channelScore, 0, 0);
|
||||
totalScore = distanceScore + channelDepthScore + channelScore + balanceScore;
|
||||
log.info("【{}】库位总分:{} - 距离评分: {} - 通道深度策略评分: {} - 通道类型评分: {} - 均衡评分: {} - 物料聚集评分: {}", point.getPointCode(), totalScore, distanceScore, channelDepthScore, channelScore, balanceScore, 0);
|
||||
|
||||
return new PointScore(point, totalScore);
|
||||
}
|
||||
|
|
@ -391,12 +394,16 @@ public class ScanTrayProcessor {
|
|||
* 计算均衡评分
|
||||
* 避免同一区域过于集中,考虑周围库位占用情况
|
||||
*/
|
||||
private double calculateBalanceScore(Point point) {
|
||||
// 查询同一巷道相邻库位的占用情况
|
||||
int sameColumnOccupied = pointMapper.countOccupiedInSameColumn(point.getColNum(), point.getLayerNum());
|
||||
|
||||
private double calculateBalanceScore(Point point, Map<String, Long> colMap, Map<String, Long> colUsedMap) {
|
||||
// 当前库位巷道的占用个数
|
||||
Long sameColumnOccupied = colUsedMap.get(point.getColNum());
|
||||
if (sameColumnOccupied == null) {
|
||||
sameColumnOccupied = 0L;
|
||||
}
|
||||
//当前库位巷道的最大深度
|
||||
Long maxDepth = colMap.get(point.getColNum());
|
||||
// 占用率越低,分数越高
|
||||
double occupancyRate = sameColumnOccupied / 7.0; // 7个深度位置
|
||||
double occupancyRate = (double) sameColumnOccupied / maxDepth; // 修复:转换为浮点数除法
|
||||
return (1 - occupancyRate) * 100;
|
||||
}
|
||||
|
||||
|
|
@ -508,4 +515,15 @@ public class ScanTrayProcessor {
|
|||
return pointList.stream().collect(Collectors.groupingBy(Point::getColNum, Collectors.counting()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取每个巷道的库位个数
|
||||
*
|
||||
* @param areaCode 库区
|
||||
* @return Map<巷道编码, 库位个数>
|
||||
*/
|
||||
private Map<String, Long> getColUsedMap(String areaCode) {
|
||||
List<Point> pointList = pointMapper.countOccupiedInSameColumn(areaCode);
|
||||
return pointList.stream().collect(Collectors.groupingBy(Point::getColNum, Collectors.counting()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,20 +363,38 @@ public class PickController {
|
|||
return Result.error("请选择需要回传的出库单");
|
||||
}
|
||||
try {
|
||||
PickData data=new PickData();
|
||||
PickData data = new PickData();
|
||||
Pick pick = pickService.getById(id);
|
||||
Map<Long,Pick> pickMap = new HashMap<>();
|
||||
pickMap.put(id,pick);
|
||||
Map<Long, Pick> pickMap = new HashMap<>();
|
||||
pickMap.put(id, pick);
|
||||
List<PickDetail> pickDetails = pickDetailService.selectByMainId(id);
|
||||
Map<Long,PickDetail> pickDetailMap = pickDetails. stream().collect(Collectors.toMap(PickDetail::getId, PickDetail -> PickDetail));
|
||||
Map<Long, PickDetail> pickDetailMap = pickDetails.stream().collect(Collectors.toMap(PickDetail::getId, PickDetail -> PickDetail));
|
||||
List<Task> tasks = taskMapper.queryTaskByMainId(id);
|
||||
data.setPickMap(pickMap);
|
||||
data.setPickDetailMap(pickDetailMap);
|
||||
pickBackProcessor.pickBack(data,tasks);
|
||||
pickBackProcessor.pickBack(data, tasks);
|
||||
pickDetailService.refreshPick(pick, pickDetailService.selectByMainId(id));
|
||||
return Result.OK("回传成功");
|
||||
} catch (Exception e) {
|
||||
return Result.error("回传异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@AutoLog(value = "手工关单")
|
||||
@Operation(summary = "手工关单")
|
||||
@RequiresPermissions("shipping:data_pick:closePick")
|
||||
@GetMapping(value = "/closePick")
|
||||
public Result<String> closePick(@RequestParam(name = "ids", required = true) String ids) {
|
||||
if (StringUtils.isBlank(ids)) {
|
||||
return Result.error("请选择需要拣货的出库单");
|
||||
}
|
||||
try {
|
||||
List<String> idsList = Arrays.asList(ids.split(","));
|
||||
List<Long> pickIds = idsList.stream().map(Long::parseLong).toList();
|
||||
pickService.closePick(pickIds);
|
||||
return Result.OK("操作成功");
|
||||
} catch (Exception e) {
|
||||
return Result.error("操作异常:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,6 +167,13 @@ public class Task implements Serializable {
|
|||
@Schema(description = "完成时间")
|
||||
private java.util.Date completeTime;
|
||||
|
||||
/**
|
||||
* 请求报文
|
||||
*/
|
||||
@Excel(name = "请求报文", width = 15)
|
||||
@Schema(description = "请求报文")
|
||||
private java.lang.String reqMessage;
|
||||
|
||||
/**
|
||||
* 返回报文
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ public interface TaskMapper extends BaseMapper<Task> {
|
|||
*
|
||||
* @return List<Pick>
|
||||
*/
|
||||
@Select("SELECT * FROM data_task WHERE agv_task_id is null order by create_time ")
|
||||
@Select("SELECT * FROM data_task WHERE agv_task_id is null and to_point_id is not null order by create_time ")
|
||||
List<Task> queryUnIssuedTask();
|
||||
|
||||
@Select("SELECT * FROM data_task WHERE agv_task_id = #{agvTaskId} ")
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public interface IPickDetailService extends IService<PickDetail> {
|
|||
* @return List<PickDetail>
|
||||
*/
|
||||
public List<PickDetail> selectByMainId(Long mainId);
|
||||
|
||||
|
||||
/**
|
||||
* 根据出库单ID查询出库单Map
|
||||
*
|
||||
|
|
|
|||
|
|
@ -69,4 +69,12 @@ public interface IPickService extends IService<Pick> {
|
|||
*/
|
||||
void pickTask(List<Task> tasks);
|
||||
|
||||
|
||||
/**
|
||||
* 关闭出库单
|
||||
*
|
||||
* @param pickIds 出库单集合
|
||||
*/
|
||||
void closePick(List<Long> pickIds);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.cpte.modules.shipping.service.impl;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.constant.enums.*;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
|
|
@ -24,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Description: 出库单
|
||||
|
|
@ -162,4 +164,35 @@ public class PickServiceImpl extends ServiceImpl<PickMapper, Pick> implements IP
|
|||
pickProcessor.pick(tasks);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void closePick(List<Long> pickIds) {
|
||||
if(CollectionUtils.isEmpty(pickIds)){
|
||||
throw new RuntimeException("请选择需要关闭的出库单");
|
||||
}
|
||||
Map<Long,Pick> pickMap = pickDetailService.queryByPickIdsToMap(pickIds);
|
||||
List<PickDetail> pickDetails = pickDetailMapper.queryByPickIds(pickIds);
|
||||
//根据出库单ID分组
|
||||
Map<Long, List<PickDetail>> pickDetailMapGroup = pickDetails.stream().collect(Collectors.groupingBy(PickDetail::getPickId));
|
||||
//遍历集合
|
||||
List<Pick> pickToUpdate = new ArrayList<>();
|
||||
List<PickDetail> pickDetailToUpdate = new ArrayList<>();
|
||||
for (Map.Entry<Long, List<PickDetail>> entry : pickDetailMapGroup.entrySet()) {
|
||||
Pick pick = pickMap.get(entry.getKey());
|
||||
List<PickDetail> pickDetailList = entry.getValue();
|
||||
for (PickDetail pickDetail : pickDetailList){
|
||||
pickDetail.setStatus(PickStatusEnum.CLOSED.getValue());
|
||||
pickDetailToUpdate.add(pickDetail);
|
||||
}
|
||||
pick.setStatus(PickStatusEnum.CLOSED.getValue());
|
||||
pickToUpdate.add(pick);
|
||||
}
|
||||
if(CollectionUtils.isNotEmpty(pickDetailToUpdate)){
|
||||
pickDetailMapper.updateById(pickDetailToUpdate);
|
||||
}
|
||||
if(CollectionUtils.isNotEmpty(pickToUpdate)){
|
||||
this.updateBatchById(pickToUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -675,8 +675,8 @@ public class AllocateProcessor {
|
|||
Point fromPoint = data.getPointMap().get(inventory.getPointId());
|
||||
|
||||
// 判断是否整托分配
|
||||
BigDecimal originalAvailableQty = inventory.getQuantity();
|
||||
Integer izAll = originalAvailableQty.compareTo(allocateQty) == 0 ? 0 : 1;
|
||||
BigDecimal originalAvailableQty = BigDecimalUtil.subtract(inventory.getQuantity(), inventory.getQueuedQty(),0);
|
||||
Integer izAll = originalAvailableQty.compareTo(BigDecimal.ZERO) <= 0 ? 0 : 1;
|
||||
|
||||
// 目标库位
|
||||
//Point toPoint = inventoryScore.getOutPoint();
|
||||
|
|
|
|||
|
|
@ -106,43 +106,42 @@ public class PickBackProcessor {
|
|||
* @param tasks 任务
|
||||
*/
|
||||
public void pickBack(PickData data, List<Task> tasks) {
|
||||
Map<Long, List<PickDetail>> pickDetailsCache = new HashMap<>();
|
||||
|
||||
tasks = tasks.stream().filter(task -> task.getPlanQty().equals(task.getMoveQty())).toList();
|
||||
for (Task task : tasks) {
|
||||
Pick pick = data.getPickMap().get(task.getPickId());
|
||||
PickDetail pickDetail = data.getPickDetailMap().get(task.getPickDetailId());
|
||||
Long pickId = pick.getId();
|
||||
try {
|
||||
// 缓存查询结果,避免重复查询
|
||||
List<PickDetail> pickDetails = pickDetailsCache.computeIfAbsent(pickId, id -> pickDetailMapper.selectByMainId(id));
|
||||
List<PickDetail> pickDetails = pickDetailMapper.selectByMainId(pickId);
|
||||
|
||||
//已关闭的出库单
|
||||
int state = 7;
|
||||
List<PickDetail> pickPickDetails = pickDetails.stream().filter(detail -> PickStatusEnum.PICKED.getValue().equals(detail.getStatus())).toList();
|
||||
List<PickDetail> pickPickDetails = pickDetails.stream().filter(
|
||||
detail -> PickStatusEnum.PICKED.getValue().equals(detail.getStatus()) ||
|
||||
PickStatusEnum.CLOSED.getValue().equals(detail.getStatus())).toList();
|
||||
if (CollectionUtils.isNotEmpty(pickPickDetails)) {
|
||||
state = pickDetails.size() - pickPickDetails.size() == 0 ? 5 : 7;
|
||||
}
|
||||
|
||||
pickBackProcessor(pick, pickDetail, task, state);
|
||||
} catch (Exception e) {
|
||||
log.error("出库任务回传失败,任务ID: {}, 错误信息: {}", task.getId(), e.getMessage(), e);
|
||||
}
|
||||
List<PickDetail> latestPickDetails = pickDetailMapper.selectByMainId(pickId);
|
||||
pickDetailsCache.put(pickId, latestPickDetails); // 更新缓存
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void pickBackProcessor(Pick pick, PickDetail pickDetail, Task task, Integer state) {
|
||||
// 检查接口开关, 未开启则返回
|
||||
if (sysDictMapper.queryByDictCode(GeneralConstant.OPEN_FLAG) == null) {
|
||||
updatePickDetailResponse(pickDetail, task, GeneralConstant.SMOM_FAIL_CODE, "接口未开启");
|
||||
updatePickDetailResponse(pickDetail, task, GeneralConstant.SMOM_FAIL_CODE,null ,"接口未开启");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TaskStatusEnum.CLOSED.getValue().equals(task.getTaskStatus())) {
|
||||
return;
|
||||
}
|
||||
|
||||
String reqMessage = null;
|
||||
try {
|
||||
Map<String, String> authInfo = swmsLoginUtil.Login();
|
||||
if (authInfo == null || authInfo.isEmpty()) {
|
||||
|
|
@ -151,13 +150,13 @@ public class PickBackProcessor {
|
|||
|
||||
String ticket = authInfo.get("Ticket");
|
||||
String authorization = authInfo.get("authorization");
|
||||
String json = pickTaskCallbackJson(pick, pickDetail, task, state, ticket);
|
||||
reqMessage = pickTaskCallbackJson(pick, pickDetail, task, state, ticket);
|
||||
String url = openApiMapper.getRequestUrl(GeneralConstant.OUTBOUND_CALLBACK).getOriginUrl();
|
||||
JSONObject jsonObject = swmsLoginUtil.sendSMOMResponse(json, url, authorization);
|
||||
JSONObject jsonObject = swmsLoginUtil.sendSMOMResponse(reqMessage, url, authorization);
|
||||
String code = validateResponse(jsonObject);
|
||||
updatePickDetailResponse(pickDetail, task, code, jsonObject.toJSONString());
|
||||
updatePickDetailResponse(pickDetail, task, code, reqMessage, jsonObject.toJSONString());
|
||||
} catch (Exception e) {
|
||||
updatePickDetailResponse(pickDetail, task, GeneralConstant.SMOM_FAIL_CODE, e.getMessage());
|
||||
updatePickDetailResponse(pickDetail, task, GeneralConstant.SMOM_FAIL_CODE,reqMessage, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -183,10 +182,11 @@ public class PickBackProcessor {
|
|||
/**
|
||||
* 更新任务状态
|
||||
*
|
||||
* @param task 出库任务
|
||||
* @param message 信息
|
||||
* @param task 出库任务
|
||||
* @param reqMessage 请求报文
|
||||
* @param resMessage 返回报文
|
||||
*/
|
||||
private void updatePickDetailResponse(PickDetail pickDetail, Task task, String code, String message) {
|
||||
private void updatePickDetailResponse(PickDetail pickDetail, Task task, String code, String reqMessage, String resMessage) {
|
||||
if (GeneralConstant.SMOM_SUCCESS_CODE.equals(code)) {
|
||||
if (pickDetail.getOrderQty().equals(pickDetail.getPickedQty())) {
|
||||
pickDetail.setStatus(PickStatusEnum.CLOSED.getValue());
|
||||
|
|
@ -194,7 +194,8 @@ public class PickBackProcessor {
|
|||
}
|
||||
task.setTaskStatus(TaskStatusEnum.CLOSED.getValue());
|
||||
}
|
||||
task.setResMessage(message);
|
||||
task.setReqMessage(reqMessage);
|
||||
task.setResMessage(resMessage);
|
||||
task.setResTime(new Date());
|
||||
taskMapper.updateById(task);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,14 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
||||
import org.cpte.modules.agvTask.service.IAgvTaskService;
|
||||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.base.mapper.PointMapper;
|
||||
import org.cpte.modules.base.service.IPointService;
|
||||
import org.cpte.modules.constant.GeneralConstant;
|
||||
import org.cpte.modules.constant.enums.AgvStatusEnum;
|
||||
import org.cpte.modules.constant.enums.AgvVendorEnum;
|
||||
import org.cpte.modules.constant.enums.BusinessTypeEnum;
|
||||
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
||||
import org.cpte.modules.inventory.service.IInventoryService;
|
||||
import org.cpte.modules.inventory.service.impl.InventoryServiceImpl;
|
||||
import org.cpte.modules.receive.service.IAsnService;
|
||||
|
|
@ -39,6 +43,9 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
@Autowired
|
||||
private SysDictMapper sysDictMapper;
|
||||
|
||||
@Autowired
|
||||
private PointMapper pointMapper;
|
||||
|
||||
@Autowired
|
||||
private TaskMapper taskMapper;
|
||||
|
||||
|
|
@ -48,6 +55,9 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
@Autowired
|
||||
private OpenApiMapper openApiMapper;
|
||||
|
||||
@Autowired
|
||||
private IPointService pointService;
|
||||
|
||||
@Autowired
|
||||
private IAsnService asnService;
|
||||
|
||||
|
|
@ -140,6 +150,7 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
//4.成功-任务完成
|
||||
handleEnd(agvTask.getBusinessDetailId(), agvTask);
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
//6.已取消-任务取消
|
||||
handleCelled(agvTask);
|
||||
|
|
@ -235,6 +246,13 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
* @param agvTask 任务
|
||||
*/
|
||||
private void handleCelled(AgvTask agvTask) {
|
||||
if(BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType()) || BusinessTypeEnum.MOVE.getValue().equals(agvTask.getType())){
|
||||
Point point = pointMapper.queryByPointCode(agvTask.getEndCode());
|
||||
if(point!=null){
|
||||
point.setStatus(CommonStatusEnum.FREE.getValue());
|
||||
pointMapper.updateById(point);
|
||||
}
|
||||
}
|
||||
agvTask.setStatus(AgvStatusEnum.CANCELLED.getValue());
|
||||
agvTask.setEndTime(new Date());
|
||||
agvTaskMapper.updateById(agvTask);
|
||||
|
|
@ -249,10 +267,17 @@ public class ITesAgvServiceImpl implements ITesAgvService {
|
|||
if (agvTaskMapper.existsByStockCode(agvTask.getCarrierCode(), AgvVendorEnum.TES.getValue()) != null) {
|
||||
throw new RuntimeException("任务已重新生成,请勿重复操作! ");
|
||||
}
|
||||
|
||||
AgvTask newAgvTask = agvTaskService.createAgvTask(agvTask.getBusinessDetailId(), agvTask.getCarrierCode(), agvTask.getStartCode(), agvTask.getEndCode(), null, agvTask.getType(), agvTask.getIzAll(), AgvVendorEnum.TES.getValue());
|
||||
if(BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType()) || BusinessTypeEnum.MOVE.getValue().equals(agvTask.getType())){
|
||||
Point point = pointMapper.queryByPointCode(agvTask.getEndCode());
|
||||
point.setStatus(CommonStatusEnum.USED.getValue());
|
||||
pointMapper.updateById(point);
|
||||
}
|
||||
switch (agvTask.getType()) {
|
||||
case "INBOUND":
|
||||
case "OUTBOUND":
|
||||
case "MOVE":
|
||||
//下发四向车任务
|
||||
sendTesAgvTask(GeneralConstant.TES_POD_TASK, generateTesAgvTaskJson(newAgvTask), newAgvTask);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -57,4 +57,6 @@ public interface SysLogMapper extends BaseMapper<SysLog> {
|
|||
* @return
|
||||
*/
|
||||
List<Map<String,Object>> findVisitCount(@Param("dayStart") Date dayStart, @Param("dayEnd") Date dayEnd, @Param("dbType") String dbType);
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue