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 5b1a6c1f..e975e0aa 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 @@ -78,4 +78,7 @@ public interface ErrorCodeConstants { ErrorCode CORE_TUBE_MATERIAL_NOT_EXISTS = new ErrorCode(51, "管芯物料不存在"); ErrorCode CORE_TUBE_CODE_GENERATE_FAILED = new ErrorCode(52, "管芯编号生成失败"); ErrorCode CORE_TUBE_BIND_FAILED = new ErrorCode(53, "管芯绑定失败,请刷新托盘后重试"); + 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, "管芯解绑失败,请刷新托盘后重试"); } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/CoreTubePdaController.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/CoreTubePdaController.java index 78fdb339..417e270c 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/CoreTubePdaController.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/CoreTubePdaController.java @@ -3,6 +3,7 @@ package cn.code.nl.module.lms.controller.pda.coretube; import cn.code.nl.framework.common.pojo.CommonResult; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindReqVO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindRespVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeMaterialRespVO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubePalletRespVO; import cn.code.nl.module.lms.service.coretube.CoreTubeBindingService; import io.swagger.v3.oas.annotations.Operation; @@ -29,7 +30,7 @@ import static cn.code.nl.framework.common.pojo.CommonResult.success; */ @Tag(name = "PDA - 管芯托盘绑定") @RestController -@RequestMapping("/api/pda/coreTube") +@RequestMapping("/admin-api/lms/api/pda/coreTube") @Validated public class CoreTubePdaController { @@ -46,6 +47,24 @@ public class CoreTubePdaController { return success(coreTubeBindingService.getPallet(vehicleCode)); } + /** 根据编码查询待绑定的管芯物料。 */ + @GetMapping("/material") + @Operation(summary = "根据编码查询管芯物料") + @Parameter(name = "materialCode", description = "管芯物料编码", required = true) + @PreAuthorize("@ss.hasPermission('lms:core-tube:bind')") + public CommonResult getMaterial( + @RequestParam("materialCode") @NotBlank String materialCode) { + return success(coreTubeBindingService.getMaterial(materialCode)); + } + + /** 查询可绑定的启用物料。 */ + @GetMapping("/materials") + @Operation(summary = "查询可绑定的启用物料") + @PreAuthorize("@ss.hasPermission('lms:core-tube:bind')") + public CommonResult> getMaterials() { + return success(coreTubeBindingService.getMaterialList()); + } + /** 批量绑定管芯到托盘格位。 */ @PostMapping("/bind") @Operation(summary = "批量绑定管芯到托盘格位") @@ -53,4 +72,14 @@ public class CoreTubePdaController { public CommonResult> bind(@Valid @RequestBody CoreTubeBindReqVO reqVO) { return success(coreTubeBindingService.bind(reqVO)); } + + /** 解绑尚未进入作业流程的管芯。 */ + @PostMapping("/unbind") + @Operation(summary = "解绑托盘格位上的管芯") + @Parameter(name = "coreTubeId", description = "管芯实例ID", required = true) + @PreAuthorize("@ss.hasPermission('lms:core-tube:bind')") + public CommonResult unbind(@RequestParam("coreTubeId") Long coreTubeId) { + coreTubeBindingService.unbind(coreTubeId); + return success(true); + } } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeMaterialRespVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeMaterialRespVO.java new file mode 100644 index 00000000..31efac8e --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeMaterialRespVO.java @@ -0,0 +1,25 @@ +package cn.code.nl.module.lms.controller.pda.coretube.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * PDA 管芯物料信息。 + */ +@Schema(description = "PDA - 管芯物料信息 Response VO") +@Data +public class CoreTubeMaterialRespVO { + + /** 物料ID。 */ + @Schema(description = "物料ID") + private Long materialId; + /** 物料编码。 */ + @Schema(description = "物料编码") + private String materialCode; + /** 物料名称。 */ + @Schema(description = "物料名称") + private String materialName; + /** 物料规格。 */ + @Schema(description = "物料规格") + private String materialSpec; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/coretube/CoreTubeMapper.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/coretube/CoreTubeMapper.java index 43f0d0d6..04542ee7 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/coretube/CoreTubeMapper.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/coretube/CoreTubeMapper.java @@ -19,6 +19,13 @@ public interface CoreTubeMapper extends BaseMapperX { /** 根据托盘号查询管芯。 */ List selectByVehicleCode(@Param("vehicleCode") String vehicleCode); + /** 锁定管芯实例。 */ + CoreTubeDO selectByIdForUpdate(@Param("coreTubeId") Long coreTubeId); + + /** 将未进入作业的管芯实例标记为解绑删除。 */ + int unbindCoreTube(@Param("coreTubeId") Long coreTubeId, @Param("stage") Integer stage, + @Param("status") Integer status, @Param("updater") String updater); + /** 插入管芯实例。 */ int insertCoreTube(@Param("tube") CoreTubeDO tube); diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/stockingivt/StockingIvtMapper.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/stockingivt/StockingIvtMapper.java index c06a5295..997ba8df 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/stockingivt/StockingIvtMapper.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/stockingivt/StockingIvtMapper.java @@ -79,8 +79,8 @@ public interface StockingIvtMapper extends BaseMapperX { */ int insertPaperVehicleCoreTube(@Param("tube") cn.code.nl.module.lms.dal.dataobject.coretube.CoreTubeDO tube); - /** 管芯离开托盘后清理格位绑定。 */ - int clearPaperVehicleCoreTube(@Param("coreTubeId") Long coreTubeId, @Param("updater") String updater); + /** 管芯离开托盘后删除对应库存明细。 */ + int deletePaperVehicleCoreTube(@Param("coreTubeId") Long coreTubeId); /** 查询当前有托盘的对接位。 */ StockingIvtDO selectOccupiedDockPoint(); diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingService.java index 7dcdede6..feb2e8c1 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingService.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingService.java @@ -2,6 +2,7 @@ package cn.code.nl.module.lms.service.coretube; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindReqVO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindRespVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeMaterialRespVO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubePalletRespVO; import jakarta.validation.Valid; @@ -15,6 +16,15 @@ public interface CoreTubeBindingService { /** 查询管芯托盘详情。 */ CoreTubePalletRespVO getPallet(String vehicleCode); + /** 根据物料编码查询待绑定的管芯物料。 */ + CoreTubeMaterialRespVO getMaterial(String materialCode); + + /** 查询可绑定的启用物料列表。 */ + List getMaterialList(); + + /** 解绑尚未进入作业流程的管芯。 */ + void unbind(Long coreTubeId); + /** 批量绑定管芯到托盘格位。 */ List bind(@Valid CoreTubeBindReqVO reqVO); } 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 64c620ad..fa7c7550 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 @@ -5,10 +5,12 @@ import cn.code.nl.framework.common.pojo.CommonResult; import cn.code.nl.module.base.api.codegen.CodeGenApi; import cn.code.nl.module.base.api.codegen.dto.CodeGenerateReqDTO; import cn.code.nl.module.base.api.materialbase.MaterialBaseApi; +import cn.code.nl.module.base.api.materialbase.dto.MaterialBaseListReqDTO; import cn.code.nl.module.base.api.materialbase.dto.MaterialBaseRespDTO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindItemReqVO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindReqVO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindRespVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeMaterialRespVO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubePalletRespVO; import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeSlotRespVO; import cn.code.nl.module.lms.dal.dataobject.coretube.CoreTubeDO; @@ -42,6 +44,9 @@ import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_SLOT 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_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; /** * 管芯托盘绑定服务实现。 @@ -95,6 +100,33 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { return response; } + /** 根据物料编码查询待绑定的管芯物料。 */ + @Override + public CoreTubeMaterialRespVO getMaterial(String materialCode) { + CommonResult result = materialBaseApi.getMaterialBaseByCode(materialCode); + MaterialBaseRespDTO material = validateMaterialResult(result); + return convertMaterial(material); + } + + /** 查询所有启用的待绑定物料,供 PDA 下拉选择。 */ + @Override + public List getMaterialList() { + MaterialBaseListReqDTO request = new MaterialBaseListReqDTO(); + request.setIsUsed(ENABLED); + CommonResult> result = materialBaseApi.getMaterialBaseList(request); + if (result == null) { + throw exception(CORE_TUBE_MATERIAL_NOT_EXISTS); + } + if (!result.isSuccess()) { + throw new ServiceException(result.getCode(), result.getMsg()); + } + List materials = result.getData(); + if (CollectionUtils.isEmpty(materials)) { + return List.of(); + } + return materials.stream().map(this::convertMaterial).toList(); + } + /** 批量绑定管芯到托盘格位。 */ @Override @Transactional(rollbackFor = Exception.class) @@ -114,6 +146,7 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { throw exception(CORE_TUBE_BIND_POINT_NOT_ALLOWED); } MaterialBaseRespDTO material = getMaterial(reqVO.getMaterialId()); + validateRowMaterialCode(reqVO, material); Set positions = new HashSet<>(); for (CoreTubeBindItemReqVO item : reqVO.getItems()) { String position = item.getRowNum() + ":" + item.getColNum(); @@ -177,6 +210,11 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { /** 查询并校验物料。 */ private MaterialBaseRespDTO getMaterial(Long materialId) { CommonResult result = materialBaseApi.getMaterialBase(materialId); + return validateMaterialResult(result); + } + + /** 校验基础物料远程调用结果。 */ + private MaterialBaseRespDTO validateMaterialResult(CommonResult result) { if (result == null) { throw exception(CORE_TUBE_MATERIAL_NOT_EXISTS); } @@ -189,6 +227,16 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { return result.getData(); } + /** 将基础物料转换为 PDA 下拉选项。 */ + private CoreTubeMaterialRespVO convertMaterial(MaterialBaseRespDTO material) { + CoreTubeMaterialRespVO response = new CoreTubeMaterialRespVO(); + response.setMaterialId(material.getMaterialId()); + response.setMaterialCode(material.getMaterialCode()); + response.setMaterialName(material.getMaterialName()); + response.setMaterialSpec(material.getMaterialSpec()); + return response; + } + /** 生成虚拟管芯编号。 */ private String generateCoreTubeCode() { CodeGenerateReqDTO request = new CodeGenerateReqDTO(); @@ -220,4 +268,37 @@ public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { } return result; } + + /** 解绑只允许发生在管芯尚未被任何备货任务选中时。 */ + @Override + @Transactional(rollbackFor = Exception.class) + public void unbind(Long coreTubeId) { + CoreTubeDO tube = coreTubeMapper.selectByIdForUpdate(coreTubeId); + if (tube == null + || !CoreTubeStageEnum.STOCKING_AREA.getCode().equals(tube.getStage()) + || !CoreTubeStatusEnum.AVAILABLE.getCode().equals(tube.getStatus()) + || !Integer.valueOf(1).equals(tube.getActiveSlot())) { + throw exception(CORE_TUBE_UNBIND_NOT_ALLOWED); + } + String operator = String.valueOf(getLoginUserId()); + if (stockingIvtMapper.deletePaperVehicleCoreTube(coreTubeId) != 1 + || coreTubeMapper.unbindCoreTube(coreTubeId, CoreTubeStageEnum.STOCKING_AREA.getCode(), + CoreTubeStatusEnum.AVAILABLE.getCode(), operator) != 1) { + throw exception(CORE_TUBE_UNBIND_FAILED); + } + } + + /** 同一托盘同一排只能存放一种物料编码。 */ + private void validateRowMaterialCode(CoreTubeBindReqVO reqVO, MaterialBaseRespDTO material) { + Set requestRows = new HashSet<>(); + reqVO.getItems().forEach(item -> requestRows.add(item.getRowNum())); + for (PaperVehicleDO slot : stockingIvtMapper.selectPaperVehicleList(reqVO.getVehicleCode())) { + if (slot.getCoreTubeId() == null || !requestRows.contains(slot.getRowNum())) { + continue; + } + if (!material.getMaterialCode().equals(slot.getMaterialCode())) { + throw exception(CORE_TUBE_ROW_MATERIAL_CONFLICT, slot.getMaterialCode()); + } + } + } } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchServiceImpl.java index e64095da..5778e42a 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchServiceImpl.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchServiceImpl.java @@ -338,7 +338,7 @@ public class CoreTubeTaskDispatchServiceImpl implements CoreTubeTaskDispatchServ dailyPlanScheduleService.increaseSleevedQuantity(context.getClaimToken(), context.getDailyPlanId(), 1, OPERATOR); } else { - stockingIvtMapper.clearPaperVehicleCoreTube(context.getCoreTubeId(), OPERATOR); + stockingIvtMapper.deletePaperVehicleCoreTube(context.getCoreTubeId()); dailyPlanScheduleService.increaseStockedQuantity(context.getClaimToken(), context.getDailyPlanId(), 1, OPERATOR); } diff --git a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/coretube/CoreTubeMapper.xml b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/coretube/CoreTubeMapper.xml index 8b5c461d..5e78f97c 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/coretube/CoreTubeMapper.xml +++ b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/coretube/CoreTubeMapper.xml @@ -32,6 +32,23 @@ ORDER BY row_num, col_num, core_tube_id + + + + UPDATE lms_core_tube + SET active_slot = NULL, vehicle_code = NULL, row_num = NULL, col_num = NULL, + deleted = b'1', updater = #{updater}, version = version + 1 + WHERE core_tube_id = #{coreTubeId} + AND stage = #{stage} AND status = #{status} + AND active_slot = 1 AND deleted = b'0' + + INSERT INTO lms_core_tube (core_tube_id, core_tube_code, bind_request_no, diff --git a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/stockingivt/StockingIvtMapper.xml b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/stockingivt/StockingIvtMapper.xml index af702ded..7006539b 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/stockingivt/StockingIvtMapper.xml +++ b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/stockingivt/StockingIvtMapper.xml @@ -113,23 +113,18 @@ INSERT INTO lms_base_papervehicle (ivt_id, core_tube_id, core_tube_code, vehicle_code, row_num, col_num, - material_code, material_name, qty, creator, updater) + material_code, material_name, qty, creator, create_time, updater, update_time) VALUES (CAST(#{tube.coreTubeId} AS CHAR), #{tube.coreTubeId}, #{tube.coreTubeCode}, #{tube.vehicleCode}, CAST(#{tube.rowNum} AS CHAR), CAST(#{tube.colNum} AS CHAR), - #{tube.materialCode}, #{tube.materialName}, 1, #{tube.creator}, #{tube.updater}) + #{tube.materialCode}, #{tube.materialName}, 1, + #{tube.creator}, NOW(), #{tube.updater}, NOW()) - - UPDATE lms_base_papervehicle - SET core_tube_id = NULL, - core_tube_code = NULL, - material_code = NULL, - material_name = NULL, - qty = 0, - updater = #{updater} + + DELETE FROM lms_base_papervehicle WHERE core_tube_id = #{coreTubeId} - +