Commit 5b61d1be885a644919e3e01776c36606c8719100

Authored by YunaiV
1 parent abfe7830

✨ feat(mes): 增加 IPQC 相关错误码和校验逻辑

新增 IPQC 相关的错误码,增强了对来源报工单的校验逻辑,确保在创建 IPQC 时,来源报工单存在待检产出行,并且来源单据行属于该报工单。
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -347,6 +347,8 @@ public interface ErrorCodeConstants { @@ -347,6 +347,8 @@ public interface ErrorCodeConstants {
347 ErrorCode QC_IPQC_NO_TEMPLATE = new ErrorCode(1_040_604_005, "当前产品未配置 IPQC 检测模板"); 347 ErrorCode QC_IPQC_NO_TEMPLATE = new ErrorCode(1_040_604_005, "当前产品未配置 IPQC 检测模板");
348 ErrorCode QC_IPQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_604_006, "完成检验单前,检测结果必须填写"); 348 ErrorCode QC_IPQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_604_006, "完成检验单前,检测结果必须填写");
349 ErrorCode QC_IPQC_SOURCE_DOC_TYPE_UNKNOWN = new ErrorCode(1_040_604_007, "未知的 IPQC 来源单据类型"); 349 ErrorCode QC_IPQC_SOURCE_DOC_TYPE_UNKNOWN = new ErrorCode(1_040_604_007, "未知的 IPQC 来源单据类型");
  350 + ErrorCode QC_IPQC_SOURCE_DOC_NO_PENDING_LINE = new ErrorCode(1_040_604_008, "来源报工单不存在待检产出行,无法创建 IPQC");
  351 + ErrorCode QC_IPQC_SOURCE_LINE_NOT_BELONG = new ErrorCode(1_040_604_009, "来源单据行不属于该报工单");
350 // ========== MES 质量管理-过程检验行(1-040-604-100) ========== 352 // ========== MES 质量管理-过程检验行(1-040-604-100) ==========
351 ErrorCode QC_IPQC_LINE_NOT_EXISTS = new ErrorCode(1_040_604_100, "过程检验行不存在"); 353 ErrorCode QC_IPQC_LINE_NOT_EXISTS = new ErrorCode(1_040_604_100, "过程检验行不存在");
352 354
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java
@@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService;
21 import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; 21 import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService;
22 import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; 22 import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService;
23 import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcService; 23 import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcService;
  24 +import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
24 import jakarta.annotation.Resource; 25 import jakarta.annotation.Resource;
25 import org.springframework.context.annotation.Lazy; 26 import org.springframework.context.annotation.Lazy;
26 import org.springframework.stereotype.Service; 27 import org.springframework.stereotype.Service;
@@ -62,6 +63,9 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @@ -62,6 +63,9 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ
62 @Lazy 63 @Lazy
63 private MesQcRqcService rqcService; 64 private MesQcRqcService rqcService;
64 65
  66 + @Resource
  67 + private DictDataApi dictDataApi;
  68 +
65 @Override 69 @Override
66 @Transactional(rollbackFor = Exception.class) 70 @Transactional(rollbackFor = Exception.class)
67 public Long createIndicatorResult(MesQcIndicatorResultSaveReqVO createReqVO) { 71 public Long createIndicatorResult(MesQcIndicatorResultSaveReqVO createReqVO) {
@@ -208,7 +212,14 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @@ -208,7 +212,14 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ
208 "检测项[" + indicator.getName() + "]要求整数,实际值=" + item.getValue()); 212 "检测项[" + indicator.getName() + "]要求整数,实际值=" + item.getValue());
209 } 213 }
210 } 214 }
211 - // TEXT / DICT / FILE 不做格式校验 215 + // DICT:校验值属于对应字典类型
  216 + if (Objects.equals(resultType, MesQcResultValueTypeEnum.DICT.getType())) {
  217 + String dictType = indicator.getResultSpecification();
  218 + if (StrUtil.isNotBlank(dictType)) {
  219 + dictDataApi.validateDictDataList(dictType, Collections.singleton(item.getValue()));
  220 + }
  221 + }
  222 + // FILE / TEXT 不做格式校验
