Commit 1b0d0773a3430448634fe91fdcf5fb42261431ed

Authored by YunaiV
1 parent b26ff0d7

feat(mes): 更新质检缺陷记录权限标识,重构相关校验逻辑,优化缺陷统计计算

yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/MesQcDefectRecordController.java
... ... @@ -28,17 +28,17 @@ public class MesQcDefectRecordController {
28 28 @Resource
29 29 private MesQcDefectRecordService defectRecordService;
30 30  
31   - // TODO @AI:使用 mes:qc-record:create 权限标识先;不要搞太复杂;当然,也写个 todo @芋艿:说下这个情况
  31 + // TODO @芋艿:说下 mes:qc-record 这个权限标识的情况
32 32 @PostMapping("/create")
33 33 @Operation(summary = "创建质检缺陷记录")
34   - @PreAuthorize("@ss.hasPermission('mes:qc-defect-record:create')")
  34 + @PreAuthorize("@ss.hasPermission('mes:qc-record:create')")
35 35 public CommonResult<Long> createDefectRecord(@Valid @RequestBody MesQcDefectRecordSaveReqVO createReqVO) {
36 36 return success(defectRecordService.createDefectRecord(createReqVO));
37 37 }
38 38  
39 39 @PutMapping("/update")
40 40 @Operation(summary = "更新质检缺陷记录")
41   - @PreAuthorize("@ss.hasPermission('mes:qc-defect-record:update')")
  41 + @PreAuthorize("@ss.hasPermission('mes:qc-record:update')")
42 42 public CommonResult<Boolean> updateDefectRecord(@Valid @RequestBody MesQcDefectRecordSaveReqVO updateReqVO) {
43 43 defectRecordService.updateDefectRecord(updateReqVO);
44 44 return success(true);
... ... @@ -47,7 +47,7 @@ public class MesQcDefectRecordController {
47 47 @DeleteMapping("/delete")
48 48 @Operation(summary = "删除质检缺陷记录")
49 49 @Parameter(name = "id", description = "编号", required = true)
50   - @PreAuthorize("@ss.hasPermission('mes:qc-defect-record:update')")
  50 + @PreAuthorize("@ss.hasPermission('mes:qc-record:update')")
51 51 public CommonResult<Boolean> deleteDefectRecord(@RequestParam("id") Long id) {
52 52 defectRecordService.deleteDefectRecord(id);
53 53 return success(true);
... ... @@ -55,7 +55,7 @@ public class MesQcDefectRecordController {
55 55  
56 56 @GetMapping("/page")
57 57 @Operation(summary = "获得质检缺陷记录分页")
58   - @PreAuthorize("@ss.hasPermission('mes:qc-defect-record:query')")
  58 + @PreAuthorize("@ss.hasPermission('mes:qc-record:query')")
59 59 public CommonResult<PageResult<MesQcDefectRecordRespVO>> getDefectRecordPage(@Valid MesQcDefectRecordPageReqVO pageReqVO) {
60 60 PageResult<MesQcDefectRecordDO> pageResult = defectRecordService.getDefectRecordPage(pageReqVO);
61 61 return success(BeanUtils.toBean(pageResult, MesQcDefectRecordRespVO.class));
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/defect/MesQcDefectRecordServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.qc.defect;
2 2  
3   -import cn.hutool.core.util.ObjUtil;
4 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 5 import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectRecordPageReqVO;
7 6 import cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo.MesQcDefectRecordSaveReqVO;
8 7 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectRecordDO;
9   -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
10   -import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
11 8 import cn.iocoder.yudao.module.mes.dal.mysql.qc.defect.MesQcDefectRecordMapper;
12   -import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper;
13   -import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
14 9 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
15 10 import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcLineService;
  11 +import cn.iocoder.yudao.module.mes.service.qc.lqc.MesQcIqcService;
16 12 import jakarta.annotation.Resource;
17 13 import org.springframework.context.annotation.Lazy;
18 14 import org.springframework.stereotype.Service;
19 15 import org.springframework.transaction.annotation.Transactional;
20 16 import org.springframework.validation.annotation.Validated;
21 17  
22   -import java.math.BigDecimal;
23   -import java.math.RoundingMode;
24   -import java.util.ArrayList;
25 18 import java.util.List;
26 19 import java.util.Objects;
27 20  
... ... @@ -40,9 +33,9 @@ public class MesQcDefectRecordServiceImpl implements MesQcDefectRecordService {
40 33 @Resource
41 34 private MesQcDefectRecordMapper defectRecordMapper;
42 35  
43   - // TODO @AI:不要调用 mapper,调用对方的 service;
44 36 @Resource
45   - private MesQcIqcMapper iqcMapper;
  37 + @Lazy
  38 + private MesQcIqcService iqcService;
46 39 @Resource
47 40 @Lazy
48 41 private MesQcIqcLineService iqcLineService;
... ... @@ -50,9 +43,8 @@ public class MesQcDefectRecordServiceImpl implements MesQcDefectRecordService {
50 43 @Override
51 44 @Transactional(rollbackFor = Exception.class)
52 45 public Long createDefectRecord(MesQcDefectRecordSaveReqVO createReqVO) {
53   - // 1. 校验主表和行表存在
54   - validateQcExists(createReqVO.getQcType(), createReqVO.getQcId());
55   - validateQcLineExists(createReqVO.getQcType(), createReqVO.getLineId());
  46 + // 1. 校验检验单和检验行存在
  47 + validateQcAndLineExists(createReqVO.getQcType(), createReqVO.getQcId(), createReqVO.getLineId());
56 48  
57 49 // 2. 插入
58 50 MesQcDefectRecordDO record = BeanUtils.toBean(createReqVO, MesQcDefectRecordDO.class);
... ... @@ -102,25 +94,10 @@ public class MesQcDefectRecordServiceImpl implements MesQcDefectRecordService {
102 94  
103 95 // ==================== 校验方法 ====================
104 96  
105   - // TODO @AI:validateQcExists、validateQcLineExists 合并成一个方法;然后调用对应的 service 方法;
106   - private void validateQcExists(Integer qcType, Long qcId) {
  97 + private void validateQcAndLineExists(Integer qcType, Long qcId, Long lineId) {
107 98 if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) {
108   - if (iqcMapper.selectById(qcId) == null) {
109   - throw exception(QC_IQC_NOT_EXISTS);
110   - }
111   - } else {
112   - // 后续扩展:IPQC、OQC、RQC
113   - throw exception(QC_DEFECT_RECORD_QC_TYPE_UNSUPPORTED);
114   - }
115   - }
116   -
117   - // TODO @AI:去掉这个,相信调用方
118   - private void validateQcLineExists(Integer qcType, Long lineId) {
119   - if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) {
120   - MesQcIqcLineDO line = iqcLineService.getIqcLine(lineId);
121   - if (line == null) {
122   - throw exception(QC_IQC_LINE_NOT_EXISTS);
123   - }
  99 + iqcService.validateIqcExists(qcId);
  100 + iqcLineService.validateIqcLineExists(lineId);
124 101 } else {
125 102 // 后续扩展:IPQC、OQC、RQC
126 103 throw exception(QC_DEFECT_RECORD_QC_TYPE_UNSUPPORTED);
... ... @@ -138,91 +115,19 @@ public class MesQcDefectRecordServiceImpl implements MesQcDefectRecordService {
138 115 // ==================== 缺陷统计 ====================
139 116  
140 117 /**
141   - * 重新计算缺陷统计(行级 + 主表级)
  118 + * 重新计算缺陷统计(行级 + 主表级),委托给对应的检验 Service
142 119 *
143 120 * @param qcType 检验类型
144 121 * @param qcId 检验单 ID
145 122 */
146   - @SuppressWarnings("DuplicatedCode")
147 123 private void recalculateDefectStats(Integer qcType, Long qcId) {
148   - // 1. 查询所有缺陷记录
149 124 List<MesQcDefectRecordDO> records = defectRecordMapper.selectListByQcTypeAndQcId(qcType, qcId);
150   -
151 125 if (Objects.equals(qcType, MesQcTypeEnum.IQC.getType())) {
152   - // TODO @AI:直接调用 iqcservice 方法;qcId、records
153   - recalculateIqcDefectStats(qcId, records);
  126 + iqcService.recalculateDefectStats(qcId, records);
154 127 } else {
155 128 // 后续扩展:IPQC、OQC、RQC
156 129 throw exception(QC_DEFECT_RECORD_QC_TYPE_UNSUPPORTED);
157 130 }
158 131 }
159 132  
160   - /**
161   - * IQC 缺陷统计重算
162   - */
163   - private void recalculateIqcDefectStats(Long qcId, List<MesQcDefectRecordDO> records) {
164   - // 1. 按行汇总缺陷数量,批量更新
165   - // TODO @AI:1 这块的逻辑,放到 iqcLineService 里,使用 qcId、records;
166   - List<MesQcIqcLineDO> lines = iqcLineService.selectListByIqcId(qcId);
167   - List<MesQcIqcLineDO> updateLines = new ArrayList<>();
168   - for (MesQcIqcLineDO line : lines) {
169   - int critical = 0, major = 0, minor = 0;
170   - for (MesQcDefectRecordDO record : records) {
171   - if (ObjUtil.notEqual(record.getLineId(), line.getId())) {
172   - continue;
173   - }
174   - int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1);
175   - if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) {
176   - critical += quantity;
177   - } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) {
178   - major += quantity;
179   - } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) {
180   - minor += quantity;
181   - } else {
182   - throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN);
183   - }
184   - }
185   - updateLines.add(new MesQcIqcLineDO().setId(line.getId())
186   - .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor));
187   - }
188   - iqcLineService.batchUpdateDefectStats(updateLines);
189   -
190   - // 2. 汇总主表的缺陷数量
191   - // TODO @AI:2-4 这块的逻辑,放到 iqcService 里,使用 qcId、records;
192   - int totalCritical = 0, totalMajor = 0, totalMinor = 0;
193   - for (MesQcDefectRecordDO record : records) {
194   - int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1);
195   - if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) {
196   - totalCritical += quantity;
197   - } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) {
198   - totalMajor += quantity;
199   - } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) {
200   - totalMinor += quantity;
201   - } else {
202   - throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN);
203   - }
204   - }
205   -
206   - // 3. 计算缺陷率
207   - MesQcIqcDO iqc = iqcMapper.selectById(qcId);
208   - BigDecimal criticalRate = BigDecimal.ZERO;
209   - BigDecimal majorRate = BigDecimal.ZERO;
210   - BigDecimal minorRate = BigDecimal.ZERO;
211   - if (iqc != null && iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) {
212   - BigDecimal checkQty = BigDecimal.valueOf(iqc.getCheckQuantity());
213   - criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100))
214   - .divide(checkQty, 2, RoundingMode.HALF_UP);
215   - majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100))
216   - .divide(checkQty, 2, RoundingMode.HALF_UP);
217   - minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100))
218   - .divide(checkQty, 2, RoundingMode.HALF_UP);
219   - }
220   -
221   - // 4. 更新主表
222   - MesQcIqcDO updateIqc = new MesQcIqcDO().setId(qcId)
223   - .setCriticalQuantity(totalCritical).setMajorQuantity(totalMajor).setMinorQuantity(totalMinor)
224   - .setCriticalRate(criticalRate).setMajorRate(majorRate).setMinorRate(minorRate);
225   - iqcMapper.updateById(updateIqc);
226   - }
227   -
228 133 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcLineService.java
... ... @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO;
5 5 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
6 6  
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectRecordDO;
  8 +
