From 5ada3c2a41cb00840b6e4b90826c7c38b313b136 Mon Sep 17 00:00:00 2001 From: liyongde <1419499670@qq.com> Date: Thu, 13 Aug 2026 16:47:46 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=87=AA=E5=8A=A8=E8=A1=A5=E7=A9=BA?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/lms/enums/PackageTaskTypeEnum.java | 3 +- .../packagepoint/PackagePointMapper.java | 6 +- .../nl/module/lms/job/box/BoxAutoJob.java | 8 ++ .../PackageBoxBusinessService.java | 5 + .../PackageBoxBusinessServiceImpl.java | 123 +++++++++++++++++- .../tasks/box/SubRollCallEmptyAgvTask.java | 92 +++++++++++++ .../packagepoint/PackagePointMapper.xml | 10 +- 7 files changed, 239 insertions(+), 8 deletions(-) create mode 100644 nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/tasks/box/SubRollCallEmptyAgvTask.java diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/PackageTaskTypeEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/PackageTaskTypeEnum.java index 89d26d5c..72db3be5 100644 --- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/PackageTaskTypeEnum.java +++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/PackageTaskTypeEnum.java @@ -9,7 +9,8 @@ import lombok.Getter; */ @Getter public enum PackageTaskTypeEnum { - SUB_ROLL_DOWN_AGV("010601", "子卷->待检AGV任务"), + SUB_ROLL_DOWN_AGV("010601", "子卷下线到待检AGV任务"), + SUB_ROLL_CALL_EMPTY_AGV("010602", "子卷下线补空架AGV任务"), ; /** * 字典键值 diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/packagepoint/PackagePointMapper.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/packagepoint/PackagePointMapper.java index 8e58d2f4..796a05ab 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/packagepoint/PackagePointMapper.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/packagepoint/PackagePointMapper.java @@ -46,17 +46,19 @@ public interface PackagePointMapper extends BaseMapperX { * 尝试锁定点位 * * @param pointId 点位标识 + * @param pointStatus 预期点位状态 * @return 更新行数 */ - int tryLockPoint(@Param("pointId") Long pointId); + int tryLockPoint(@Param("pointId") Long pointId, @Param("pointStatus") String pointStatus); /** * 释放点位锁 * * @param pointId 点位标识 + * @param pointStatus 预期点位状态 * @return 更新行数 */ - int unlockPoint(@Param("pointId") Long pointId); + int unlockPoint(@Param("pointId") Long pointId, @Param("pointStatus") String pointStatus); default PageResult selectPage(PackagePointPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/job/box/BoxAutoJob.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/job/box/BoxAutoJob.java index 6a425f0c..0cc5263e 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/job/box/BoxAutoJob.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/job/box/BoxAutoJob.java @@ -44,6 +44,14 @@ public class BoxAutoJob { @XxlJob("autoSubRollDownCallEmptyJob") @TenantJob public void autoSubRollDownCallEmptyJob() { + log.info("子卷下线补充空架子任务创建开始....."); + XxlJobHelper.log("子卷下线补充空架子任务创建开始"); + packageBoxBusinessService.autoSubRollDownCallEmpty(); + + String msg = "子卷下线补充空架子任务创建结束"; + XxlJobHelper.log(msg); + XxlJobHelper.handleSuccess(msg); + log.info(msg); } } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/packagepoint/PackageBoxBusinessService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/packagepoint/PackageBoxBusinessService.java index a6c3c79b..8240debd 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/packagepoint/PackageBoxBusinessService.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/packagepoint/PackageBoxBusinessService.java @@ -11,4 +11,9 @@ public interface PackageBoxBusinessService { * 自动创建子卷下线送待检区任务 */ void autoSendSubRollTask(); + + /** + * 自动创建子卷下线补充空架子任务 + */ + void autoSubRollDownCallEmpty(); } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/packagepoint/PackageBoxBusinessServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/packagepoint/PackageBoxBusinessServiceImpl.java index 5ffde31f..713d63af 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/packagepoint/PackageBoxBusinessServiceImpl.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/packagepoint/PackageBoxBusinessServiceImpl.java @@ -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_CALL_EMPTY_BIZ_TYPE = "SUB_ROLL_CALL_EMPTY"; + + /** 子卷下线补充空架子任务回调处理器编码 */ + private static final String SUB_ROLL_CALL_EMPTY_HANDLE_CODE = "subRollCallEmptyAgvTask"; + /** * ACS 搬运任务类型 */ @@ -66,13 +72,13 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService Iterator destinationIterator = destinationPointList.iterator(); for (PackagePointDO sourcePoint : sourcePointList) { - if (packagePointMapper.tryLockPoint(sourcePoint.getPointId()) == 0) { + if (packagePointMapper.tryLockPoint(sourcePoint.getPointId(), sourcePoint.getPointStatus()) == 0) { continue; } PackagePointDO destinationPoint = lockNextDestinationPoint(destinationIterator); if (destinationPoint == null) { - packagePointMapper.unlockPoint(sourcePoint.getPointId()); + packagePointMapper.unlockPoint(sourcePoint.getPointId(), sourcePoint.getPointStatus()); log.info("没有可用的待检区点位,结束本轮任务创建"); break; } @@ -83,6 +89,47 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService } } + /** + * 自动创建子卷下线补充空架子任务 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void autoSubRollDownCallEmpty() { + List offlineEmptyPointList = packagePointMapper.selectAvailablePointList( + BoxPointTypeEnum.OFFLINE_POINT.getCode(), BoxPointStatusEnum.EMPTY.getCode()); + List packingEmptyContainerPointList = packagePointMapper.selectAvailablePointList( + BoxPointTypeEnum.PACKING_POINT.getCode(), BoxPointStatusEnum.EMPTY_CONTAINER.getCode()); + List inspectionEmptyContainerPointList = packagePointMapper.selectAvailablePointList( + BoxPointTypeEnum.INSPECTION_PENDING_POINT.getCode(), BoxPointStatusEnum.EMPTY_CONTAINER.getCode()); + List inspectionEmptyPointList = packagePointMapper.selectAvailablePointList( + BoxPointTypeEnum.INSPECTION_PENDING_POINT.getCode(), BoxPointStatusEnum.EMPTY.getCode()); + + Iterator packingSourceIterator = packingEmptyContainerPointList.iterator(); + Iterator 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(); } + /** + * 创建子卷下线补充空架子运输任务 + * + * @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 sourceIterator, + Iterator 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 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 destinationIterator) { while (destinationIterator.hasNext()) { PackagePointDO destinationPoint = destinationIterator.next(); - if (packagePointMapper.tryLockPoint(destinationPoint.getPointId()) > 0) { + if (packagePointMapper.tryLockPoint( + destinationPoint.getPointId(), destinationPoint.getPointStatus()) > 0) { return destinationPoint; } } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/tasks/box/SubRollCallEmptyAgvTask.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/tasks/box/SubRollCallEmptyAgvTask.java new file mode 100644 index 00000000..27da5ef1 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/tasks/box/SubRollCallEmptyAgvTask.java @@ -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()); + } +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/packagepoint/PackagePointMapper.xml b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/packagepoint/PackagePointMapper.xml index a5d4f711..5397af76 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/packagepoint/PackagePointMapper.xml +++ b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/packagepoint/PackagePointMapper.xml @@ -16,16 +16,22 @@ UPDATE lms_package_point - SET lock_status = '1' + SET lock_status = '1', + updater = '0', + update_time = CURRENT_TIMESTAMP WHERE point_id = #{pointId} + AND point_status = #{pointStatus} AND lock_status = '0' AND deleted = b'0' UPDATE lms_package_point - SET lock_status = '0' + SET lock_status = '0', + updater = '0', + update_time = CURRENT_TIMESTAMP WHERE point_id = #{pointId} + AND point_status = #{pointStatus} AND lock_status = '1' AND deleted = b'0'