fix: 调整管芯绑定解绑位置校验

This commit is contained in:
zhouz
2026-08-18 17:09:58 +08:00
parent e53e5cdb36
commit abf87d0805
8 changed files with 71 additions and 18 deletions

View File

@@ -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, "托盘任务状态查询失败,请稍后重试");
}

View File

@@ -10,6 +10,8 @@ import lombok.Getter;
@AllArgsConstructor
public enum CoreTubeLocationTypeEnum {
/** 托盘尚未进入备货区域点位。 */
OUTSIDE_STOCKING_AREA(0),
/** PDA 绑定管芯时托盘所在的绑定位。 */
STOCKING_BINDING(1),
/** 备货区缓存位。 */

View File

@@ -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<String> 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<PaperVehicleDO> inventory = stockingIvtMapper.selectPaperVehicleList(vehicleCode);
List<CoreTubeSlotRespVO> 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<String> 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<Boolean> 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<Integer> requestRows = new HashSet<>();

View File

@@ -57,6 +57,10 @@ public interface TransportTaskApi {
@RequestParam("bizType") String bizType,
@RequestParam("bizId") String bizId);
@GetMapping(PREFIX + "/hasUnfinishedTaskByVehicleCode")
@Operation(summary = "判断载具是否存在未完成任务")
CommonResult<Boolean> hasUnfinishedTaskByVehicleCode(@RequestParam("vehicleCode") String vehicleCode);
@GetMapping(PREFIX + "/getRunningTaskByMaterialId")
@Operation(summary = "根据 materialId 和 ownerService 查询运行中任务")
CommonResult<List<TaskInfoDTO>> getRunningTaskByMaterialId(@RequestParam("materialId") Long materialId,

View File

@@ -65,6 +65,11 @@ public class TransportTaskApiImpl implements TransportTaskApi {
return success(transportTaskService.getUnfinishedTaskInfoByBiz(ownerService, bizType, bizId));
}
@Override
public CommonResult<Boolean> hasUnfinishedTaskByVehicleCode(String vehicleCode) {
return success(transportTaskService.hasUnfinishedTaskByVehicleCode(vehicleCode));
}
@Override
public CommonResult<List<TaskInfoDTO>> getRunningTaskByMaterialId(Long materialId, String ownerService) {
return success(transportTaskService.getRunningTaskInfoByMaterialId(materialId, ownerService));

View File

@@ -88,6 +88,15 @@ public interface TransportTaskMapper extends BaseMapperX<TransportTaskDO> {
.lt(TransportTaskDO::getTaskStatus, TransportTaskStatusEnum.FINISHED_CALLBACK_PENDING.getCode()));
}
/** 判断载具作为主载具或副载具时是否仍有关联的未完成任务。 */
default boolean existsUnfinishedByVehicleCode(String vehicleCode) {
return selectCount(new LambdaQueryWrapperX<TransportTaskDO>()
.and(wrapper -> wrapper.eq(TransportTaskDO::getVehicleCode, vehicleCode)
.or().eq(TransportTaskDO::getVehicleCode2, vehicleCode))
.lt(TransportTaskDO::getTaskStatus,
TransportTaskStatusEnum.FINISHED_CALLBACK_PENDING.getCode())) > 0;
}
/**
* 根据物料ID和业务归属查询运行中任务
*/

View File

@@ -115,6 +115,9 @@ public interface TransportTaskService {
*/
TaskInfoDTO getUnfinishedTaskInfoByBiz(String ownerService, String bizType, String bizId);
/** 判断载具是否存在未完成任务。 */
boolean hasUnfinishedTaskByVehicleCode(String vehicleCode);
/**
* 根据物料ID和业务归属查询运行中任务状态小于75
*

View File

@@ -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<TaskInfoDTO> getRunningTaskInfoByMaterialId(Long materialId, String ownerService) {
List<TransportTaskDO> tasks = transportTaskMapper.selectRunningListByMaterialId(materialId, ownerService);