7 9 import java.util.List;
8 10  
9 11 /**
... ... @@ -14,6 +16,14 @@ import java.util.List;
14 16 public interface MesQcIqcLineService {
15 17  
16 18 /**
  19 + * 校验来料检验行存在
  20 + *
  21 + * @param id 编号
  22 + * @return 来料检验行
  23 + */
  24 + MesQcIqcLineDO validateIqcLineExists(Long id);
  25 +
  26 + /**
17 27 * 获得来料检验行
18 28 *
19 29 * @param id 编号
... ... @@ -30,14 +40,6 @@ public interface MesQcIqcLineService {
30 40 PageResult<MesQcIqcLineDO> getIqcLinePage(MesQcIqcLinePageReqVO pageReqVO);
31 41  
32 42 /**
33   - * 根据来料检验单 ID 查询所有行
34   - *
35   - * @param iqcId 来料检验单 ID
36   - * @return 行列表
37   - */
38   - List<MesQcIqcLineDO> selectListByIqcId(Long iqcId);
39   -
40   - /**
41 43 * 从模板指标自动生成检验行
42 44 *
43 45 * @param iqcId 来料检验单 ID
... ... @@ -46,11 +48,12 @@ public interface MesQcIqcLineService {
46 48 void createLinesFromTemplate(Long iqcId, Long templateId);
47 49  
48 50 /**
49   - * 批量更新行的缺陷统计数量
  51 + * 根据缺陷记录重新计算各行的缺陷统计数量
50 52 *
51   - * @param lines 待更新的行列表(只需设置 id、criticalQuantity、majorQuantity、minorQuantity)
  53 + * @param iqcId 来料检验单 ID
  54 + * @param records 缺陷记录列表
52 55 */
53   - void batchUpdateDefectStats(List<MesQcIqcLineDO> lines);
  56 + void recalculateLineDefectStats(Long iqcId, List<MesQcDefectRecordDO> records);
