no message
parent
786dc1a9b9
commit
952351f951
|
|
@ -4,7 +4,6 @@ import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
import org.cpte.modules.agvTask.entity.AgvTask;
|
import org.cpte.modules.agvTask.entity.AgvTask;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import org.cpte.modules.agvTask.vo.ConNoAgv;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
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")
|
@Select(value = "select * from data_agv_task where type in ('INBOUND','OUTBOUND') and status=2 LIMIT 5")
|
||||||
List<AgvTask> queryExecuteTopFive();
|
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
|
LIMIT 1
|
||||||
</select>
|
</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 id="pointTaskCountMap" resultType="java.util.Map">
|
||||||
SELECT
|
SELECT
|
||||||
bp.point_code,
|
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.base.entity.Point;
|
||||||
import org.cpte.modules.conveyorLine.vo.ScanTrayData;
|
import org.cpte.modules.conveyorLine.vo.ScanTrayData;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: AGV任务表
|
* @Description: AGV任务表
|
||||||
* @author: cpte
|
* @author: cpte
|
||||||
|
|
@ -52,5 +54,4 @@ public interface IAgvTaskService extends IService<AgvTask> {
|
||||||
* @param agvTask AGV任务
|
* @param agvTask AGV任务
|
||||||
*/
|
*/
|
||||||
void editAgvTask(AgvTask agvTask);
|
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 lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.mapper.AgvTaskMapper;
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
import org.cpte.modules.shipping.entity.PickDetail;
|
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.GeneralConstant;
|
||||||
import org.cpte.modules.constant.enums.AgvStatusEnum;
|
import org.cpte.modules.constant.enums.AgvStatusEnum;
|
||||||
import org.cpte.modules.constant.enums.AgvVendorEnum;
|
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.shipping.service.ITaskService;
|
||||||
import org.cpte.modules.tesAgv.service.ITesAgvService;
|
import org.cpte.modules.tesAgv.service.ITesAgvService;
|
||||||
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
import org.cpte.modules.utils.RedisDistributedLockUtil;
|
||||||
|
|
@ -17,9 +16,7 @@ import org.quartz.JobExecutionContext;
|
||||||
import org.quartz.JobExecutionException;
|
import org.quartz.JobExecutionException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class TesAgvJob implements Job {
|
public class TesAgvJob implements Job {
|
||||||
|
|
@ -74,91 +71,15 @@ public class TesAgvJob implements Job {
|
||||||
if (CollectionUtils.isEmpty(agvTaskList)) {
|
if (CollectionUtils.isEmpty(agvTaskList)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AgvTask agvTask : agvTaskList) {
|
for (AgvTask agvTask : agvTaskList) {
|
||||||
sendTesAgvTask(agvTask);
|
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任务
|
* 发送TES任务
|
||||||
*/
|
*/
|
||||||
private boolean sendTesAgvTask(AgvTask agvTask) {
|
private void sendTesAgvTask(AgvTask agvTask) {
|
||||||
return tesAgvService.sendTesAgvTask(GeneralConstant.TES_POD_TASK, tesAgvService.generateTesAgvTaskJson(agvTask), agvTask);
|
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package org.cpte.modules.receive.service.impl;
|
package org.cpte.modules.receive.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
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.base.mapper.StockMapper;
|
||||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||||
import org.cpte.modules.constant.enums.CommonStatusEnum;
|
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.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.Asn;
|
||||||
import org.cpte.modules.receive.entity.AsnDetail;
|
import org.cpte.modules.receive.entity.AsnDetail;
|
||||||
import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
import org.cpte.modules.receive.mapper.AsnDetailMapper;
|
||||||
|
|
@ -48,6 +52,8 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsnDetailMapper asnDetailMapper;
|
private AsnDetailMapper asnDetailMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
private InventoryMapper inventoryMapper;
|
||||||
|
@Autowired
|
||||||
private IAsnDetailService asnDetailService;
|
private IAsnDetailService asnDetailService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ReceiveProcessor receiveProcessor;
|
private ReceiveProcessor receiveProcessor;
|
||||||
|
|
@ -193,6 +199,20 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
|
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
|
||||||
this.baseMapper.updateById(asn);
|
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);
|
iSaiWmsService.inBoundCancel(inBoundCancel);
|
||||||
return Result.OK("操作成功!");
|
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 inBoundCancel(InBoundCancelRequest inBoundCancel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入库关单
|
||||||
|
*/
|
||||||
|
void inBoundClose(InBoundCancelRequest inBoundCancel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出库关单
|
||||||
|
*/
|
||||||
|
void outBoundClose(InBoundCancelRequest inBoundCancel);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,12 @@ public class ISMOMServiceImpl implements ISMOMService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private InBoundCancelProcessor inBoundCancelProcessor;
|
private InBoundCancelProcessor inBoundCancelProcessor;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InBoundCloseProcessor inBoundCloseProcessor;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OutBoundCloseProcessor outBoundCloseProcessor;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisDistributedLockUtil redissonLock;
|
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
|
@Service
|
||||||
@Slf4j
|
@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.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 任务
|
* @Description: 任务
|
||||||
|
|
@ -236,7 +237,7 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//目前是四个工作站
|
//获取所以工作站
|
||||||
List<Point> outCpPoints = pointService.queryPoints(null, null, AreaTypeEnum.CK_DOCK.getValue());
|
List<Point> outCpPoints = pointService.queryPoints(null, null, AreaTypeEnum.CK_DOCK.getValue());
|
||||||
if (CollectionUtils.isEmpty(outCpPoints)) {
|
if (CollectionUtils.isEmpty(outCpPoints)) {
|
||||||
log.info("没有成品出库工作站");
|
log.info("没有成品出库工作站");
|
||||||
|
|
@ -249,8 +250,6 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//当前所有工作站执行中的任务
|
|
||||||
Map<String, Integer> pointTaskCountMap = queryPointTaskCount();
|
|
||||||
|
|
||||||
//获取所有起点库位
|
//获取所有起点库位
|
||||||
List<Long> fromPointIds = taskList.stream().map(Task::getFromPointId).distinct().toList();
|
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();
|
List<Long> pickDetailId = taskList.stream().map(Task::getPickDetailId).distinct().toList();
|
||||||
Map<Long, PickDetail> pickDetailMap = pickDetailService.queryByPickDetailIdsToMap(pickDetailId);
|
Map<Long, PickDetail> pickDetailMap = pickDetailService.queryByPickDetailIdsToMap(pickDetailId);
|
||||||
|
|
||||||
|
//当前所有工作站执行中的任务
|
||||||
|
Map<String, Integer> workStationTaskCountMap = getWorkStationTaskCountMap();
|
||||||
|
|
||||||
|
//当前所有工作站正在执行的任务
|
||||||
|
Map<String, String> workStationTaskMap = getWorkStationTaskMap();
|
||||||
for (Task task : taskList) {
|
for (Task task : taskList) {
|
||||||
//起点
|
//起点
|
||||||
Point fromPoint = fromPointMap.get(task.getFromPointId());
|
Point fromPoint = fromPointMap.get(task.getFromPointId());
|
||||||
|
|
@ -275,7 +280,13 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
||||||
//选择最优且任务数最少的工作站
|
//选择最优且任务数最少的工作站
|
||||||
Point bestOutPoint;
|
Point bestOutPoint;
|
||||||
if (Set.of(4, 5, 6, 7).contains(pick.getOrderType())) {
|
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 {
|
} else {
|
||||||
bestOutPoint = outMjPoints.get(0);
|
bestOutPoint = outMjPoints.get(0);
|
||||||
}
|
}
|
||||||
|
|
@ -290,9 +301,6 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
||||||
inventoryLogService.addAllocInventoryLog(inventory, bestOutPoint.getId(),
|
inventoryLogService.addAllocInventoryLog(inventory, bestOutPoint.getId(),
|
||||||
task.getPlanQty(), pick.getThirdOrderNo(), pickDetail.getId(), pickDetail.getDescription());
|
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>
|
* @return Map<Point, Integer>
|
||||||
*/
|
*/
|
||||||
private Map<String, Integer> queryPointTaskCount() {
|
private Map<String, Integer> getWorkStationTaskCountMap() {
|
||||||
// 从数据库查询点位任务数量列表
|
// 从数据库查询点位任务数量列表
|
||||||
List<Map<String, Object>> result = agvTaskMapper.pointTaskCountMap();
|
List<Map<String, Object>> result = agvTaskMapper.pointTaskCountMap();
|
||||||
|
|
||||||
|
|
@ -322,6 +330,18 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
||||||
return pointTaskCountMap;
|
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的最优工作站,如果没有则选择任务数最少的)
|
* 选择最优且可用的工作站(任务数小于3的最优工作站,如果没有则选择任务数最少的)
|
||||||
*/
|
*/
|
||||||
|
|
@ -424,5 +444,54 @@ public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements IT
|
||||||
.orElse(outPoints.get(0));
|
.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,10 +842,11 @@ public class AllocateProcessor {
|
||||||
* @param createToTask 创建的拣货任务集合
|
* @param createToTask 创建的拣货任务集合
|
||||||
* @param data 数据
|
* @param data 数据
|
||||||
*/
|
*/
|
||||||
|
private final Object taskCreationLock = new Object();
|
||||||
private void createPickTask(PickDetail pickDetail, Pick pick, Item item,
|
private void createPickTask(PickDetail pickDetail, Pick pick, Item item,
|
||||||
Inventory inventory, InventoryScore inventoryScore, BigDecimal allocateQty,
|
Inventory inventory, InventoryScore inventoryScore, BigDecimal allocateQty,
|
||||||
List<Task> createToTask, AllocationData data) {
|
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());
|
||||||
|
|
@ -870,7 +871,7 @@ public class AllocateProcessor {
|
||||||
task.getTaskNo(), stock.getStockCode(),
|
task.getTaskNo(), stock.getStockCode(),
|
||||||
fromPoint.getPointCode(), izAll, allocateQty);
|
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.PickStatusEnum;
|
||||||
import org.cpte.modules.constant.enums.TaskStatusEnum;
|
import org.cpte.modules.constant.enums.TaskStatusEnum;
|
||||||
import org.cpte.modules.inventory.entity.Inventory;
|
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.inventory.service.IInventoryService;
|
||||||
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
import org.cpte.modules.inventoryLog.service.IInventoryLogService;
|
||||||
import org.cpte.modules.shipping.entity.Pick;
|
import org.cpte.modules.shipping.entity.Pick;
|
||||||
|
|
@ -42,6 +43,9 @@ public class PickProcessor {
|
||||||
@Autowired
|
@Autowired
|
||||||
private PickDetailMapper pickDetailMapper;
|
private PickDetailMapper pickDetailMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InventoryMapper inventoryMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IPointService pointService;
|
private IPointService pointService;
|
||||||
|
|
||||||
|
|
@ -247,13 +251,15 @@ public class PickProcessor {
|
||||||
* @param deleteToInventory 删除集合
|
* @param deleteToInventory 删除集合
|
||||||
*/
|
*/
|
||||||
private void deleteInventory(PickData data, Task task, List<Inventory> deleteToInventory) {
|
private void deleteInventory(PickData data, Task task, List<Inventory> deleteToInventory) {
|
||||||
Inventory inventory = data.getInventoryMap().get(task.getInventoryId());
|
List<Inventory> inventories = inventoryMapper.queryInventoryByStockId(task.getStockId());
|
||||||
|
for (Inventory inventory : inventories){
|
||||||
if (inventory != null) {
|
if (inventory != null) {
|
||||||
if (!deleteToInventory.contains(inventory)) {
|
if (!deleteToInventory.contains(inventory)) {
|
||||||
deleteToInventory.add(inventory);
|
deleteToInventory.add(inventory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新出库明细
|
* 更新出库明细
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,44 @@ import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
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 class TesStock {
|
||||||
public static void main(String[] args) {
|
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();
|
JSONObject params = new JSONObject();
|
||||||
params.put("warehouseID", "HETU");
|
params.put("warehouseID", "HETU");
|
||||||
params.put("clientCode", "WMS");
|
params.put("clientCode", "WMS");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue