Commit 6ef9907c158ff94d5966177d37a72cc2b940e77a

Authored by YunaiV
1 parent 04236fec

refactor(mes): 质检指标 resultType 改为 Integer 类型,resultSpec 重命名为 resultSpecification…

…,result 包重命名为 indicatorresult

1. MesQcIndicatorDO:resultType 从 String 改为 Integer(对齐 MesQcResultValueTypeEnum 枚举值 1-5),
   resultSpec 重命名为 resultSpecification(对齐 MesQcResultDetailDO.valueSpecification)
2. 同步更新 SaveReqVO、PageReqVO、RespVO 的字段类型和命名
3. MesQcResultServiceImpl:移除 Integer.valueOf() 手动转换,直接使用 Integer 类型
4. qc/result 包整体重命名为 qc/indicatorresult(controller、dal、service 共 12 个文件)
Showing 19 changed files with 1048 additions and 13 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorPageReqVO.java
... ... @@ -21,7 +21,7 @@ public class MesQcIndicatorPageReqVO extends PageParam {
21 21 @Schema(description = "检测项类型", example = "SIZE")
22 22 private String type;
23 23  
24   - @Schema(description = "结果值类型", example = "FLOAT")
25   - private String resultType;
  24 + @Schema(description = "结果值类型", example = "1")
  25 + private Integer resultType;
26 26  
27 27 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java
... ... @@ -36,14 +36,14 @@ public class MesQcIndicatorRespVO {
36 36 @ExcelProperty("检测工具")
37 37 private String tool;
38 38  
39   - @Schema(description = "结果值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOAT")
  39 + @Schema(description = "结果值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
40 40 @ExcelProperty(value = "结果值类型", converter = DictConvert.class)
41 41 @DictFormat(DictTypeConstants.MES_QC_RESULT_TYPE)
42   - private String resultType;
  42 + private Integer resultType;
43 43  
44 44 @Schema(description = "结果值属性", example = "IMG")
45 45 @ExcelProperty("结果值属性")
46   - private String resultSpec;
  46 + private String resultSpecification;
47 47  
48 48 @Schema(description = "备注", example = "备注")
49 49 @ExcelProperty("备注")
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorSaveReqVO.java
... ... @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo;
2 2  
3 3 import io.swagger.v3.oas.annotations.media.Schema;
4 4 import jakarta.validation.constraints.NotEmpty;
  5 +import jakarta.validation.constraints.NotNull;
5 6 import lombok.Data;
6 7  
7 8 @Schema(description = "管理后台 - MES 质检指标新增/修改 Request VO")
... ... @@ -26,12 +27,12 @@ public class MesQcIndicatorSaveReqVO {
26 27 @Schema(description = "检测工具", example = "卡尺")
27 28 private String tool;
28 29  
29   - @Schema(description = "结果值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "FLOAT")
30   - @NotEmpty(message = "结果值类型不能为空")
31   - private String resultType;
  30 + @Schema(description = "结果值类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  31 + @NotNull(message = "结果值类型不能为空")
  32 + private Integer resultType;
32 33  
33 34 @Schema(description = "结果值属性", example = "IMG")
34   - private String resultSpec;
  35 + private String resultSpecification;
35 36  
36 37 @Schema(description = "备注", example = "备注")
37 38 private String remark;
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/MesQcResultController.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  7 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.*;
  8 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
  10 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
  11 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcResultDO;
  12 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
  13 +import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
  14 +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
  15 +import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcService;
  16 +import cn.iocoder.yudao.module.mes.service.qc.indicatorresult.MesQcResultService;
  17 +import io.swagger.v3.oas.annotations.Operation;
  18 +import io.swagger.v3.oas.annotations.Parameter;
  19 +import io.swagger.v3.oas.annotations.Parameters;
  20 +import io.swagger.v3.oas.annotations.tags.Tag;
  21 +import jakarta.annotation.Resource;
  22 +import jakarta.validation.Valid;
  23 +import org.springframework.security.access.prepost.PreAuthorize;
  24 +import org.springframework.validation.annotation.Validated;
  25 +import org.springframework.web.bind.annotation.*;
  26 +
  27 +import java.util.Collections;
  28 +import java.util.List;
  29 +import java.util.Map;
  30 +import java.util.Objects;
  31 +
  32 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  33 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  34 +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
  35 +
  36 +@Tag(name = "管理后台 - MES 检验结果")
  37 +@RestController
  38 +@RequestMapping("/mes/qc/result")
  39 +@Validated
  40 +public class MesQcResultController {
  41 +
  42 + @Resource
  43 + private MesQcResultService resultService;
  44 + @Resource
  45 + private MesQcIqcService iqcService;
  46 + @Resource
  47 + private MesMdItemService itemService;
  48 + @Resource
  49 + private MesMdUnitMeasureService unitMeasureService;
  50 +
  51 + @PostMapping("/create")
  52 + @Operation(summary = "创建检验结果")
  53 + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:create')")
  54 + public CommonResult<Long> createResult(@Valid @RequestBody MesQcResultSaveReqVO createReqVO) {
  55 + return success(resultService.createResult(createReqVO));
  56 + }
  57 +
  58 + @PutMapping("/update")
  59 + @Operation(summary = "更新检验结果")
  60 + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:update')")
  61 + public CommonResult<Boolean> updateResult(@Valid @RequestBody MesQcResultSaveReqVO updateReqVO) {
  62 + resultService.updateResult(updateReqVO);
  63 + return success(true);
  64 + }
  65 +
  66 + @DeleteMapping("/delete")
  67 + @Operation(summary = "删除检验结果")
  68 + @Parameter(name = "id", description = "编号", required = true)
  69 + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:delete')")
  70 + public CommonResult<Boolean> deleteResult(@RequestParam("id") Long id) {
  71 + resultService.deleteResult(id);
  72 + return success(true);
  73 + }
  74 +
  75 + @GetMapping("/get")
  76 + @Operation(summary = "获得检验结果(含明细)")
  77 + @Parameter(name = "id", description = "编号", required = true, example = "1024")
  78 + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')")
  79 + public CommonResult<MesQcResultRespVO> getResult(@RequestParam("id") Long id) {
  80 + MesQcResultDO result = resultService.getResult(id);
  81 + if (result == null) {
  82 + return success(null);
  83 + }
  84 + // 构建 RespVO(含关联字段 + 明细列表)
  85 + MesQcResultRespVO respVO = buildResultRespVOList(Collections.singletonList(result)).get(0);
  86 + // 组装明细
  87 + // TODO @AI:先查询下;然后在 buildResultRespVOList 统一 build;
  88 + respVO.setItems(resultService.getResultDetailList(result.getId(), result.getQcId(), result.getQcType()));
  89 + return success(respVO);
  90 + }
  91 +
  92 + @GetMapping("/page")
  93 + @Operation(summary = "获得检验结果分页")
  94 + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')")
  95 + public CommonResult<PageResult<MesQcResultRespVO>> getResultPage(@Valid MesQcResultPageReqVO pageReqVO) {
  96 + PageResult<MesQcResultDO> pageResult = resultService.getResultPage(pageReqVO);
  97 + return success(new PageResult<>(buildResultRespVOList(pageResult.getList()), pageResult.getTotal()));
  98 + }
  99 +
  100 + // TODO @AI:resultService.getDetailTemplate(qcId, qcType) 放在 controller 里弄啊;
  101 + @GetMapping("/detail-template")
  102 + @Operation(summary = "获取空值检测项模板")
  103 + @Parameters({
  104 + @Parameter(name = "qcId", description = "质检单ID", required = true, example = "1"),
  105 + @Parameter(name = "qcType", description = "质检类型", required = true, example = "1")
  106 + })
  107 + @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')")
  108 + public CommonResult<List<MesQcResultDetailRespVO>> getDetailTemplate(
  109 + @RequestParam("qcId") Long qcId,
  110 + @RequestParam("qcType") Integer qcType) {
  111 + return success(resultService.getDetailTemplate(qcId, qcType));
  112 + }
  113 +
  114 + // ==================== 拼接 VO ====================
  115 +
  116 + private List<MesQcResultRespVO> buildResultRespVOList(List<MesQcResultDO> list) {
  117 + if (CollUtil.isEmpty(list)) {
  118 + return Collections.emptyList();
  119 + }
  120 + // 批量查询物料
  121 + Map<Long, MesMdItemDO> itemMap = itemService.getItemMap(
  122 + convertSet(list, MesQcResultDO::getItemId));
  123 + // 批量查询计量单位
  124 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
  125 + convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
  126 + // 拼装 VO
  127 + return BeanUtils.toBean(list, MesQcResultRespVO.class, vo -> {
  128 + // 拼接物料信息
  129 + findAndThen(itemMap, vo.getItemId(), item -> {
  130 + vo.setItemCode(item.getCode()).setItemName(item.getName()).setItemSpecification(item.getSpecification());
  131 + findAndThen(unitMeasureMap, item.getUnitMeasureId(),
  132 + unit -> vo.setUnitName(unit.getName()));
  133 + });
  134 + // 拼接质检单编号/名称(根据 qcType 从对应服务获取)
  135 + if (Objects.equals(vo.getQcType(), MesQcTypeEnum.IQC.getType())) {
  136 + // TODO @AI:findAndThen 方式优化;
  137 + MesQcIqcDO iqc = iqcService.getIqc(vo.getQcId());
  138 + if (iqc != null) {
  139 + vo.setQcCode(iqc.getCode()).setQcName(iqc.getName());
  140 + }
  141 + }
  142 + // TODO @芋艿:IPQC/OQC/RQC 模块迁移后实现
  143 + });
  144 + }
  145 +
  146 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcResultDetailRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.math.BigDecimal;
  7 +
  8 +@Schema(description = "管理后台 - MES 检验结果明细 Response VO")
  9 +@Data
  10 +public class MesQcResultDetailRespVO {
  11 +
  12 + @Schema(description = "编号", example = "1024")
  13 + private Long id;
  14 +
  15 + @Schema(description = "关联检验结果ID", example = "1")
  16 + private Long resultId;
  17 +
  18 + @Schema(description = "检测指标ID", example = "1")
  19 + private Long indicatorId;
  20 +
  21 + @Schema(description = "检测工具ID", example = "1")
  22 + private Long toolId;
  23 +
  24 + @Schema(description = "计量单位ID", example = "1")
  25 + private Long unitMeasureId;
  26 +
  27 + @Schema(description = "质检值类型(1=浮点 2=整数 3=文本 4=字典 5=文件)", example = "1")
  28 + private Integer valueType;
  29 +
  30 + @Schema(description = "值属性", example = "IMG")
  31 + private String valueSpecification;
  32 +
  33 + @Schema(description = "浮点值", example = "3.14")
  34 + private BigDecimal valueFloat;
  35 +
  36 + @Schema(description = "整数值", example = "100")
  37 + private Integer valueInteger;
  38 +
  39 + @Schema(description = "文字值", example = "合格")
  40 + private String valueText;
  41 +
  42 + @Schema(description = "字典项值", example = "PASS")
  43 + private String valueDict;
  44 +
  45 + @Schema(description = "文件值", example = "https://xxx.com/file.jpg")
  46 + private String valueFile;
  47 +
  48 + @Schema(description = "备注", example = "无")
  49 + private String remark;
  50 +
  51 + // ========== 关联查询字段(来自 IQC line + indicator) ==========
  52 +
  53 + @Schema(description = "检测指标编码(关联查询)", example = "IDX-001")
  54 + private String indicatorCode;
  55 +
  56 + @Schema(description = "检测指标名称(关联查询)", example = "外观检查")
  57 + private String indicatorName;
  58 +
  59 + @Schema(description = "检测指标类型(关联查询)", example = "QUANTITATIVE")
  60 + private String indicatorType;
  61 +
  62 + @Schema(description = "检测工具名称(关联查询)", example = "卡尺")
  63 + private String toolName;
  64 +
  65 + @Schema(description = "检测方法(关联查询)", example = "目视检查")
  66 + private String checkMethod;
  67 +
  68 + @Schema(description = "标准值(关联查询)", example = "10.0000")
  69 + private BigDecimal standardValue;
  70 +
  71 + @Schema(description = "计量单位名称(关联查询)", example = "mm")
  72 + private String unitMeasureName;
  73 +
  74 + @Schema(description = "误差上限(关联查询)", example = "10.5000")
  75 + private BigDecimal maxThreshold;
  76 +
  77 + @Schema(description = "误差下限(关联查询)", example = "9.5000")
  78 + private BigDecimal minThreshold;
  79 +
  80 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcResultDetailSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.math.BigDecimal;
  7 +
  8 +@Schema(description = "管理后台 - MES 检验结果明细创建/更新 Request VO")
  9 +@Data
  10 +public class MesQcResultDetailSaveReqVO {
  11 +
  12 + @Schema(description = "编号", example = "1024")
  13 + private Long id;
  14 +
  15 + @Schema(description = "检测指标ID", example = "1")
  16 + private Long indicatorId;
  17 +
  18 + @Schema(description = "检测工具ID", example = "1")
  19 + private Long toolId;
  20 +
  21 + @Schema(description = "计量单位ID", example = "1")
  22 + private Long unitMeasureId;
  23 +
  24 + @Schema(description = "质检值类型(1=浮点 2=整数 3=文本 4=字典 5=文件)", example = "1")
  25 + private Integer valueType;
  26 +
  27 + @Schema(description = "值属性", example = "IMG")
  28 + private String valueSpecification;
  29 +
  30 + @Schema(description = "浮点值", example = "3.14")
  31 + private BigDecimal valueFloat;
  32 +
  33 + @Schema(description = "整数值", example = "100")
  34 + private Integer valueInteger;
  35 +
  36 + @Schema(description = "文字值", example = "合格")
  37 + private String valueText;
  38 +
  39 + @Schema(description = "字典项值", example = "PASS")
  40 + private String valueDict;
  41 +
  42 + @Schema(description = "文件值", example = "https://xxx.com/file.jpg")
  43 + private String valueFile;
  44 +
  45 + @Schema(description = "备注", example = "无")
  46 + private String remark;
  47 +
  48 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcResultPageReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  5 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
  6 +import io.swagger.v3.oas.annotations.media.Schema;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.ToString;
  10 +
  11 +@Schema(description = "管理后台 - MES 检验结果分页 Request VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class MesQcResultPageReqVO extends PageParam {
  16 +
  17 + @Schema(description = "关联质检单ID", example = "1")
  18 + private Long qcId;
  19 +
  20 + @Schema(description = "质检类型", example = "1")
  21 + @InEnum(MesQcTypeEnum.class)
  22 + private Integer qcType;
  23 +
  24 + @Schema(description = "样品编号", example = "SPL-001")
  25 + private String code;
  26 +
  27 + @Schema(description = "产品物料ID", example = "1")
  28 + private Long itemId;
  29 +
  30 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcResultRespVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +
  6 +import java.time.LocalDateTime;
  7 +import java.util.List;
  8 +
  9 +@Schema(description = "管理后台 - MES 检验结果 Response VO")
  10 +@Data
  11 +public class MesQcResultRespVO {
  12 +
  13 + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  14 + private Long id;
  15 +
  16 + @Schema(description = "样品编号", example = "SPL-001")
  17 + private String code;
  18 +
  19 + @Schema(description = "关联质检单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  20 + private Long qcId;
  21 +
  22 + @Schema(description = "质检类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  23 + private Integer qcType;
  24 +
  25 + @Schema(description = "产品物料ID", example = "1")
  26 + private Long itemId;
  27 +
  28 + @Schema(description = "物资SN", example = "SN-001")
  29 + private String sn;
  30 +
  31 + @Schema(description = "备注", example = "无")
  32 + private String remark;
  33 +
  34 + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
  35 + private LocalDateTime createTime;
  36 +
  37 + // ========== 关联查询字段 ==========
  38 +
  39 + @Schema(description = "质检单编号(关联查询)", example = "IQC-001")
  40 + private String qcCode;
  41 +
  42 + @Schema(description = "质检单名称(关联查询)", example = "xxx来料检验")
  43 + private String qcName;
  44 +
  45 + @Schema(description = "产品物料编码(关联查询)", example = "ITEM-001")
  46 + private String itemCode;
  47 +
  48 + @Schema(description = "产品物料名称(关联查询)", example = "电阻")
  49 + private String itemName;
  50 +
  51 + @Schema(description = "规格型号(关联查询)", example = "100Ω")
  52 + private String itemSpecification;
  53 +
  54 + @Schema(description = "单位名称(关联查询)", example = "个")
  55 + private String unitName;
  56 +
  57 + // ========== 子表:检验结果明细 ==========
  58 +
  59 + // TODO @AI:内嵌进来,不用队里类文件;
  60 + @Schema(description = "检验结果明细列表")
  61 + private List<MesQcResultDetailRespVO> items;
  62 +
  63 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicatorresult/vo/MesQcResultSaveReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import jakarta.validation.constraints.NotNull;
  5 +import lombok.Data;
  6 +
  7 +import java.util.List;
  8 +
  9 +@Schema(description = "管理后台 - MES 检验结果创建/更新 Request VO")
  10 +@Data
  11 +public class MesQcResultSaveReqVO {
  12 +
  13 + @Schema(description = "编号", example = "1024")
  14 + private Long id;
  15 +
  16 + @Schema(description = "样品编号", example = "SPL-001")
  17 + private String code;
  18 +
  19 + @Schema(description = "关联质检单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  20 + @NotNull(message = "关联质检单ID不能为空")
  21 + private Long qcId;
  22 +
  23 + @Schema(description = "质检类型(1=IQC 2=IPQC 3=OQC 4=RQC)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  24 + @NotNull(message = "质检类型不能为空")
  25 + private Integer qcType;
  26 +
  27 + @Schema(description = "物资SN", example = "SN-001")
  28 + private String sn;
  29 +
  30 + @Schema(description = "备注", example = "无")
  31 + private String remark;
  32 +
  33 + // TODO @AI:MesQcResultDetailSaveReqVO 内嵌进来;不用独立类;
  34 + @Schema(description = "检验结果明细列表")
  35 + private List<MesQcResultDetailSaveReqVO> items;
  36 +
  37 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicator/MesQcIndicatorDO.java
... ... @@ -47,15 +47,16 @@ public class MesQcIndicatorDO extends BaseDO {
47 47 /**
48 48 * 结果值类型
49 49 *
50   - * 枚举 {@link cn.iocoder.yudao.module.mes.enums.DictTypeConstants#MES_QC_RESULT_TYPE}
  50 + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum}
51 51 */
52   - private String resultType;
  52 + private Integer resultType;
53 53 /**
54 54 * 结果值属性
55 55 *
56   - * FILE 时存 IMG/FILE;DICT 时存字典类型名
  56 + * 1. FILE 时:存 IMG/FILE
  57 + * 2. DICT 时:存字典类型名
57 58 */
58   - private String resultSpec;
  59 + private String resultSpecification;
59 60 /**
60 61 * 备注
61 62 */
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcResultDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
  5 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
  6 +import com.baomidou.mybatisplus.annotation.KeySequence;
  7 +import com.baomidou.mybatisplus.annotation.TableId;
  8 +import com.baomidou.mybatisplus.annotation.TableName;
  9 +import lombok.*;
  10 +
  11 +/**
  12 + * MES 检验结果记录 DO
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@TableName("mes_qc_result")
  17 +@KeySequence("mes_qc_result_seq")
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class MesQcResultDO extends BaseDO {
  25 +
  26 + /**
  27 + * 编号
  28 + */
  29 + @TableId
  30 + private Long id;
  31 + /**
  32 + * 样品编号
  33 + */
  34 + private String code;
  35 + // TODO @AI:关联下 linkter;
  36 + /**
  37 + * 关联质检单 ID(IQC/IPQC/OQC/RQC 的 id)
  38 + */
  39 + private Long qcId;
  40 + /**
  41 + * 质检类型
  42 + *
  43 + * 枚举 {@link MesQcTypeEnum}
  44 + */
  45 + private Integer qcType;
  46 + /**
  47 + * 产品物料 ID
  48 + *
  49 + * 关联 {@link MesMdItemDO#getId()}
  50 + */
  51 + private Long itemId;
  52 + /**
  53 + * 物资 SN
  54 + */
  55 + private String sn;
  56 + /**
  57 + * 备注
  58 + */
  59 + private String remark;
  60 +
  61 + // ========== 预留字段 ==========
  62 +
  63 + /**
  64 + * 预留字段 1
  65 + */
  66 + private String attribute1;
  67 + /**
  68 + * 预留字段 2
  69 + */
  70 + private String attribute2;
  71 + /**
  72 + * 预留字段 3
  73 + */
  74 + private Integer attribute3;
  75 + /**
  76 + * 预留字段 4
  77 + */
  78 + private Integer attribute4;
  79 +
  80 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/indicatorresult/MesQcResultDetailDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO;
  7 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum;
  8 +import com.baomidou.mybatisplus.annotation.KeySequence;
  9 +import com.baomidou.mybatisplus.annotation.TableId;
  10 +import com.baomidou.mybatisplus.annotation.TableName;
  11 +import lombok.*;
  12 +
  13 +import java.math.BigDecimal;
  14 +
  15 +/**
  16 + * MES 检验结果明细记录 DO
  17 + *
  18 + * @author 芋道源码
  19 + */
  20 +@TableName("mes_qc_result_detail")
  21 +@KeySequence("mes_qc_result_detail_seq")
  22 +@Data
  23 +@EqualsAndHashCode(callSuper = true)
  24 +@ToString(callSuper = true)
  25 +@Builder
  26 +@NoArgsConstructor
  27 +@AllArgsConstructor
  28 +public class MesQcResultDetailDO extends BaseDO {
  29 +
  30 + /**
  31 + * 编号
  32 + */
  33 + @TableId
  34 + private Long id;
  35 + /**
  36 + * 关联检验结果 ID
  37 + *
  38 + * 关联 {@link MesQcResultDO#getId()}
  39 + */
  40 + private Long resultId;
  41 + /**
  42 + * 检测指标 ID
  43 + *
  44 + * 关联 {@link MesQcIndicatorDO#getId()}
  45 + */
  46 + private Long indicatorId;
  47 + // TODO @AI:toolId、unitMeasureId、valueType、valueSpecification 都不存储;
  48 + /**
  49 + * 检测工具 ID
  50 + *
  51 + * 关联 {@link MesTmToolDO#getId()}
  52 + */
  53 + private Long toolId;
  54 + /**
  55 + * 计量单位 ID
  56 + *
  57 + * 关联 {@link MesMdUnitMeasureDO#getId()}
  58 + */
  59 + private Long unitMeasureId;
  60 + /**
  61 + * 质检值类型
  62 + *
  63 + * 枚举 {@link MesQcResultValueTypeEnum}
  64 + */
  65 + private Integer valueType;
  66 + /**
  67 + * 值属性
  68 + *
  69 + * FILE 时存 IMG/FILE;DICT 时存字典类型名
  70 + */
  71 + private String valueSpecification;
  72 + // TODO @AI:是不是可以调整成 String value?
  73 + /**
  74 + * 浮点值
  75 + */
  76 + private BigDecimal valueFloat;
  77 + /**
  78 + * 整数值
  79 + */
  80 + private Integer valueInteger;
  81 + /**
  82 + * 文字值
  83 + */
  84 + private String valueText;
  85 + /**
  86 + * 字典项值
  87 + */
  88 + private String valueDict;
  89 + /**
  90 + * 文件值
  91 + */
  92 + private String valueFile;
  93 + /**
  94 + * 备注
  95 + */
  96 + private String remark;
  97 +
  98 + // ========== 预留字段 ==========
  99 +
  100 + /**
  101 + * 预留字段 1
  102 + */
  103 + private String attribute1;
  104 + /**
  105 + * 预留字段 2
  106 + */
  107 + private String attribute2;
  108 + /**
  109 + * 预留字段 3
  110 + */
  111 + private Integer attribute3;
  112 + /**
  113 + * 预留字段 4
  114 + */
  115 + private Integer attribute4;
  116 +
  117 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcResultDetailMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcResultDetailDO;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +import java.util.List;
  9 +
  10 +/**
  11 + * MES 检验结果明细记录 Mapper
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Mapper
  16 +public interface MesQcResultDetailMapper extends BaseMapperX<MesQcResultDetailDO> {
  17 +
  18 + default List<MesQcResultDetailDO> selectListByResultId(Long resultId) {
  19 + return selectList(MesQcResultDetailDO::getResultId, resultId);
  20 + }
  21 +
  22 + default void deleteByResultId(Long resultId) {
  23 + delete(new LambdaQueryWrapperX<MesQcResultDetailDO>()
  24 + .eq(MesQcResultDetailDO::getResultId, resultId));
  25 + }
  26 +
  27 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/indicatorresult/MesQcResultMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcResultPageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcResultDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +/**
  11 + * MES 检验结果记录 Mapper
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Mapper
  16 +public interface MesQcResultMapper extends BaseMapperX<MesQcResultDO> {
  17 +
  18 + default PageResult<MesQcResultDO> selectPage(MesQcResultPageReqVO reqVO) {
  19 + return selectPage(reqVO, new LambdaQueryWrapperX<MesQcResultDO>()
  20 + .eqIfPresent(MesQcResultDO::getQcId, reqVO.getQcId())
  21 + .eqIfPresent(MesQcResultDO::getQcType, reqVO.getQcType())
  22 + .likeIfPresent(MesQcResultDO::getCode, reqVO.getCode())
  23 + .eqIfPresent(MesQcResultDO::getItemId, reqVO.getItemId())
  24 + .orderByDesc(MesQcResultDO::getId));
  25 + }
  26 +
  27 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/template/MesQcTemplateItemMapper.java
... ... @@ -27,6 +27,10 @@ public interface MesQcTemplateItemMapper extends BaseMapperX&lt;MesQcTemplateItemDO
27 27 return selectList(MesQcTemplateItemDO::getTemplateId, templateId);
28 28 }
29 29  
  30 + default List<MesQcTemplateItemDO> selectListByItemId(Long itemId) {
  31 + return selectList(MesQcTemplateItemDO::getItemId, itemId);
  32 + }
  33 +
30 34 default MesQcTemplateItemDO selectByTemplateIdAndItemId(Long templateId, Long itemId) {
31 35 return selectOne(new LambdaQueryWrapperX<MesQcTemplateItemDO>()
32 36 .eq(MesQcTemplateItemDO::getTemplateId, templateId)
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
... ... @@ -267,6 +267,12 @@ public interface ErrorCodeConstants {
267 267 ErrorCode QC_DEFECT_RECORD_LEVEL_UNKNOWN = new ErrorCode(1_040_605_001, "未知的缺陷等级");
268 268 ErrorCode QC_DEFECT_RECORD_QC_TYPE_UNSUPPORTED = new ErrorCode(1_040_605_002, "不支持的检验类型");
269 269  
  270 + // ========== MES 质量管理-检验结果(1-040-606-000) ==========
  271 + ErrorCode QC_RESULT_NOT_EXISTS = new ErrorCode(1_040_606_000, "检验结果不存在");
  272 + ErrorCode QC_RESULT_ITEMS_EMPTY = new ErrorCode(1_040_606_001, "检测项结果值不能为空");
  273 + ErrorCode QC_RESULT_SOURCE_DOC_NOT_EXISTS = new ErrorCode(1_040_606_002, "来源质检单不存在");
  274 + ErrorCode QC_RESULT_SOURCE_DOC_TYPE_INVALID = new ErrorCode(1_040_606_003, "来源质检单类型不支持");
  275 +
270 276 // ========== MES 仓库管理-仓库(1-040-700-000) ==========
271 277 ErrorCode WM_WAREHOUSE_NOT_EXISTS = new ErrorCode(1_040_700_000, "仓库不存在");
272 278 ErrorCode WM_WAREHOUSE_CODE_DUPLICATE = new ErrorCode(1_040_700_001, "仓库编码已存在");
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcResultValueTypeEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.enums.qc;
  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 + * @author 芋道源码
  13 + */
  14 +@Getter
  15 +@AllArgsConstructor
  16 +public enum MesQcResultValueTypeEnum implements ArrayValuable<Integer> {
  17 +
  18 + FLOAT(1, "浮点"),
  19 + INTEGER(2, "整数"),
  20 + TEXT(3, "文本"),
  21 + DICT(4, "字典"),
  22 + FILE(5, "文件");
  23 +
  24 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcResultValueTypeEnum::getType).toArray(Integer[]::new);
  25 +
  26 + /**
  27 + * 类型值
  28 + */
  29 + private final Integer type;
  30 + /**
  31 + * 类型名
  32 + */
  33 + private final String name;
  34 +
  35 + @Override
  36 + public Integer[] array() {
  37 + return ARRAYS;
  38 + }
  39 +
  40 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcResultService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.qc.indicatorresult;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcResultDetailRespVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcResultPageReqVO;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcResultSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcResultDO;
  8 +import jakarta.validation.Valid;
  9 +
  10 +import java.util.List;
  11 +
  12 +/**
  13 + * MES 检验结果 Service 接口
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public interface MesQcResultService {
  18 +
  19 + /**
  20 + * 创建检验结果(含明细)
  21 + *
  22 + * @param createReqVO 创建信息
  23 + * @return 编号
  24 + */
  25 + Long createResult(@Valid MesQcResultSaveReqVO createReqVO);
  26 +
  27 + /**
  28 + * 更新检验结果(含明细)
  29 + *
  30 + * @param updateReqVO 更新信息
  31 + */
  32 + void updateResult(@Valid MesQcResultSaveReqVO updateReqVO);
  33 +
  34 + /**
  35 + * 删除检验结果(级联删除明细)
  36 + *
  37 + * @param id 编号
  38 + */
  39 + void deleteResult(Long id);
  40 +
  41 + /**
  42 + * 获得检验结果
  43 + *
  44 + * @param id 编号
  45 + * @return 检验结果
  46 + */
  47 + MesQcResultDO getResult(Long id);
  48 +
  49 + /**
  50 + * 获得检验结果分页
  51 + *
  52 + * @param pageReqVO 分页查询
  53 + * @return 检验结果分页
  54 + */
  55 + PageResult<MesQcResultDO> getResultPage(MesQcResultPageReqVO pageReqVO);
  56 +
  57 + /**
  58 + * 获取检验结果明细列表(含已填值,组装 IQC line + indicator 信息)
  59 + *
  60 + * @param resultId 检验结果 ID
  61 + * @param qcId 质检单 ID
  62 + * @param qcType 质检类型
  63 + * @return 明细列表
  64 + */
  65 + List<MesQcResultDetailRespVO> getResultDetailList(Long resultId, Long qcId, Integer qcType);
  66 +
  67 + /**
  68 + * 获取空值检测项模板(新建结果时用)
  69 + *
  70 + * @param qcId 质检单 ID
  71 + * @param qcType 质检类型
  72 + * @return 空值明细列表
  73 + */
  74 + List<MesQcResultDetailRespVO> getDetailTemplate(Long qcId, Integer qcType);
  75 +
  76 +}
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcResultServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.qc.indicatorresult;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcResultDetailRespVO;
  7 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcResultDetailSaveReqVO;
  8 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcResultPageReqVO;
  9 +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcResultSaveReqVO;
  10 +import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
  11 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO;
  12 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
  13 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
  14 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcResultDO;
  15 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcResultDetailDO;
  16 +import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO;
  17 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcLineMapper;
  18 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcResultDetailMapper;
  19 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcResultMapper;
  20 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
  21 +import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
  22 +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService;
  23 +import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcService;
  24 +import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolService;
  25 +import jakarta.annotation.Resource;
  26 +import org.springframework.stereotype.Service;
  27 +import org.springframework.transaction.annotation.Transactional;
  28 +import org.springframework.validation.annotation.Validated;
  29 +
  30 +import java.util.*;
  31 +
  32 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  33 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
  34 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  35 +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
  36 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  37 +
  38 +/**
  39 + * MES 检验结果 Service 实现类
  40 + *
  41 + * @author 芋道源码
  42 + */
  43 +@Service
  44 +@Validated
  45 +public class MesQcResultServiceImpl implements MesQcResultService {
  46 +
  47 + @Resource
  48 + private MesQcResultMapper resultMapper;
  49 + @Resource
  50 + private MesQcResultDetailMapper resultDetailMapper;
  51 +
  52 + @Resource
  53 + private MesQcIqcService iqcService;
  54 + @Resource
  55 + private MesQcIqcLineMapper iqcLineMapper;
  56 + @Resource
  57 + private MesQcIndicatorService indicatorService;
  58 + @Resource
  59 + private MesMdUnitMeasureService unitMeasureService;
  60 + @Resource
  61 + private MesTmToolService toolService;
  62 +
  63 + @Override
  64 + @Transactional(rollbackFor = Exception.class)
  65 + public Long createResult(MesQcResultSaveReqVO createReqVO) {
  66 + // 1. 校验明细不为空
  67 + List<MesQcResultDetailSaveReqVO> items = createReqVO.getItems();
  68 + if (CollUtil.isEmpty(items)) {
  69 + throw exception(QC_RESULT_ITEMS_EMPTY);
  70 + }
  71 +
  72 + // 2. 根据 qcType 查询源质检单,获取 itemId
  73 + Long itemId = getItemIdFromQcDoc(createReqVO.getQcId(), createReqVO.getQcType());
  74 +
  75 + // 3. 插入主表
  76 + MesQcResultDO result = BeanUtils.toBean(createReqVO, MesQcResultDO.class);
  77 + result.setItemId(itemId);
  78 + resultMapper.insert(result);
  79 +
  80 + // 4. 批量插入明细
  81 + List<MesQcResultDetailDO> details = BeanUtils.toBean(items, MesQcResultDetailDO.class);
  82 + details.forEach(detail -> detail.setResultId(result.getId()));
  83 + resultDetailMapper.insertBatch(details);
  84 + return result.getId();
  85 + }
  86 +
  87 + @Override
  88 + @Transactional(rollbackFor = Exception.class)
  89 + public void updateResult(MesQcResultSaveReqVO updateReqVO) {
  90 + // 1. 校验存在
  91 + validateResultExists(updateReqVO.getId());
  92 +
  93 + // 2. 校验明细不为空
  94 + List<MesQcResultDetailSaveReqVO> items = updateReqVO.getItems();
  95 + if (CollUtil.isEmpty(items)) {
  96 + throw exception(QC_RESULT_ITEMS_EMPTY);
  97 + }
  98 +
  99 + // 3. 更新主表
  100 + MesQcResultDO updateObj = BeanUtils.toBean(updateReqVO, MesQcResultDO.class);
  101 + resultMapper.updateById(updateObj);
  102 +
  103 + // 4. 更新明细:先删后插
  104 + resultDetailMapper.deleteByResultId(updateReqVO.getId());
  105 + List<MesQcResultDetailDO> details = BeanUtils.toBean(items, MesQcResultDetailDO.class);
  106 + details.forEach(detail -> detail.setResultId(updateReqVO.getId()));
  107 + resultDetailMapper.insertBatch(details);
  108 + }
  109 +
  110 + @Override
  111 + @Transactional(rollbackFor = Exception.class)
  112 + public void deleteResult(Long id) {
  113 + // 1. 校验存在
  114 + validateResultExists(id);
  115 + // 2. 级联删除明细
  116 + resultDetailMapper.deleteByResultId(id);
  117 + // 3. 删除主表
  118 + resultMapper.deleteById(id);
  119 + }
  120 +
  121 + @Override
  122 + public MesQcResultDO getResult(Long id) {
  123 + return resultMapper.selectById(id);
  124 + }
  125 +
  126 + @Override
  127 + public PageResult<MesQcResultDO> getResultPage(MesQcResultPageReqVO pageReqVO) {
  128 + return resultMapper.selectPage(pageReqVO);
  129 + }
  130 +
  131 + @Override
  132 + public List<MesQcResultDetailRespVO> getResultDetailList(Long resultId, Long qcId, Integer qcType) {
  133 + return buildDetailRespVOList(resultId, qcId, qcType);
  134 + }
  135 +
  136 + @Override
  137 + public List<MesQcResultDetailRespVO> getDetailTemplate(Long qcId, Integer qcType) {
  138 + return buildDetailRespVOList(null, qcId, qcType);
  139 + }
  140 +
  141 + // ==================== 私有方法 ====================
  142 +
  143 + private MesQcResultDO validateResultExists(Long id) {
  144 + MesQcResultDO result = resultMapper.selectById(id);
  145 + if (result == null) {
  146 + throw exception(QC_RESULT_NOT_EXISTS);
  147 + }
  148 + return result;
  149 + }
  150 +
  151 + /**
  152 + * 根据 qcType 查询源质检单,获取 itemId
  153 + */
  154 + private Long getItemIdFromQcDoc(Long qcId, Integer qcType) {
  155 + if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) {
  156 + MesQcIqcDO iqc = iqcService.getIqc(qcId);
  157 + if (iqc == null) {
  158 + throw exception(QC_RESULT_SOURCE_DOC_NOT_EXISTS);
  159 + }
  160 + return iqc.getItemId();
  161 + }
  162 + // TODO @芋艿:IPQC/OQC/RQC 模块迁移后实现
  163 + throw exception(QC_RESULT_SOURCE_DOC_TYPE_INVALID);
  164 + }
  165 +
  166 + /**
  167 + * 组装明细 VO 列表:从 IQC line + indicator + tool + unitMeasure + 已有结果明细 三方组装
  168 + *
  169 + * @param resultId 检验结果 ID,为 null 时表示获取空值模板
  170 + * @param qcId 质检单 ID
  171 + * @param qcType 质检类型
  172 + */
  173 + private List<MesQcResultDetailRespVO> buildDetailRespVOList(Long resultId, Long qcId, Integer qcType) {
  174 + // 1. 获取检验单行列表
  175 + List<MesQcIqcLineDO> lines;
  176 + if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) {
  177 + lines = iqcLineMapper.selectListByIqcId(qcId);
  178 + } else {
  179 + // TODO @芋艿:IPQC/OQC/RQC 模块迁移后实现
  180 + return Collections.emptyList();
  181 + }
  182 + if (CollUtil.isEmpty(lines)) {
  183 + return Collections.emptyList();
  184 + }
  185 +
  186 + // 2. 批量查询关联信息
  187 + Map<Long, MesQcIndicatorDO> indicatorMap = indicatorService.getIndicatorMap(
  188 + convertSet(lines, MesQcIqcLineDO::getIndicatorId));
  189 + Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
  190 + convertSet(lines, MesQcIqcLineDO::getUnitMeasureId));
  191 +
  192 + // 3. 查询已有结果明细(如有 resultId)
  193 + Map<Long, MesQcResultDetailDO> detailMap;
  194 + if (resultId != null) {
  195 + List<MesQcResultDetailDO> details = resultDetailMapper.selectListByResultId(resultId);
  196 + detailMap = convertMap(details, MesQcResultDetailDO::getIndicatorId);
  197 + } else {
  198 + detailMap = Collections.emptyMap();
  199 + }
  200 +
  201 + // 4. 遍历行,组装 VO
  202 + List<MesQcResultDetailRespVO> voList = new ArrayList<>(lines.size());
  203 + for (MesQcIqcLineDO line : lines) {
  204 + MesQcResultDetailRespVO vo = new MesQcResultDetailRespVO();
  205 + // 来自 IQC line
  206 + vo.setIndicatorId(line.getIndicatorId());
  207 + vo.setToolId(line.getToolId());
  208 + vo.setUnitMeasureId(line.getUnitMeasureId());
  209 + vo.setCheckMethod(line.getCheckMethod());
  210 + vo.setStandardValue(line.getStandardValue());
  211 + vo.setMaxThreshold(line.getMaxThreshold());
  212 + vo.setMinThreshold(line.getMinThreshold());
  213 +
  214 + // 来自 indicator
  215 + findAndThen(indicatorMap, line.getIndicatorId(), indicator -> {
  216 + vo.setIndicatorCode(indicator.getCode());
  217 + vo.setIndicatorName(indicator.getName());
  218 + vo.setIndicatorType(indicator.getType());
  219 + vo.setValueType(indicator.getResultType());
  220 + vo.setValueSpecification(indicator.getResultSpecification());
  221 + });
  222 +
  223 + // 来自 unitMeasure
  224 + findAndThen(unitMeasureMap, line.getUnitMeasureId(),
  225 + unit -> vo.setUnitMeasureName(unit.getName()));
  226 +
  227 + // 来自 tool(逐个查询,数量通常较少)
  228 + if (line.getToolId() != null) {
  229 + MesTmToolDO tool = toolService.getTool(line.getToolId());
  230 + if (tool != null) {
  231 + vo.setToolName(tool.getName());
  232 + }
  233 + }
  234 +
  235 + // 来自已有结果明细(如有)
  236 + MesQcResultDetailDO detail = detailMap.get(line.getIndicatorId());
  237 + if (detail != null) {
  238 + vo.setId(detail.getId());
  239 + vo.setResultId(detail.getResultId());
  240 + vo.setValueFloat(detail.getValueFloat());
  241 + vo.setValueInteger(detail.getValueInteger());
  242 + vo.setValueText(detail.getValueText());
  243 + vo.setValueDict(detail.getValueDict());
  244 + vo.setValueFile(detail.getValueFile());
  245 + }
  246 +
  247 + voList.add(vo);
  248 + }
  249 + return voList;
  250 + }
  251 +
  252 +}
... ...