fix: 装箱点位管理

This commit is contained in:
2026-08-18 15:13:25 +08:00
parent d3feb61e62
commit 5d988431a6
18 changed files with 234 additions and 0 deletions

View File

@@ -52,6 +52,8 @@ public interface ErrorCodeConstants {
// ========== 装箱区点位库存 ==========
ErrorCode PACKAGE_POINT_NOT_EXISTS = new ErrorCode(200001, "装箱区点位库存不存在");
ErrorCode PACKAGE_POINT_TASK_QUERY_FAILED = new ErrorCode(200002, "查询点位关联任务失败,请稍后重试");
ErrorCode PACKAGE_POINT_HAS_UNFINISHED_TASK = new ErrorCode(200003, "选中点位存在未完成任务,无法解锁");
// ========== 子卷包装关系 ==========
ErrorCode SUB_PACKAGE_RELATION_NOT_EXISTS = new ErrorCode(300001, "子卷包装关系不存在");

View File

@@ -54,6 +54,15 @@ public class PackagePointController {
return success(true);
}
@PutMapping("/unlock-list")
@Operation(summary = "批量解锁装箱区点位")
@PreAuthorize("@ss.hasPermission('lms:package-point:update')")
public CommonResult<Boolean> unlockPackagePointList(
@RequestBody @NotEmpty List<@NotNull Long> ids) {
packagePointService.unlockPackagePointList(ids);
return success(true);
}
@DeleteMapping("/delete")
@Operation(summary = "删除装箱区点位库存")
@Parameter(name = "id", description = "编号", required = true)

View File

@@ -60,6 +60,22 @@ public interface PackagePointMapper extends BaseMapperX<PackagePointDO> {
*/
int unlockPoint(@Param("pointId") Long pointId, @Param("pointStatus") String pointStatus);
/**
* 批量解锁点位
*
* @param ids 点位标识列表
* @return 更新行数
*/
int unlockPointList(@Param("ids") List<Long> ids);
/**
* 根据点位标识查询点位编码
*
* @param ids 点位标识列表
* @return 点位编码列表
*/
List<String> selectPointCodeListByIds(@Param("ids") List<Long> ids);
default PageResult<PackagePointDO> selectPage(PackagePointPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<PackagePointDO>()
.eqIfPresent(PackagePointDO::getPointType, reqVO.getPointType())

View File

@@ -54,4 +54,20 @@ public class BoxAutoJob {
XxlJobHelper.handleSuccess(msg);
log.info(msg);
}
/**
* 待检区->装箱区定时器
*/
@XxlJob("autoSendPackageAgvTaskJob")
@TenantJob
public void autoSendPackageAgvTaskJob() {
log.info("待检区送卷到装箱区任务创建开始.....");
XxlJobHelper.log("待检区送卷到装箱区任务创建开始");
packageBoxBusinessService.autoSendPackageAgvTaskJob();
String msg = "待检区送卷到装箱区任务创建结束";
XxlJobHelper.log(msg);
XxlJobHelper.handleSuccess(msg);
log.info(msg);
}
}

View File

@@ -16,4 +16,9 @@ public interface PackageBoxBusinessService {
* 自动创建子卷下线补充空架子任务
*/
void autoSubRollDownCallEmpty();
/**
* 待检区->装箱区定时器
*/
void autoSendPackageAgvTaskJob();
}

View File

@@ -130,6 +130,18 @@ public class PackageBoxBusinessServiceImpl implements PackageBoxBusinessService
createPackingToInspectionTask(packingSourceIterator, inspectionEmptyPointList.iterator());
}
@Override
public void autoSendPackageAgvTaskJob() {
// 查找符合的任务任务状态10taskType = 010603,
// 查找对应装箱区的空位lms_package_point没锁、状态是空位、点位类型是装箱点block = 任务中的request_param:({"block": "1"})的block1/2代表第一块或者第二块的任务的值
// 补齐任务将任务的pointCode2设置找到的装箱区的站点,任务状态设置成40
// 终点点位上锁
}
/**
* 创建子卷下线送待检区运输任务
*

View File

@@ -29,6 +29,13 @@ public interface PackagePointService {
*/
void updatePackagePoint(@Valid PackagePointSaveReqVO updateReqVO);
/**
* 批量解锁装箱区点位
*
* @param ids 点位标识列表
*/
void unlockPackagePointList(List<Long> ids);
/**
* 删除装箱区点位库存
*

View File

@@ -1,11 +1,14 @@
package cn.code.nl.module.lms.service.packagepoint;
import cn.code.nl.framework.common.pojo.CommonResult;
import cn.code.nl.framework.common.pojo.PageResult;
import cn.code.nl.framework.common.util.object.BeanUtils;
import cn.code.nl.module.lms.controller.admin.packagepoint.vo.PackagePointPageReqVO;
import cn.code.nl.module.lms.controller.admin.packagepoint.vo.PackagePointSaveReqVO;
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.task.api.TransportTaskApi;
import cn.code.nl.module.task.dto.UnfinishedTaskPointReqDTO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -13,7 +16,9 @@ import org.springframework.validation.annotation.Validated;
import java.util.List;
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.PACKAGE_POINT_HAS_UNFINISHED_TASK;
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.PACKAGE_POINT_NOT_EXISTS;
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.PACKAGE_POINT_TASK_QUERY_FAILED;
/**
* 装箱区点位库存 Service 实现类
@@ -27,6 +32,9 @@ public class PackagePointServiceImpl implements PackagePointService {
@Resource
private PackagePointMapper packagePointMapper;
@Resource
private TransportTaskApi transportTaskApi;
@Override
public Long createPackagePoint(PackagePointSaveReqVO createReqVO) {
// 插入
@@ -46,6 +54,21 @@ public class PackagePointServiceImpl implements PackagePointService {
packagePointMapper.updateById(updateObj);
}
@Override
public void unlockPackagePointList(List<Long> ids) {
List<String> pointCodes = packagePointMapper.selectPointCodeListByIds(ids);
UnfinishedTaskPointReqDTO reqDTO = new UnfinishedTaskPointReqDTO();
reqDTO.setPointCodes(pointCodes);
CommonResult<Boolean> result = transportTaskApi.hasUnfinishedByPointCodes(reqDTO);
if (result.isError()) {
throw exception(PACKAGE_POINT_TASK_QUERY_FAILED);
}
if (Boolean.TRUE.equals(result.getData())) {
throw exception(PACKAGE_POINT_HAS_UNFINISHED_TASK);
}
packagePointMapper.unlockPointList(ids);
}
@Override
public void deletePackagePoint(Long id) {
// 校验存在

View File

@@ -36,4 +36,24 @@
AND deleted = b'0'
</update>
<update id="unlockPointList">
UPDATE lms_package_point
SET lock_status = '0'
WHERE point_id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
AND deleted = b'0'
</update>
<select id="selectPointCodeListByIds" resultType="string">
SELECT point_code
FROM lms_package_point
WHERE point_id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
AND deleted = b'0'
</select>
</mapper>

View File

@@ -3,6 +3,7 @@ package cn.code.nl.module.task.api;
import cn.code.nl.framework.common.pojo.CommonResult;
import cn.code.nl.module.task.dto.TaskInfoDTO;
import cn.code.nl.module.task.dto.TransportTaskCreateReqDTO;
import cn.code.nl.module.task.dto.UnfinishedTaskPointReqDTO;
import cn.code.nl.module.task.dto.TaskCallbackResultReqDTO;
import cn.code.nl.module.task.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
@@ -65,4 +66,13 @@ public interface TransportTaskApi {
@Operation(summary = "统计指定目的点的未完成任务数")
CommonResult<Long> countUnfinishedByDestination(@RequestParam("pointCode") String pointCode,
@RequestParam("ownerService") String ownerService);
/**
* 检查指定点位是否存在未完成任务
*
* @param reqDTO 点位查询请求
* @return 是否存在未完成任务
*/
@PostMapping(PREFIX + "/hasUnfinishedByPointCodes")
CommonResult<Boolean> hasUnfinishedByPointCodes(@Valid @RequestBody UnfinishedTaskPointReqDTO reqDTO);
}

