feat: 自动补空任务
This commit is contained in:
@@ -9,7 +9,8 @@ import lombok.Getter;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public enum PackageTaskTypeEnum {
|
public enum PackageTaskTypeEnum {
|
||||||
SUB_ROLL_DOWN_AGV("010601", "子卷->待检AGV任务"),
|
SUB_ROLL_DOWN_AGV("010601", "子卷下线到待检AGV任务"),
|
||||||
|
SUB_ROLL_CALL_EMPTY_AGV("010602", "子卷下线补空架AGV任务"),
|
||||||
;
|
;
|
||||||
/**
|
/**
|
||||||
* 字典键值
|
* 字典键值
|
||||||
|
|||||||
@@ -46,17 +46,19 @@ public interface PackagePointMapper extends BaseMapperX<PackagePointDO> {
|
|||||||
* 尝试锁定点位
|
* 尝试锁定点位
|
||||||
*
|
*
|
||||||
* @param pointId 点位标识
|
* @param pointId 点位标识
|
||||||
|
* @param pointStatus 预期点位状态
|
||||||
* @return 更新行数
|
* @return 更新行数
|
||||||
*/
|
*/
|
||||||
int tryLockPoint(@Param("pointId") Long pointId);
|
int tryLockPoint(@Param("pointId") Long pointId, @Param("pointStatus") String pointStatus);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 释放点位锁
|
* 释放点位锁
|
||||||
*
|
*
|
||||||
* @param pointId 点位标识
|
* @param pointId 点位标识
|
||||||
|
* @param pointStatus 预期点位状态
|
||||||
* @return 更新行数
|
* @return 更新行数
|
||||||
*/
|
*/
|
||||||
int unlockPoint(@Param("pointId") Long pointId);
|
int unlockPoint(@Param("pointId") Long pointId, @Param("pointStatus") String pointStatus);
|
||||||
|
|
||||||
default PageResult<PackagePointDO> selectPage(PackagePointPageReqVO reqVO) {
|
default PageResult<PackagePointDO> selectPage(PackagePointPageReqVO reqVO) {
|
||||||
return selectPage(reqVO, new LambdaQueryWrapperX<PackagePointDO>()
|
return selectPage(reqVO, new LambdaQueryWrapperX<PackagePointDO>()
|
||||||
|
|||||||
@@ -44,6 +44,14 @@ public class BoxAutoJob {
|
|||||||
@XxlJob("autoSubRollDownCallEmptyJob")
|
@XxlJob("autoSubRollDownCallEmptyJob")
|
||||||
@TenantJob
|
@TenantJob
|
||||||
public void autoSubRollDownCallEmptyJob() {
|
public void autoSubRollDownCallEmptyJob() {
|
||||||
|
log.info("子卷下线补充空架子任务创建开始.....");
|
||||||
|
XxlJobHelper.log("子卷下线补充空架子任务创建开始");
|
||||||
|
|
||||||
|
packageBoxBusinessService.autoSubRollDownCallEmpty();
|
||||||
|
|
||||||
|
String msg = "子卷下线补充空架子任务创建结束";
|
||||||
|
XxlJobHelper.log(msg);
|
||||||
|
XxlJobHelper.handleSuccess(msg);
|
||||||
|
log.info(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,4 +11,9 @@ public interface PackageBoxBusinessService {
|
|||||||
* 自动创建子卷下线送待检区任务
|
* 自动创建子卷下线送待检区任务
|
||||||
*/
|
*/
|
||||||
void autoSendSubRollTask();
|
void autoSendSubRollTask();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动创建子卷下线补充空架子任务
|
||||||
|
*/
|
||||||
|
void autoSubRollDownCallEmpty();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,12 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
|
|||||||
/** 子卷下线任务回调处理器编码 */
|
/** 子卷下线任务回调处理器编码 */
|
||||||
private static final String SUB_ROLL_DOWN_HANDLE_CODE = "subRollDownAgvTask";
|
private static final String SUB_ROLL_DOWN_HANDLE_CODE = "subRollDownAgvTask";
|
||||||
|
|
||||||
|
/** 子卷下线补充空架子业务类型 */
|
||||||
|
private static final String SUB_ROLL_CALL_EMPTY_BIZ_TYPE = "SUB_ROLL_CALL_EMPTY";
|
||||||
|
|
||||||
|
/** 子卷下线补充空架子任务回调处理器编码 */
|
||||||
|
private static final String SUB_ROLL_CALL_EMPTY_HANDLE_CODE = "subRollCallEmptyAgvTask";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ACS 搬运任务类型
|
* ACS 搬运任务类型
|
||||||
*/
|
*/
|
||||||
@@ -66,13 +72,13 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
|
|||||||
|
|
||||||
Iterator<PackagePointDO> destinationIterator = destinationPointList.iterator();
|
Iterator<PackagePointDO> destinationIterator = destinationPointList.iterator();
|
||||||
for (PackagePointDO sourcePoint : sourcePointList) {
|
for (PackagePointDO sourcePoint : sourcePointList) {
|
||||||
if (packagePointMapper.tryLockPoint(sourcePoint.getPointId()) == 0) {
|
if (packagePointMapper.tryLockPoint(sourcePoint.getPointId(), sourcePoint.getPointStatus()) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackagePointDO destinationPoint = lockNextDestinationPoint(destinationIterator);
|
PackagePointDO destinationPoint = lockNextDestinationPoint(destinationIterator);
|
||||||
if (destinationPoint == null) {
|
if (destinationPoint == null) {
|
||||||
packagePointMapper.unlockPoint(sourcePoint.getPointId());
|
packagePointMapper.unlockPoint(sourcePoint.getPointId(), sourcePoint.getPointStatus());
|
||||||
log.info("没有可用的待检区点位,结束本轮任务创建");
|
log.info("没有可用的待检区点位,结束本轮任务创建");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -83,6 +89,47 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动创建子卷下线补充空架子任务
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void autoSubRollDownCallEmpty() {
|
||||||
|
List<PackagePointDO> offlineEmptyPointList = packagePointMapper.selectAvailablePointList(
|
||||||
|
BoxPointTypeEnum.OFFLINE_POINT.getCode(), BoxPointStatusEnum.EMPTY.getCode());
|
||||||
|
List<PackagePointDO> packingEmptyContainerPointList = packagePointMapper.selectAvailablePointList(
|
||||||
|
BoxPointTypeEnum.PACKING_POINT.getCode(), BoxPointStatusEnum.EMPTY_CONTAINER.getCode());
|
||||||
|
List<PackagePointDO> inspectionEmptyContainerPointList = packagePointMapper.selectAvailablePointList(
|
||||||
|
BoxPointTypeEnum.INSPECTION_PENDING_POINT.getCode(), BoxPointStatusEnum.EMPTY_CONTAINER.getCode());
|
||||||
|
List<PackagePointDO> inspectionEmptyPointList = packagePointMapper.selectAvailablePointList(
|
||||||
|
BoxPointTypeEnum.INSPECTION_PENDING_POINT.getCode(), BoxPointStatusEnum.EMPTY.getCode());
|
||||||
|
|
||||||
|
Iterator<PackagePointDO> packingSourceIterator = packingEmptyContainerPointList.iterator();
|
||||||
|
Iterator<PackagePointDO> inspectionSourceIterator = inspectionEmptyContainerPointList.iterator();
|
||||||
|
for (PackagePointDO offlineDestinationPoint : offlineEmptyPointList) {
|
||||||
|
if (packagePointMapper.tryLockPoint(
|
||||||
|
offlineDestinationPoint.getPointId(), offlineDestinationPoint.getPointStatus()) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackagePointDO sourcePoint = lockNextSourcePoint(packingSourceIterator);
|
||||||
|
if (sourcePoint == null) {
|
||||||
|
sourcePoint = lockNextSourcePoint(inspectionSourceIterator);
|
||||||
|
}
|
||||||
|
if (sourcePoint == null) {
|
||||||
|
packagePointMapper.unlockPoint(
|
||||||
|
offlineDestinationPoint.getPointId(), offlineDestinationPoint.getPointStatus());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long taskId = createCallEmptyTransportTask(sourcePoint, offlineDestinationPoint);
|
||||||
|
log.info("子卷下线补充空架子任务创建成功,任务标识={},起点编码={},目的点编码={}",
|
||||||
|
taskId, sourcePoint.getPointCode(), offlineDestinationPoint.getPointCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
createPackingToInspectionTask(packingSourceIterator, inspectionEmptyPointList.iterator());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建子卷下线送待检区运输任务
|
* 创建子卷下线送待检区运输任务
|
||||||
*
|
*
|
||||||
@@ -110,6 +157,75 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
|
|||||||
return transportTaskApi.createTransportTask(task).getCheckedData();
|
return transportTaskApi.createTransportTask(task).getCheckedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建子卷下线补充空架子运输任务
|
||||||
|
*
|
||||||
|
* @param sourcePoint 起点
|
||||||
|
* @param destinationPoint 目的点
|
||||||
|
* @return 运输任务标识
|
||||||
|
*/
|
||||||
|
private Long createCallEmptyTransportTask(PackagePointDO sourcePoint, PackagePointDO destinationPoint) {
|
||||||
|
TransportTaskCreateReqDTO task = new TransportTaskCreateReqDTO();
|
||||||
|
task.setTaskName("子卷下线补充空架子任务");
|
||||||
|
task.setOwnerService(TaskOwnerServiceEnum.LMS.name());
|
||||||
|
task.setBizType(SUB_ROLL_CALL_EMPTY_BIZ_TYPE);
|
||||||
|
task.setBizId(sourcePoint.getVehicleCode());
|
||||||
|
task.setTaskType(PackageTaskTypeEnum.SUB_ROLL_CALL_EMPTY_AGV.getCode());
|
||||||
|
task.setHandleCode(SUB_ROLL_CALL_EMPTY_HANDLE_CODE);
|
||||||
|
task.setAcsTaskType(ACS_MOVE_TASK_TYPE);
|
||||||
|
task.setAgvSystemType(AGV_SYSTEM_TYPE);
|
||||||
|
task.setPointCode1(sourcePoint.getPointCode());
|
||||||
|
task.setPointCode2(destinationPoint.getPointCode());
|
||||||
|
task.setVehicleCode(sourcePoint.getVehicleCode());
|
||||||
|
task.setProductArea(sourcePoint.getProductArea());
|
||||||
|
task.setIsAutoIssue("1");
|
||||||
|
task.setIsCreateFinish(true);
|
||||||
|
return transportTaskApi.createTransportTask(task).getCheckedData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将剩余装箱点空架子转运到待检点空位
|
||||||
|
*
|
||||||
|
* @param sourceIterator 装箱点空架子候选迭代器
|
||||||
|
* @param destinationIterator 待检点空位候选迭代器
|
||||||
|
*/
|
||||||
|
private void createPackingToInspectionTask(Iterator<PackagePointDO> sourceIterator,
|
||||||
|
Iterator<PackagePointDO> destinationIterator) {
|
||||||
|
while (destinationIterator.hasNext()) {
|
||||||
|
PackagePointDO destinationPoint = destinationIterator.next();
|
||||||
|
if (packagePointMapper.tryLockPoint(
|
||||||
|
destinationPoint.getPointId(), destinationPoint.getPointStatus()) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
PackagePointDO sourcePoint = lockNextSourcePoint(sourceIterator);
|
||||||
|
if (sourcePoint == null) {
|
||||||
|
packagePointMapper.unlockPoint(destinationPoint.getPointId(), destinationPoint.getPointStatus());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long taskId = createCallEmptyTransportTask(sourcePoint, destinationPoint);
|
||||||
|
log.info("装箱点空架子送待检点任务创建成功,任务标识={},起点编码={},目的点编码={}",
|
||||||
|
taskId, sourcePoint.getPointCode(), destinationPoint.getPointCode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从候选点位中锁定下一个可用的空架子起点
|
||||||
|
*
|
||||||
|
* @param sourceIterator 空架子起点候选迭代器
|
||||||
|
* @return 成功锁定的起点,没有可用点位时返回 null
|
||||||
|
*/
|
||||||
|
private PackagePointDO lockNextSourcePoint(Iterator<PackagePointDO> sourceIterator) {
|
||||||
|
while (sourceIterator.hasNext()) {
|
||||||
|
PackagePointDO sourcePoint = sourceIterator.next();
|
||||||
|
if (packagePointMapper.tryLockPoint(sourcePoint.getPointId(), sourcePoint.getPointStatus()) > 0) {
|
||||||
|
return sourcePoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从候选点位中锁定下一个可用的待检区点位
|
* 从候选点位中锁定下一个可用的待检区点位
|
||||||
*
|
*
|
||||||
@@ -119,7 +235,8 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
|
|||||||
private PackagePointDO lockNextDestinationPoint(Iterator<PackagePointDO> destinationIterator) {
|
private PackagePointDO lockNextDestinationPoint(Iterator<PackagePointDO> destinationIterator) {
|
||||||
while (destinationIterator.hasNext()) {
|
while (destinationIterator.hasNext()) {
|
||||||
PackagePointDO destinationPoint = destinationIterator.next();
|
PackagePointDO destinationPoint = destinationIterator.next();
|
||||||
if (packagePointMapper.tryLockPoint(destinationPoint.getPointId()) > 0) {
|
if (packagePointMapper.tryLockPoint(
|
||||||
|
destinationPoint.getPointId(), destinationPoint.getPointStatus()) > 0) {
|
||||||
return destinationPoint;
|
return destinationPoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package cn.code.nl.module.lms.tasks.box;
|
||||||
|
|
||||||
|
import cn.code.nl.framework.execute.core.AbstractTask;
|
||||||
|
import cn.code.nl.framework.execute.core.dto.TaskExecuteDTO;
|
||||||
|
import cn.code.nl.module.lms.dal.dataobject.packagepoint.PackagePointDO;
|
||||||
|
import cn.code.nl.module.lms.dal.mysql.packagepoint.PackagePointMapper;
|
||||||
|
import cn.code.nl.module.lms.enums.BoxPointStatusEnum;
|
||||||
|
import cn.code.nl.module.task.api.TransportTaskApi;
|
||||||
|
import cn.code.nl.module.task.dto.TaskInfoDTO;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子卷下线补充空架子 AGV 任务
|
||||||
|
*
|
||||||
|
* @Author: liyongde
|
||||||
|
* @Date: 2026/8/13
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component("subRollCallEmptyAgvTask")
|
||||||
|
public class SubRollCallEmptyAgvTask extends AbstractTask {
|
||||||
|
|
||||||
|
/** 运输任务接口 */
|
||||||
|
@Resource
|
||||||
|
private TransportTaskApi transportTaskApi;
|
||||||
|
|
||||||
|
/** 装箱点位 Mapper */
|
||||||
|
@Resource
|
||||||
|
private PackagePointMapper packagePointMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务完成后将目的点更新为空载具
|
||||||
|
*
|
||||||
|
* @param taskExecuteDTO 任务执行信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doHandleFinish(TaskExecuteDTO taskExecuteDTO) {
|
||||||
|
TaskInfoDTO taskInfoDTO = transportTaskApi.getTaskById(taskExecuteDTO.getTaskId()).getCheckedData();
|
||||||
|
PackagePointDO endPoint = packagePointMapper.selectByPointCode(taskInfoDTO.getPointCode2(), false);
|
||||||
|
PackagePointDO updatePoint = new PackagePointDO();
|
||||||
|
updatePoint.setPointId(endPoint.getPointId());
|
||||||
|
updatePoint.setVehicleCode(taskInfoDTO.getVehicleCode());
|
||||||
|
updatePoint.setContainerName("");
|
||||||
|
updatePoint.setPointStatus(BoxPointStatusEnum.EMPTY_CONTAINER.getCode());
|
||||||
|
updatePoint.setLockStatus("0");
|
||||||
|
packagePointMapper.updateById(updatePoint);
|
||||||
|
log.info("任务{}执行完成,空架子已存入点位{}", taskExecuteDTO.getTaskId(), taskInfoDTO.getPointCode2());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 任务取消后解锁起点和目的点
|
||||||
|
*
|
||||||
|
* @param taskExecuteDTO 任务执行信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doHandleCancel(TaskExecuteDTO taskExecuteDTO) {
|
||||||
|
TaskInfoDTO taskInfoDTO = transportTaskApi.getTaskById(taskExecuteDTO.getTaskId()).getCheckedData();
|
||||||
|
PackagePointDO startPoint = packagePointMapper.selectByPointCode(taskInfoDTO.getPointCode1(), false);
|
||||||
|
PackagePointDO endPoint = packagePointMapper.selectByPointCode(taskInfoDTO.getPointCode2(), false);
|
||||||
|
PackagePointDO updateStartPoint = new PackagePointDO();
|
||||||
|
updateStartPoint.setPointId(startPoint.getPointId());
|
||||||
|
updateStartPoint.setLockStatus("0");
|
||||||
|
PackagePointDO updateEndPoint = new PackagePointDO();
|
||||||
|
updateEndPoint.setPointId(endPoint.getPointId());
|
||||||
|
updateEndPoint.setLockStatus("0");
|
||||||
|
packagePointMapper.updateBatch(List.of(updateStartPoint, updateEndPoint));
|
||||||
|
log.info("任务{}已取消,起点{}和目的点{}已解锁", taskExecuteDTO.getTaskId(),
|
||||||
|
taskInfoDTO.getPointCode1(), taskInfoDTO.getPointCode2());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取货完成后将起点更新为空位
|
||||||
|
*
|
||||||
|
* @param taskExecuteDTO 任务执行信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doHandlePicked(TaskExecuteDTO taskExecuteDTO) {
|
||||||
|
TaskInfoDTO taskInfoDTO = transportTaskApi.getTaskById(taskExecuteDTO.getTaskId()).getCheckedData();
|
||||||
|
PackagePointDO startPoint = packagePointMapper.selectByPointCode(taskInfoDTO.getPointCode1(), false);
|
||||||
|
PackagePointDO updatePoint = new PackagePointDO();
|
||||||
|
updatePoint.setPointId(startPoint.getPointId());
|
||||||
|
updatePoint.setLockStatus("0");
|
||||||
|
updatePoint.setPointStatus(BoxPointStatusEnum.EMPTY.getCode());
|
||||||
|
updatePoint.setVehicleCode("");
|
||||||
|
updatePoint.setContainerName("");
|
||||||
|
packagePointMapper.updateById(updatePoint);
|
||||||
|
log.info("任务{}执行取货完成,点位{}已释放", taskExecuteDTO.getTaskId(), taskInfoDTO.getPointCode1());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,16 +16,22 @@
|
|||||||
|
|
||||||
<update id="tryLockPoint">
|
<update id="tryLockPoint">
|
||||||
UPDATE lms_package_point
|
UPDATE lms_package_point
|
||||||
SET lock_status = '1'
|
SET lock_status = '1',
|
||||||
|
updater = '0',
|
||||||
|
update_time = CURRENT_TIMESTAMP
|
||||||
WHERE point_id = #{pointId}
|
WHERE point_id = #{pointId}
|
||||||
|
AND point_status = #{pointStatus}
|
||||||
AND lock_status = '0'
|
AND lock_status = '0'
|
||||||
AND deleted = b'0'
|
AND deleted = b'0'
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="unlockPoint">
|
<update id="unlockPoint">
|
||||||
UPDATE lms_package_point
|
UPDATE lms_package_point
|
||||||
SET lock_status = '0'
|
SET lock_status = '0',
|
||||||
|
updater = '0',
|
||||||
|
update_time = CURRENT_TIMESTAMP
|
||||||
WHERE point_id = #{pointId}
|
WHERE point_id = #{pointId}
|
||||||
|
AND point_status = #{pointStatus}
|
||||||
AND lock_status = '1'
|
AND lock_status = '1'
|
||||||
AND deleted = b'0'
|
AND deleted = b'0'
|
||||||
</update>
|
</update>
|
||||||
|
|||||||
Reference in New Issue
Block a user