feat:装箱入库查询、确认更新点位、释放锁

This commit is contained in:
2026-08-19 16:43:32 +08:00
parent f77503b798
commit d8c071a3c6
14 changed files with 509 additions and 13 deletions

View File

@@ -1,10 +1,7 @@
package cn.code.nl.module.lms.controller.pda.boxpackage;
import cn.code.nl.framework.common.pojo.CommonResult;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.PackagePointPdaRespVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.QueryPackagePointInfoReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.UpdateWeightPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.*;
import cn.code.nl.module.lms.service.packagepoint.PackagePdaService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -35,6 +32,7 @@ public class PackagePdaController {
private PackagePdaService packagePdaService;
@PostMapping("/query-point-info")
@Tag(name = "通用")
@Operation(summary = "查询点位信息")
@PermitAll
public CommonResult<PackagePointPdaRespVO> queryPointInfo(
@@ -45,6 +43,7 @@ public class PackagePdaController {
@PostMapping("/quality-check")
@Operation(summary = "人工质检")
@Tag(name = "人工质检")
@PermitAll
public CommonResult<String> executeManualQualityCheck(@Valid @RequestBody ManaQualityCheckPdaReqVO manaQualityCheckPdaReqVO) {
packagePdaService.executeManualQualityCheck(manaQualityCheckPdaReqVO);
@@ -53,10 +52,45 @@ public class PackagePdaController {
@PostMapping("/update-weight")
@Operation(summary = "维护重量")
@Tag(name = "子卷重量维护")
@PermitAll
public CommonResult<String> executeUpdateWeight(@Valid @RequestBody UpdateWeightPdaReqVO weightPdaReqVO) {
packagePdaService.executeUpdateWeight(weightPdaReqVO);
return success("操作成功!");
}
@PostMapping("/confirm-update-point")
@Tag(name = "装箱区管理")
@Operation(summary = "确认更新点位")
@PermitAll
public CommonResult<String> executeUpdatePoint(@Valid @RequestBody UpdatePointInfoPdaReqVO pointInfoPdaReqVO) {
return success(packagePdaService.executeUpdatePoint(pointInfoPdaReqVO));
}
@PostMapping("/release-point")
@Tag(name = "装箱区管理")
@Operation(summary = "释放锁")
@PermitAll
public CommonResult<String> executeReleasePoint(@Valid @RequestBody QueryPackagePointInfoReqVO pointInfoPdaReqVO) {
packagePdaService.executeReleasePoint(pointInfoPdaReqVO);
return success("操作成功!");
}
@PostMapping("/query-box-info")
@Tag(name = "装箱入库")
@Operation(summary = "查询装箱信息")
@PermitAll
public CommonResult<BoxRelationRespVO> queryBoxInfo(@Valid @RequestBody QueryPackagePointInfoReqVO pointInfoPdaReqVO) {
return success(packagePdaService.queryBoxInfo(pointInfoPdaReqVO));
}
@PostMapping("/confirm-inbound")
@Tag(name = "装箱入库")
@Operation(summary = "确认入库")
@PermitAll
public CommonResult<String> executeConfirmInbound(@Valid @RequestBody QueryPackagePointInfoReqVO pointInfoPdaReqVO) {
packagePdaService.executeConfirmInbound(pointInfoPdaReqVO);
return success("操作成功!");
}
}

View File

@@ -0,0 +1,81 @@
package cn.code.nl.module.lms.controller.pda.boxpackage.vo;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
*
* @Author: liyongde
* @Date: 2026/8/19 15:52
*/
@Data
public class BoxRelationRespVO {
/**
* 木箱号
*/
private String boxNo;
/**
* 总卷数
*/
private Integer totalRollNum;
/**
* 扫描站点
*/
private String scanSiteCode;
/**
* 整箱状态:待入库/已入库
*/
private String boxStatus;
/**
* 子卷明细列表
*/
private List<SubRollItemVO> subRollList;
/**
* 子卷明细
*/
@Data
public static class SubRollItemVO {
/**
* 子卷号
*/
private String containerName;
/**
* 站点号
*/
private String pointCode;
/**
* 子卷状态
*/
private String status;
/**
* 子卷重量 kg
*/
private BigDecimal weight;
/**
* 管芯重量 kg
*/
private BigDecimal tubeWeight;
/**
* 保质期 天
*/
private Integer qualityGuaranPeriod;
/**
* 入库时间
*/
private String dateOfFgInbound;
}
}

View File

@@ -0,0 +1,31 @@
package cn.code.nl.module.lms.controller.pda.boxpackage.vo;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
/**
* 点位更新
* @Author: liyongde
* @Date: 2026/8/19 11:12
*/
@Data
public class UpdatePointInfoPdaReqVO {
/**
* 子卷号
*/
private String containerName;
/**
* 点位编码
*/
@NotEmpty(message = "点位编码不能为空")
private String pointCode;
/**
* 点位状态
*/
@NotEmpty(message = "点位状态不能为空")
private String pointStatus;
/**
* 载具号(架子号)
*/
private String vehicleCode;
}

View File

@@ -67,6 +67,14 @@ public interface PackagePointMapper extends BaseMapperX<PackagePointDO> {
@Param("pointStatus") String pointStatus,
@Param("containerNames") List<String> containerNames);
/**
* 根据子卷号集合查询装箱区点位
*
* @param containerNames 子卷号集合
* @return 装箱区点位列表
*/
List<PackagePointDO> selectListByContainerNames(@Param("containerNames") List<String> containerNames);
/**
* 尝试锁定点位
*

View File

@@ -34,10 +34,12 @@ public interface SlittingproductionplanMapper extends BaseMapperX<Slittingproduc
/**
* 根据 ERP 子卷号集合查询分切生产计划
*
* @param extContainerNames ERP 子卷号集合
* @return 分切生产计划列表
*/
default List<SlittingproductionplanDO> selectListByExtContainerNames(Collection<String> extContainerNames) {
return selectList(SlittingproductionplanDO::getExtContainerName, extContainerNames);
}
List<SlittingproductionplanDO> selectListByExtContainerNames(
@Param("extContainerNames") Collection<String> extContainerNames);
/**
* 根据子卷号或 ERP 子卷号查询分切生产计划

View File

@@ -19,6 +19,22 @@ import cn.code.nl.module.lms.controller.admin.subpackagerelation.vo.*;
@Mapper
public interface SubPackageRelationMapper extends BaseMapperX<SubPackageRelationDO> {
/**
* 根据子卷号查询子卷包装关系
*
* @param containerName 子卷号
* @return 子卷包装关系
*/
SubPackageRelationDO selectByContainerName(@Param("containerName") String containerName);
/**
* 根据木箱唯一码查询全部子卷包装关系
*
* @param packageBoxSn 木箱唯一码
* @return 子卷包装关系列表
*/
List<SubPackageRelationDO> selectListByPackageBoxSn(@Param("packageBoxSn") String packageBoxSn);
/**
* 根据木箱唯一码和状态查询子卷包装关系
*

View File

@@ -1,8 +1,6 @@
package cn.code.nl.module.lms.service.packagepoint;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.PackagePointPdaRespVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.UpdateWeightPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.*;
import jakarta.validation.Valid;
/**
@@ -31,4 +29,29 @@ public interface PackagePdaService {
* @param weightPdaReqVO
*/
void executeUpdateWeight(@Valid UpdateWeightPdaReqVO weightPdaReqVO);
/**
* 确认更新点位
* @param pointInfoPdaReqVO
*/
String executeUpdatePoint(@Valid UpdatePointInfoPdaReqVO pointInfoPdaReqVO);
/**
* 释放锁
* @param pointInfoPdaReqVO
*/
void executeReleasePoint(@Valid QueryPackagePointInfoReqVO pointInfoPdaReqVO);
/**
* 操作入库
* @param pointInfoPdaReqVO
*/
void executeConfirmInbound(@Valid QueryPackagePointInfoReqVO pointInfoPdaReqVO);
/**
* 返回装箱信息
* @param pointInfoPdaReqVO
* @return
*/
BoxRelationRespVO queryBoxInfo(@Valid QueryPackagePointInfoReqVO pointInfoPdaReqVO);
}

View File

@@ -3,15 +3,16 @@ package cn.code.nl.module.lms.service.packagepoint;
import cn.code.nl.framework.common.exception.ServiceException;
import cn.code.nl.framework.common.pojo.CommonResult;
import cn.code.nl.framework.security.core.util.SecurityFrameworkUtils;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.ManaQualityCheckPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.PackagePointPdaRespVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.UpdateWeightPdaReqVO;
import cn.code.nl.module.lms.controller.pda.boxpackage.vo.*;
import cn.code.nl.module.lms.dal.dataobject.packagepoint.PackagePointDO;
import cn.code.nl.module.lms.dal.dataobject.slittingproductionplan.SlittingproductionplanDO;
import cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO;
import cn.code.nl.module.lms.dal.mysql.packagepoint.PackagePointMapper;
import cn.code.nl.module.lms.dal.mysql.slittingproductionplan.SlittingproductionplanMapper;
import cn.code.nl.module.lms.dal.mysql.subpackagerelation.SubPackageRelationMapper;
import cn.code.nl.module.lms.enums.BoxPointStatusEnum;
import cn.code.nl.module.lms.enums.BoxPointTypeEnum;
import cn.code.nl.module.lms.enums.PackageStatusEnum;
import cn.code.nl.module.lms.enums.PackageTaskTypeEnum;
import cn.code.nl.module.task.api.TransportTaskApi;
import cn.code.nl.module.task.dto.TaskInfoDTO;
@@ -28,7 +29,10 @@ import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.*;
@@ -73,6 +77,15 @@ public class PackagePdaServiceImpl implements PackagePdaService {
/** AGV 系统类型 */
private static final String AGV_SYSTEM_TYPE = "1";
/** 待入库状态 */
private static final String PENDING_INBOUND_STATUS = "待入库";
/** 已入库状态 */
private static final String INBOUNDED_STATUS = "已入库";
/** 包装关系已入库状态 */
private static final String PACKAGE_RELATION_INBOUNDED_STATUS = "1";
@Resource
private RedissonClient redissonClient;
@@ -92,6 +105,10 @@ public class PackagePdaServiceImpl implements PackagePdaService {
@Resource
private SlittingproductionplanMapper slittingproductionplanMapper;
/** 子卷包装关系 Mapper */
@Resource
private SubPackageRelationMapper subPackageRelationMapper;
/**
* 根据点位编码查询装箱区点位信息
*
@@ -207,6 +224,176 @@ public class PackagePdaServiceImpl implements PackagePdaService {
}
}
@Override
public String executeUpdatePoint(UpdatePointInfoPdaReqVO pointInfoPdaReqVO) {
// 查询点位信息
PackagePointDO packagePoint = packagePointService.getPackagePointByCode(
pointInfoPdaReqVO.getPointCode(), false);
if (packagePoint == null) {
throw exception(PACKAGE_POINT_NOT_EXISTS);
}
// 存在未完成任务的点位不允许更新
CommonResult<TaskInfoDTO> taskResult = transportTaskApi
.getFirstUnfinishedTaskByPointCode(pointInfoPdaReqVO.getPointCode());
if (taskResult.isError()) {
log.error("查询点位未完成任务失败pointInfoPdaReqVO={},返回={}", pointInfoPdaReqVO, taskResult);
throw exception(PACKAGE_POINT_TASK_QUERY_FAILED);
}
if (taskResult.getData() != null) {
throw exception(PACKAGE_POINT_UPDATE_HAS_UNFINISHED_TASK);
}
BoxPointStatusEnum pointStatus = BoxPointStatusEnum.getByCode(pointInfoPdaReqVO.getPointStatus());
if (pointStatus == null) {
throw exception(PACKAGE_POINT_STATUS_NOT_EXISTS);
}
if (pointStatus == BoxPointStatusEnum.QUALIFIED || pointStatus == BoxPointStatusEnum.CONTROLLED) {
return "请到质检页面进行操作。";
}
PackagePointDO updatePoint = new PackagePointDO();
updatePoint.setPointId(packagePoint.getPointId());
updatePoint.setPointStatus(pointStatus.getCode());
if (pointStatus == BoxPointStatusEnum.EMPTY) {
updatePoint.setContainerName("");
updatePoint.setVehicleCode("");
} else if (pointStatus == BoxPointStatusEnum.HAS_SUB_ROLL) {
if (StrUtil.isBlank(pointInfoPdaReqVO.getContainerName())) {
throw exception(PACKAGE_POINT_CONTAINER_NAME_REQUIRED);
}
if (StrUtil.isBlank(pointInfoPdaReqVO.getVehicleCode())) {
throw exception(PACKAGE_POINT_VEHICLE_CODE_REQUIRED);
}
updatePoint.setContainerName(pointInfoPdaReqVO.getContainerName());
updatePoint.setVehicleCode(pointInfoPdaReqVO.getVehicleCode());
} else if (pointStatus == BoxPointStatusEnum.EMPTY_CONTAINER) {
if (StrUtil.isBlank(pointInfoPdaReqVO.getVehicleCode())) {
throw exception(PACKAGE_POINT_VEHICLE_CODE_REQUIRED);
}
updatePoint.setContainerName("");
updatePoint.setVehicleCode(pointInfoPdaReqVO.getVehicleCode());
}
packagePointMapper.updateById(updatePoint);
log.info("用户{}更新点位信息pointInfoPdaReqVO={}",
SecurityFrameworkUtils.getLoginUserNickname(), pointInfoPdaReqVO);
return "操作成功";
}
@Override
public void executeReleasePoint(QueryPackagePointInfoReqVO pointInfoPdaReqVO) {
PackagePointDO packagePoint = packagePointService.getPackagePointByCode(
pointInfoPdaReqVO.getPointCode(), false);
if (packagePoint == null) {
throw exception(PACKAGE_POINT_NOT_EXISTS);
}
// 存在未完成任务的点位不允许解锁
CommonResult<TaskInfoDTO> taskResult = transportTaskApi
.getFirstUnfinishedTaskByPointCode(pointInfoPdaReqVO.getPointCode());
if (taskResult.isError()) {
log.error("查询点位未完成任务失败pointInfoPdaReqVO={},返回={}", pointInfoPdaReqVO, taskResult);
throw exception(PACKAGE_POINT_TASK_QUERY_FAILED);
}
if (taskResult.getData() != null) {
throw exception(PACKAGE_POINT_HAS_UNFINISHED_TASK);
}
PackagePointDO updatePoint = new PackagePointDO();
updatePoint.setPointId(packagePoint.getPointId());
updatePoint.setLockStatus("0");
packagePointMapper.updateById(updatePoint);
log.info("用户{}释放点位锁,点位编码={}",
SecurityFrameworkUtils.getLoginUserNickname(), pointInfoPdaReqVO.getPointCode());
}
@Override
public void executeConfirmInbound(QueryPackagePointInfoReqVO pointInfoPdaReqVO) {
// 需要用redisson分布式锁
// 查找点位信息
// 根据点位的子卷号查找子卷信息查找lms_slittingproductionplan#ext_container_name找不到就提示erp卷号未导入
// 查看包装信息是否正确根据子卷号查询lms_sub_package_relationcustomer_name=子卷号 & status = 1 & 没删除
// 创建半条任务010603任务只有起点没有终点起点是传入的待检点任务状态是10任务的扩展参数需要加入block
// 调用wms创建出木箱任务api待定先todo但是传参可以先准备。
// 创建出木箱任务的参数装箱对接位需要根据任务数最少判断木箱类型子卷包装关系对应的boxType
// 判断哪一块的对接位:
}
/**
* 根据扫描点位查询整箱及其全部子卷信息
*
* @param pointInfoPdaReqVO 点位查询参数
* @return 整箱及子卷信息
*/
@Override
public BoxRelationRespVO queryBoxInfo(QueryPackagePointInfoReqVO pointInfoPdaReqVO) {
// 查询扫描点位及其绑定的子卷
PackagePointDO scanPoint = packagePointService.getPackagePointByCode(
pointInfoPdaReqVO.getPointCode(), false);
if (scanPoint == null) {
throw exception(PACKAGE_POINT_NOT_EXISTS);
}
// 根据点位子卷查找所在木箱,再查询木箱下的全部子卷
SubPackageRelationDO scanRelation = subPackageRelationMapper
.selectByContainerName(scanPoint.getContainerName());
if (scanRelation == null) {
throw exception(SUB_PACKAGE_RELATION_NOT_EXISTS);
}
List<SubPackageRelationDO> relationList = subPackageRelationMapper
.selectListByPackageBoxSn(scanRelation.getPackageBoxSn());
if (CollectionUtils.isEmpty(relationList)) {
throw exception(SUB_PACKAGE_RELATION_NOT_EXISTS);
}
List<String> containerNames = relationList.stream()
.map(SubPackageRelationDO::getContainerName)
.toList();
Map<String, SlittingproductionplanDO> planMap = slittingproductionplanMapper
.selectListByExtContainerNames(containerNames).stream()
.collect(Collectors.toMap(SlittingproductionplanDO::getExtContainerName,
Function.identity(), (first, second) -> first));
Map<String, PackagePointDO> pointMap = packagePointMapper
.selectListByContainerNames(containerNames).stream()
.collect(Collectors.toMap(PackagePointDO::getContainerName,
Function.identity(), (first, second) -> first));
// 组装木箱及子卷明细
List<BoxRelationRespVO.SubRollItemVO> subRollList = relationList.stream().map(relation -> {
SlittingproductionplanDO plan = planMap.get(relation.getContainerName());
PackagePointDO point = pointMap.get(relation.getContainerName());
BoxRelationRespVO.SubRollItemVO item = new BoxRelationRespVO.SubRollItemVO();
item.setContainerName(relation.getContainerName());
item.setPointCode(point == null ? null : point.getPointCode());
item.setStatus(Objects.requireNonNull(PackageStatusEnum.getByCode(relation.getStatus())).getDesc());
item.setWeight(plan == null || StrUtil.isBlank(plan.getWeight())
? null : new BigDecimal(plan.getWeight()));
item.setTubeWeight(plan == null || StrUtil.isBlank(plan.getPaperWeight())
? null : new BigDecimal(plan.getPaperWeight()));
item.setQualityGuaranPeriod(StrUtil.isBlank(relation.getQualityGuaranPeriod())
? null : Integer.valueOf(relation.getQualityGuaranPeriod()));
item.setDateOfFgInbound(relation.getDateOfFgInbound());
return item;
}).toList();
BoxRelationRespVO response = new BoxRelationRespVO();
response.setBoxNo(scanRelation.getPackageBoxSn());
response.setTotalRollNum(subRollList.size());
response.setScanSiteCode(scanPoint.getPointCode());
response.setBoxStatus(relationList.stream().allMatch(relation ->
PACKAGE_RELATION_INBOUNDED_STATUS.equals(relation.getStatus()))
? INBOUNDED_STATUS : PENDING_INBOUND_STATUS);
response.setSubRollList(subRollList);
return response;
}
/**
* 执行人工质检合格操作
*

View File

@@ -43,6 +43,18 @@
ORDER BY sort_seq, point_id
</select>
<select id="selectListByContainerNames"
resultType="cn.code.nl.module.lms.dal.dataobject.packagepoint.PackagePointDO">
SELECT *
FROM lms_package_point
WHERE container_name IN
<foreach collection="containerNames" item="containerName" open="(" separator="," close=")">
#{containerName}
</foreach>
AND deleted = b'0'
ORDER BY point_id DESC
</select>
<update id="tryLockPoint">
UPDATE lms_package_point
SET lock_status = '1',

View File

@@ -2,6 +2,18 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.code.nl.module.lms.dal.mysql.slittingproductionplan.SlittingproductionplanMapper">
<select id="selectListByExtContainerNames"
resultType="cn.code.nl.module.lms.dal.dataobject.slittingproductionplan.SlittingproductionplanDO">
SELECT *
FROM lms_slittingproductionplan
WHERE ext_container_name IN
<foreach collection="extContainerNames" item="extContainerName" open="(" separator="," close=")">
#{extContainerName}
</foreach>
AND deleted = b'0'
ORDER BY workorder_id DESC
</select>
<select id="selectByContainerName"
resultType="cn.code.nl.module.lms.dal.dataobject.slittingproductionplan.SlittingproductionplanDO">
SELECT *

View File

@@ -2,6 +2,25 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.code.nl.module.lms.dal.mysql.subpackagerelation.SubPackageRelationMapper">
<select id="selectByContainerName"
resultType="cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO">
SELECT *
FROM lms_sub_package_relation
WHERE container_name = #{containerName}
AND deleted = b'0'
ORDER BY id DESC
LIMIT 1
</select>
<select id="selectListByPackageBoxSn"
resultType="cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO">
SELECT *
FROM lms_sub_package_relation
WHERE package_box_sn = #{packageBoxSn}
AND deleted = b'0'
ORDER BY id DESC
</select>
<select id="selectListByPackageBoxSnAndStatus"
resultType="cn.code.nl.module.lms.dal.dataobject.subpackagerelation.SubPackageRelationDO">
SELECT *