View File

@@ -0,0 +1,20 @@
package cn.code.nl.module.task.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import java.util.List;
/**
* 未完成任务点位查询请求
*/
@Data
public class UnfinishedTaskPointReqDTO {
/**
* 点位编码列表
*/
@NotEmpty(message = "点位编码列表不能为空")
private List<@NotBlank(message = "点位编码不能为空") String> pointCodes;
}

View File

@@ -3,6 +3,7 @@ package cn.code.nl.module.task.api;
import cn.code.nl.framework.common.pojo.CommonResult;
import cn.code.nl.module.task.dto.TaskInfoDTO;
import cn.code.nl.module.task.dto.TransportTaskCreateReqDTO;
import cn.code.nl.module.task.dto.UnfinishedTaskPointReqDTO;
import cn.code.nl.module.task.dto.TaskCallbackResultReqDTO;
import cn.code.nl.module.task.service.transporttask.TransportTaskCallbackService;
import cn.code.nl.module.task.service.transporttask.TransportTaskService;
@@ -74,4 +75,15 @@ public class TransportTaskApiImpl implements TransportTaskApi {
public CommonResult<Long> countUnfinishedByDestination(String pointCode, String ownerService) {
return success(transportTaskService.countUnfinishedByDestination(pointCode, ownerService));
}
/**
* 检查指定点位是否存在未完成任务
*
* @param reqDTO 点位查询请求
* @return 是否存在未完成任务
*/
@Override
public CommonResult<Boolean> hasUnfinishedByPointCodes(UnfinishedTaskPointReqDTO reqDTO) {
return success(transportTaskService.hasUnfinishedByPointCodes(reqDTO.getPointCodes()));
}
}

