Commit 32e1b772b512d1f58d78a983774ecc33c566a526

Authored by YunaiV
1 parent 91120504

✨ feat(qc): 修改检测项类型为整数并更新相关文档

Showing 17 changed files with 159 additions and 59 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectPageReqVO.java
@@ -18,8 +18,8 @@ public class MesQcDefectPageReqVO extends PageParam { @@ -18,8 +18,8 @@ public class MesQcDefectPageReqVO extends PageParam {
18 @Schema(description = "缺陷描述", example = "外观缺陷") 18 @Schema(description = "缺陷描述", example = "外观缺陷")
19 private String name; 19 private String name;
20 20
21 - @Schema(description = "检测项类型", example = "APPEARANCE")  
22 - private String type; 21 + @Schema(description = "检测项类型", example = "2")
  22 + private Integer type;
23 23
24 @Schema(description = "缺陷等级", example = "1") 24 @Schema(description = "缺陷等级", example = "1")
25 private Integer level; 25 private Integer level;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java
@@ -27,10 +27,10 @@ public class MesQcDefectRespVO { @@ -27,10 +27,10 @@ public class MesQcDefectRespVO {
27 @ExcelProperty("缺陷描述") 27 @ExcelProperty("缺陷描述")
28 private String name; 28 private String name;
29 29
30 - @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "APPEARANCE") 30 + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
31 @ExcelProperty(value = "检测项类型", converter = DictConvert.class) 31 @ExcelProperty(value = "检测项类型", converter = DictConvert.class)
32 @DictFormat(DictTypeConstants.MES_DEFECT_TYPE) 32 @DictFormat(DictTypeConstants.MES_DEFECT_TYPE)
33 - private String type; 33 + private Integer type;
34 34
35 @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 35 @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
36 @ExcelProperty(value = "缺陷等级", converter = DictConvert.class) 36 @ExcelProperty(value = "缺陷等级", converter = DictConvert.class)
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectSaveReqVO.java
@@ -22,9 +22,9 @@ public class MesQcDefectSaveReqVO { @@ -22,9 +22,9 @@ public class MesQcDefectSaveReqVO {
22 @NotEmpty(message = "缺陷描述不能为空") 22 @NotEmpty(message = "缺陷描述不能为空")
23 private String name; 23 private String name;
24 24
25 - @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "APPEARANCE")  
26 - @NotEmpty(message = "检测项类型不能为空")  
27 - private String type; 25 + @Schema(description = "检测项类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
  26 + @NotNull(message = "检测项类型不能为空")
  27 + private Integer type;
28 28
29 @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 29 @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
30 @NotNull(message = "缺陷等级不能为空") 30 @NotNull(message = "缺陷等级不能为空")
@@ -34,4 +34,4 @@ public class MesQcDefectSaveReqVO { @@ -34,4 +34,4 @@ public class MesQcDefectSaveReqVO {
34 @Schema(description = "备注", example = "备注") 34 @Schema(description = "备注", example = "备注")
35 private String remark; 35 private String remark;
36 36
37 - } 37 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/defect/MesQcDefectDO.java
@@ -39,7 +39,7 @@ public class MesQcDefectDO extends BaseDO { @@ -39,7 +39,7 @@ public class MesQcDefectDO extends BaseDO {
39 * 39 *
40 * 字典类型 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_DEFECT_TYPE} 40 * 字典类型 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_DEFECT_TYPE}
41 */ 41 */
42 - private String type; 42 + private Integer type;
43 /** 43 /**
44 * 缺陷等级 44 * 缺陷等级
45 * 45 *
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/miscreceipt/MesWmMiscReceiptDO.java
1 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt; 1 package cn.iocoder.yudao.module.mes.dal.dataobject.wm.miscreceipt;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
4 import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscReceiptStatusEnum; 5 import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscReceiptStatusEnum;
5 -import cn.iocoder.yudao.module.mes.enums.wm.MesWmMiscReceiptTypeEnum;  
6 import com.baomidou.mybatisplus.annotation.KeySequence; 6 import com.baomidou.mybatisplus.annotation.KeySequence;
7 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
8 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
@@ -41,7 +41,7 @@ public class MesWmMiscReceiptDO extends BaseDO { @@ -41,7 +41,7 @@ public class MesWmMiscReceiptDO extends BaseDO {
41 /** 41 /**
42 * 杂项类型 42 * 杂项类型
43 * 43 *
44 - * 枚举 {@link MesWmMiscReceiptTypeEnum} 44 + * 字典 {@link DictTypeConstants#MES_WM_MISC_RECEIPT_TYPE}
45 */ 45 */
46 private Integer type; 46 private Integer type;
47 /** 47 /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcIndicatorResultMapper.java
@@ -24,4 +24,10 @@ public interface MesQcIndicatorResultMapper extends BaseMapperX<MesQcIndicatorRe @@ -24,4 +24,10 @@ public interface MesQcIndicatorResultMapper extends BaseMapperX<MesQcIndicatorRe
24 .orderByDesc(MesQcIndicatorResultDO::getId)); 24 .orderByDesc(MesQcIndicatorResultDO::getId));
25 } 25 }
26 26
  27 + default Long selectCountByQcIdAndType(Long qcId, Integer qcType) {
  28 + return selectCount(new LambdaQueryWrapperX<MesQcIndicatorResultDO>()
  29 + .eq(MesQcIndicatorResultDO::getQcId, qcId)
  30 + .eq(MesQcIndicatorResultDO::getQcType, qcType));
  31 + }
  32 +
27 } 33 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/DictTypeConstants.java
@@ -54,6 +54,7 @@ public interface DictTypeConstants { @@ -54,6 +54,7 @@ public interface DictTypeConstants {
54 String MES_WM_QUALITY_STATUS = "mes_wm_quality_status"; // MES 质量状态(待检/合格/不合格) 54 String MES_WM_QUALITY_STATUS = "mes_wm_quality_status"; // MES 质量状态(待检/合格/不合格)
55 String MES_WM_RETURN_ISSUE_STATUS = "mes_wm_return_issue_status"; // MES 生产退料单状态 55 String MES_WM_RETURN_ISSUE_STATUS = "mes_wm_return_issue_status"; // MES 生产退料单状态
56 String MES_WM_RETURN_ISSUE_TYPE = "mes_wm_return_issue_type"; // MES 生产退料类型 56 String MES_WM_RETURN_ISSUE_TYPE = "mes_wm_return_issue_type"; // MES 生产退料类型
  57 + String MES_WM_MISC_RECEIPT_TYPE = "mes_wm_misc_receipt_type"; // MES 杂项入库类型
57 String MES_WM_MISC_ISSUE_TYPE = "mes_wm_misc_issue_type"; // MES 杂项出库类型 58 String MES_WM_MISC_ISSUE_TYPE = "mes_wm_misc_issue_type"; // MES 杂项出库类型
58 String MES_WM_MISC_ISSUE_STATUS = "mes_wm_misc_issue_status"; // MES 杂项出库单状态 59 String MES_WM_MISC_ISSUE_STATUS = "mes_wm_misc_issue_status"; // MES 杂项出库单状态
59 String MES_WM_SALES_NOTICE_STATUS = "mes_wm_sales_notice_status"; // MES 发货通知单状态 60 String MES_WM_SALES_NOTICE_STATUS = "mes_wm_sales_notice_status"; // MES 发货通知单状态
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -345,6 +345,7 @@ public interface ErrorCodeConstants { @@ -345,6 +345,7 @@ public interface ErrorCodeConstants {
345 ErrorCode QC_IPQC_QUANTITY_MISMATCH = new ErrorCode(1_040_604_004, "合格品与不合格品数量之和须等于检测数量"); 345 ErrorCode QC_IPQC_QUANTITY_MISMATCH = new ErrorCode(1_040_604_004, "合格品与不合格品数量之和须等于检测数量");
346 ErrorCode QC_IPQC_NO_TEMPLATE = new ErrorCode(1_040_604_005, "当前产品未配置 IPQC 检测模板"); 346 ErrorCode QC_IPQC_NO_TEMPLATE = new ErrorCode(1_040_604_005, "当前产品未配置 IPQC 检测模板");
347 ErrorCode QC_IPQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_604_006, "完成检验单前,检测结果必须填写"); 347 ErrorCode QC_IPQC_CHECK_RESULT_EMPTY = new ErrorCode(1_040_604_006, "完成检验单前,检测结果必须填写");
  348 + ErrorCode QC_IPQC_SOURCE_DOC_TYPE_UNKNOWN = new ErrorCode(1_040_604_007, "未知的 IPQC 来源单据类型");
348 // ========== MES 质量管理-过程检验行(1-040-604-100) ========== 349 // ========== MES 质量管理-过程检验行(1-040-604-100) ==========
349 ErrorCode QC_IPQC_LINE_NOT_EXISTS = new ErrorCode(1_040_604_100, "过程检验行不存在"); 350 ErrorCode QC_IPQC_LINE_NOT_EXISTS = new ErrorCode(1_040_604_100, "过程检验行不存在");
350 351
@@ -355,6 +356,8 @@ public interface ErrorCodeConstants { @@ -355,6 +356,8 @@ public interface ErrorCodeConstants {
355 356
356 // ========== MES 质量管理-检验结果(1-040-606-000) ========== 357 // ========== MES 质量管理-检验结果(1-040-606-000) ==========
357 ErrorCode QC_RESULT_NOT_EXISTS = new ErrorCode(1_040_606_000, "检验结果不存在"); 358 ErrorCode QC_RESULT_NOT_EXISTS = new ErrorCode(1_040_606_000, "检验结果不存在");
  359 + ErrorCode QC_RESULT_VALUE_FORMAT_INVALID = new ErrorCode(1_040_606_001, "检测值格式不正确:{}");
  360 + ErrorCode QC_FINISH_INDICATOR_RESULT_REQUIRED = new ErrorCode(1_040_606_002, "完成检验单前,至少需要录入一条检测结果");
358 361
359 // ========== MES 质量管理-出货检验(1-040-607-000) ========== 362 // ========== MES 质量管理-出货检验(1-040-607-000) ==========
360 ErrorCode QC_OQC_NOT_EXISTS = new ErrorCode(1_040_607_000, "出货检验单不存在"); 363 ErrorCode QC_OQC_NOT_EXISTS = new ErrorCode(1_040_607_000, "出货检验单不存在");
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/wm/MesWmMiscReceiptTypeEnum.java deleted
1 -package cn.iocoder.yudao.module.mes.enums.wm;  
2 -  
3 -import cn.iocoder.yudao.framework.common.core.ArrayValuable;  
4 -import lombok.AllArgsConstructor;  
5 -import lombok.Getter;  
6 -  
7 -import java.util.Arrays;  
8 -  
9 -/**  
10 - * MES 杂项入库类型枚举  
11 - */  
12 -@Getter  
13 -@AllArgsConstructor  
14 -public enum MesWmMiscReceiptTypeEnum implements ArrayValuable<Integer> {  
15 -  
16 - ADJUST(1, "库存调整");  
17 -  
18 - public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesWmMiscReceiptTypeEnum::getType).toArray(Integer[]::new);  
19 -  
20 - /**  
21 - * 类型值  
22 - */  
23 - private final Integer type;  
24 - /**  
25 - * 类型名  
26 - */  
27 - private final String name;  
28 -  
29 - @Override  
30 - public Integer[] array() {  
31 - return ARRAYS;  
32 - }  
33 -  
34 -}  
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorService.java
@@ -82,4 +82,12 @@ public interface MesQcIndicatorService { @@ -82,4 +82,12 @@ public interface MesQcIndicatorService {
82 return convertMap(getIndicatorList(ids), MesQcIndicatorDO::getId); 82 return convertMap(getIndicatorList(ids), MesQcIndicatorDO::getId);
83 } 83 }
84 84
  85 + /**
  86 + * 批量校验质检指标是否都存在
  87 + *
  88 + * @param ids 编号数组
  89 + * @return 质检指标 Map
  90 + */
  91 + Map<Long, MesQcIndicatorDO> validateIndicatorListExists(Collection<Long> ids);
  92 +
85 } 93 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicator/MesQcIndicatorServiceImpl.java
@@ -18,8 +18,10 @@ import org.springframework.validation.annotation.Validated; @@ -18,8 +18,10 @@ import org.springframework.validation.annotation.Validated;
18 import java.util.Collection; 18 import java.util.Collection;
19 import java.util.Collections; 19 import java.util.Collections;
20 import java.util.List; 20 import java.util.List;
  21 +import java.util.Map;
21 22
22 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  24 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
23 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; 25 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
24 26
25 /** 27 /**
@@ -132,4 +134,13 @@ public class MesQcIndicatorServiceImpl implements MesQcIndicatorService { @@ -132,4 +134,13 @@ public class MesQcIndicatorServiceImpl implements MesQcIndicatorService {
132 return indicatorMapper.selectByIds(ids); 134 return indicatorMapper.selectByIds(ids);
133 } 135 }
134 136
  137 + @Override
  138 + public Map<Long, MesQcIndicatorDO> validateIndicatorListExists(Collection<Long> ids) {
  139 + List<MesQcIndicatorDO> indicators = getIndicatorList(ids);
  140 + if (indicators.size() != ids.size()) {
  141 + throw exception(QC_INDICATOR_NOT_EXISTS);
  142 + }
  143 + return convertMap(indicators, MesQcIndicatorDO::getId);
  144 + }
  145 +
135 } 146 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultService.java
@@ -62,4 +62,21 @@ public interface MesQcIndicatorResultService { @@ -62,4 +62,21 @@ public interface MesQcIndicatorResultService {
62 */ 62 */
63 List<MesQcIndicatorResultDetailDO> getIndicatorResultDetailListByResultId(Long resultId); 63 List<MesQcIndicatorResultDetailDO> getIndicatorResultDetailListByResultId(Long resultId);
64 64
  65 + /**
  66 + * 获取指定质检单下的检验结果数量
  67 + *
  68 + * @param qcId 质检单 ID
  69 + * @param qcType 质检类型
  70 + * @return 结果数量
  71 + */
  72 + Long getIndicatorResultCountByQcIdAndType(Long qcId, Integer qcType);
  73 +
  74 + /**
  75 + * 校验指定质检单下至少存在一条检验结果
  76 + *
  77 + * @param qcId 质检单 ID
  78 + * @param qcType 质检类型
  79 + */
  80 + void validateIndicatorResultExistsByQcIdAndType(Long qcId, Integer qcType);
  81 +
65 } 82 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java
1 package cn.iocoder.yudao.module.mes.service.qc.indicatorresult; 1 package cn.iocoder.yudao.module.mes.service.qc.indicatorresult;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultPageReqVO; 7 import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultPageReqVO;
@@ -8,11 +9,12 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcI @@ -8,11 +9,12 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcI
8 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; 9 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO;
9 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO; 10 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO;
10 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO; 11 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDetailDO;
11 -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO;  
12 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO; 12 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.ipqc.MesQcIpqcDO;
  13 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO;
13 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO; 14 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.oqc.MesQcOqcDO;
14 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO; 15 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.rqc.MesQcRqcDO;
15 import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcIndicatorResultMapper; 16 import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcIndicatorResultMapper;
  17 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum;
16 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; 18 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
17 import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; 19 import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService;
18 import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; 20 import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService;
@@ -25,6 +27,7 @@ import org.springframework.stereotype.Service; @@ -25,6 +27,7 @@ import org.springframework.stereotype.Service;
25 import org.springframework.transaction.annotation.Transactional; 27 import org.springframework.transaction.annotation.Transactional;
26 import org.springframework.validation.annotation.Validated; 28 import org.springframework.validation.annotation.Validated;
27 29
  30 +import java.math.BigDecimal;
28 import java.util.*; 31 import java.util.*;
29 32
30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 33 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -42,9 +45,9 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @@ -42,9 +45,9 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ
42 45
43 @Resource 46 @Resource
44 private MesQcIndicatorResultMapper resultMapper; 47 private MesQcIndicatorResultMapper resultMapper;
  48 +
45 @Resource 49 @Resource
46 private MesQcIndicatorResultDetailService resultDetailService; 50 private MesQcIndicatorResultDetailService resultDetailService;
47 -  
48 @Resource 51 @Resource
49 private MesQcIndicatorService indicatorService; 52 private MesQcIndicatorService indicatorService;
50 @Resource 53 @Resource
@@ -64,8 +67,8 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @@ -64,8 +67,8 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ
64 public Long createIndicatorResult(MesQcIndicatorResultSaveReqVO createReqVO) { 67 public Long createIndicatorResult(MesQcIndicatorResultSaveReqVO createReqVO) {
65 // 1.1 根据 qcType 查询源质检单,获取 itemId 68 // 1.1 根据 qcType 查询源质检单,获取 itemId
66 Long itemId = getItemIdFromQcDoc(createReqVO.getQcId(), createReqVO.getQcType()); 69 Long itemId = getItemIdFromQcDoc(createReqVO.getQcId(), createReqVO.getQcType());
67 - // 1.2 校验所有明细的 indicatorId 是否存在  
68 - validateIndicatorIds(createReqVO.getItems()); 70 + // 1.2 校验明细数据(indicatorId 存在性 + 值格式)
  71 + validateItemsSaveData(createReqVO.getItems());
69 72
70 // 2.1 插入主表 73 // 2.1 插入主表
71 MesQcIndicatorResultDO result = BeanUtils.toBean(createReqVO, MesQcIndicatorResultDO.class); 74 MesQcIndicatorResultDO result = BeanUtils.toBean(createReqVO, MesQcIndicatorResultDO.class);
@@ -84,8 +87,8 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @@ -84,8 +87,8 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ
84 public void updateIndicatorResult(MesQcIndicatorResultSaveReqVO updateReqVO) { 87 public void updateIndicatorResult(MesQcIndicatorResultSaveReqVO updateReqVO) {
85 // 1.1 校验存在 88 // 1.1 校验存在
86 validateIndicatorResultExists(updateReqVO.getId()); 89 validateIndicatorResultExists(updateReqVO.getId());
87 - // 1.2 校验所有明细的 indicatorId 是否存在  
88 - validateIndicatorIds(updateReqVO.getItems()); 90 + // 1.2 校验明细数据(indicatorId 存在性 + 值格式)
  91 + validateItemsSaveData(updateReqVO.getItems());
89 92
90 // 2.1 更新主表(锁定 qcId/qcType/itemId,不允许改挂到其他质检单) 93 // 2.1 更新主表(锁定 qcId/qcType/itemId,不允许改挂到其他质检单)
91 MesQcIndicatorResultDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIndicatorResultDO.class); 94 MesQcIndicatorResultDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIndicatorResultDO.class);
@@ -124,6 +127,19 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @@ -124,6 +127,19 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ
124 return resultDetailService.getDetailListByResultId(resultId); 127 return resultDetailService.getDetailListByResultId(resultId);
125 } 128 }
126 129
  130 + @Override
  131 + public Long getIndicatorResultCountByQcIdAndType(Long qcId, Integer qcType) {
  132 + return resultMapper.selectCountByQcIdAndType(qcId, qcType);
  133 + }
  134 +
  135 + @Override
  136 + public void validateIndicatorResultExistsByQcIdAndType(Long qcId, Integer qcType) {
  137 + Long resultCount = getIndicatorResultCountByQcIdAndType(qcId, qcType);
  138 + if (resultCount == 0) {
  139 + throw exception(QC_FINISH_INDICATOR_RESULT_REQUIRED);
  140 + }
  141 + }
  142 +
127 // ==================== 私有方法 ==================== 143 // ==================== 私有方法 ====================
128 144
129 private MesQcIndicatorResultDO validateIndicatorResultExists(Long id) { 145 private MesQcIndicatorResultDO validateIndicatorResultExists(Long id) {
@@ -135,18 +151,64 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ @@ -135,18 +151,64 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ
135 } 151 }
136 152
137 /** 153 /**
  154 + * 校验明细保存数据(indicatorId 存在性 + 值格式)
  155 + */
  156 + private void validateItemsSaveData(List<MesQcIndicatorResultSaveReqVO.Item> items) {
  157 + // 校验所有明细的 indicatorId 是否存在
  158 + Map<Long, MesQcIndicatorDO> indicatorMap = validateIndicatorIds(items);
  159 + // 校验明细值格式是否符合指标的 resultType
  160 + validateDetailValues(items, indicatorMap);
  161 + }
  162 +
  163 + /**
138 * 校验所有明细的 indicatorId 是否存在 164 * 校验所有明细的 indicatorId 是否存在
  165 + *
  166 + * @return indicatorId -> MesQcIndicatorDO 映射,供后续值格式校验使用
139 */ 167 */
140 - private void validateIndicatorIds(List<MesQcIndicatorResultSaveReqVO.Item> items) { 168 + private Map<Long, MesQcIndicatorDO> validateIndicatorIds(List<MesQcIndicatorResultSaveReqVO.Item> items) {
141 if (CollUtil.isEmpty(items)) { 169 if (CollUtil.isEmpty(items)) {
142 - return; 170 + return Collections.emptyMap();
143 } 171 }
144 Set<Long> indicatorIds = convertSet(items, MesQcIndicatorResultSaveReqVO.Item::getIndicatorId); 172 Set<Long> indicatorIds = convertSet(items, MesQcIndicatorResultSaveReqVO.Item::getIndicatorId);
145 - List<MesQcIndicatorDO> indicators = indicatorService.getIndicatorList(indicatorIds);  
146 - if (indicators.size() != indicatorIds.size()) {  
147 - Set<Long> existIds = convertSet(indicators, MesQcIndicatorDO::getId);  
148 - indicatorIds.removeAll(existIds);  
149 - throw exception(QC_INDICATOR_NOT_EXISTS); 173 + return indicatorService.validateIndicatorListExists(indicatorIds);
  174 + }
  175 +
  176 + /**
  177 + * 按检测项的 resultType 校验明细值格式
  178 + *
  179 + * <p>FLOAT → 必须可解析为 BigDecimal;INTEGER → 必须可解析为整数;
  180 + * TEXT / DICT / FILE → 放行
  181 + */
  182 + private void validateDetailValues(List<MesQcIndicatorResultSaveReqVO.Item> items,
  183 + Map<Long, MesQcIndicatorDO> indicatorMap) {
  184 + if (CollUtil.isEmpty(items)) {
  185 + return;
  186 + }
  187 + for (MesQcIndicatorResultSaveReqVO.Item item : items) {
  188 + if (item.getIndicatorId() == null || StrUtil.isBlank(item.getValue())) {
  189 + continue;
  190 + }
  191 + MesQcIndicatorDO indicator = indicatorMap.get(item.getIndicatorId());
  192 + if (indicator == null || indicator.getResultType() == null) {
  193 + continue;
  194 + }
  195 + Integer resultType = indicator.getResultType();
  196 + if (Objects.equals(resultType, MesQcResultValueTypeEnum.FLOAT.getType())) {
  197 + try {
  198 + new BigDecimal(item.getValue());
  199 + } catch (NumberFormatException e) {
  200 + throw exception(QC_RESULT_VALUE_FORMAT_INVALID,
  201 + "检测项[" + indicator.getName() + "]要求浮点数,实际值=" + item.getValue());
  202 + }
  203 + } else if (Objects.equals(resultType, MesQcResultValueTypeEnum.INTEGER.getType())) {
  204 + try {
  205 + Long.parseLong(item.getValue());
  206 + } catch (NumberFormatException e) {
  207 + throw exception(QC_RESULT_VALUE_FORMAT_INVALID,
  208 + "检测项[" + indicator.getName() + "]要求整数,实际值=" + item.getValue());
  209 + }
  210 + }
  211 + // TEXT / DICT / FILE 不做格式校验
150 } 212 }
151 } 213 }
152 214
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/ipqc/MesQcIpqcServiceImpl.java
@@ -27,6 +27,7 @@ import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService; @@ -27,6 +27,7 @@ import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService;
27 import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService; 27 import cn.iocoder.yudao.module.mes.service.pro.task.MesProTaskService;
28 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; 28 import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
29 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 29 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
  30 +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
30 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; 31 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService;
31 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 32 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
32 import jakarta.annotation.Resource; 33 import jakarta.annotation.Resource;
@@ -87,6 +88,9 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -87,6 +88,9 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
87 @Resource 88 @Resource
88 @Lazy 89 @Lazy
89 private MesProFeedbackService feedbackService; 90 private MesProFeedbackService feedbackService;
  91 + @Resource
  92 + @Lazy
  93 + private MesQcIndicatorResultService indicatorResultService;
90 94
91 @Override 95 @Override
92 @Transactional(rollbackFor = Exception.class) 96 @Transactional(rollbackFor = Exception.class)
@@ -183,6 +187,8 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -183,6 +187,8 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
183 if (ipqc.getCheckResult() == null) { 187 if (ipqc.getCheckResult() == null) {
184 throw exception(QC_IPQC_CHECK_RESULT_EMPTY); 188 throw exception(QC_IPQC_CHECK_RESULT_EMPTY);
185 } 189 }
  190 + // 1.3 校验至少存在一条检测结果
  191 + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.IPQC.getType());
186 192
187 // 2. 更新状态为已完成 193 // 2. 更新状态为已完成
188 ipqcMapper.updateById(new MesQcIpqcDO() 194 ipqcMapper.updateById(new MesQcIpqcDO()
@@ -276,7 +282,8 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService { @@ -276,7 +282,8 @@ public class MesQcIpqcServiceImpl implements MesQcIpqcService {
276 MesProFeedbackDO feedback = feedbackService.validateFeedbackExists(sourceDocId); 282 MesProFeedbackDO feedback = feedbackService.validateFeedbackExists(sourceDocId);
277 return feedback.getCode(); 283 return feedback.getCode();
278 } 284 }
279 - return null; 285 + // 未知来源类型应报错,而不是静默忽略
  286 + throw exception(QC_IPQC_SOURCE_DOC_TYPE_UNKNOWN);
280 } 287 }
281 288
282 /** 289 /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/iqc/MesQcIqcServiceImpl.java
@@ -18,11 +18,13 @@ import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; @@ -18,11 +18,13 @@ import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
18 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 18 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
19 import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; 19 import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService;
20 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 20 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
  21 +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
21 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; 22 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService;
22 import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; 23 import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService;
23 import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService; 24 import cn.iocoder.yudao.module.mes.service.wm.outsourcereceipt.MesWmOutsourceReceiptService;
24 import cn.iocoder.yudao.module.system.api.user.AdminUserApi; 25 import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
25 import jakarta.annotation.Resource; 26 import jakarta.annotation.Resource;
  27 +import org.springframework.context.annotation.Lazy;
26 import org.springframework.stereotype.Service; 28 import org.springframework.stereotype.Service;
27 import org.springframework.transaction.annotation.Transactional; 29 import org.springframework.transaction.annotation.Transactional;
28 import org.springframework.validation.annotation.Validated; 30 import org.springframework.validation.annotation.Validated;
@@ -65,6 +67,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -65,6 +67,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
65 67
66 @Resource 68 @Resource
67 private AdminUserApi adminUserApi; 69 private AdminUserApi adminUserApi;
  70 + @Resource
  71 + @Lazy
  72 + private MesQcIndicatorResultService indicatorResultService;
68 73
69 @Override 74 @Override
70 @Transactional(rollbackFor = Exception.class) 75 @Transactional(rollbackFor = Exception.class)
@@ -125,6 +130,8 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -125,6 +130,8 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
125 if (iqc.getCheckResult() == null) { 130 if (iqc.getCheckResult() == null) {
126 throw exception(QC_IQC_CHECK_RESULT_EMPTY); 131 throw exception(QC_IQC_CHECK_RESULT_EMPTY);
127 } 132 }
  133 + // 1.2 校验至少存在一条检测结果
  134 + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.IQC.getType());
128 135
129 // 2. 更新状态为已完成 136 // 2. 更新状态为已完成
130 MesQcIqcDO updateObj = new MesQcIqcDO() 137 MesQcIqcDO updateObj = new MesQcIqcDO()
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/oqc/MesQcOqcServiceImpl.java
@@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; @@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
16 import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService; 16 import cn.iocoder.yudao.module.mes.service.md.client.MesMdClientService;
17 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 17 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
18 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 18 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
  19 +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
19 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; 20 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService;
20 import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService; 21 import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesLineService;
21 import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService; 22 import cn.iocoder.yudao.module.mes.service.wm.productsales.MesWmProductSalesService;
@@ -69,6 +70,9 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @@ -69,6 +70,9 @@ public class MesQcOqcServiceImpl implements MesQcOqcService {
69 70
70 @Resource 71 @Resource
71 private AdminUserApi adminUserApi; 72 private AdminUserApi adminUserApi;
  73 + @Resource
  74 + @Lazy
  75 + private MesQcIndicatorResultService indicatorResultService;
72 76
73 @Override 77 @Override
74 @Transactional(rollbackFor = Exception.class) 78 @Transactional(rollbackFor = Exception.class)
@@ -128,6 +132,8 @@ public class MesQcOqcServiceImpl implements MesQcOqcService { @@ -128,6 +132,8 @@ public class MesQcOqcServiceImpl implements MesQcOqcService {
128 if (oqc.getCheckResult() == null) { 132 if (oqc.getCheckResult() == null) {
129 throw exception(QC_OQC_CHECK_RESULT_EMPTY); 133 throw exception(QC_OQC_CHECK_RESULT_EMPTY);
130 } 134 }
  135 + // 1.3 校验至少存在一条检测结果
  136 + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.OQC.getType());
131 137
132 // 2. 更新状态为已完成 138 // 2. 更新状态为已完成
133 MesQcOqcDO updateObj = new MesQcOqcDO() 139 MesQcOqcDO updateObj = new MesQcOqcDO()
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/rqc/MesQcRqcServiceImpl.java
@@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
15 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; 15 import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
16 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; 16 import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
17 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService; 17 import cn.iocoder.yudao.module.mes.service.qc.defectrecord.MesQcDefectRecordService;
  18 +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcIndicatorResultService;
18 import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueService; 19 import cn.iocoder.yudao.module.mes.service.wm.returnissue.MesWmReturnIssueService;
19 import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesService; 20 import cn.iocoder.yudao.module.mes.service.wm.returnsales.MesWmReturnSalesService;
20 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService; 21 import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateItemService;
@@ -68,6 +69,9 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @@ -68,6 +69,9 @@ public class MesQcRqcServiceImpl implements MesQcRqcService {
68 @Resource 69 @Resource
69 @Lazy 70 @Lazy
70 private MesWmReturnSalesService returnSalesService; 71 private MesWmReturnSalesService returnSalesService;
  72 + @Resource
  73 + @Lazy
  74 + private MesQcIndicatorResultService indicatorResultService;
71 75
72 @Resource 76 @Resource
73 private AdminUserApi adminUserApi; 77 private AdminUserApi adminUserApi;
@@ -137,6 +141,8 @@ public class MesQcRqcServiceImpl implements MesQcRqcService { @@ -137,6 +141,8 @@ public class MesQcRqcServiceImpl implements MesQcRqcService {
137 throw exception(QC_RQC_QUANTITY_MISMATCH); 141 throw exception(QC_RQC_QUANTITY_MISMATCH);
138 } 142 }
139 } 143 }
  144 + // 1.4 校验至少存在一条检测结果
  145 + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(id, MesQcTypeEnum.RQC.getType());
140 146
141 // 2. 更新状态为已完成 147 // 2. 更新状态为已完成
142 MesQcRqcDO updateObj = new MesQcRqcDO().setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus()); 148 MesQcRqcDO updateObj = new MesQcRqcDO().setId(id).setStatus(MesQcStatusEnum.FINISHED.getStatus());