From abf87d080536c9988e987e93ba674b5a808d048f Mon Sep 17 00:00:00 2001 From: zhouz <> Date: Tue, 18 Aug 2026 17:09:58 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4=E7=AE=A1=E8=8A=AF?= =?UTF-8?q?=E7=BB=91=E5=AE=9A=E8=A7=A3=E7=BB=91=E4=BD=8D=E7=BD=AE=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/lms/enums/ErrorCodeConstants.java | 2 + .../lms/enums/CoreTubeLocationTypeEnum.java | 2 + .../coretube/CoreTubeBindingServiceImpl.java | 59 +++++++++++++------ .../nl/module/task/api/TransportTaskApi.java | 4 ++ .../module/task/api/TransportTaskApiImpl.java | 5 ++ .../transporttask/TransportTaskMapper.java | 9 +++ .../transporttask/TransportTaskService.java | 3 + .../TransportTaskServiceImpl.java | 5 ++ 8 files changed, 71 insertions(+), 18 deletions(-) diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java index e975e0aa..5f14f3d6 100644 --- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java +++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java @@ -81,4 +81,6 @@ public interface ErrorCodeConstants { ErrorCode CORE_TUBE_ROW_MATERIAL_CONFLICT = new ErrorCode(54, "同一排只能绑定一种管芯物料,当前排物料编码为{}"); ErrorCode CORE_TUBE_UNBIND_NOT_ALLOWED = new ErrorCode(55, "管芯已进入作业流程,不能解绑"); ErrorCode CORE_TUBE_UNBIND_FAILED = new ErrorCode(56, "管芯解绑失败,请刷新托盘后重试"); + ErrorCode CORE_TUBE_PALLET_TASK_EXISTS = new ErrorCode(57, "托盘{}存在未完成任务,不能绑定或解绑管芯"); + ErrorCode CORE_TUBE_PALLET_TASK_CHECK_FAILED = new ErrorCode(58, "托盘任务状态查询失败,请稍后重试"); } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeLocationTypeEnum.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeLocationTypeEnum.java index a0fc950f..7eef702a 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeLocationTypeEnum.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeLocationTypeEnum.java @@ -10,6 +10,8 @@ import lombok.Getter; @AllArgsConstructor public enum CoreTubeLocationTypeEnum { + /** 托盘尚未进入备货区域点位。 */ + OUTSIDE_STOCKING_AREA(0), /** PDA 绑定管芯时托盘所在的绑定位。 */ STOCKING_BINDING(1), /** 备货区缓存位。 */ diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingServiceImpl.java index fa7c7550..3aaedcb2 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingServiceImpl.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingServiceImpl.java @@ -21,6 +21,7 @@ import cn.code.nl.module.lms.dal.mysql.stockingivt.StockingIvtMapper; import cn.code.nl.module.lms.enums.CoreTubeLocationTypeEnum; import cn.code.nl.module.lms.enums.CoreTubeStageEnum; import cn.code.nl.module.lms.enums.CoreTubeStatusEnum; +import cn.code.nl.module.task.api.TransportTaskApi; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import jakarta.annotation.Resource; import org.springframework.dao.DuplicateKeyException; @@ -38,12 +39,13 @@ import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.ex import static cn.code.nl.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_FAILED; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_POINT_NOT_ALLOWED; -import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_POINT_NOT_EXISTS; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_REQUEST_CONFLICT; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_SLOT_DUPLICATED; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_SLOT_OCCUPIED; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_CODE_GENERATE_FAILED; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_MATERIAL_NOT_EXISTS; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_PALLET_TASK_CHECK_FAILED; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_PALLET_TASK_EXISTS; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_ROW_MATERIAL_CONFLICT; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_UNBIND_FAILED; import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_UNBIND_NOT_ALLOWED; @@ -56,7 +58,7 @@ import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_UNBIND_NO public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { private static final String CORE_TUBE_CODE_RULE = "CORE_TUBE_CODE"; - private static final String BINDING_POINT_TYPE = "1"; + private static final Set OPERABLE_POINT_TYPES = Set.of("1", "2"); private static final String ENABLED = "0"; private static final String WEIGHT_UNIT = "kg"; @@ -68,20 +70,21 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { private MaterialBaseApi materialBaseApi; @Resource private CodeGenApi codeGenApi; + @Resource + private TransportTaskApi transportTaskApi; /** 查询管芯托盘详情。 */ @Override public CoreTubePalletRespVO getPallet(String vehicleCode) { StockingIvtDO point = stockingIvtMapper.selectByVehicleCode(vehicleCode); - if (point == null) { - throw exception(CORE_TUBE_BIND_POINT_NOT_EXISTS); - } CoreTubePalletRespVO response = new CoreTubePalletRespVO(); response.setVehicleCode(vehicleCode); - response.setPointId(point.getIvtId()); - response.setPointCode(point.getPointCode()); - response.setPointName(point.getPointName()); - response.setPointType(point.getPointType()); + if (point != null) { + response.setPointId(point.getIvtId()); + response.setPointCode(point.getPointCode()); + response.setPointName(point.getPointName()); + response.setPointType(point.getPointType()); + } List inventory = stockingIvtMapper.selectPaperVehicleList(vehicleCode); List slots = new ArrayList<>(inventory.size()); for (PaperVehicleDO item : inventory) { @@ -139,12 +142,7 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { return convertBindResult(existing); } StockingIvtDO point = stockingIvtMapper.selectByVehicleCodeForUpdate(reqVO.getVehicleCode()); - if (point == null) { - throw exception(CORE_TUBE_BIND_POINT_NOT_EXISTS); - } - if (!BINDING_POINT_TYPE.equals(point.getPointType()) || !ENABLED.equals(point.getIsUsed())) { - throw exception(CORE_TUBE_BIND_POINT_NOT_ALLOWED); - } + validatePalletOperation(point, reqVO.getVehicleCode()); MaterialBaseRespDTO material = getMaterial(reqVO.getMaterialId()); validateRowMaterialCode(reqVO, material); Set positions = new HashSet<>(); @@ -189,9 +187,13 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { tube.setVehicleCode(reqVO.getVehicleCode()); tube.setRowNum(item.getRowNum()); tube.setColNum(item.getColNum()); - tube.setCurrentLocationType(CoreTubeLocationTypeEnum.STOCKING_BINDING.getCode()); - tube.setCurrentLocationId(point.getIvtId()); - tube.setCurrentLocationCode(point.getPointCode()); + tube.setCurrentLocationType(point == null + ? CoreTubeLocationTypeEnum.OUTSIDE_STOCKING_AREA.getCode() + : "2".equals(point.getPointType()) + ? CoreTubeLocationTypeEnum.STOCKING_CACHE.getCode() + : CoreTubeLocationTypeEnum.STOCKING_BINDING.getCode()); + tube.setCurrentLocationId(point == null ? null : point.getIvtId()); + tube.setCurrentLocationCode(point == null ? null : point.getPointCode()); tube.setCreator(operator); tube.setUpdater(operator); if (coreTubeMapper.insertCoreTube(tube) != 1) { @@ -273,8 +275,15 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { @Override @Transactional(rollbackFor = Exception.class) public void unbind(Long coreTubeId) { + CoreTubeDO snapshot = coreTubeMapper.selectById(coreTubeId); + if (snapshot == null || snapshot.getVehicleCode() == null) { + throw exception(CORE_TUBE_UNBIND_NOT_ALLOWED); + } + StockingIvtDO point = stockingIvtMapper.selectByVehicleCodeForUpdate(snapshot.getVehicleCode()); + validatePalletOperation(point, snapshot.getVehicleCode()); CoreTubeDO tube = coreTubeMapper.selectByIdForUpdate(coreTubeId); if (tube == null + || !snapshot.getVehicleCode().equals(tube.getVehicleCode()) || !CoreTubeStageEnum.STOCKING_AREA.getCode().equals(tube.getStage()) || !CoreTubeStatusEnum.AVAILABLE.getCode().equals(tube.getStatus()) || !Integer.valueOf(1).equals(tube.getActiveSlot())) { @@ -288,6 +297,20 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { } } + /** 绑定、解绑仅禁止在对接位或载具存在未完成任务时操作。 */ + private void validatePalletOperation(StockingIvtDO point, String vehicleCode) { + if (point != null && !OPERABLE_POINT_TYPES.contains(point.getPointType())) { + throw exception(CORE_TUBE_BIND_POINT_NOT_ALLOWED); + } + CommonResult result = transportTaskApi.hasUnfinishedTaskByVehicleCode(vehicleCode); + if (result == null || !result.isSuccess() || result.getData() == null) { + throw exception(CORE_TUBE_PALLET_TASK_CHECK_FAILED); + } + if (Boolean.TRUE.equals(result.getData())) { + throw exception(CORE_TUBE_PALLET_TASK_EXISTS, vehicleCode); + } + } + /** 同一托盘同一排只能存放一种物料编码。 */ private void validateRowMaterialCode(CoreTubeBindReqVO reqVO, MaterialBaseRespDTO material) { Set requestRows = new HashSet<>(); diff --git a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/api/TransportTaskApi.java b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/api/TransportTaskApi.java index 44ba34a1..bfa449c1 100644 --- a/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/api/TransportTaskApi.java +++ b/nl-module-task/nl-module-task-api/src/main/java/cn/code/nl/module/task/api/TransportTaskApi.java @@ -57,6 +57,10 @@ public interface TransportTaskApi { @RequestParam("bizType") String bizType, @RequestParam("bizId") String bizId); + @GetMapping(PREFIX + "/hasUnfinishedTaskByVehicleCode") + @Operation(summary = "判断载具是否存在未完成任务") + CommonResult hasUnfinishedTaskByVehicleCode(@RequestParam("vehicleCode") String vehicleCode); + @GetMapping(PREFIX + "/getRunningTaskByMaterialId") @Operation(summary = "根据 materialId 和 ownerService 查询运行中任务") CommonResult> getRunningTaskByMaterialId(@RequestParam("materialId") Long materialId, diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/api/TransportTaskApiImpl.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/api/TransportTaskApiImpl.java index e669265e..a71310a8 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/api/TransportTaskApiImpl.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/api/TransportTaskApiImpl.java @@ -65,6 +65,11 @@ public class TransportTaskApiImpl implements TransportTaskApi { return success(transportTaskService.getUnfinishedTaskInfoByBiz(ownerService, bizType, bizId)); } + @Override + public CommonResult hasUnfinishedTaskByVehicleCode(String vehicleCode) { + return success(transportTaskService.hasUnfinishedTaskByVehicleCode(vehicleCode)); + } + @Override public CommonResult> getRunningTaskByMaterialId(Long materialId, String ownerService) { return success(transportTaskService.getRunningTaskInfoByMaterialId(materialId, ownerService)); diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java index c5f268f9..d29c352e 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/dal/mysql/transporttask/TransportTaskMapper.java @@ -88,6 +88,15 @@ public interface TransportTaskMapper extends BaseMapperX { .lt(TransportTaskDO::getTaskStatus, TransportTaskStatusEnum.FINISHED_CALLBACK_PENDING.getCode())); } + /** 判断载具作为主载具或副载具时是否仍有关联的未完成任务。 */ + default boolean existsUnfinishedByVehicleCode(String vehicleCode) { + return selectCount(new LambdaQueryWrapperX() + .and(wrapper -> wrapper.eq(TransportTaskDO::getVehicleCode, vehicleCode) + .or().eq(TransportTaskDO::getVehicleCode2, vehicleCode)) + .lt(TransportTaskDO::getTaskStatus, + TransportTaskStatusEnum.FINISHED_CALLBACK_PENDING.getCode())) > 0; + } + /** * 根据物料ID和业务归属查询运行中任务 */ diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java index 057bce9e..989de077 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskService.java @@ -115,6 +115,9 @@ public interface TransportTaskService { */ TaskInfoDTO getUnfinishedTaskInfoByBiz(String ownerService, String bizType, String bizId); + /** 判断载具是否存在未完成任务。 */ + boolean hasUnfinishedTaskByVehicleCode(String vehicleCode); + /** * 根据物料ID和业务归属查询运行中任务(状态小于75) * diff --git a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java index 24178698..2f01ed44 100644 --- a/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java +++ b/nl-module-task/nl-module-task-server/src/main/java/cn/code/nl/module/task/service/transporttask/TransportTaskServiceImpl.java @@ -256,6 +256,11 @@ public class TransportTaskServiceImpl implements TransportTaskService { return TransportTaskConvert.INSTANCE.convert(task); } + @Override + public boolean hasUnfinishedTaskByVehicleCode(String vehicleCode) { + return transportTaskMapper.existsUnfinishedByVehicleCode(vehicleCode); + } + @Override public List getRunningTaskInfoByMaterialId(Long materialId, String ownerService) { List tasks = transportTaskMapper.selectRunningListByMaterialId(materialId, ownerService);