View File

@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import cn.code.nl.framework.mybatis.core.mapper.BaseMapperX;
import cn.code.nl.module.task.dal.dataobject.transporttask.TransportTaskDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import cn.code.nl.module.task.controller.admin.transporttask.vo.*;
/**
@@ -117,6 +118,14 @@ public interface TransportTaskMapper extends BaseMapperX<TransportTaskDO> {
TransportTaskStatusEnum.FINISHED_CALLBACK_PENDING.getCode()));
}
/**
* 统计指定点位关联的未完成任务
*
* @param pointCodes 点位编码列表
* @return 未完成任务数量
*/
long selectUnfinishedCountByPointCodes(@Param("pointCodes") List<String> pointCodes);
/**
* 条件更新任务状态CAS 抢占)
*/

View File

@@ -125,6 +125,14 @@ public interface TransportTaskService {
Long countUnfinishedByDestination(String pointCode, String ownerService);
/**
* 检查指定点位是否存在未完成任务
*
* @param pointCodes 点位编码列表
* @return 是否存在未完成任务
*/
boolean hasUnfinishedByPointCodes(List<String> pointCodes);
/**
* 自动下发待下发任务到 ACS
*/

View File

@@ -236,6 +236,11 @@ public class TransportTaskServiceImpl implements TransportTaskService {
return transportTaskMapper.selectUnfinishedCountByDestination(pointCode, ownerService);
}
@Override
public boolean hasUnfinishedByPointCodes(List<String> pointCodes) {
return transportTaskMapper.selectUnfinishedCountByPointCodes(pointCodes) > 0;
}
/**
* 查询待下发任务,并委托下发管理器按生产区域下发到 ACS
*/

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.code.nl.module.task.dal.mysql.transporttask.TransportTaskMapper">
<select id="selectUnfinishedCountByPointCodes" resultType="long">
SELECT COUNT(1)
FROM task_transport_job
WHERE deleted = b'0'
AND task_status &lt; '75'
AND (
point_code1 IN
<foreach collection="pointCodes" item="pointCode" open="(" separator="," close=")">
#{pointCode}
</foreach>
OR point_code2 IN
<foreach collection="pointCodes" item="pointCode" open="(" separator="," close=")">
#{pointCode}
</foreach>
OR point_code3 IN
<foreach collection="pointCodes" item="pointCode" open="(" separator="," close=")">
#{pointCode}
</foreach>
OR point_code4 IN
<foreach collection="pointCodes" item="pointCode" open="(" separator="," close=")">
#{pointCode}
</foreach>
)
</select>
</mapper>

View File

@@ -22,6 +22,7 @@ export namespace LmsPackagePointApi {
colNum: string; // 列
depth: string; // 深浅位0浅位1深位
waitPointType: string; // 所属等待点类型
lockStatus: string; // 锁状态
updaterName?: string; // 更新者名称
updateTime?: string; // 更新时间
}
@@ -64,6 +65,11 @@ export function deletePackagePointList(ids: number[]) {
);
}
/** 批量解锁装箱区点位 */
export function unlockPackagePointList(ids: number[]) {
return requestClient.put('/lms/package-point/unlock-list', ids);
}
/** 导出装箱区点位库存 */
export function exportPackagePoint(params: any) {
return requestClient.download('/lms/package-point/export-excel', { params });

View File

@@ -15,6 +15,7 @@ import {
deletePackagePointList,
exportPackagePoint,
getPackagePointPage,
unlockPackagePointList,
} from '#/api/lms/packagepoint';
import { $t } from '#/locales';
@@ -73,6 +74,22 @@ async function handleDeleteBatch() {
}
}
/** 批量解锁装箱区点位 */
async function handleUnlockBatch() {
const hideLoading = message.loading({
content: '正在解锁选中点位',
duration: 0,
});
try {
await unlockPackagePointList(checkedIds.value);
checkedIds.value = [];
message.success('选中点位解锁成功');
handleRefresh();
} finally {
hideLoading();
}
}
const checkedIds = ref<number[]>([]);
function handleRowCheckboxChange({
records,
@@ -145,6 +162,13 @@ const [Grid, gridApi] = useVbenVxeGrid({
auth: ['lms:package-point:export'],
onClick: handleExport,
},
{
label: '一键解锁',
type: 'primary',
auth: ['lms:package-point:update'],
disabled: isEmpty(checkedIds),
onClick: handleUnlockBatch,
},
{
label: $t('ui.actionTitle.deleteBatch'),
type: 'primary',