Commit f74a063d441534d7f9dd308aae7048551a33ef78

Authored by YunaiV
1 parent 94b808d7

feat(mes):通过枚举和用户关联来重构缺陷处理流程,并增强内部质量控制功能

Showing 21 changed files with 628 additions and 313 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcController.java
@@ -18,6 +18,8 @@ import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; @@ -18,6 +18,8 @@ import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
18 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; 18 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
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.lqc.MesQcIqcService; 20 import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcService;
  21 +import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
  22 +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
21 import io.swagger.v3.oas.annotations.Operation; 23 import io.swagger.v3.oas.annotations.Operation;
22 import io.swagger.v3.oas.annotations.Parameter; 24 import io.swagger.v3.oas.annotations.Parameter;
23 import io.swagger.v3.oas.annotations.tags.Tag; 25 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -53,6 +55,9 @@ public class MesQcIqcController { @@ -53,6 +55,9 @@ public class MesQcIqcController {
53 @Resource 55 @Resource
54 private MesMdUnitMeasureService unitMeasureService; 56 private MesMdUnitMeasureService unitMeasureService;
55 57
  58 + @Resource
  59 + private AdminUserApi adminUserApi;
  60 +
56 @PostMapping("/create") 61 @PostMapping("/create")
57 @Operation(summary = "创建来料检验单") 62 @Operation(summary = "创建来料检验单")
58 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:create')") 63 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:create')")
@@ -130,6 +135,9 @@ public class MesQcIqcController { @@ -130,6 +135,9 @@ public class MesQcIqcController {
130 // 批量查询计量单位(通过物料的 unitMeasureId) 135 // 批量查询计量单位(通过物料的 unitMeasureId)
131 Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap( 136 Map<Long, MesMdUnitMeasureDO> unitMeasureMap = unitMeasureService.getUnitMeasureMap(
132 convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId)); 137 convertSet(itemMap.values(), MesMdItemDO::getUnitMeasureId));
  138 + // 批量查询检测人员
  139 + Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
  140 + convertSet(list, MesQcIqcDO::getInspectorUserId));
133 // 拼装 VO 141 // 拼装 VO
134 return BeanUtils.toBean(list, MesQcIqcRespVO.class, vo -> { 142 return BeanUtils.toBean(list, MesQcIqcRespVO.class, vo -> {
135 findAndThen(vendorMap, vo.getVendorId(), 143 findAndThen(vendorMap, vo.getVendorId(),
@@ -141,6 +149,8 @@ public class MesQcIqcController { @@ -141,6 +149,8 @@ public class MesQcIqcController {
141 findAndThen(unitMeasureMap, item.getUnitMeasureId(), 149 findAndThen(unitMeasureMap, item.getUnitMeasureId(),
142 unit -> vo.setUnitName(unit.getName())); 150 unit -> vo.setUnitName(unit.getName()));
143 }); 151 });
  152 + findAndThen(userMap, vo.getInspectorUserId(),
  153 + user -> vo.setInspectorNickname(user.getNickname()));
144 }); 154 });
145 } 155 }
146 156
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcDefectController.java
@@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDef @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDef
7 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectRespVO; 7 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectRespVO;
8 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectSaveReqVO; 8 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectSaveReqVO;
9 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDefectDO; 9 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDefectDO;
10 -import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcService; 10 +import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcDefectService;
11 import io.swagger.v3.oas.annotations.Operation; 11 import io.swagger.v3.oas.annotations.Operation;
12 import io.swagger.v3.oas.annotations.Parameter; 12 import io.swagger.v3.oas.annotations.Parameter;
13 import io.swagger.v3.oas.annotations.tags.Tag; 13 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -26,20 +26,20 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -26,20 +26,20 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
26 public class MesQcIqcDefectController { 26 public class MesQcIqcDefectController {
27 27
28 @Resource 28 @Resource
29 - private MesQcIqcService iqcService; 29 + private MesQcIqcDefectService iqcDefectService;
30 30
31 @PostMapping("/create") 31 @PostMapping("/create")
32 @Operation(summary = "创建来料检验缺陷记录") 32 @Operation(summary = "创建来料检验缺陷记录")
33 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:create')") 33 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:create')")
34 public CommonResult<Long> createIqcDefect(@Valid @RequestBody MesQcIqcDefectSaveReqVO createReqVO) { 34 public CommonResult<Long> createIqcDefect(@Valid @RequestBody MesQcIqcDefectSaveReqVO createReqVO) {
35 - return success(iqcService.createIqcDefect(createReqVO)); 35 + return success(iqcDefectService.createIqcDefect(createReqVO));
36 } 36 }
37 37
38 @PutMapping("/update") 38 @PutMapping("/update")
39 @Operation(summary = "更新来料检验缺陷记录") 39 @Operation(summary = "更新来料检验缺陷记录")
40 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:update')") 40 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:update')")
41 public CommonResult<Boolean> updateIqcDefect(@Valid @RequestBody MesQcIqcDefectSaveReqVO updateReqVO) { 41 public CommonResult<Boolean> updateIqcDefect(@Valid @RequestBody MesQcIqcDefectSaveReqVO updateReqVO) {
42 - iqcService.updateIqcDefect(updateReqVO); 42 + iqcDefectService.updateIqcDefect(updateReqVO);
43 return success(true); 43 return success(true);
44 } 44 }
45 45
@@ -48,7 +48,7 @@ public class MesQcIqcDefectController { @@ -48,7 +48,7 @@ public class MesQcIqcDefectController {
48 @Parameter(name = "id", description = "编号", required = true) 48 @Parameter(name = "id", description = "编号", required = true)
49 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:update')") 49 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:update')")
50 public CommonResult<Boolean> deleteIqcDefect(@RequestParam("id") Long id) { 50 public CommonResult<Boolean> deleteIqcDefect(@RequestParam("id") Long id) {
51 - iqcService.deleteIqcDefect(id); 51 + iqcDefectService.deleteIqcDefect(id);
52 return success(true); 52 return success(true);
53 } 53 }
54 54
@@ -56,7 +56,7 @@ public class MesQcIqcDefectController { @@ -56,7 +56,7 @@ public class MesQcIqcDefectController {
56 @Operation(summary = "获得来料检验缺陷记录分页") 56 @Operation(summary = "获得来料检验缺陷记录分页")
57 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") 57 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')")
58 public CommonResult<PageResult<MesQcIqcDefectRespVO>> getIqcDefectPage(@Valid MesQcIqcDefectPageReqVO pageReqVO) { 58 public CommonResult<PageResult<MesQcIqcDefectRespVO>> getIqcDefectPage(@Valid MesQcIqcDefectPageReqVO pageReqVO) {
59 - PageResult<MesQcIqcDefectDO> pageResult = iqcService.getIqcDefectPage(pageReqVO); 59 + PageResult<MesQcIqcDefectDO> pageResult = iqcDefectService.getIqcDefectPage(pageReqVO);
60 return success(BeanUtils.toBean(pageResult, MesQcIqcDefectRespVO.class)); 60 return success(BeanUtils.toBean(pageResult, MesQcIqcDefectRespVO.class));
61 } 61 }
62 62
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/MesQcIqcLineController.java
@@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO; @@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
11 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; 11 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO;
12 import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO; 12 import cn.iocoder.yudao.module.mes.dal.dataobject.tm.tool.MesTmToolDO;
13 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService; 13 import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
14 -import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcService; 14 +import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcLineService;
15 import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; 15 import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService;
16 import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolService; 16 import cn.iocoder.yudao.module.mes.service.tm.tool.MesTmToolService;
17 import io.swagger.v3.oas.annotations.Operation; 17 import io.swagger.v3.oas.annotations.Operation;
@@ -41,7 +41,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd @@ -41,7 +41,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAnd
41 public class MesQcIqcLineController { 41 public class MesQcIqcLineController {
42 42
43 @Resource 43 @Resource
44 - private MesQcIqcService iqcService; 44 + private MesQcIqcLineService iqcLineService;
45 @Resource 45 @Resource
46 private MesQcIndicatorService indicatorService; 46 private MesQcIndicatorService indicatorService;
47 @Resource 47 @Resource
@@ -54,7 +54,7 @@ public class MesQcIqcLineController { @@ -54,7 +54,7 @@ public class MesQcIqcLineController {
54 @Parameter(name = "id", description = "编号", required = true, example = "1024") 54 @Parameter(name = "id", description = "编号", required = true, example = "1024")
55 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") 55 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')")
56 public CommonResult<MesQcIqcLineRespVO> getIqcLine(@RequestParam("id") Long id) { 56 public CommonResult<MesQcIqcLineRespVO> getIqcLine(@RequestParam("id") Long id) {
57 - MesQcIqcLineDO line = iqcService.getIqcLine(id); 57 + MesQcIqcLineDO line = iqcLineService.getIqcLine(id);
58 return success(buildLineRespVOList(Collections.singletonList(line)).get(0)); 58 return success(buildLineRespVOList(Collections.singletonList(line)).get(0));
59 } 59 }
60 60
@@ -62,7 +62,7 @@ public class MesQcIqcLineController { @@ -62,7 +62,7 @@ public class MesQcIqcLineController {
62 @Operation(summary = "获得来料检验单行分页") 62 @Operation(summary = "获得来料检验单行分页")
63 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')") 63 @PreAuthorize("@ss.hasPermission('mes:qc-iqc:query')")
64 public CommonResult<PageResult<MesQcIqcLineRespVO>> getIqcLinePage(@Valid MesQcIqcLinePageReqVO pageReqVO) { 64 public CommonResult<PageResult<MesQcIqcLineRespVO>> getIqcLinePage(@Valid MesQcIqcLinePageReqVO pageReqVO) {
65 - PageResult<MesQcIqcLineDO> pageResult = iqcService.getIqcLinePage(pageReqVO); 65 + PageResult<MesQcIqcLineDO> pageResult = iqcLineService.getIqcLinePage(pageReqVO);
66 return success(new PageResult<>(buildLineRespVOList(pageResult.getList()), pageResult.getTotal())); 66 return success(new PageResult<>(buildLineRespVOList(pageResult.getList()), pageResult.getTotal()));
67 } 67 }
68 68
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcPageReqVO.java
@@ -29,12 +29,15 @@ public class MesQcIqcPageReqVO extends PageParam { @@ -29,12 +29,15 @@ public class MesQcIqcPageReqVO extends PageParam {
29 @Schema(description = "产品物料 ID", example = "20") 29 @Schema(description = "产品物料 ID", example = "20")
30 private Long itemId; 30 private Long itemId;
31 31
32 - @Schema(description = "检测结果", example = "PASS")  
33 - private String checkResult; 32 + @Schema(description = "检测结果", example = "1")
  33 + private Integer checkResult;
34 34
35 @Schema(description = "状态", example = "0") 35 @Schema(description = "状态", example = "0")
36 private Integer status; 36 private Integer status;
37 37
  38 + @Schema(description = "检测人员用户 ID", example = "1")
  39 + private Long inspectorUserId;
  40 +
38 @Schema(description = "来料日期") 41 @Schema(description = "来料日期")
39 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) 42 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
40 private LocalDateTime[] receiveDate; 43 private LocalDateTime[] receiveDate;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java
@@ -119,9 +119,9 @@ public class MesQcIqcRespVO { @@ -119,9 +119,9 @@ public class MesQcIqcRespVO {
119 119
120 // ========== 检验 ========== 120 // ========== 检验 ==========
121 121
122 - @Schema(description = "检测结果", example = "PASS") 122 + @Schema(description = "检测结果", example = "1")
123 @ExcelProperty("检测结果") 123 @ExcelProperty("检测结果")
124 - private String checkResult; 124 + private Integer checkResult;
125 125
126 @Schema(description = "来料日期") 126 @Schema(description = "来料日期")
127 @ExcelProperty("来料日期") 127 @ExcelProperty("来料日期")
@@ -131,9 +131,12 @@ public class MesQcIqcRespVO { @@ -131,9 +131,12 @@ public class MesQcIqcRespVO {
131 @ExcelProperty("检测日期") 131 @ExcelProperty("检测日期")
132 private LocalDateTime inspectDate; 132 private LocalDateTime inspectDate;
133 133
134 - @Schema(description = "检测人员", example = "张三") 134 + @Schema(description = "检测人员用户 ID", example = "1")
  135 + private Long inspectorUserId;
  136 +
  137 + @Schema(description = "检测人员昵称", example = "张三")
135 @ExcelProperty("检测人员") 138 @ExcelProperty("检测人员")
136 - private String inspector; 139 + private String inspectorNickname;
137 140
138 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") 141 @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
139 @ExcelProperty("状态") 142 @ExcelProperty("状态")
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcSaveReqVO.java
@@ -79,8 +79,8 @@ public class MesQcIqcSaveReqVO { @@ -79,8 +79,8 @@ public class MesQcIqcSaveReqVO {
79 79
80 // ========== 检验 ========== 80 // ========== 检验 ==========
81 81
82 - @Schema(description = "检测结果", example = "PASS")  
83 - private String checkResult; 82 + @Schema(description = "检测结果", example = "1")
  83 + private Integer checkResult;
84 84
85 @Schema(description = "来料日期") 85 @Schema(description = "来料日期")
86 private LocalDateTime receiveDate; 86 private LocalDateTime receiveDate;
@@ -88,8 +88,8 @@ public class MesQcIqcSaveReqVO { @@ -88,8 +88,8 @@ public class MesQcIqcSaveReqVO {
88 @Schema(description = "检测日期") 88 @Schema(description = "检测日期")
89 private LocalDateTime inspectDate; 89 private LocalDateTime inspectDate;
90 90
91 - @Schema(description = "检测人员", example = "张三")  
92 - private String inspector; 91 + @Schema(description = "检测人员用户 ID", example = "1")
  92 + private Long inspectorUserId;
93 93
94 @Schema(description = "备注", example = "备注") 94 @Schema(description = "备注", example = "备注")
95 private String remark; 95 private String remark;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/defect/MesQcIqcDefectRespVO.java
@@ -21,8 +21,8 @@ public class MesQcIqcDefectRespVO { @@ -21,8 +21,8 @@ public class MesQcIqcDefectRespVO {
21 @Schema(description = "缺陷描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "表面划伤") 21 @Schema(description = "缺陷描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "表面划伤")
22 private String defectName; 22 private String defectName;
23 23
24 - @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "CRITICAL")  
25 - private String defectLevel; 24 + @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  25 + private Integer defectLevel;
26 26
27 @Schema(description = "缺陷数量", example = "1") 27 @Schema(description = "缺陷数量", example = "1")
28 private Integer defectQuantity; 28 private Integer defectQuantity;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/defect/MesQcIqcDefectSaveReqVO.java
@@ -24,9 +24,9 @@ public class MesQcIqcDefectSaveReqVO { @@ -24,9 +24,9 @@ public class MesQcIqcDefectSaveReqVO {
24 @NotEmpty(message = "缺陷描述不能为空") 24 @NotEmpty(message = "缺陷描述不能为空")
25 private String defectName; 25 private String defectName;
26 26
27 - @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "CRITICAL")  
28 - @NotEmpty(message = "缺陷等级不能为空")  
29 - private String defectLevel; 27 + @Schema(description = "缺陷等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  28 + @NotNull(message = "缺陷等级不能为空")
  29 + private Integer defectLevel;
30 30
31 @Schema(description = "缺陷数量", example = "1") 31 @Schema(description = "缺陷数量", example = "1")
32 private Integer defectQuantity; 32 private Integer defectQuantity;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/lqc/MesQcIqcDO.java
@@ -12,9 +12,8 @@ import lombok.*; @@ -12,9 +12,8 @@ import lombok.*;
12 import java.math.BigDecimal; 12 import java.math.BigDecimal;
13 import java.time.LocalDateTime; 13 import java.time.LocalDateTime;
14 14
15 -// TODO @AI:IQC 完整的拼写,也加下;  
16 /** 15 /**
17 - * MES 来料检验单(IQC) DO 16 + * MES 来料检验单(IQC, Incoming Quality Control) DO
18 * 17 *
19 * @author 芋道源码 18 * @author 芋道源码
20 */ 19 */
@@ -147,13 +146,12 @@ public class MesQcIqcDO extends BaseDO { @@ -147,13 +146,12 @@ public class MesQcIqcDO extends BaseDO {
147 146
148 // ========== 检验 ========== 147 // ========== 检验 ==========
149 148
150 - // TODO @AI:需要搞个枚举么?使用 int 把。现在就搞了;  
151 /** 149 /**
152 * 检测结果 150 * 检测结果
153 * 151 *
154 - * 字典 mes_qc_check_result 152 + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcCheckResultEnum}
155 */ 153 */
156 - private String checkResult; 154 + private Integer checkResult;
157 /** 155 /**
158 * 来料日期 156 * 来料日期
159 */ 157 */
@@ -165,13 +163,16 @@ public class MesQcIqcDO extends BaseDO { @@ -165,13 +163,16 @@ public class MesQcIqcDO extends BaseDO {
165 /** 163 /**
166 * 检测人员 164 * 检测人员
167 */ 165 */
168 - // TODO @AI:改成 inspectorUserId;  
169 - private String inspector;  
170 - // TODO @AI:需要搞个枚举么?使用 int 把。现在就搞了;  
171 /** 166 /**
172 - * 状态(0=草稿 1=已完成) 167 + * 检测人员用户 ID
173 * 168 *
174 - * 字典 mes_qc_iqc_status 169 + * 关联 AdminUserDO 的 id
  170 + */
  171 + private Long inspectorUserId;
  172 + /**
  173 + * 状态
  174 + *
  175 + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcIqcStatusEnum}
175 */ 176 */
176 private Integer status; 177 private Integer status;
177 /** 178 /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/qc/lqc/MesQcIqcDefectDO.java
@@ -42,13 +42,12 @@ public class MesQcIqcDefectDO extends BaseDO { @@ -42,13 +42,12 @@ public class MesQcIqcDefectDO extends BaseDO {
42 * 缺陷描述 42 * 缺陷描述
43 */ 43 */
44 private String defectName; 44 private String defectName;
45 - // TODO @AI:要不枚举值也加下,也改成 int;  
46 /** 45 /**
47 * 缺陷等级 46 * 缺陷等级
48 * 47 *
49 - * 字典 mes_defect_level 48 + * 枚举 {@link cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum}
50 */ 49 */
51 - private String defectLevel; 50 + private Integer defectLevel;
52 /** 51 /**
53 * 缺陷数量 52 * 缺陷数量
54 */ 53 */
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/qc/lqc/MesQcIqcMapper.java
@@ -25,6 +25,7 @@ public interface MesQcIqcMapper extends BaseMapperX&lt;MesQcIqcDO&gt; { @@ -25,6 +25,7 @@ public interface MesQcIqcMapper extends BaseMapperX&lt;MesQcIqcDO&gt; {
25 .eqIfPresent(MesQcIqcDO::getStatus, reqVO.getStatus()) 25 .eqIfPresent(MesQcIqcDO::getStatus, reqVO.getStatus())
26 .betweenIfPresent(MesQcIqcDO::getReceiveDate, reqVO.getReceiveDate()) 26 .betweenIfPresent(MesQcIqcDO::getReceiveDate, reqVO.getReceiveDate())
27 .betweenIfPresent(MesQcIqcDO::getInspectDate, reqVO.getInspectDate()) 27 .betweenIfPresent(MesQcIqcDO::getInspectDate, reqVO.getInspectDate())
  28 + .eqIfPresent(MesQcIqcDO::getInspectorUserId, reqVO.getInspectorUserId())
28 .orderByDesc(MesQcIqcDO::getId)); 29 .orderByDesc(MesQcIqcDO::getId));
29 } 30 }
30 31
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcCheckResultEnum.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 MesQcCheckResultEnum implements ArrayValuable<Integer> {
  17 +
  18 + PASS(1, "合格"), // TODO @AI:检验通过;
  19 + FAIL(2, "不合格"), // TODO @AI:检验不通过;
  20 + ACCEPT(3, "让步接收"); // TODO @AI:去掉;
  21 +
  22 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcCheckResultEnum::getType).toArray(Integer[]::new);
  23 +
  24 + /**
  25 + * 结果值
  26 + */
  27 + private final Integer type;
  28 + /**
  29 + * 结果名
  30 + */
  31 + private final String name;
  32 +
  33 + @Override
  34 + public Integer[] array() {
  35 + return ARRAYS;
  36 + }
  37 +
  38 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcDefectLevelEnum.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 MesQcDefectLevelEnum implements ArrayValuable<Integer> {
  17 +
  18 + CRITICAL(1, "致命"),
  19 + MAJOR(2, "严重"),
  20 + MINOR(3, "轻微");
  21 +
  22 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcDefectLevelEnum::getType).toArray(Integer[]::new);
  23 +
  24 + /**
  25 + * 等级值
  26 + */
  27 + private final Integer type;
  28 + /**
  29 + * 等级名
  30 + */
  31 + private final String name;
  32 +
  33 + @Override
  34 + public Integer[] array() {
  35 + return ARRAYS;
  36 + }
  37 +
  38 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcIqcStatusEnum.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 MesQcIqcStatusEnum implements ArrayValuable<Integer> {
  17 +
  18 + PREPARE(0, "草稿"),
  19 + FINISHED(1, "已完成");
  20 +
  21 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcIqcStatusEnum::getType).toArray(Integer[]::new);
  22 +
  23 + /**
  24 + * 状态值
  25 + */
  26 + private final Integer type;
  27 + /**
  28 + * 状态名
  29 + */
  30 + private final String name;
  31 +
  32 + @Override
  33 + public Integer[] array() {
  34 + return ARRAYS;
  35 + }
  36 +
  37 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/qc/MesQcTypeEnum.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 MesQcTypeEnum implements ArrayValuable<Integer> {
  17 +
  18 + IQC(1, "来料检验"),
  19 + IPQC(2, "过程检验"),
  20 + OQC(3, "出货检验"),
  21 + RQC(4, "退货检验");
  22 +
  23 + public static final Integer[] ARRAYS = Arrays.stream(values()).map(MesQcTypeEnum::getType).toArray(Integer[]::new);
  24 +
  25 + /**
  26 + * 类型值
  27 + */
  28 + private final Integer type;
  29 + /**
  30 + * 类型名
  31 + */
  32 + private final String name;
  33 +
  34 + @Override
  35 + public Integer[] array() {
  36 + return ARRAYS;
  37 + }
  38 +
  39 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.qc.lqc;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectPageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDefectDO;
  7 +import jakarta.validation.Valid;
  8 +
  9 +/**
  10 + * MES 来料检验缺陷记录 Service 接口
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +public interface MesQcIqcDefectService {
  15 +
  16 + /**
  17 + * 创建来料检验缺陷记录
  18 + *
  19 + * @param createReqVO 创建信息
  20 + * @return 编号
  21 + */
  22 + Long createIqcDefect(@Valid MesQcIqcDefectSaveReqVO createReqVO);
  23 +
  24 + /**
  25 + * 更新来料检验缺陷记录
  26 + *
  27 + * @param updateReqVO 更新信息
  28 + */
  29 + void updateIqcDefect(@Valid MesQcIqcDefectSaveReqVO updateReqVO);
  30 +
  31 + /**
  32 + * 删除来料检验缺陷记录
  33 + *
  34 + * @param id 编号
  35 + */
  36 + void deleteIqcDefect(Long id);
  37 +
  38 + /**
  39 + * 获得来料检验缺陷记录分页
  40 + *
  41 + * @param pageReqVO 分页查询
  42 + * @return 来料检验缺陷记录分页
  43 + */
  44 + PageResult<MesQcIqcDefectDO> getIqcDefectPage(MesQcIqcDefectPageReqVO pageReqVO);
  45 +
  46 + /**
  47 + * 根据来料检验单 ID 级联删除所有缺陷记录
  48 + *
  49 + * @param iqcId 来料检验单 ID
  50 + */
  51 + void deleteByIqcId(Long iqcId);
  52 +
  53 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.qc.lqc;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectPageReqVO;
  6 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectSaveReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
  8 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDefectDO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
  10 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcDefectMapper;
  11 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcLineMapper;
  12 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper;
  13 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
  14 +import jakarta.annotation.Resource;
  15 +import org.springframework.context.annotation.Lazy;
  16 +import org.springframework.stereotype.Service;
  17 +import org.springframework.transaction.annotation.Transactional;
  18 +import org.springframework.validation.annotation.Validated;
  19 +
  20 +import java.math.BigDecimal;
  21 +import java.math.RoundingMode;
  22 +import java.util.List;
  23 +import java.util.Objects;
  24 +
  25 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  26 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
  27 +
  28 +/**
  29 + * MES 来料检验缺陷记录 Service 实现类
  30 + *
  31 + * @author 芋道源码
  32 + */
  33 +@Service
  34 +@Validated
  35 +public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService {
  36 +
  37 + @Resource
  38 + private MesQcIqcDefectMapper iqcDefectMapper;
  39 + @Resource
  40 + private MesQcIqcLineMapper iqcLineMapper;
  41 + @Resource
  42 + private MesQcIqcMapper iqcMapper;
  43 + @Resource
  44 + @Lazy
  45 + private MesQcIqcLineService iqcLineService;
  46 +
  47 + @Override
  48 + @Transactional(rollbackFor = Exception.class)
  49 + public Long createIqcDefect(MesQcIqcDefectSaveReqVO createReqVO) {
  50 + // 1.1 校验 IQC 存在
  51 + validateIqcExists(createReqVO.getIqcId());
  52 + // 1.2 校验行存在
  53 + validateIqcLineExists(createReqVO.getLineId());
  54 +
  55 + // 2. 插入
  56 + MesQcIqcDefectDO defect = BeanUtils.toBean(createReqVO, MesQcIqcDefectDO.class);
  57 + iqcDefectMapper.insert(defect);
  58 +
  59 + // 3. 重新计算缺陷统计
  60 + recalculateDefectStats(createReqVO.getIqcId());
  61 + return defect.getId();
  62 + }
  63 +
  64 + @Override
  65 + @Transactional(rollbackFor = Exception.class)
  66 + public void updateIqcDefect(MesQcIqcDefectSaveReqVO updateReqVO) {
  67 + // 1. 校验存在
  68 + validateIqcDefectExists(updateReqVO.getId());
  69 +
  70 + // 2. 更新
  71 + MesQcIqcDefectDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIqcDefectDO.class);
  72 + iqcDefectMapper.updateById(updateObj);
  73 +
  74 + // 3. 重新计算缺陷统计
  75 + recalculateDefectStats(updateReqVO.getIqcId());
  76 + }
  77 +
  78 + @Override
  79 + @Transactional(rollbackFor = Exception.class)
  80 + public void deleteIqcDefect(Long id) {
  81 + // 1. 校验存在
  82 + MesQcIqcDefectDO defect = validateIqcDefectExists(id);
  83 +
  84 + // 2. 删除
  85 + iqcDefectMapper.deleteById(id);
  86 +
  87 + // 3. 重新计算缺陷统计
  88 + recalculateDefectStats(defect.getIqcId());
  89 + }
  90 +
  91 + @Override
  92 + public PageResult<MesQcIqcDefectDO> getIqcDefectPage(MesQcIqcDefectPageReqVO pageReqVO) {
  93 + return iqcDefectMapper.selectPage(pageReqVO);
  94 + }
  95 +
  96 + @Override
  97 + public void deleteByIqcId(Long iqcId) {
  98 + iqcDefectMapper.deleteByIqcId(iqcId);
  99 + }
  100 +
  101 + private void validateIqcExists(Long iqcId) {
  102 + if (iqcMapper.selectById(iqcId) == null) {
  103 + throw exception(QC_IQC_NOT_EXISTS);
  104 + }
  105 + }
  106 +
  107 + private void validateIqcLineExists(Long lineId) {
  108 + MesQcIqcLineDO line = iqcLineService.getIqcLine(lineId);
  109 + if (line == null) {
  110 + throw exception(QC_IQC_LINE_NOT_EXISTS);
  111 + }
  112 + }
  113 +
  114 + private MesQcIqcDefectDO validateIqcDefectExists(Long id) {
  115 + MesQcIqcDefectDO defect = iqcDefectMapper.selectById(id);
  116 + if (defect == null) {
  117 + throw exception(QC_IQC_DEFECT_NOT_EXISTS);
  118 + }
  119 + return defect;
  120 + }
  121 +
  122 + /**
  123 + * 重新计算缺陷统计(行级 + 主表级)
  124 + *
  125 + * @param iqcId 来料检验单 ID
  126 + */
  127 + private void recalculateDefectStats(Long iqcId) {
  128 + // 1. 查询所有缺陷记录
  129 + List<MesQcIqcDefectDO> defects = iqcDefectMapper.selectListByIqcId(iqcId);
  130 +
  131 + // 2. 更新每行的缺陷数量
  132 + List<MesQcIqcLineDO> lines = iqcLineService.selectListByIqcId(iqcId);
  133 + for (MesQcIqcLineDO line : lines) {
  134 + int critical = 0;
  135 + int major = 0;
  136 + int minor = 0;
  137 + for (MesQcIqcDefectDO defect : defects) {
  138 + // TODO @AI:notEquals continue;减少括号层级;
  139 + if (Objects.equals(defect.getLineId(), line.getId())) {
  140 + // TODO @AI:defaultIfNull;变量改成 quantity
  141 + int qty = defect.getDefectQuantity() != null ? defect.getDefectQuantity() : 1;
  142 + if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) {
  143 + critical += qty;
  144 + } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MAJOR.getType())) {
  145 + major += qty;
  146 + } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MINOR.getType())) {
  147 + minor += qty;
  148 + }
  149 + // TODO @AI:抛出异常;未知的缺陷等级
  150 + }
  151 + }
  152 + MesQcIqcLineDO updateLine = new MesQcIqcLineDO().setId(line.getId())
  153 + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor);
  154 + // 直接通过 lineService 内部更新(避免循环依赖,使用 mapper)
  155 + // TODO @AI:单独搞个 updateLineDefectStats 方法;减少 updateLine 变量的作用域;
  156 + iqcLineMapper.updateById(updateLine);
  157 + }
  158 +
  159 + // 3.1 汇总主表的缺陷数量
  160 + int totalCritical = 0, totalMajor = 0, totalMinor = 0;
  161 + for (MesQcIqcDefectDO defect : defects) {
  162 + // TODO @AI:defaultIfNull;变量改成 quantity
  163 + int qty = defect.getDefectQuantity() != null ? defect.getDefectQuantity() : 1;
  164 + if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) {
  165 + totalCritical += qty;
  166 + } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MAJOR.getType())) {
  167 + totalMajor += qty;
  168 + } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MINOR.getType())) {
  169 + totalMinor += qty;
  170 + }
  171 + // TODO @AI:抛出异常;未知的缺陷等级
  172 + }
  173 + // 3.2 计算缺陷率
  174 + MesQcIqcDO iqc = iqcMapper.selectById(iqcId);
  175 + BigDecimal criticalRate = BigDecimal.ZERO;
  176 + BigDecimal majorRate = BigDecimal.ZERO;
  177 + BigDecimal minorRate = BigDecimal.ZERO;
  178 + if (iqc != null && iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) {
  179 + BigDecimal checkQty = BigDecimal.valueOf(iqc.getCheckQuantity());
  180 + criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100))
  181 + .divide(checkQty, 2, RoundingMode.HALF_UP);
  182 + majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100))
  183 + .divide(checkQty, 2, RoundingMode.HALF_UP);
  184 + minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100))
  185 + .divide(checkQty, 2, RoundingMode.HALF_UP);
  186 + }
  187 + // 3.3 更新主表
  188 + MesQcIqcDO updateIqc = new MesQcIqcDO().setId(iqcId)
  189 + .setCriticalQuantity(totalCritical).setMajorQuantity(totalMajor).setMinorQuantity(totalMinor)
  190 + .setCriticalRate(criticalRate).setMajorRate(majorRate).setMinorRate(minorRate);
  191 + iqcMapper.updateById(updateIqc);
  192 + }
  193 +
  194 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcLineService.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.qc.lqc;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * MES 来料检验单行 Service 接口
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +public interface MesQcIqcLineService {
  15 +
  16 + /**
  17 + * 获得来料检验行
  18 + *
  19 + * @param id 编号
  20 + * @return 来料检验行
  21 + */
  22 + MesQcIqcLineDO getIqcLine(Long id);
  23 +
  24 + /**
  25 + * 获得来料检验行分页
  26 + *
  27 + * @param pageReqVO 分页查询
  28 + * @return 来料检验行分页
  29 + */
  30 + PageResult<MesQcIqcLineDO> getIqcLinePage(MesQcIqcLinePageReqVO pageReqVO);
  31 +
  32 + /**
  33 + * 根据来料检验单 ID 查询所有行
  34 + *
  35 + * @param iqcId 来料检验单 ID
  36 + * @return 行列表
  37 + */
  38 + List<MesQcIqcLineDO> selectListByIqcId(Long iqcId);
  39 +
  40 + /**
  41 + * 从模板指标自动生成检验行
  42 + *
  43 + * @param iqcId 来料检验单 ID
  44 + * @param templateId 模板 ID
  45 + */
  46 + void createLinesFromTemplate(Long iqcId, Long templateId);
  47 +
  48 + /**
  49 + * 根据来料检验单 ID 级联删除所有行
  50 + *
  51 + * @param iqcId 来料检验单 ID
  52 + */
  53 + void deleteByIqcId(Long iqcId);
  54 +
  55 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcLineServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.mes.service.qc.lqc;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO;
  5 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO;
  7 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcLineMapper;
  8 +import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper;
  9 +import jakarta.annotation.Resource;
  10 +import org.springframework.stereotype.Service;
  11 +import org.springframework.validation.annotation.Validated;
  12 +
  13 +import java.util.List;
  14 +
  15 +/**
  16 + * MES 来料检验单行 Service 实现类
  17 + *
  18 + * @author 芋道源码
  19 + */
  20 +@Service
  21 +@Validated
  22 +public class MesQcIqcLineServiceImpl implements MesQcIqcLineService {
  23 +
  24 + @Resource
  25 + private MesQcIqcLineMapper iqcLineMapper;
  26 + @Resource
  27 + private MesQcTemplateIndicatorMapper templateIndicatorMapper;
  28 +
  29 + @Override
  30 + public MesQcIqcLineDO getIqcLine(Long id) {
  31 + return iqcLineMapper.selectById(id);
  32 + }
  33 +
  34 + @Override
  35 + public PageResult<MesQcIqcLineDO> getIqcLinePage(MesQcIqcLinePageReqVO pageReqVO) {
  36 + return iqcLineMapper.selectPage(pageReqVO);
  37 + }
  38 +
  39 + @Override
  40 + public List<MesQcIqcLineDO> selectListByIqcId(Long iqcId) {
  41 + return iqcLineMapper.selectListByIqcId(iqcId);
  42 + }
  43 +
  44 + @Override
  45 + public void createLinesFromTemplate(Long iqcId, Long templateId) {
  46 + List<MesQcTemplateIndicatorDO> indicators = templateIndicatorMapper.selectListByTemplateId(templateId);
  47 + // TODO @AI:convertList;
  48 + for (MesQcTemplateIndicatorDO indicator : indicators) {
  49 + // TODO @AI:链式设置;
  50 + MesQcIqcLineDO line = new MesQcIqcLineDO();
  51 + line.setIqcId(iqcId);
  52 + line.setIndicatorId(indicator.getIndicatorId());
  53 + line.setToolId(null); // TODO @芋艿:模板指标暂无 toolId,后续可扩展
  54 + line.setCheckMethod(indicator.getCheckMethod());
  55 + line.setStandardValue(indicator.getStandardValue());
  56 + line.setUnitMeasureId(indicator.getUnitMeasureId());
  57 + line.setMaxThreshold(indicator.getThresholdMax());
  58 + line.setMinThreshold(indicator.getThresholdMin());
  59 + line.setCriticalQuantity(0);
  60 + line.setMajorQuantity(0);
  61 + line.setMinorQuantity(0);
  62 + // TODO @AI:insertBatch;
  63 + iqcLineMapper.insert(line);
  64 + }
  65 + }
  66 +
  67 + @Override
  68 + public void deleteByIqcId(Long iqcId) {
  69 + iqcLineMapper.deleteByIqcId(iqcId);
  70 + }
  71 +
  72 +}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcService.java
1 package cn.iocoder.yudao.module.mes.service.qc.lqc; 1 package cn.iocoder.yudao.module.mes.service.qc.lqc;
2 2
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 -import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.*;  
5 -import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectPageReqVO;  
6 -import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectSaveReqVO;  
7 -import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO; 4 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO;
  5 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcSaveReqVO;
8 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO; 6 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
9 -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDefectDO;  
10 -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;  
11 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
12 8
13 -// TODO @AI:和别的模块一样,拆分成多个 service  
14 /** 9 /**
15 * MES 来料检验单(IQC) Service 接口 10 * MES 来料检验单(IQC) Service 接口
16 * 11 *
@@ -18,8 +13,6 @@ import jakarta.validation.Valid; @@ -18,8 +13,6 @@ import jakarta.validation.Valid;
18 */ 13 */
19 public interface MesQcIqcService { 14 public interface MesQcIqcService {
20 15
21 - // ========== 来料检验主表 ==========  
22 -  
23 /** 16 /**
24 * 创建来料检验单 17 * 创建来料检验单
25 * 18 *
@@ -65,54 +58,4 @@ public interface MesQcIqcService { @@ -65,54 +58,4 @@ public interface MesQcIqcService {
65 */ 58 */
66 PageResult<MesQcIqcDO> getIqcPage(MesQcIqcPageReqVO pageReqVO); 59 PageResult<MesQcIqcDO> getIqcPage(MesQcIqcPageReqVO pageReqVO);
67 60
68 - // ========== 来料检验行(只读) ==========  
69 -  
70 - /**  
71 - * 获得来料检验行  
72 - *  
73 - * @param id 编号  
74 - * @return 来料检验行  
75 - */  
76 - MesQcIqcLineDO getIqcLine(Long id);  
77 -  
78 - /**  
79 - * 获得来料检验行分页  
80 - *  
81 - * @param pageReqVO 分页查询  
82 - * @return 来料检验行分页  
83 - */  
84 - PageResult<MesQcIqcLineDO> getIqcLinePage(MesQcIqcLinePageReqVO pageReqVO);  
85 -  
86 - // ========== 来料检验缺陷记录 ==========  
87 -  
88 - /**  
89 - * 创建来料检验缺陷记录  
90 - *  
91 - * @param createReqVO 创建信息  
92 - * @return 编号  
93 - */  
94 - Long createIqcDefect(@Valid MesQcIqcDefectSaveReqVO createReqVO);  
95 -  
96 - /**  
97 - * 更新来料检验缺陷记录  
98 - *  
99 - * @param updateReqVO 更新信息  
100 - */  
101 - void updateIqcDefect(@Valid MesQcIqcDefectSaveReqVO updateReqVO);  
102 -  
103 - /**  
104 - * 删除来料检验缺陷记录  
105 - *  
106 - * @param id 编号  
107 - */  
108 - void deleteIqcDefect(Long id);  
109 -  
110 - /**  
111 - * 获得来料检验缺陷记录分页  
112 - *  
113 - * @param pageReqVO 分页查询  
114 - * @return 来料检验缺陷记录分页  
115 - */  
116 - PageResult<MesQcIqcDefectDO> getIqcDefectPage(MesQcIqcDefectPageReqVO pageReqVO);  
117 -  
118 } 61 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java
@@ -3,36 +3,26 @@ package cn.iocoder.yudao.module.mes.service.qc.lqc; @@ -3,36 +3,26 @@ package cn.iocoder.yudao.module.mes.service.qc.lqc;
3 import cn.hutool.core.util.ObjUtil; 3 import cn.hutool.core.util.ObjUtil;
4 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 -import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.*;  
7 -import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectPageReqVO;  
8 -import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectSaveReqVO;  
9 -import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO; 6 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO;
  7 +import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcSaveReqVO;
10 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO; 8 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
11 -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDefectDO;  
12 -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;  
13 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; 9 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO;
14 -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO;  
15 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; 10 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO;
16 -import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcDefectMapper;  
17 -import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcLineMapper;  
18 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper; 11 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper;
19 -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper;  
20 import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateItemMapper; 12 import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateItemMapper;
21 import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateMapper; 13 import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateMapper;
  14 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcIqcStatusEnum;
  15 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
22 import jakarta.annotation.Resource; 16 import jakarta.annotation.Resource;
23 import org.springframework.stereotype.Service; 17 import org.springframework.stereotype.Service;
24 import org.springframework.transaction.annotation.Transactional; 18 import org.springframework.transaction.annotation.Transactional;
25 import org.springframework.validation.annotation.Validated; 19 import org.springframework.validation.annotation.Validated;
26 20
27 -import java.math.BigDecimal;  
28 -import java.math.RoundingMode;  
29 -import java.util.List;  
30 import java.util.Objects; 21 import java.util.Objects;
31 22
32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
33 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; 24 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
34 25
35 -// TODO @AI:和别的模块一样,拆分成多个 service  
36 /** 26 /**
37 * MES 来料检验单(IQC) Service 实现类 27 * MES 来料检验单(IQC) Service 实现类
38 * 28 *
@@ -42,41 +32,34 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; @@ -42,41 +32,34 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
42 @Validated 32 @Validated
43 public class MesQcIqcServiceImpl implements MesQcIqcService { 33 public class MesQcIqcServiceImpl implements MesQcIqcService {
44 34
45 - // TODO @AI:搞个枚举类;  
46 - /**  
47 - * IQC 检测种类值(对应 mes_qc_type 字典 value=1)  
48 - */  
49 - private static final int QC_TYPE_IQC = 1;  
50 -  
51 @Resource 35 @Resource
52 private MesQcIqcMapper iqcMapper; 36 private MesQcIqcMapper iqcMapper;
53 @Resource 37 @Resource
54 - private MesQcIqcLineMapper iqcLineMapper;  
55 - @Resource  
56 - private MesQcIqcDefectMapper iqcDefectMapper;  
57 - @Resource  
58 private MesQcTemplateMapper templateMapper; 38 private MesQcTemplateMapper templateMapper;
59 @Resource 39 @Resource
60 - private MesQcTemplateIndicatorMapper templateIndicatorMapper;  
61 - @Resource  
62 private MesQcTemplateItemMapper templateItemMapper; 40 private MesQcTemplateItemMapper templateItemMapper;
63 41
64 - // ========== 来料检验主表 ========== 42 + @Resource
  43 + private MesQcIqcLineService iqcLineService;
  44 + @Resource
  45 + private MesQcIqcDefectService iqcDefectService;
65 46
66 @Override 47 @Override
67 @Transactional(rollbackFor = Exception.class) 48 @Transactional(rollbackFor = Exception.class)
68 public Long createIqc(MesQcIqcSaveReqVO createReqVO) { 49 public Long createIqc(MesQcIqcSaveReqVO createReqVO) {
69 - // 1. 校验编号唯一 50 + // 1.1 校验编号唯一
70 validateIqcCodeUnique(null, createReqVO.getCode()); 51 validateIqcCodeUnique(null, createReqVO.getCode());
71 -  
72 - // 2. 查找物料关联的 IQC 检测模板 52 + // 1.2 查找物料关联的 IQC 检测模板
73 Long templateId = createReqVO.getTemplateId(); 53 Long templateId = createReqVO.getTemplateId();
  54 + // TODO @AI:直接使用 templateService 的 validateTemplateExists() 方法,后续如果有更多模板相关的校验,也可以放在该方法中
74 MesQcTemplateDO template = templateMapper.selectById(templateId); 55 MesQcTemplateDO template = templateMapper.selectById(templateId);
75 - if (template == null || template.getTypes() == null || !template.getTypes().contains(QC_TYPE_IQC)) { 56 + // TODO @AI:CollUtil.contains 这样更合适;
  57 + if (template == null || template.getTypes() == null || !template.getTypes().contains(MesQcTypeEnum.IQC.getType())) {
76 throw exception(QC_IQC_NO_TEMPLATE); 58 throw exception(QC_IQC_NO_TEMPLATE);
77 } 59 }
78 60
79 - // 3. 从模板的产品关联中获取检测参数(min_check_quantity、max_unqualified_quantity) 61 + // 3.1 从模板的产品关联中获取检测参数(min_check_quantity、max_unqualified_quantity)
  62 + // TODO @AI:使用 templateItemService 方法,不要直接使用对方的 mapper;
80 MesQcTemplateItemDO templateItem = templateItemMapper.selectByTemplateIdAndItemId( 63 MesQcTemplateItemDO templateItem = templateItemMapper.selectByTemplateIdAndItemId(
81 templateId, createReqVO.getItemId()); 64 templateId, createReqVO.getItemId());
82 if (templateItem != null) { 65 if (templateItem != null) {
@@ -87,57 +70,43 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -87,57 +70,43 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
87 createReqVO.setMaxUnqualifiedQuantity(templateItem.getQuantityUnqualified()); 70 createReqVO.setMaxUnqualifiedQuantity(templateItem.getQuantityUnqualified());
88 } 71 }
89 } 72 }
90 -  
91 - // 4. 插入主表 73 + // 3.2 插入主表
92 MesQcIqcDO iqc = BeanUtils.toBean(createReqVO, MesQcIqcDO.class); 74 MesQcIqcDO iqc = BeanUtils.toBean(createReqVO, MesQcIqcDO.class);
93 - iqc.setStatus(0); // 草稿 75 + iqc.setStatus(MesQcIqcStatusEnum.PREPARE.getType());
94 iqcMapper.insert(iqc); 76 iqcMapper.insert(iqc);
95 77
96 - // 5. 从模板指标自动生成检验行  
97 - List<MesQcTemplateIndicatorDO> indicators = templateIndicatorMapper.selectListByTemplateId(templateId);  
98 - for (MesQcTemplateIndicatorDO indicator : indicators) {  
99 - MesQcIqcLineDO line = new MesQcIqcLineDO();  
100 - line.setIqcId(iqc.getId());  
101 - line.setIndicatorId(indicator.getIndicatorId());  
102 - line.setToolId(null); // TODO @芋艿:模板指标暂无 toolId,后续可扩展  
103 - line.setCheckMethod(indicator.getCheckMethod());  
104 - line.setStandardValue(indicator.getStandardValue());  
105 - line.setUnitMeasureId(indicator.getUnitMeasureId());  
106 - line.setMaxThreshold(indicator.getThresholdMax());  
107 - line.setMinThreshold(indicator.getThresholdMin());  
108 - line.setCriticalQuantity(0);  
109 - line.setMajorQuantity(0);  
110 - line.setMinorQuantity(0);  
111 - iqcLineMapper.insert(line);  
112 - }  
113 - 78 + // 4. 从模板指标自动生成检验行
  79 + iqcLineService.createLinesFromTemplate(iqc.getId(), templateId);
114 return iqc.getId(); 80 return iqc.getId();
115 } 81 }
116 82
117 @Override 83 @Override
118 public void updateIqc(MesQcIqcSaveReqVO updateReqVO) { 84 public void updateIqc(MesQcIqcSaveReqVO updateReqVO) {
119 - // 1. 校验存在 85 + // 1.1 校验存在
120 MesQcIqcDO iqc = validateIqcExists(updateReqVO.getId()); 86 MesQcIqcDO iqc = validateIqcExists(updateReqVO.getId());
121 - // 2. 校验状态为草稿  
122 - if (!Objects.equals(iqc.getStatus(), 0)) { 87 + // 1.2 校验状态为草稿
  88 + // TODO @AI:notEquals;
  89 + // TODO @AI:抽成一个方法,这样 completeIqc 和 deleteIqc 也可以复用,避免重复代码;
  90 + if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
123 throw exception(QC_IQC_ONLY_PREPARE_CAN_COMPLETE); 91 throw exception(QC_IQC_ONLY_PREPARE_CAN_COMPLETE);
124 } 92 }
125 - // 3. 校验编号唯一 93 + // 1.3 校验编号唯一
126 validateIqcCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); 94 validateIqcCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
127 - // 4. 更新 95 +
  96 + // 2. 更新
128 MesQcIqcDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIqcDO.class); 97 MesQcIqcDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIqcDO.class);
129 iqcMapper.updateById(updateObj); 98 iqcMapper.updateById(updateObj);
130 } 99 }
131 100
132 @Override 101 @Override
133 public void completeIqc(Long id) { 102 public void completeIqc(Long id) {
134 - // 1. 校验存在 103 + // 1.1 校验存在
135 MesQcIqcDO iqc = validateIqcExists(id); 104 MesQcIqcDO iqc = validateIqcExists(id);
136 - // 2. 校验状态为草稿  
137 - if (!Objects.equals(iqc.getStatus(), 0)) { 105 + // 1.2 校验状态为草稿
  106 + if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
138 throw exception(QC_IQC_ONLY_PREPARE_CAN_COMPLETE); 107 throw exception(QC_IQC_ONLY_PREPARE_CAN_COMPLETE);
139 } 108 }
140 - // 3. 校验合格品 + 不合格品 = 检测数量 109 + // 1.3 校验合格品 + 不合格品 = 检测数量
141 if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) { 110 if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) {
142 int total = (iqc.getQualifiedQuantity() != null ? iqc.getQualifiedQuantity() : 0) 111 int total = (iqc.getQualifiedQuantity() != null ? iqc.getQualifiedQuantity() : 0)
143 + (iqc.getUnqualifiedQuantity() != null ? iqc.getUnqualifiedQuantity() : 0); 112 + (iqc.getUnqualifiedQuantity() != null ? iqc.getUnqualifiedQuantity() : 0);
@@ -145,29 +114,31 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -145,29 +114,31 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
145 throw exception(QC_IQC_QUANTITY_MISMATCH); 114 throw exception(QC_IQC_QUANTITY_MISMATCH);
146 } 115 }
147 } 116 }
148 - // 4. 更新状态为已完成  
149 - MesQcIqcDO updateObj = new MesQcIqcDO();  
150 - updateObj.setId(id);  
151 - updateObj.setStatus(1); 117 +
  118 + // 2. 更新状态为已完成
  119 + MesQcIqcDO updateObj = new MesQcIqcDO()
  120 + .setId(id).setStatus(MesQcIqcStatusEnum.FINISHED.getType());
