fix: 子卷下线区送满卷任务

This commit is contained in:
2026-08-12 17:20:07 +08:00
parent 757ab83bee
commit e20c0f2168
13 changed files with 264 additions and 27 deletions

View File

@@ -12,34 +12,34 @@ public enum BoxPointStatusEnum {
/**
* 空位
*/
EMPTY(1, "空位"),
EMPTY("1", "空位"),
/**
* 空载具
*/
EMPTY_CONTAINER(2, "空载具"),
EMPTY_CONTAINER("2", "空载具"),
/**
* 有子卷
*/
HAS_SUB_ROLL(3, "有子卷"),
HAS_SUB_ROLL("3", "有子卷"),
/**
* 合格品
*/
QUALIFIED(4, "合格品"),
QUALIFIED("4", "合格品"),
/**
* 管制品
*/
CONTROLLED(5, "管制品");
CONTROLLED("5", "管制品");
/**
* 字典键值
*/
private final Integer code;
private final String code;
/**
* 字典标签
*/
private final String desc;
BoxPointStatusEnum(Integer code, String desc) {
BoxPointStatusEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
@@ -49,7 +49,7 @@ public enum BoxPointStatusEnum {
* @param code 编码
* @return 匹配的枚举未找到返回null
*/
public static BoxPointStatusEnum getByCode(Integer code) {
public static BoxPointStatusEnum getByCode(String code) {
for (BoxPointStatusEnum statusEnum : values()) {
if (statusEnum.getCode().equals(code)) {
return statusEnum;

View File

@@ -13,28 +13,28 @@ public enum BoxPointTypeEnum {
/**
* 下线点
*/
OFFLINE_POINT(1, "下线点"),
OFFLINE_POINT("1", "下线点"),
/**
* 待检点
*/
INSPECTION_PENDING_POINT(2, "待检点"),
INSPECTION_PENDING_POINT("2", "待检点"),
/**
* 不合格点
*/
UNQUALIFIED_POINT(3, "不合格点"),
UNQUALIFIED_POINT("3", "不合格点"),
/**
* 装箱点
*/
PACKING_POINT(4, "装箱点"),
PACKING_POINT("4", "装箱点"),
/**
* 装箱对接点
*/
PACKING_DOCK_POINT(5, "装箱对接点");
PACKING_DOCK_POINT("5", "装箱对接点");
private final Integer code;
private final String code;
private final String desc;
BoxPointTypeEnum(Integer code, String desc) {
BoxPointTypeEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
@@ -44,7 +44,7 @@ public enum BoxPointTypeEnum {
* @param code 字典键值
* @return 匹配枚举无匹配返回null
*/
public static BoxPointTypeEnum getByCode(Integer code) {
public static BoxPointTypeEnum getByCode(String code) {
for (BoxPointTypeEnum item : values()) {
if (item.getCode().equals(code)) {
return item;

View File

@@ -86,6 +86,14 @@ public class PackagePointRespVO implements VO {
@ExcelProperty("所属等待点类型")
private String waitPointType;
@Schema(description = "锁状态")
@ExcelProperty("锁状态")
private String lockStatus;
@Schema(description = "生产区域")
@ExcelProperty("生产区域")
private String productArea;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("更新时间")
private LocalDateTime updateTime;

View File

@@ -1,5 +1,6 @@
package cn.code.nl.module.lms.dal.dataobject.packagepoint;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.util.*;
import java.time.LocalDateTime;
@@ -97,5 +98,10 @@ public class PackagePointDO extends BaseDO {
*/
private String lockStatus;
/**
* 生产区域
*/
private String productArea;
}

View File

@@ -6,8 +6,11 @@ import cn.code.nl.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.code.nl.module.lms.controller.admin.packagepoint.vo.PackagePointPageReqVO;
import cn.code.nl.module.lms.dal.dataobject.packagepoint.PackagePointDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.util.StringUtils;
import java.util.List;
/**
* 装箱区点位库存 Mapper
*
@@ -16,6 +19,32 @@ import org.springframework.util.StringUtils;
@Mapper
public interface PackagePointMapper extends BaseMapperX<PackagePointDO> {
/**
* 查询可用点位
*
* @param pointType 点位类型
* @param pointStatus 点位状态
* @return 可用点位列表
*/
List<PackagePointDO> selectAvailablePointList(@Param("pointType") String pointType,
@Param("pointStatus") String pointStatus);
/**
* 尝试锁定点位
*
* @param pointId 点位标识
* @return 更新行数
*/
int tryLockPoint(@Param("pointId") Long pointId);
/**
* 释放点位锁
*
* @param pointId 点位标识
* @return 更新行数
*/
int unlockPoint(@Param("pointId") Long pointId);
default PageResult<PackagePointDO> selectPage(PackagePointPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<PackagePointDO>()
.eqIfPresent(PackagePointDO::getPointType, reqVO.getPointType())

View File

@@ -29,7 +29,7 @@ public class BoxAutoJob {
log.info("子卷下线送到待检区任务创建开始.....");
XxlJobHelper.log("子卷下线送到待检区任务创建开始");
packageBoxBusinessService.autoSendSubRollTask();
String msg = "子卷下线送到待检区任务创建结束";
XxlJobHelper.log(msg);

View File

@@ -6,4 +6,9 @@ package cn.code.nl.module.lms.service.packagepoint;
* @Date: 2026/8/10 17:15
*/
public interface PackageBoxBusinessService {
/**
* 自动创建子卷下线送待检区任务
*/
void autoSendSubRollTask();
}

View File

@@ -1,12 +1,126 @@
package cn.code.nl.module.lms.service.packagepoint;
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.lms.enums.BoxPointTypeEnum;
import cn.code.nl.module.task.api.TransportTaskApi;
import cn.code.nl.module.task.dto.TransportTaskCreateReqDTO;
import cn.code.nl.module.task.enums.TaskOwnerServiceEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.Iterator;
import java.util.List;
/**
* 装箱业务服务实现类
*
* @Author: liyongde
* @Date: 2026/8/10 17:16
*/
@Slf4j
@Service
public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService{
public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService {
/** 子卷下线送待检区业务类型 */
private static final String SUB_ROLL_DOWN_BIZ_TYPE = "SUB_ROLL_DOWN";
/** 子卷下线任务回调处理器编码 */
private static final String SUB_ROLL_DOWN_HANDLE_CODE = "subRollDownAgvTask";
/**
* ACS 搬运任务类型
*/
private static final String ACS_MOVE_TASK_TYPE = "7";
/**
* AGV 系统类型
*/
private static final String AGV_SYSTEM_TYPE = "1";
@Resource
private PackagePointMapper packagePointMapper;
@Resource
private TransportTaskApi transportTaskApi;
/**
* 自动创建子卷下线送待检区任务
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void autoSendSubRollTask() {
List<PackagePointDO> sourcePointList = packagePointMapper.selectAvailablePointList(
BoxPointTypeEnum.OFFLINE_POINT.getCode(), BoxPointStatusEnum.HAS_SUB_ROLL.getCode());
List<PackagePointDO> destinationPointList = packagePointMapper.selectAvailablePointList(
BoxPointTypeEnum.INSPECTION_PENDING_POINT.getCode(), BoxPointStatusEnum.EMPTY.getCode());
if (CollectionUtils.isEmpty(sourcePointList) || CollectionUtils.isEmpty(destinationPointList)) {
log.info("没有可配对的子卷下线点或待检区点位,结束本轮任务创建");
return;
}
Iterator<PackagePointDO> destinationIterator = destinationPointList.iterator();
for (PackagePointDO sourcePoint : sourcePointList) {
if (packagePointMapper.tryLockPoint(sourcePoint.getPointId()) == 0) {
continue;
}
PackagePointDO destinationPoint = lockNextDestinationPoint(destinationIterator);
if (destinationPoint == null) {
packagePointMapper.unlockPoint(sourcePoint.getPointId());
log.info("没有可用的待检区点位,结束本轮任务创建");
break;
}
Long taskId = createSubRollTransportTask(sourcePoint, destinationPoint);
log.info("子卷下线送待检区任务创建成功,任务标识={},起点编码={},目的点编码={}",
taskId, sourcePoint.getPointCode(), destinationPoint.getPointCode());
}
}
/**
* 创建子卷下线送待检区运输任务
*
* @param sourcePoint 起点
* @param destinationPoint 目的点
* @return 运输任务标识
*/
private Long createSubRollTransportTask(PackagePointDO sourcePoint, PackagePointDO destinationPoint) {
TransportTaskCreateReqDTO task = new TransportTaskCreateReqDTO();
task.setTaskName("子卷下线送待检区任务");
task.setOwnerService(TaskOwnerServiceEnum.LMS.name());
task.setBizType(SUB_ROLL_DOWN_BIZ_TYPE);
task.setBizId(sourcePoint.getContainerName());
task.setHandleCode(SUB_ROLL_DOWN_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.setMaterialCode(sourcePoint.getContainerName());
task.setProductArea(sourcePoint.getProductArea());
task.setIsAutoIssue("1");
task.setIsCreateFinish(true);
return transportTaskApi.createTransportTask(task).getCheckedData();
}
/**
* 从候选点位中锁定下一个可用的待检区点位
*
* @param destinationIterator 待检区候选点位迭代器
* @return 成功锁定的待检区点位,没有可用点位时返回 null
*/
private PackagePointDO lockNextDestinationPoint(Iterator<PackagePointDO> destinationIterator) {
while (destinationIterator.hasNext()) {
PackagePointDO destinationPoint = destinationIterator.next();
if (packagePointMapper.tryLockPoint(destinationPoint.getPointId()) > 0) {
return destinationPoint;
}
}
return null;
}
}

View File

@@ -0,0 +1,30 @@
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 lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 子卷下线AGV任务
* @Author: liyongde
* @Date: 2026/8/12 14:44
*/
@Slf4j
@Component("subRollDownAgvTask")
public class SubRollDownAgvTask extends AbstractTask {
@Override
public void doHandleFinish(TaskExecuteDTO taskExecuteDTO) {
}
@Override
public void doHandleCancel(TaskExecuteDTO taskExecuteDTO) {
}
@Override
public void doHandlePicked(TaskExecuteDTO taskExecuteDTO) {
// 取货完成,释放点位
}
}

View File

@@ -0,0 +1,6 @@
/**
*
* @Author: liyongde
* @Date: 2026/8/12 14:44
*/
package cn.code.nl.module.lms.tasks;

View File

@@ -2,11 +2,49 @@
<!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.packagepoint.PackagePointMapper">
<!--
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
文档可见https://www.iocoder.cn/MyBatis/x-plugins/
-->
<select id="selectAvailablePointList"
resultType="cn.code.nl.module.lms.dal.dataobject.packagepoint.PackagePointDO">
SELECT point_id,
point_code,
point_name,
point_type,
container_name,
point_status,
vehicle_code,
block,
point_location,
sort_seq,
is_used,
remark,
plan,
row_num,
col_num,
depth,
wait_point_type,
lock_status
FROM lms_package_point
WHERE point_type = #{pointType}
AND point_status = #{pointStatus}
AND lock_status = '0'
AND deleted = b'0'
AND is_used = true
ORDER BY sort_seq, point_id
</select>
</mapper>
<update id="tryLockPoint">
UPDATE lms_package_point
SET lock_status = '1'
WHERE point_id = #{pointId}
AND lock_status = '0'
AND deleted = b'0'
</update>
<update id="unlockPoint">
UPDATE lms_package_point
SET lock_status = '0'
WHERE point_id = #{pointId}
AND lock_status = '1'
AND deleted = b'0'
</update>
</mapper>

View File

@@ -10,8 +10,8 @@ import lombok.Getter;
@AllArgsConstructor
public enum TaskOwnerServiceEnum {
LMS("lms", "lms-server"),
WMS("wms", "wms-server");
LMS("lms", "LMS"),
WMS("wms", "WMS");
/**
* MQ Topic 前缀

View File

@@ -17,6 +17,7 @@ CREATE TABLE `lms_package_point`
`col_num` char(6) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '0' COMMENT '',
`depth` char(1) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '0' COMMENT '深浅位0浅位1深位',
`wait_point_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '0' COMMENT '所属等待点类型',
`lock_status` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '0' COMMENT '锁状态',
`creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',