54 57  
55 58 /**
56 59 * 根据来料检验单 ID 级联删除所有行
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcLineServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.qc.lqc;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
3 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 6 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.line.MesQcIqcLinePageReqVO;
  7 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectRecordDO;
5 8 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
6 9 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateIndicatorDO;
7 10 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcLineMapper;
8 11 import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateIndicatorMapper;
  12 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
9 13 import jakarta.annotation.Resource;
10 14 import org.springframework.stereotype.Service;
11 15 import org.springframework.validation.annotation.Validated;
12 16  
  17 +import java.util.ArrayList;
13 18 import java.util.List;
  19 +import java.util.Objects;
14 20  
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
15 22 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  23 +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
16 24  
17 25 /**
18 26 * MES 来料检验单行 Service 实现类
... ... @@ -29,6 +37,15 @@ public class MesQcIqcLineServiceImpl implements MesQcIqcLineService {
29 37 private MesQcTemplateIndicatorMapper templateIndicatorMapper;
30 38  
31 39 @Override
  40 + public MesQcIqcLineDO validateIqcLineExists(Long id) {
  41 + MesQcIqcLineDO line = iqcLineMapper.selectById(id);
  42 + if (line == null) {
  43 + throw exception(QC_IQC_LINE_NOT_EXISTS);
  44 + }
  45 + return line;
  46 + }
  47 +
  48 + @Override
32 49 public MesQcIqcLineDO getIqcLine(Long id) {
33 50 return iqcLineMapper.selectById(id);
34 51 }
... ... @@ -39,11 +56,6 @@ public class MesQcIqcLineServiceImpl implements MesQcIqcLineService {
39 56 }
40 57  
41 58 @Override
42   - public List<MesQcIqcLineDO> selectListByIqcId(Long iqcId) {
43   - return iqcLineMapper.selectListByIqcId(iqcId);
44   - }
45   -
46   - @Override
47 59 public void createLinesFromTemplate(Long iqcId, Long templateId) {
48 60 List<MesQcTemplateIndicatorDO> indicators = templateIndicatorMapper.selectListByTemplateId(templateId);
49 61 List<MesQcIqcLineDO> lines = convertList(indicators, indicator -> new MesQcIqcLineDO()
... ... @@ -57,9 +69,34 @@ public class MesQcIqcLineServiceImpl implements MesQcIqcLineService {
57 69 }
58 70  
59 71 @Override
60   - public void batchUpdateDefectStats(List<MesQcIqcLineDO> lines) {
  72 + public void recalculateLineDefectStats(Long iqcId, List<MesQcDefectRecordDO> records) {
  73 + List<MesQcIqcLineDO> lines = iqcLineMapper.selectListByIqcId(iqcId);
  74 + if (CollUtil.isEmpty(lines)) {
  75 + return;
  76 + }
  77 + List<MesQcIqcLineDO> updateLines = new ArrayList<>(lines.size());
61 78 for (MesQcIqcLineDO line : lines) {
62   - iqcLineMapper.updateById(line);
  79 + int critical = 0, major = 0, minor = 0;
  80 + for (MesQcDefectRecordDO record : records) {
  81 + if (ObjUtil.notEqual(record.getLineId(), line.getId())) {
  82 + continue;
  83 + }
  84 + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1);
  85 + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) {
  86 + critical += quantity;
  87 + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) {
  88 + major += quantity;
  89 + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) {
  90 + minor += quantity;
  91 + } else {
  92 + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN);
  93 + }
  94 + }
  95 + updateLines.add(new MesQcIqcLineDO().setId(line.getId())
  96 + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor));
  97 + }
  98 + for (MesQcIqcLineDO updateLine : updateLines) {
  99 + iqcLineMapper.updateById(updateLine);
63 100 }
64 101 }
65 102  
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcService.java
... ... @@ -3,9 +3,12 @@ package cn.iocoder.yudao.module.mes.service.qc.lqc;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO;
5 5 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcSaveReqVO;
  6 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectRecordDO;
6 7 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
7 8 import jakarta.validation.Valid;
8 9  
  10 +import java.util.List;
  11 +
9 12 /**
10 13 * MES 来料检验单(IQC) Service 接口
11 14 *
... ... @@ -43,6 +46,14 @@ public interface MesQcIqcService {
43 46 void deleteIqc(Long id);
44 47  
45 48 /**
  49 + * 校验来料检验单存在
  50 + *
  51 + * @param id 编号
  52 + * @return 来料检验单
  53 + */
  54 + MesQcIqcDO validateIqcExists(Long id);
  55 +
  56 + /**
46 57 * 获得来料检验单
47 58 *
48 59 * @param id 编号
... ... @@ -58,4 +69,12 @@ public interface MesQcIqcService {
58 69 */
59 70 PageResult<MesQcIqcDO> getIqcPage(MesQcIqcPageReqVO pageReqVO);
60 71  
  72 + /**
  73 + * 根据缺陷记录重新计算主表的缺陷统计(含行级下沉)
  74 + *
  75 + * @param iqcId 来料检验单 ID
  76 + * @param records 缺陷记录列表
  77 + */
  78 + void recalculateDefectStats(Long iqcId, List<MesQcDefectRecordDO> records);
  79 +
