feat:子卷装箱桁架任务

This commit is contained in:
2026-08-18 16:35:49 +08:00
parent f07062bb4f
commit 3ec762c7a3
7 changed files with 217 additions and 7 deletions

View File

@@ -12,6 +12,7 @@ public enum PackageTaskTypeEnum {
SUB_ROLL_DOWN_AGV("010601", "子卷下线到待检AGV任务"),
SUB_ROLL_CALL_EMPTY_AGV("010602", "子卷下线补空架AGV任务"),
PACKAGE_AGV("010603", "装箱AGV任务"),
PACKAGE_BOX_TRUSS("010604", "子卷装箱桁架任务"),
;
/**
* 字典键值

View File

@@ -54,6 +54,19 @@ public interface PackagePointMapper extends BaseMapperX<PackagePointDO> {
@Param("pointStatus") String pointStatus,
@Param("block") String block);
/**
* 根据容器编号集合查询可用点位
*
* @param pointType 点位类型
* @param pointStatus 点位状态
* @param containerNames 容器编号集合
* @return 可用点位列表
*/
List<PackagePointDO> selectAvailablePointListByContainerNames(
@Param("pointType") String pointType,
@Param("pointStatus") String pointStatus,
@Param("containerNames") List<String> containerNames);
/**
* 尝试锁定点位
*

View File

@@ -8,6 +8,7 @@ import cn.code.nl.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.code.nl.framework.mybatis.core.mapper.BaseMapperX;
import cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import cn.code.nl.module.lms.controller.admin.subpackagerelation.vo.*;
/**
@@ -18,6 +19,16 @@ import cn.code.nl.module.lms.controller.admin.subpackagerelation.vo.*;
@Mapper
public interface SubPackageRelationMapper extends BaseMapperX<SubPackageRelationDO> {
/**
* 根据木箱唯一码和状态查询子卷包装关系
*
* @param packageBoxSn 木箱唯一码
* @param status 状态
* @return 子卷包装关系列表
*/
List<SubPackageRelationDO> selectListByPackageBoxSnAndStatus(
@Param("packageBoxSn") String packageBoxSn, @Param("status") String status);
default PageResult<SubPackageRelationDO> selectPage(SubPackageRelationPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<SubPackageRelationDO>()
.eqIfPresent(SubPackageRelationDO::getPackageBoxSn, reqVO.getPackageBoxSn())

View File

@@ -2,7 +2,9 @@ package cn.code.nl.module.lms.service.packagepoint;
import cn.code.nl.framework.common.util.json.JsonUtils;
import cn.code.nl.module.lms.dal.dataobject.packagepoint.PackagePointDO;
import cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO;
import cn.code.nl.module.lms.dal.mysql.packagepoint.PackagePointMapper;
import cn.code.nl.module.lms.dal.mysql.subpackagerelation.SubPackageRelationMapper;
import cn.code.nl.module.lms.enums.BoxPointStatusEnum;
import cn.code.nl.module.lms.enums.BoxPointTypeEnum;
import cn.code.nl.module.lms.enums.PackageTaskTypeEnum;
@@ -45,11 +47,28 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
/** 子卷下线补充空架子任务回调处理器编码 */
private static final String SUB_ROLL_CALL_EMPTY_HANDLE_CODE = "subRollCallEmptyAgvTask";
/** 子卷装箱桁架业务类型 */
private static final String PACKAGE_BOX_TRUSS_BIZ_TYPE = "PACKAGE_BOX_TRUSS";
/** 子卷装箱桁架任务回调处理器编码 */
private static final String PACKAGE_BOX_TRUSS_HANDLE_CODE = "packageBoxTrussTask";
/** 待装箱包装关系状态 */
private static final String PENDING_PACKAGE_RELATION_STATUS = "0";
/** 最后一卷任务扩展参数 */
private static final String LAST_ROLL_REQUEST_PARAM = "{\"isLast\":\"1\"}";
/**
* ACS 搬运任务类型
*/
private static final String ACS_MOVE_TASK_TYPE = "7";
/**
* ACS 桁架任务类型
*/
private static final String ACS_TRUSS_TASK_TYPE = "6";
/**
* AGV 系统类型
*/
@@ -58,6 +77,9 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
@Resource
private PackagePointMapper packagePointMapper;
@Resource
private SubPackageRelationMapper subPackageRelationMapper;
@Resource
private TransportTaskApi transportTaskApi;
@@ -182,9 +204,88 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
}
}
/**
* 自动创建子卷装箱桁架任务
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void autoPackageTrussTaskJob() {
List<PackagePointDO> dockingPointList = packagePointMapper.selectAvailablePointList(
BoxPointTypeEnum.PACKING_DOCK_POINT.getCode(), BoxPointStatusEnum.EMPTY_CONTAINER.getCode());
if (CollectionUtils.isEmpty(dockingPointList)) {
log.info("自动创建子卷装箱桁架任务结束:没有可用的装箱对接位");
return;
}
for (PackagePointDO dockingPoint : dockingPointList) {
if (packagePointMapper.tryLockPoint(dockingPoint.getPointId(), dockingPoint.getPointStatus()) == 0) {
continue;
}
List<SubPackageRelationDO> relationList =
subPackageRelationMapper.selectListByPackageBoxSnAndStatus(
dockingPoint.getVehicleCode(), PENDING_PACKAGE_RELATION_STATUS);
if (CollectionUtils.isEmpty(relationList)) {
packagePointMapper.unlockPoint(dockingPoint.getPointId(), dockingPoint.getPointStatus());
log.info("装箱对接位对应木箱没有待装箱子卷,点位编码={},木箱号={}",
dockingPoint.getPointCode(), dockingPoint.getVehicleCode());
continue;
}
List<String> containerNames = relationList.stream()
.map(SubPackageRelationDO::getContainerName)
.toList();
List<PackagePointDO> sourcePointList = packagePointMapper.selectAvailablePointListByContainerNames(
BoxPointTypeEnum.PACKING_POINT.getCode(), BoxPointStatusEnum.QUALIFIED.getCode(),
containerNames);
PackagePointDO sourcePoint = lockNextSourcePoint(sourcePointList.iterator());
if (sourcePoint == null) {
packagePointMapper.unlockPoint(dockingPoint.getPointId(), dockingPoint.getPointStatus());
log.info("木箱待装子卷暂无可用装箱点,点位编码={},木箱号={}",
dockingPoint.getPointCode(), dockingPoint.getVehicleCode());
continue;
}
Long taskId = createPackageBoxTrussTask(
sourcePoint, dockingPoint, relationList.size() == 1);
log.info("子卷装箱桁架任务创建成功,任务标识={},木箱号={},子卷号={},起点编码={},目的点编码={}",
taskId, dockingPoint.getVehicleCode(), sourcePoint.getContainerName(),
sourcePoint.getPointCode(), dockingPoint.getPointCode());
}
}
/**
* 创建子卷装箱桁架任务
*
* @param sourcePoint 装箱点起点
* @param dockingPoint 装箱对接位终点
* @param isLast 是否为木箱最后一卷
* @return 运输任务标识
*/
private Long createPackageBoxTrussTask(PackagePointDO sourcePoint,
PackagePointDO dockingPoint,
boolean isLast) {
TransportTaskCreateReqDTO task = new TransportTaskCreateReqDTO();
task.setTaskName("子卷装箱桁架任务");
task.setOwnerService(TaskOwnerServiceEnum.LMS.name());
task.setBizType(PACKAGE_BOX_TRUSS_BIZ_TYPE);
task.setBizId(sourcePoint.getContainerName());
task.setTaskType(PackageTaskTypeEnum.PACKAGE_BOX_TRUSS.getCode());
task.setHandleCode(PACKAGE_BOX_TRUSS_HANDLE_CODE);
task.setAcsTaskType(ACS_TRUSS_TASK_TYPE);
task.setAgvSystemType(AGV_SYSTEM_TYPE);
task.setPointCode1(sourcePoint.getPointCode());
task.setPointCode2(dockingPoint.getPointCode());
task.setVehicleCode(dockingPoint.getVehicleCode());
task.setMaterialCode(sourcePoint.getContainerName());
task.setProductArea(sourcePoint.getProductArea());
task.setIsAutoIssue("1");
task.setIsCreateFinish(true);
if (isLast) {
task.setRequestParam(LAST_ROLL_REQUEST_PARAM);
}
return transportTaskApi.createTransportTask(task).getCheckedData();
}
/**

View File

@@ -0,0 +1,65 @@
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;
/**
* 子卷装箱桁架任务
* 装箱区 -> 装箱对接位
* @Author: liyongde
* @Date: 2026/8/18 15:50
*/
@Slf4j
@Component("packageBoxTrussTask")
public class PackageBoxTrussTask extends AbstractTask {
@Resource
private TransportTaskApi transportTaskApi;
@Resource
private PackagePointMapper packagePointMapper;
@Override
public void doHandleFinish(TaskExecuteDTO taskExecuteDTO) {
// 起点设置空载具
TaskInfoDTO taskInfoDTO = transportTaskApi.getTaskById(taskExecuteDTO.getTaskId()).getCheckedData();
PackagePointDO startPoint = packagePointMapper.selectByPointCode(taskInfoDTO.getPointCode1(), false);
PackagePointDO endPoint = packagePointMapper.selectByPointCode(taskInfoDTO.getPointCode2(), false);
PackagePointDO upStartPoint = new PackagePointDO();
upStartPoint.setPointId(startPoint.getPointId());
upStartPoint.setPointStatus(BoxPointStatusEnum.EMPTY_CONTAINER.getCode());
upStartPoint.setContainerName("");
upStartPoint.setLockStatus("0");
PackagePointDO upEndPoint = new PackagePointDO();
upEndPoint.setPointId(endPoint.getPointId());
upEndPoint.setLockStatus("0");
upEndPoint.setVehicleCode("");
upEndPoint.setPointStatus(BoxPointStatusEnum.EMPTY.getCode());
packagePointMapper.updateBatch(List.of(upStartPoint, upEndPoint));
}
@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 upStartPoint = new PackagePointDO();
upStartPoint.setPointId(startPoint.getPointId());
upStartPoint.setLockStatus("0");
PackagePointDO upEndPoint = new PackagePointDO();
upEndPoint.setPointId(endPoint.getPointId());
upEndPoint.setLockStatus("0");
packagePointMapper.updateBatch(List.of(upStartPoint, upEndPoint));
}
}

View File

@@ -27,6 +27,22 @@
ORDER BY sort_seq, point_id
</select>
<select id="selectAvailablePointListByContainerNames"
resultType="cn.code.nl.module.lms.dal.dataobject.packagepoint.PackagePointDO">
SELECT *
FROM lms_package_point
WHERE point_type = #{pointType}
AND point_status = #{pointStatus}
AND container_name IN
<foreach collection="containerNames" item="containerName" open="(" separator="," close=")">
#{containerName}
</foreach>
AND lock_status = '0'
AND deleted = b'0'
AND is_used = true
ORDER BY sort_seq, point_id
</select>
<update id="tryLockPoint">
UPDATE lms_package_point
SET lock_status = '1',

View File

@@ -2,11 +2,14 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.code.nl.module.lms.dal.mysql.subpackagerelation.SubPackageRelationMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="selectListByPackageBoxSnAndStatus"
resultType="cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO">
SELECT *
FROM lms_sub_package_relation
WHERE package_box_sn = #{packageBoxSn}
AND status = #{status}
AND deleted = b'0'
ORDER BY id DESC
</select>
</mapper>
</mapper>