no message
parent
786dc1a9b9
commit
952351f951
|
|
@ -4,7 +4,6 @@ import org.apache.ibatis.annotations.Param;
|
|||
import org.apache.ibatis.annotations.Select;
|
||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.cpte.modules.agvTask.vo.ConNoAgv;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
|
@ -84,9 +83,4 @@ public interface AgvTaskMapper extends BaseMapper<AgvTask> {
|
|||
@Select(value = "select * from data_agv_task where type in ('INBOUND','OUTBOUND') and status=2 LIMIT 5")
|
||||
List<AgvTask> queryExecuteTopFive();
|
||||
|
||||
/**
|
||||
* 根据出库的起点找到对应需要移位的任务
|
||||
*/
|
||||
@Select(value = "select * from data_agv_task where con_no = #{startCode} and type='MOVE' and status=1 and agv_vendor = 'TES' ")
|
||||
List<AgvTask> queryOutPointForMove(@Param("startCode") String startCode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,16 +19,6 @@
|
|||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<select id="queryIsExecuteAgvTask" resultType="org.cpte.modules.agvTask.vo.ConNoAgv">
|
||||
SELECT p.con_no, t.item_id
|
||||
FROM data_pick p
|
||||
JOIN data_task t ON t.pick_id = p.id
|
||||
JOIN data_agv_task agv ON agv.id = t.agv_task_id
|
||||
WHERE agv.type = 'OUTBOUND'
|
||||
AND p.order_type in (4,5)
|
||||
AND agv.status IN (1, 2, 3)
|
||||
</select>
|
||||
|
||||
<select id="pointTaskCountMap" resultType="java.util.Map">
|
||||
SELECT
|
||||
bp.point_code,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
|||
import org.cpte.modules.base.entity.Point;
|
||||
import org.cpte.modules.conveyorLine.vo.ScanTrayData;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description: AGV任务表
|
||||
* @author: cpte
|
||||
|
|
@ -52,5 +54,4 @@ public interface IAgvTaskService extends IService<AgvTask> {
|
|||
* @param agvTask AGV任务
|
||||
*/
|
||||
void editAgvTask(AgvTask agvTask);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
package org.cpte.modules.agvTask.vo;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class ConNoAgv {
|
||||
private String conNo;
|
||||
private Long itemId;
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package org.cpte.modules.quartz.job;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||
import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
import org.cpte.modules.shipping.entity.PickDetail;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import org.cpte.modules.agvTask.mapper.AgvTaskMapper;
|
|||
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.shipping.service.ITaskService;
|
||||
import org.cpte.modules.tesAgv.service.ITesAgvService;
|
||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||
|
|
@ -17,9 +16,7 @@ import org.quartz.JobExecutionContext;
|
|||
import org.quartz.JobExecutionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
public class TesAgvJob implements Job {
|
||||
|
|
@ -74,91 +71,15 @@ public class TesAgvJob implements Job {
|
|||
if (CollectionUtils.isEmpty(agvTaskList)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (AgvTask agvTask : agvTaskList) {
|
||||
sendTesAgvTask(agvTask);
|
||||
/*if (BusinessTypeEnum.INBOUND.getValue().equals(agvTask.getType())) {
|
||||
sendTesAgvTask(agvTask);
|
||||
} else if (BusinessTypeEnum.OUTBOUND.getValue().equals(agvTask.getType())) {
|
||||
Map<String, String> pointTaskMap = queryPointTaskMap();
|
||||
boolean flag = sendOutTesAgvTask(agvTask, pointTaskMap);
|
||||
} else if (BusinessTypeEnum.MOVE.getValue().equals(agvTask.getType())) {
|
||||
//如果没有柜号说明是入库的移位
|
||||
if (StringUtils.isEmpty(agvTask.getConNo())) {
|
||||
sendTesAgvTask(agvTask);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送TES任务
|
||||
*/
|
||||
private boolean sendTesAgvTask(AgvTask agvTask) {
|
||||
return tesAgvService.sendTesAgvTask(GeneralConstant.TES_POD_TASK, tesAgvService.generateTesAgvTaskJson(agvTask), agvTask);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送TES出库任务
|
||||
*/
|
||||
private boolean sendOutTesAgvTask(AgvTask agvTask, Map<String, String> pointTaskMap) {
|
||||
|
||||
// 标记当前任务的key
|
||||
String currKey = agvTask.getConNo() + "_" + agvTask.getItemId();
|
||||
|
||||
// 获取当前任务的目标工作站
|
||||
String targetEndCode = agvTask.getEndCode();
|
||||
|
||||
// 1. 检查目标工作站
|
||||
String executeKey = pointTaskMap.get(targetEndCode);
|
||||
if (StringUtils.isEmpty(executeKey)) {
|
||||
// 目标工作站空闲,直接下发
|
||||
return sendTaskToWorkstation(agvTask, targetEndCode, currKey, pointTaskMap);
|
||||
}
|
||||
|
||||
// 2. 目标工作站任务匹配
|
||||
if (currKey.equals(executeKey)) {
|
||||
return sendTaskToWorkstation(agvTask, targetEndCode, currKey, pointTaskMap);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下发任务到指定工作站
|
||||
*/
|
||||
private boolean sendTaskToWorkstation(AgvTask agvTask, String workstationCode, String taskKey,
|
||||
Map<String, String> pointTaskMap) {
|
||||
boolean flag = sendTesAgvTask(agvTask);
|
||||
if (flag) {
|
||||
pointTaskMap.put(workstationCode, taskKey);
|
||||
sendOutPointForMove(agvTask);
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 当前出库任务有移位任务则下发移位任务
|
||||
*/
|
||||
private void sendOutPointForMove(AgvTask currOutAgvTask) {
|
||||
List<AgvTask> agvTasks = agvTaskMapper.queryOutPointForMove(currOutAgvTask.getStartCode());
|
||||
if (CollectionUtils.isNotEmpty(agvTasks)) {
|
||||
for (AgvTask agvTask : agvTasks) {
|
||||
sendTesAgvTask(agvTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> queryPointTaskMap() {
|
||||
// 从数据库查询每个工作站当前的任务列表
|
||||
List<Map<String, Object>> result = agvTaskMapper.pointTaskMap();
|
||||
Map<String, String> pointTaskMap = new HashMap<>();
|
||||
for (Map<String, Object> map : result) {
|
||||
String key = map.get("point_code").toString();
|
||||
String no_item = map.get("no_item") == null ? "" : map.get("no_item").toString();
|
||||
pointTaskMap.put(key, no_item);
|
||||
}
|
||||
return pointTaskMap;
|
||||
private void sendTesAgvTask(AgvTask agvTask) {
|
||||
tesAgvService.sendTesAgvTask(GeneralConstant.TES_POD_TASK, tesAgvService.generateTesAgvTaskJson(agvTask), agvTask);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.cpte.modules.receive.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
|
@ -10,7 +11,10 @@ import org.cpte.modules.base.entity.Stock;
|
|||
import org.cpte.modules.base.mapper.StockMapper;
|
||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
||||
import org.cpte.modules.constant.enums.InventoryStatusEnum;
|
||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import org.cpte.modules.receive.entity.AsnDetail;
|
||||
import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||
|
|
@ -48,6 +52,8 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
@Autowired
|
||||
private AsnDetailMapper asnDetailMapper;
|
||||
@Autowired
|
||||
private InventoryMapper inventoryMapper;
|
||||
@Autowired
|
||||
private IAsnDetailService asnDetailService;
|
||||
@Autowired
|
||||
private ReceiveProcessor receiveProcessor;
|
||||
|
|
@ -193,6 +199,20 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
|||
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
|
||||
this.baseMapper.updateById(asn);
|
||||
}
|
||||
//库存可用
|
||||
List<Long> stockIds = asnDetails.stream().map(AsnDetail::getStockId).distinct().toList();
|
||||
if(CollectionUtils.isNotEmpty(stockIds)){
|
||||
LambdaQueryWrapper<Inventory> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(Inventory::getStockId, stockIds);
|
||||
List<Inventory> inventoryList = inventoryMapper.selectList(queryWrapper);
|
||||
for (Inventory inventory : inventoryList){
|
||||
inventory.setStatus(InventoryStatusEnum.AVAILABLE.getValue());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(inventoryList)){
|
||||
inventoryMapper.updateById(inventoryList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,4 +87,30 @@ public class SaiWmsController {
|
|||
iSaiWmsService.inBoundCancel(inBoundCancel);
|
||||
return Result.OK("操作成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 入库任务关闭
|
||||
*
|
||||
* @param inBoundCancel 请求参数
|
||||
*/
|
||||
@AutoLog(value = "入库任务关闭")
|
||||
@Operation(summary = "入库任务关闭")
|
||||
@PostMapping(value = "/inBoundClose")
|
||||
public Result<String> inBoundClose(@RequestBody InBoundCancelRequest inBoundCancel) {
|
||||
iSaiWmsService.inBoundClose(inBoundCancel);
|
||||
return Result.OK("操作成功!");
|
||||
}
|
||||
|
||||
/**
|
||||
* 出库任务关闭
|
||||
*
|
||||
* @param inBoundCancel 请求参数
|
||||
*/
|
||||
@AutoLog(value = "出库任务关闭")
|
||||
@Operation(summary = "出库任务关闭")
|
||||
@PostMapping(value = "/outBoundClose")
|
||||
public Result<String> outBoundClose(@RequestBody InBoundCancelRequest inBoundCancel) {
|
||||
iSaiWmsService.outBoundClose(inBoundCancel);
|
||||
return Result.OK("操作成功!");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,4 +33,14 @@ public interface ISMOMService {
|
|||
* 入库取消
|
||||
*/
|
||||
void inBoundCancel(InBoundCancelRequest inBoundCancel);
|
||||
|
||||
/**
|
||||
* 入库关单
|
||||
*/
|
||||
void inBoundClose(InBoundCancelRequest inBoundCancel);
|
||||
|
||||
/**
|
||||
* 出库关单
|
||||
*/
|
||||
void outBoundClose(InBoundCancelRequest inBoundCancel);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,12 @@ public class ISMOMServiceImpl implements ISMOMService {
|
|||
@Autowired
|
||||
private InBoundCancelProcessor inBoundCancelProcessor;
|
||||
|
||||
@Autowired
|
||||
private InBoundCloseProcessor inBoundCloseProcessor;
|
||||
|
||||
@Autowired
|
||||
private OutBoundCloseProcessor outBoundCloseProcessor;
|
||||
|
||||
@Autowired
|
||||
private RedisDistributedLockUtil redissonLock;
|
||||
|
||||
|
|
@ -117,6 +123,46 @@ public class ISMOMServiceImpl implements ISMOMService {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void inBoundClose(InBoundCancelRequest inBoundCancel) {
|
||||
String lockKey = "inClose:" + inBoundCancel.getNo();
|
||||
String lockValue = null;
|
||||
try {
|
||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||
if (StringUtils.isEmpty(lockValue)) {
|
||||
throw new RuntimeException("入库单关闭中,请稍后重试");
|
||||
}
|
||||
inBoundCloseProcessor.inBoundClose(inBoundCancel);
|
||||
} catch (Exception e) {
|
||||
log.error("入库单关闭异常", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outBoundClose(InBoundCancelRequest inBoundCancel) {
|
||||
String lockKey = "outClose:" + inBoundCancel.getNo();
|
||||
String lockValue = null;
|
||||
try {
|
||||
lockValue = redissonLock.tryLock(lockKey, 10);
|
||||
if (StringUtils.isEmpty(lockValue)) {
|
||||
throw new RuntimeException("出库单关闭中,请稍后重试");
|
||||
}
|
||||
outBoundCloseProcessor.outBoundClose(inBoundCancel);
|
||||
} catch (Exception e) {
|
||||
log.error("出库单关闭异常", e);
|
||||
throw e;
|
||||
} finally {
|
||||
if (StringUtils.isNotEmpty(lockValue)) {
|
||||
redissonLock.unlock(lockKey, lockValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import org.springframework.stereotype.Service;
|
|||
|
||||
|
||||
/**
|
||||
* 接收入库任务处理
|
||||
* 接收入库任务取消
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
package org.cpte.modules.saiWms.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||
import org.cpte.modules.receive.entity.Asn;
|
||||
import org.cpte.modules.receive.mapper.AsnMapper;
|
||||
import org.cpte.modules.receive.service.IAsnService;
|
||||
import org.cpte.modules.saiWms.request.InBoundCancelRequest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
/**
|
||||
* 接收入库任务关单
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class InBoundCloseProcessor {
|
||||
|
||||
@Autowired
|
||||
private AsnMapper asnMapper;
|
||||
|
||||
@Autowired
|
||||
private IAsnService asnService;
|
||||
|
||||
/**
|
||||
* 入库关单
|
||||
*
|
||||
* @param inBoundCancel 入库关单参数
|
||||
*/
|
||||
public void inBoundClose(InBoundCancelRequest inBoundCancel) {
|
||||
// 1.参数校验
|
||||
validateParams(inBoundCancel);
|
||||
|
||||
// 2.验证任务号
|
||||
Asn asn = validateAsn(inBoundCancel.getNo());
|
||||
|
||||
if (AsnStatusEnum.CLOSED.getValue().equals(asn.getStatus())) {
|
||||
throw new RuntimeException("【" + inBoundCancel.getNo() + "】任务号已关闭,请勿重复操作");
|
||||
}
|
||||
asnService.closeAsn(Collections.singletonList(asn.getId()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 入库参数校验
|
||||
*
|
||||
* @param inboundRequest 入库参数
|
||||
*/
|
||||
private void validateParams(InBoundCancelRequest inboundRequest) {
|
||||
if (StringUtils.isBlank(inboundRequest.getNo())) {
|
||||
throw new RuntimeException("任务号(No)必填");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证任务号
|
||||
*
|
||||
* @param no 任务号
|
||||
*/
|
||||
private Asn validateAsn(String no) {
|
||||
Asn asn = asnMapper.queryByNo(no);
|
||||
if (asn == null) {
|
||||
throw new RuntimeException("【" + no + "】任务号不存在");
|
||||
}
|
||||
return asn;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
package org.cpte.modules.saiWms.service.processor;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||
import org.cpte.modules.saiWms.request.InBoundCancelRequest;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
import org.cpte.modules.shipping.mapper.PickMapper;
|
||||
import org.cpte.modules.shipping.service.IPickService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
|
||||
/**
|
||||
* 接收出库任务关单
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OutBoundCloseProcessor {
|
||||
|
||||
@Autowired
|
||||
private PickMapper pickMapper;
|
||||
|
||||
@Autowired
|
||||
private IPickService pickService;
|
||||
|
||||
/**
|
||||
* 出库关单
|
||||
*
|
||||
* @param inBoundCancel 出库关单参数
|
||||
*/
|
||||
public void outBoundClose(InBoundCancelRequest inBoundCancel) {
|
||||
// 1.参数校验
|
||||
validateParams(inBoundCancel);
|
||||
|
||||
// 2.验证任务号
|
||||
Pick pick = validatePick(inBoundCancel.getNo());
|
||||
|
||||
if (PickStatusEnum.CLOSED.getValue().equals(pick.getStatus())) {
|
||||
throw new RuntimeException("【" + inBoundCancel.getNo() + "】任务号已关闭,请勿重复操作");
|
||||
}
|
||||
pickService.closePick(Collections.singletonList(pick.getId()));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 出库参数校验
|
||||
*
|
||||
* @param inboundRequest 出库参数
|
||||
*/
|
||||
private void validateParams(InBoundCancelRequest inboundRequest) {
|
||||
if (StringUtils.isBlank(inboundRequest.getNo())) {
|
||||
throw new RuntimeException("任务号(No)必填");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证任务号
|
||||
*
|
||||
* @param no 任务号
|
||||
*/
|
||||
private Pick validatePick(String no) {
|
||||
Pick pick = pickMapper.queryByNo(no);
|
||||
if (pick == null) {
|
||||
throw new RuntimeException("【" + no + "】任务号不存在");
|
||||
}
|
||||
return pick;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -32,6 +32,7 @@ import java.math.BigDecimal;
|
|||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @Description: 任务
|
||||
|
|
@ -236,7 +237,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
return;
|
||||
}
|
||||
|
||||
//目前是四个工作站
|
||||
//获取所以工作站
|
||||
List<Point> outCpPoints = pointService.queryPoints(null, null, AreaTypeEnum.CK_DOCK.getValue());
|
||||
if (CollectionUtils.isEmpty(outCpPoints)) {
|
||||
log.info("没有成品出库工作站");
|
||||
|
|
@ -249,8 +250,6 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
return;
|
||||
}
|
||||
|
||||
//当前所有工作站执行中的任务
|
||||
Map<String, Integer> pointTaskCountMap = queryPointTaskCount();
|
||||
|
||||
//获取所有起点库位
|
||||
List<Long> fromPointIds = taskList.stream().map(Task::getFromPointId).distinct().toList();
|
||||
|
|
@ -267,6 +266,12 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
//获取所有出库单明细
|
||||
List<Long> pickDetailId = taskList.stream().map(Task::getPickDetailId).distinct().toList();
|
||||
Map<Long, PickDetail> pickDetailMap = pickDetailService.queryByPickDetailIdsToMap(pickDetailId);
|
||||
|
||||
//当前所有工作站执行中的任务
|
||||
Map<String, Integer> workStationTaskCountMap = getWorkStationTaskCountMap();
|
||||
|
||||
//当前所有工作站正在执行的任务
|
||||
Map<String, String> workStationTaskMap = getWorkStationTaskMap();
|
||||
for (Task task : taskList) {
|
||||
//起点
|
||||
Point fromPoint = fromPointMap.get(task.getFromPointId());
|
||||
|
|
@ -275,7 +280,13 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
//选择最优且任务数最少的工作站
|
||||
Point bestOutPoint;
|
||||
if (Set.of(4, 5, 6, 7).contains(pick.getOrderType())) {
|
||||
bestOutPoint = selectBestAvailableOutboundPoint(fromPoint, outCpPoints, pointTaskCountMap);
|
||||
//1.允许分配空闲工作站+当前Key执行的工作站
|
||||
String currKey = pick.getConNo() + "_" + task.getItemId();
|
||||
outCpPoints= getAvailableWorkStation(currKey, outCpPoints,workStationTaskMap,workStationTaskCountMap);
|
||||
bestOutPoint = selectBestAvailableOutboundPoint(fromPoint, outCpPoints, workStationTaskCountMap);
|
||||
//更新该工作站任务计数
|
||||
workStationTaskCountMap.put(bestOutPoint.getPointCode(), workStationTaskCountMap.getOrDefault(bestOutPoint.getPointCode(), 0) + 1);
|
||||
workStationTaskMap.put(bestOutPoint.getPointCode(), currKey);
|
||||
} else {
|
||||
bestOutPoint = outMjPoints.get(0);
|
||||
}
|
||||
|
|
@ -290,9 +301,6 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
inventoryLogService.addAllocInventoryLog(inventory, bestOutPoint.getId(),
|
||||
task.getPlanQty(), pick.getThirdOrderNo(), pickDetail.getId(), pickDetail.getDescription());
|
||||
}
|
||||
|
||||
//更新该工作站任务计数
|
||||
pointTaskCountMap.put(bestOutPoint.getPointCode(), pointTaskCountMap.getOrDefault(bestOutPoint.getPointCode(), 0) + 1);
|
||||
}
|
||||
|
||||
//批量更新任务
|
||||
|
|
@ -307,7 +315,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
*
|
||||
* @return Map<Point, Integer>
|
||||
*/
|
||||
private Map<String, Integer> queryPointTaskCount() {
|
||||
private Map<String, Integer> getWorkStationTaskCountMap() {
|
||||
// 从数据库查询点位任务数量列表
|
||||
List<Map<String, Object>> result = agvTaskMapper.pointTaskCountMap();
|
||||
|
||||
|
|
@ -322,6 +330,18 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
return pointTaskCountMap;
|
||||
}
|
||||
|
||||
private Map<String, String> getWorkStationTaskMap() {
|
||||
// 从数据库查询每个工作站当前的任务列表
|
||||
List<Map<String, Object>> result = agvTaskMapper.pointTaskMap();
|
||||
Map<String, String> pointTaskMap = new HashMap<>();
|
||||
for (Map<String, Object> map : result) {
|
||||
String key = map.get("point_code").toString();
|
||||
String no_item = map.get("no_item") == null ? "" : map.get("no_item").toString();
|
||||
pointTaskMap.put(key, no_item);
|
||||
}
|
||||
return pointTaskMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择最优且可用的工作站(任务数小于3的最优工作站,如果没有则选择任务数最少的)
|
||||
*/
|
||||
|
|
@ -424,5 +444,54 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
|||
.orElse(outPoints.get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取可分配的工作站
|
||||
* @param currKey 当前key
|
||||
* @param outCpPoints 成品出库工作站
|
||||
* @param workStationTaskCountMap 工作站任务数
|
||||
* @return 可分配的工作站
|
||||
*/
|
||||
private List<Point> getAvailableWorkStation(String currKey,List<Point> outCpPoints,Map<String, String> workStationTaskMap,Map<String, Integer> workStationTaskCountMap) {
|
||||
//1.获取空闲的工作站
|
||||
List<String> freeWorkStationKeys = getFreeWorkStationKeys(workStationTaskCountMap);
|
||||
|
||||
//2.获取当前key匹配的工作站
|
||||
List<String> workStationList = getWorkStationByKeys(currKey,workStationTaskMap);
|
||||
|
||||
//3.合并
|
||||
List<String> mergedWorkStationList = Stream.concat(
|
||||
freeWorkStationKeys.stream(),
|
||||
workStationList.stream()
|
||||
).distinct() // 去重,防止重复的工作站
|
||||
.toList();
|
||||
|
||||
//4.从所有成品出库工作站中筛选出可分配的工作站
|
||||
return outCpPoints.stream().filter(point -> mergedWorkStationList.contains(point.getPointCode())).toList();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1.获取空闲的工作站(工作站执行的任务为0)
|
||||
*/
|
||||
private List<String> getFreeWorkStationKeys(Map<String, Integer> workStationTaskCountMap) {
|
||||
List<String> workStationList = workStationTaskCountMap.entrySet().stream().filter(entry -> entry.getValue() == 0).map(Map.Entry::getKey).toList();
|
||||
if(CollectionUtils.isEmpty(workStationList)){
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return workStationList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 2.获取当前key匹配的工作站
|
||||
*/
|
||||
private List<String> getWorkStationByKeys(String currKey,Map<String, String> workStationTaskMap) {
|
||||
List<String> workStationList = workStationTaskMap.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().equals(currKey))
|
||||
.map(Map.Entry::getKey)
|
||||
.toList();
|
||||
if(CollectionUtils.isEmpty(workStationList)){
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return workStationList;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -842,35 +842,36 @@ public class AllocateProcessor {
|
|||
* @param createToTask 创建的拣货任务集合
|
||||
* @param data 数据
|
||||
*/
|
||||
private final Object taskCreationLock = new Object();
|
||||
private void createPickTask(PickDetail pickDetail, Pick pick, Item item,
|
||||
Inventory inventory, InventoryScore inventoryScore, BigDecimal allocateQty,
|
||||
List<Task> createToTask, AllocationData data) {
|
||||
synchronized (taskCreationLock) {
|
||||
Stock stock = data.getStockMap().get(inventory.getStockId());
|
||||
|
||||
Stock stock = data.getStockMap().get(inventory.getStockId());
|
||||
Point fromPoint = data.getPointMap().get(inventory.getPointId());
|
||||
|
||||
Point fromPoint = data.getPointMap().get(inventory.getPointId());
|
||||
// 判断是否整托分配
|
||||
BigDecimal availableQty = BigDecimalUtil.subtract(inventory.getQuantity(), inventory.getQueuedQty(), 0);
|
||||
Integer izAll = availableQty.compareTo(BigDecimal.ZERO) <= 0 ? 0 : 1;
|
||||
|
||||
// 判断是否整托分配
|
||||
BigDecimal availableQty = BigDecimalUtil.subtract(inventory.getQuantity(), inventory.getQueuedQty(), 0);
|
||||
Integer izAll = availableQty.compareTo(BigDecimal.ZERO) <= 0 ? 0 : 1;
|
||||
// 目标库位
|
||||
//Point toPoint = inventoryScore.getOutPoint();
|
||||
|
||||
// 目标库位
|
||||
//Point toPoint = inventoryScore.getOutPoint();
|
||||
// 构建拣货任务
|
||||
String taskNo = String.format("%s_%d", pick.getNo(), pickDetail.getLineNo());
|
||||
Task task = taskService.bulidTask(
|
||||
taskNo, TaskTypeEnum.PICK.getValue(), item, fromPoint, null,
|
||||
stock, pick.getId(), pickDetail.getId(), inventory.getItemKeyId(), inventory.getId(),
|
||||
allocateQty, izAll, null);
|
||||
|
||||
// 构建拣货任务
|
||||
String taskNo = String.format("%s_%d", pick.getNo(), pickDetail.getLineNo());
|
||||
Task task = taskService.bulidTask(
|
||||
taskNo, TaskTypeEnum.PICK.getValue(), item, fromPoint, null,
|
||||
stock, pick.getId(), pickDetail.getId(), inventory.getItemKeyId(), inventory.getId(),
|
||||
allocateQty, izAll, null);
|
||||
|
||||
if (task != null) {
|
||||
createToTask.add(task);
|
||||
log.info("生成拣货任务: {}- 容器:{} - 库位:{} - 类型:{}- 分配数量:{}",
|
||||
task.getTaskNo(), stock.getStockCode(),
|
||||
fromPoint.getPointCode(), izAll, allocateQty);
|
||||
if (task != null) {
|
||||
createToTask.add(task);
|
||||
log.info("生成拣货任务: {}- 容器:{} - 库位:{} - 类型:{}- 分配数量:{}",
|
||||
task.getTaskNo(), stock.getStockCode(),
|
||||
fromPoint.getPointCode(), izAll, allocateQty);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import org.cpte.modules.constant.enums.CommonStatusEnum;
|
|||
import org.cpte.modules.constant.enums.PickStatusEnum;
|
||||
import org.cpte.modules.constant.enums.TaskStatusEnum;
|
||||
import org.cpte.modules.inventory.entity.Inventory;
|
||||
import org.cpte.modules.inventory.mapper.InventoryMapper;
|
||||
import org.cpte.modules.inventory.service.IInventoryService;
|
||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||
import org.cpte.modules.shipping.entity.Pick;
|
||||
|
|
@ -42,6 +43,9 @@ public class PickProcessor {
|
|||
@Autowired
|
||||
private PickDetailMapper pickDetailMapper;
|
||||
|
||||
@Autowired
|
||||
private InventoryMapper inventoryMapper;
|
||||
|
||||
@Autowired
|
||||
private IPointService pointService;
|
||||
|
||||
|
|
@ -227,8 +231,8 @@ public class PickProcessor {
|
|||
/**
|
||||
* 更新库存
|
||||
*
|
||||
* @param inventory 库存
|
||||
* @param pickedQty 拣货数量
|
||||
* @param inventory 库存
|
||||
* @param pickedQty 拣货数量
|
||||
*/
|
||||
private void updateInventory(Inventory inventory, BigDecimal pickedQty) {
|
||||
if (inventory != null) {
|
||||
|
|
@ -247,10 +251,12 @@ public class PickProcessor {
|
|||
* @param deleteToInventory 删除集合
|
||||
*/
|
||||
private void deleteInventory(PickData data, Task task, List<Inventory> deleteToInventory) {
|
||||
Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
||||
if (inventory != null) {
|
||||
if (!deleteToInventory.contains(inventory)) {
|
||||
deleteToInventory.add(inventory);
|
||||
List<Inventory> inventories = inventoryMapper.queryInventoryByStockId(task.getStockId());
|
||||
for (Inventory inventory : inventories){
|
||||
if (inventory != null) {
|
||||
if (!deleteToInventory.contains(inventory)) {
|
||||
deleteToInventory.add(inventory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,44 @@ import java.io.InputStreamReader;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
public class TesStock {
|
||||
public static void main(String[] args) {
|
||||
//工作站
|
||||
Map<String, Integer> workStationTaskCountMap = new HashMap<>();
|
||||
workStationTaskCountMap.put("3F-F1-ELE-02L-L", 0);
|
||||
workStationTaskCountMap.put("3F-F1-OUT-02-02-R", 0);
|
||||
workStationTaskCountMap.put("3F-F1-OUT-03-03-R", 0);
|
||||
//获取工作站任务数为0的工作站
|
||||
List<String> workStationList = workStationTaskCountMap.entrySet().stream().filter(entry -> entry.getValue() == 0).map(Map.Entry::getKey).toList();
|
||||
|
||||
String currKey = "TEST_2008406424763838480";
|
||||
Map<String, String> workStationTaskMap = new HashMap<>();
|
||||
workStationTaskMap.put("3F-F1-ELE-02L-L", "");
|
||||
workStationTaskMap.put("3F-F1-OUT-02-02-R", "");
|
||||
workStationTaskMap.put("3F-F1-OUT-03-03-R", "");
|
||||
List<String> workStationList2 = workStationTaskMap.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().equals(currKey))
|
||||
.map(Map.Entry::getKey)
|
||||
.toList();
|
||||
|
||||
//合并workStationList、workStationList2
|
||||
List<String> mergedWorkStationList = Stream.concat(
|
||||
workStationList.stream(),
|
||||
workStationList2.stream()
|
||||
).distinct() // 去重,防止重复的工作站
|
||||
.toList();
|
||||
System.out.println(mergedWorkStationList);
|
||||
}
|
||||
|
||||
|
||||
private static void getStockInfo() {
|
||||
JSONObject params = new JSONObject();
|
||||
params.put("warehouseID", "HETU");
|
||||
params.put("clientCode", "WMS");
|
||||
|
|
@ -43,7 +76,7 @@ public class TesStock {
|
|||
}
|
||||
}
|
||||
|
||||
private static JSONObject stockInfo(){
|
||||
private static JSONObject stockInfo() {
|
||||
// 方案2:从外部文件读取
|
||||
try {
|
||||
String jsonString = readFileToString("stock_data.json"); // 从资源文件读取
|
||||
|
|
|
|||
Loading…
Reference in New Issue