212 } 223 }
213 } 224 }
214 225
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
@@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.mes.service.qc.ipqc; @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.mes.service.qc.ipqc;
3 import cn.hutool.core.util.ObjUtil; 3 import cn.hutool.core.util.ObjUtil;
4 import cn.hutool.core.util.ObjectUtil; 4 import cn.hutool.core.util.ObjectUtil;
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.wm.productproduce.MesWmProductProduceLineDO;
  7 +import cn.iocoder.yudao.module.mes.enums.wm.MesWmQualityStatusEnum;
6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO; 9 import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcPageReqVO;
8 import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO; 10 import cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo.MesQcIpqcSaveReqVO;
@@ -29,6 +31,7 @@ import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; @@ -29,6 +31,7 @@ import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
29 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 31 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
30 import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService; 32 import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
31 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; 33 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService;
  34 +import cn.iocoder.yudao.module.mes.service.wm.productproduce.MesWmProductProduceLineService;
32 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 35 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
33 import jakarta.annotation.Resource; 36 import jakarta.annotation.Resource;
34 import org.springframework.context.annotation.Lazy; 37 import org.springframework.context.annotation.Lazy;
@@ -88,6 +91,9 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -88,6 +91,9 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
88 @Resource 91 @Resource
89 @Lazy 92 @Lazy
90 private MesQcIndicatorResultService indicatorResultService; 93 private MesQcIndicatorResultService indicatorResultService;
  94 + @Resource
  95 + @Lazy
  96 + private MesWmProductProduceLineService productProduceLineService;
91 97
92 @Resource 98 @Resource
93 private AdminUserApi adminUserApi; 99 private AdminUserApi adminUserApi;
@@ -105,7 +111,7 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -105,7 +111,7 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
105 Long templateId = templateItem.getTemplateId(); 111 Long templateId = templateItem.getTemplateId();
106 // 1.4 获取来源单据编号 112 // 1.4 获取来源单据编号
107 String sourceDocCode = validateAndGetSourceDocCode( 113 String sourceDocCode = validateAndGetSourceDocCode(
108 - createReqVO.getSourceDocType(), createReqVO.getSourceDocId()); 114 + createReqVO.getSourceDocType(), createReqVO.getSourceDocId(), createReqVO.getSourceLineId());
109 115
110 // 2. 插入主表 116 // 2. 插入主表
111 MesQcIpqcDO ipqc = BeanUtils.toBean(createReqVO, MesQcIpqcDO.class) 117 MesQcIpqcDO ipqc = BeanUtils.toBean(createReqVO, MesQcIpqcDO.class)
@@ -274,12 +280,27 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -274,12 +280,27 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
274 } 280 }
275 } 281 }
276 282
277 - private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId) { 283 + private String validateAndGetSourceDocCode(Integer sourceDocType, Long sourceDocId, Long sourceLineId) {
278 if (sourceDocType == null || sourceDocId == null) { 284 if (sourceDocType == null || sourceDocId == null) {
279 return null; 285 return null;
280 } 286 }
281 if (Objects.equals(sourceDocType, MesBizTypeConstants.PRO_FEEDBACK)) { 287 if (Objects.equals(sourceDocType, MesBizTypeConstants.PRO_FEEDBACK)) {
282 MesProFeedbackDO feedback = feedbackService.validateFeedbackExists(sourceDocId); 288 MesProFeedbackDO feedback = feedbackService.validateFeedbackExists(sourceDocId);
  289 + // 校验该报工存在待检产出行
  290 + List<MesWmProductProduceLineDO> lines = productProduceLineService
  291 + .getProductProduceLineListByFeedbackId(sourceDocId);
  292 + boolean hasPending = lines.stream().anyMatch(
  293 + l -> Objects.equals(l.getQualityStatus(), MesWmQualityStatusEnum.PENDING.getStatus()));
  294 + if (!hasPending) {
  295 + throw exception(QC_IPQC_SOURCE_DOC_NO_PENDING_LINE);
  296 + }
  297 + // 校验 sourceLineId 属于该报工的产出行
  298 + if (sourceLineId != null) {
  299 + boolean belongs = lines.stream().anyMatch(l -> Objects.equals(l.getId(), sourceLineId));
  300 + if (!belongs) {
  301 + throw exception(QC_IPQC_SOURCE_LINE_NOT_BELONG);
  302 + }
  303 + }
283 return feedback.getCode(); 304 return feedback.getCode();
284 } 305 }
285 // 未知来源类型应报错,而不是静默忽略 306 // 未知来源类型应报错,而不是静默忽略