feat: 增加手持端管芯物料查询接口

This commit is contained in:
zhouz
2026-08-18 15:42:38 +08:00
parent 0129230639
commit 5e8f7bca12
10 changed files with 182 additions and 15 deletions

View File

@@ -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, "管芯解绑失败,请刷新托盘后重试");
}

View File

@@ -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<CoreTubeMaterialRespVO> getMaterial(
@RequestParam("materialCode") @NotBlank String materialCode) {
return success(coreTubeBindingService.getMaterial(materialCode));
}
/** 查询可绑定的启用物料。 */
@GetMapping("/materials")
@Operation(summary = "查询可绑定的启用物料")
@PreAuthorize("@ss.hasPermission('lms:core-tube:bind')")
public CommonResult<List<CoreTubeMaterialRespVO>> getMaterials() {
return success(coreTubeBindingService.getMaterialList());
}
/** 批量绑定管芯到托盘格位。 */
@PostMapping("/bind")
@Operation(summary = "批量绑定管芯到托盘格位")
@@ -53,4 +72,14 @@ public class CoreTubePdaController {
public CommonResult<List<CoreTubeBindRespVO>> 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<Boolean> unbind(@RequestParam("coreTubeId") Long coreTubeId) {
coreTubeBindingService.unbind(coreTubeId);
return success(true);
}
}

View File

@@ -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;
}

View File

@@ -19,6 +19,13 @@ public interface CoreTubeMapper extends BaseMapperX<CoreTubeDO> {
/** 根据托盘号查询管芯。 */
List<CoreTubeDO> 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);

View File

@@ -79,8 +79,8 @@ public interface StockingIvtMapper extends BaseMapperX<StockingIvtDO> {
*/
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();

View File

@@ -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<CoreTubeMaterialRespVO> getMaterialList();
/** 解绑尚未进入作业流程的管芯。 */
void unbind(Long coreTubeId);
/** 批量绑定管芯到托盘格位。 */
List<CoreTubeBindRespVO> bind(@Valid CoreTubeBindReqVO reqVO);
}

View File

@@ -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<MaterialBaseRespDTO> result = materialBaseApi.getMaterialBaseByCode(materialCode);
MaterialBaseRespDTO material = validateMaterialResult(result);
return convertMaterial(material);
}
/** 查询所有启用的待绑定物料,供 PDA 下拉选择。 */
@Override
public List<CoreTubeMaterialRespVO> getMaterialList() {
MaterialBaseListReqDTO request = new MaterialBaseListReqDTO();
request.setIsUsed(ENABLED);
CommonResult<List<MaterialBaseRespDTO>> 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<MaterialBaseRespDTO> 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<String> 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<MaterialBaseRespDTO> result = materialBaseApi.getMaterialBase(materialId);
return validateMaterialResult(result);
}
/** 校验基础物料远程调用结果。 */
private MaterialBaseRespDTO validateMaterialResult(CommonResult<MaterialBaseRespDTO> 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<Integer> 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());
}
}
}
}

View File

@@ -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);
}

View File

@@ -32,6 +32,23 @@
ORDER BY row_num, col_num, core_tube_id
</select>
<select id="selectByIdForUpdate"
resultType="cn.code.nl.module.lms.dal.dataobject.coretube.CoreTubeDO">
SELECT <include refid="coreTubeColumns"/>
FROM lms_core_tube
WHERE core_tube_id = #{coreTubeId} AND deleted = b'0'
FOR UPDATE
</select>
<update id="unbindCoreTube">
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'
</update>
<insert id="insertCoreTube">
INSERT INTO lms_core_tube
(core_tube_id, core_tube_code, bind_request_no,

View File

@@ -113,23 +113,18 @@
<insert id="insertPaperVehicleCoreTube">
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())
</insert>
<update id="clearPaperVehicleCoreTube">
UPDATE lms_base_papervehicle
SET core_tube_id = NULL,
core_tube_code = NULL,
material_code = NULL,
material_name = NULL,
qty = 0,
updater = #{updater}
<delete id="deletePaperVehicleCoreTube">
DELETE FROM lms_base_papervehicle
WHERE core_tube_id = #{coreTubeId}
</update>
</delete>
<select id="selectOccupiedDockPoint"
resultType="cn.code.nl.module.lms.dal.dataobject.stockingivt.StockingIvtDO">