61 80 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java
... ... @@ -6,10 +6,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
7 7 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO;
8 8 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcSaveReqVO;
  9 +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.defect.MesQcDefectRecordDO;
9 10 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
10 11 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO;
11 12 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO;
12 13 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper;
  14 +import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
13 15 import cn.iocoder.yudao.module.mes.enums.qc.MesQcIqcStatusEnum;
14 16 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
15 17 import cn.iocoder.yudao.module.mes.service.qc.defect.MesQcDefectRecordService;
... ... @@ -19,6 +21,11 @@ import org.springframework.stereotype.Service;
19 21 import org.springframework.transaction.annotation.Transactional;
20 22 import org.springframework.validation.annotation.Validated;
21 23  
  24 +import java.math.BigDecimal;
  25 +import java.math.RoundingMode;
  26 +import java.util.List;
  27 +import java.util.Objects;
  28 +
22 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
23 30 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
24 31  
... ... @@ -121,6 +128,15 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
121 128 defectRecordService.deleteByQcTypeAndQcId(MesQcTypeEnum.IQC.getType(), id);
122 129 }
123 130  
  131 + @Override
  132 + public MesQcIqcDO validateIqcExists(Long id) {
  133 + MesQcIqcDO iqc = iqcMapper.selectById(id);
  134 + if (iqc == null) {
  135 + throw exception(QC_IQC_NOT_EXISTS);
  136 + }
  137 + return iqc;
  138 + }
  139 +