152 iqcMapper.updateById(updateObj); 121 iqcMapper.updateById(updateObj);
  122 +
153 // TODO @芋艿:WM 模块迁移后,更新到货通知单行/外协入库单行的检验结果 123 // TODO @芋艿:WM 模块迁移后,更新到货通知单行/外协入库单行的检验结果
154 } 124 }
155 125
156 @Override 126 @Override
157 @Transactional(rollbackFor = Exception.class) 127 @Transactional(rollbackFor = Exception.class)
158 public void deleteIqc(Long id) { 128 public void deleteIqc(Long id) {
159 - // 1. 校验存在 129 + // 1.1 校验存在
160 MesQcIqcDO iqc = validateIqcExists(id); 130 MesQcIqcDO iqc = validateIqcExists(id);
161 - // 2. 仅草稿可删  
162 - if (!Objects.equals(iqc.getStatus(), 0)) { 131 + // 1.2 仅草稿可删
  132 + if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
163 throw exception(QC_IQC_ONLY_PREPARE_CAN_DELETE); 133 throw exception(QC_IQC_ONLY_PREPARE_CAN_DELETE);
164 } 134 }
165 - // 3. 删除主表 135 +
  136 + // 2.1 删除主表
166 iqcMapper.deleteById(id); 137 iqcMapper.deleteById(id);
167 - // 4. 级联删除行  
168 - iqcLineMapper.deleteByIqcId(id);  
169 - // 5. 级联删除缺陷记录  
170 - iqcDefectMapper.deleteByIqcId(id); 138 + // 2.2 级联删除行
  139 + iqcLineService.deleteByIqcId(id);
  140 + // 2.3 级联删除缺陷记录
  141 + iqcDefectService.deleteByIqcId(id);
171 } 142 }
172 143
173 private MesQcIqcDO validateIqcExists(Long id) { 144 private MesQcIqcDO validateIqcExists(Long id) {
@@ -198,146 +169,4 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -198,146 +169,4 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
198 return iqcMapper.selectPage(pageReqVO); 169 return iqcMapper.selectPage(pageReqVO);
199 } 170 }
200 171
201 - // ========== 来料检验行(只读) ==========  
202 -  
203 - @Override  
204 - public MesQcIqcLineDO getIqcLine(Long id) {  
205 - return iqcLineMapper.selectById(id);  
206 - }  
207 -  
208 - @Override  
209 - public PageResult<MesQcIqcLineDO> getIqcLinePage(MesQcIqcLinePageReqVO pageReqVO) {  
210 - return iqcLineMapper.selectPage(pageReqVO);  
211 - }  
212 -  
213 - // ========== 来料检验缺陷记录 ==========  
214 -  
215 - @Override  
216 - @Transactional(rollbackFor = Exception.class)  
217 - public Long createIqcDefect(MesQcIqcDefectSaveReqVO createReqVO) {  
218 - // 1. 校验 IQC 存在  
219 - validateIqcExists(createReqVO.getIqcId());  
220 - // 2. 校验行存在  
221 - validateIqcLineExists(createReqVO.getLineId());  
222 - // 3. 插入  
223 - MesQcIqcDefectDO defect = BeanUtils.toBean(createReqVO, MesQcIqcDefectDO.class);  
224 - iqcDefectMapper.insert(defect);  
225 - // 4. 重新计算缺陷统计  
226 - recalculateDefectStats(createReqVO.getIqcId());  
227 - return defect.getId();  
228 - }  
229 -  
230 - @Override  
231 - @Transactional(rollbackFor = Exception.class)  
232 - public void updateIqcDefect(MesQcIqcDefectSaveReqVO updateReqVO) {  
233 - // 1. 校验存在  
234 - validateIqcDefectExists(updateReqVO.getId());  
235 - // 2. 更新  
236 - MesQcIqcDefectDO updateObj = BeanUtils.toBean(updateReqVO, MesQcIqcDefectDO.class);  
237 - iqcDefectMapper.updateById(updateObj);  
238 - // 3. 重新计算缺陷统计  
239 - recalculateDefectStats(updateReqVO.getIqcId());  
240 - }  
241 -  
242 - @Override  
243 - @Transactional(rollbackFor = Exception.class)  
244 - public void deleteIqcDefect(Long id) {  
245 - // 1. 校验存在  
246 - MesQcIqcDefectDO defect = validateIqcDefectExists(id);  
247 - // 2. 删除  
248 - iqcDefectMapper.deleteById(id);  
249 - // 3. 重新计算缺陷统计  
250 - recalculateDefectStats(defect.getIqcId());  
251 - }  
252 -  
253 - private void validateIqcLineExists(Long id) {  
254 - if (iqcLineMapper.selectById(id) == null) {  
255 - throw exception(QC_IQC_LINE_NOT_EXISTS);  
256 - }  
257 - }  
258 -  
259 - private MesQcIqcDefectDO validateIqcDefectExists(Long id) {  
260 - MesQcIqcDefectDO defect = iqcDefectMapper.selectById(id);  
261 - if (defect == null) {  
262 - throw exception(QC_IQC_DEFECT_NOT_EXISTS);  
263 - }  
264 - return defect;  
265 - }  
266 -  
267 - @Override  
268 - public PageResult<MesQcIqcDefectDO> getIqcDefectPage(MesQcIqcDefectPageReqVO pageReqVO) {  
269 - return iqcDefectMapper.selectPage(pageReqVO);  
270 - }  
271 -  
272 - // ========== 内部方法 ==========  
273 -  
274 - /**  
275 - * 重新计算缺陷统计(行级 + 主表级)  
276 - *  
277 - * @param iqcId 来料检验单 ID  
278 - */  
279 - private void recalculateDefectStats(Long iqcId) {  
280 - // 1. 查询所有缺陷记录  
281 - List<MesQcIqcDefectDO> defects = iqcDefectMapper.selectListByIqcId(iqcId);  
282 -  
283 - // 2. 更新每行的缺陷数量  
284 - List<MesQcIqcLineDO> lines = iqcLineMapper.selectListByIqcId(iqcId);  
285 - for (MesQcIqcLineDO line : lines) {  
286 - int critical = 0, major = 0, minor = 0;  
287 - for (MesQcIqcDefectDO defect : defects) {  
288 - if (Objects.equals(defect.getLineId(), line.getId())) {  
289 - int qty = defect.getDefectQuantity() != null ? defect.getDefectQuantity() : 1;  
290 - switch (defect.getDefectLevel()) {  
291 - case "CRITICAL": critical += qty; break;  
292 - case "MAJOR": major += qty; break;  
293 - case "MINOR": minor += qty; break;  
294 - }  
295 - }  
296 - }  
297 - MesQcIqcLineDO updateLine = new MesQcIqcLineDO();  
298 - updateLine.setId(line.getId());  
299 - updateLine.setCriticalQuantity(critical);  
300 - updateLine.setMajorQuantity(major);  
301 - updateLine.setMinorQuantity(minor);  
302 - iqcLineMapper.updateById(updateLine);  
303 - }  
304 -  
305 - // 3. 汇总主表的缺陷数量  
306 - int totalCritical = 0, totalMajor = 0, totalMinor = 0;  
307 - for (MesQcIqcDefectDO defect : defects) {  
308 - int qty = defect.getDefectQuantity() != null ? defect.getDefectQuantity() : 1;  
309 - switch (defect.getDefectLevel()) {  
310 - case "CRITICAL": totalCritical += qty; break;  
311 - case "MAJOR": totalMajor += qty; break;  
312 - case "MINOR": totalMinor += qty; break;  
313 - }  
314 - }  
315 -  
316 - // 4. 计算缺陷率  
317 - MesQcIqcDO iqc = iqcMapper.selectById(iqcId);  
318 - BigDecimal criticalRate = BigDecimal.ZERO;  
319 - BigDecimal majorRate = BigDecimal.ZERO;  
320 - BigDecimal minorRate = BigDecimal.ZERO;  
321 - if (iqc != null && iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) {  
322 - BigDecimal checkQty = BigDecimal.valueOf(iqc.getCheckQuantity());  
323 - criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100))  
324 - .divide(checkQty, 2, RoundingMode.HALF_UP);  
325 - majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100))  
326 - .divide(checkQty, 2, RoundingMode.HALF_UP);  
327 - minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100))  
328 - .divide(checkQty, 2, RoundingMode.HALF_UP);  
329 - }  
330 -  
331 - // 5. 更新主表  
332 - MesQcIqcDO updateIqc = new MesQcIqcDO();  
333 - updateIqc.setId(iqcId);  
334 - updateIqc.setCriticalQuantity(totalCritical);  
335 - updateIqc.setMajorQuantity(totalMajor);  
336 - updateIqc.setMinorQuantity(totalMinor);  
337 - updateIqc.setCriticalRate(criticalRate);  
338 - updateIqc.setMajorRate(majorRate);  
339 - updateIqc.setMinorRate(minorRate);  
340 - iqcMapper.updateById(updateIqc);  
341 - }  
342 -  
343 } 172 }