124 140 /**
125 141 * 校验来料检验单存在且为草稿状态
126 142 *
... ... @@ -128,10 +144,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
128 144 * @return 来料检验单
129 145 */
130 146 private MesQcIqcDO validateIqcStatusPrepare(Long id) {
131   - MesQcIqcDO iqc = iqcMapper.selectById(id);
132   - if (iqc == null) {
133   - throw exception(QC_IQC_NOT_EXISTS);
134   - }
  147 + MesQcIqcDO iqc = validateIqcExists(id);
135 148 if (ObjUtil.notEqual(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
136 149 throw exception(QC_IQC_NOT_PREPARE);
137 150 }
... ... @@ -158,4 +171,45 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
158 171 return iqcMapper.selectPage(pageReqVO);
159 172 }
160 173  
  174 + @Override
  175 + public void recalculateDefectStats(Long iqcId, List<MesQcDefectRecordDO> records) {
  176 + // 1. 行级缺陷统计
  177 + iqcLineService.recalculateLineDefectStats(iqcId, records);
  178 +
  179 + // 2.1 汇总主表的缺陷数量
  180 + int totalCritical = 0, totalMajor = 0, totalMinor = 0;
  181 + for (MesQcDefectRecordDO record : records) {
  182 + int quantity = ObjUtil.defaultIfNull(record.getQuantity(), 1);
  183 + if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) {
  184 + totalCritical += quantity;
  185 + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MAJOR.getType())) {
  186 + totalMajor += quantity;
  187 + } else if (Objects.equals(record.getLevel(), MesQcDefectLevelEnum.MINOR.getType())) {
  188 + totalMinor += quantity;
  189 + } else {
  190 + throw exception(QC_DEFECT_RECORD_LEVEL_UNKNOWN);
  191 + }
  192 + }
  193 + // 2.2 计算缺陷率
  194 + MesQcIqcDO iqc = validateIqcExists(iqcId);
  195 + BigDecimal criticalRate = BigDecimal.ZERO;
  196 + BigDecimal majorRate = BigDecimal.ZERO;
  197 + BigDecimal minorRate = BigDecimal.ZERO;
  198 + if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) {
  199 + BigDecimal checkQty = BigDecimal.valueOf(iqc.getCheckQuantity());
  200 + criticalRate = BigDecimal.valueOf(totalCritical).multiply(BigDecimal.valueOf(100))
  201 + .divide(checkQty, 2, RoundingMode.HALF_UP);
  202 + majorRate = BigDecimal.valueOf(totalMajor).multiply(BigDecimal.valueOf(100))
  203 + .divide(checkQty, 2, RoundingMode.HALF_UP);
  204 + minorRate = BigDecimal.valueOf(totalMinor).multiply(BigDecimal.valueOf(100))
  205 + .divide(checkQty, 2, RoundingMode.HALF_UP);
  206 + }
  207 +
  208 + // 3. 更新主表
  209 + MesQcIqcDO updateIqc = new MesQcIqcDO().setId(iqcId)
  210 + .setCriticalQuantity(totalCritical).setMajorQuantity(totalMajor).setMinorQuantity(totalMinor)
  211 + .setCriticalRate(criticalRate).setMajorRate(majorRate).setMinorRate(minorRate);
  212 + iqcMapper.updateById(updateIqc);
  213 + }
  214 +
161 215 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java
... ... @@ -25,8 +25,11 @@ import org.springframework.validation.annotation.Validated;
25 25 import java.util.Collection;
26 26 import java.util.Collections;
27 27 import java.util.List;
  28 +import java.util.Set;
28 29  
29 30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  31 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
  32 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst;
30 33 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
31 34  
32 35 /**
... ... @@ -116,15 +119,11 @@ public class MesQcTemplateServiceImpl implements MesQcTemplateService {
116 119 return null;
117 120 }
118 121 // 1.2 批量查模板,筛选 types 包含给定 qcType 的第一个
119   - // TODO @AI:convertSet;
120   - List<Long> templateIds = templateItems.stream()
121   - .map(MesQcTemplateItemDO::getTemplateId).distinct().toList();
122   - List<MesQcTemplateDO> templates = templateMapper.selectByIds(templateIds);
123   -
124   - // 2. 筛选 types 包含给定 qcType 的第一个 TODO @AI:findOne;
125   - return templates.stream()
126   - .filter(t -> CollUtil.contains(t.getTypes(), qcType))
127   - .findFirst().orElse(null);
  122 + List<MesQcTemplateDO> templates = templateMapper.selectByIds(
  123 + convertSet(templateItems, MesQcTemplateItemDO::getTemplateId));
  124 +
  125 + // 2. 筛选 types 包含给定 qcType 的第一个
  126 + return findFirst(templates, template -> CollUtil.contains(template.getTypes(), qcType));
128 127 }
129 128  
130 129 @Override
... ...