Commit a347943b68595902809f67578fdf5cca84b7f8af

Authored by YunaiV
1 parent 015eab68

feat(mes): 优化缺陷统计计算逻辑,重构模板校验方法,增强代码可读性

yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.qc.lqc;
2 2  
  3 +import cn.hutool.core.util.ObjUtil;
3 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 6 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectPageReqVO;
... ... @@ -124,6 +125,7 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService {
124 125 *
125 126 * @param iqcId 来料检验单 ID
126 127 */
  128 + @SuppressWarnings("DuplicatedCode")
127 129 private void recalculateDefectStats(Long iqcId) {
128 130 // 1. 查询所有缺陷记录
129 131 List<MesQcIqcDefectDO> defects = iqcDefectMapper.selectListByIqcId(iqcId);
... ... @@ -131,44 +133,38 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService {
131 133 // 2. 更新每行的缺陷数量
132 134 List<MesQcIqcLineDO> lines = iqcLineService.selectListByIqcId(iqcId);
133 135 for (MesQcIqcLineDO line : lines) {
134   - int critical = 0;
135   - int major = 0;
136   - int minor = 0;
  136 + int critical = 0, major = 0, minor = 0;
137 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:抛出异常;未知的缺陷等级
  138 + if (ObjUtil.notEqual(defect.getLineId(), line.getId())) {
  139 + continue;
  140 + }
  141 + int quantity = ObjUtil.defaultIfNull(defect.getDefectQuantity(), 1);
  142 + if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) {
  143 + critical += quantity;
  144 + } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MAJOR.getType())) {
  145 + major += quantity;
  146 + } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MINOR.getType())) {
  147 + minor += quantity;
  148 + } else {
  149 + throw exception(QC_IQC_DEFECT_LEVEL_UNKNOWN);
150 150 }
151 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);
  152 + updateLineDefectStats(line.getId(), critical, major, minor);
157 153 }
158 154  
159 155 // 3.1 汇总主表的缺陷数量
160 156 int totalCritical = 0, totalMajor = 0, totalMinor = 0;
161 157 for (MesQcIqcDefectDO defect : defects) {
162   - // TODO @AI:defaultIfNull;变量改成 quantity
163   - int qty = defect.getDefectQuantity() != null ? defect.getDefectQuantity() : 1;
  158 + int quantity = ObjUtil.defaultIfNull(defect.getDefectQuantity(), 1);
164 159 if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) {
165   - totalCritical += qty;
  160 + totalCritical += quantity;
166 161 } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MAJOR.getType())) {
167   - totalMajor += qty;
  162 + totalMajor += quantity;
168 163 } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MINOR.getType())) {
169   - totalMinor += qty;
  164 + totalMinor += quantity;
  165 + } else {
  166 + throw exception(QC_IQC_DEFECT_LEVEL_UNKNOWN);
170 167 }
171   - // TODO @AI:抛出异常;未知的缺陷等级
172 168 }
173 169 // 3.2 计算缺陷率
174 170 MesQcIqcDO iqc = iqcMapper.selectById(iqcId);
... ... @@ -191,4 +187,14 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService {
191 187 iqcMapper.updateById(updateIqc);
192 188 }
193 189  
  190 + // TODO @AI:在 iqclineservice 里,提供一个方法,直接根据行 ID 列表,批量更新缺陷统计数量。然后这里直接调用即可,避免循环更新数据库。
  191 + /**
  192 + * 更新检验行的缺陷统计数量
  193 + */
  194 + private void updateLineDefectStats(Long lineId, int critical, int major, int minor) {
  195 + MesQcIqcLineDO updateLine = new MesQcIqcLineDO().setId(lineId)
  196 + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor);
  197 + iqcLineMapper.updateById(updateLine);
  198 + }
  199 +
194 200 }
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java
1 1 package cn.iocoder.yudao.module.mes.service.qc.lqc;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.hutool.core.util.ObjUtil;
  5 +import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6 8 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO;
... ... @@ -9,17 +11,14 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
9 11 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO;
10 12 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO;
11 13 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper;
12   -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateItemMapper;
13   -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateMapper;
14 14 import cn.iocoder.yudao.module.mes.enums.qc.MesQcIqcStatusEnum;
15 15 import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum;
  16 +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateService;
16 17 import jakarta.annotation.Resource;
17 18 import org.springframework.stereotype.Service;
18 19 import org.springframework.transaction.annotation.Transactional;
19 20 import org.springframework.validation.annotation.Validated;
20 21  
21   -import java.util.Objects;
22   -
23 22 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
24 23 import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;
25 24  
... ... @@ -35,9 +34,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
35 34 @Resource
36 35 private MesQcIqcMapper iqcMapper;
37 36 @Resource
38   - private MesQcTemplateMapper templateMapper;
39   - @Resource
40   - private MesQcTemplateItemMapper templateItemMapper;
  37 + private MesQcTemplateService templateService;
41 38  
42 39 @Resource
43 40 private MesQcIqcLineService iqcLineService;
... ... @@ -51,16 +48,13 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
51 48 validateIqcCodeUnique(null, createReqVO.getCode());
52 49 // 1.2 查找物料关联的 IQC 检测模板
53 50 Long templateId = createReqVO.getTemplateId();
54   - // TODO @AI:直接使用 templateService 的 validateTemplateExists() 方法,后续如果有更多模板相关的校验,也可以放在该方法中
55   - MesQcTemplateDO template = templateMapper.selectById(templateId);
56   - // TODO @AI:CollUtil.contains 这样更合适;
57   - if (template == null || template.getTypes() == null || !template.getTypes().contains(MesQcTypeEnum.IQC.getType())) {
  51 + MesQcTemplateDO template = templateService.validateTemplateExists(templateId);
  52 + if (!CollUtil.contains(template.getTypes(), MesQcTypeEnum.IQC.getType())) {
58 53 throw exception(QC_IQC_NO_TEMPLATE);
59 54 }
60 55  
61 56 // 3.1 从模板的产品关联中获取检测参数(min_check_quantity、max_unqualified_quantity)
62   - // TODO @AI:使用 templateItemService 方法,不要直接使用对方的 mapper;
63   - MesQcTemplateItemDO templateItem = templateItemMapper.selectByTemplateIdAndItemId(
  57 + MesQcTemplateItemDO templateItem = templateService.getTemplateItemByTemplateIdAndItemId(
64 58 templateId, createReqVO.getItemId());
65 59 if (templateItem != null) {
66 60 if (createReqVO.getMinCheckQuantity() == null) {
... ... @@ -85,11 +79,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
85 79 // 1.1 校验存在
86 80 MesQcIqcDO iqc = validateIqcExists(updateReqVO.getId());
87 81 // 1.2 校验状态为草稿
88   - // TODO @AI:notEquals;
89   - // TODO @AI:抽成一个方法,这样 completeIqc 和 deleteIqc 也可以复用,避免重复代码;
90   - if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
91   - throw exception(QC_IQC_ONLY_PREPARE_CAN_COMPLETE);
92   - }
  82 + validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_COMPLETE);
93 83 // 1.3 校验编号唯一
94 84 validateIqcCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
95 85  
... ... @@ -103,9 +93,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
103 93 // 1.1 校验存在
104 94 MesQcIqcDO iqc = validateIqcExists(id);
105 95 // 1.2 校验状态为草稿
106   - if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
107   - throw exception(QC_IQC_ONLY_PREPARE_CAN_COMPLETE);
108   - }
  96 + validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_COMPLETE);
109 97 // 1.3 校验合格品 + 不合格品 = 检测数量
110 98 if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) {
111 99 int total = (iqc.getQualifiedQuantity() != null ? iqc.getQualifiedQuantity() : 0)
... ... @@ -129,9 +117,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
129 117 // 1.1 校验存在
130 118 MesQcIqcDO iqc = validateIqcExists(id);
131 119 // 1.2 仅草稿可删
132   - if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
133   - throw exception(QC_IQC_ONLY_PREPARE_CAN_DELETE);
134   - }
  120 + validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_DELETE);
135 121  
136 122 // 2.1 删除主表
137 123 iqcMapper.deleteById(id);
... ... @@ -149,6 +135,13 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
149 135 return iqc;
150 136 }
151 137  
  138 + // TODO @AI:就搞个方法,传递 id 进去;抛出不为 草稿状态的异常;然后在 update/delete/complete 方法中调用这个方法(不用专门 errorCode)
  139 + private void validatePrepareStatus(MesQcIqcDO iqc, ErrorCode errorCode) {
  140 + if (ObjUtil.notEqual(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
  141 + throw exception(errorCode);
  142 + }
  143 + }
  144 +
152 145 private void validateIqcCodeUnique(Long id, String code) {
153 146 MesQcIqcDO iqc = iqcMapper.selectByCode(code);
154 147 if (iqc == null) {
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java
... ... @@ -90,6 +90,23 @@ public interface MesQcTemplateService {
90 90 return convertMap(getTemplateList(ids), MesQcTemplateDO::getId);
91 91 }
92 92  
  93 + /**
  94 + * 校验质检方案存在
  95 + *
  96 + * @param id 编号
  97 + * @return 质检方案
  98 + */
  99 + MesQcTemplateDO validateTemplateExists(Long id);
  100 +
  101 + /**
  102 + * 根据方案 ID + 产品 ID 获取产品关联
  103 + *
  104 + * @param templateId 方案 ID
  105 + * @param itemId 产品 ID
  106 + * @return 产品关联(可能为 null)
  107 + */
  108 + MesQcTemplateItemDO getTemplateItemByTemplateIdAndItemId(Long templateId, Long itemId);
  109 +
93 110 // ========== 质检方案-检测指标项 ==========
94 111  
95 112 /**
... ...
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java
... ... @@ -84,10 +84,13 @@ public class MesQcTemplateServiceImpl implements MesQcTemplateService {
84 84 templateItemMapper.deleteByTemplateId(id);
85 85 }
86 86  
87   - private void validateTemplateExists(Long id) {
88   - if (templateMapper.selectById(id) == null) {
  87 + @Override
  88 + public MesQcTemplateDO validateTemplateExists(Long id) {
  89 + MesQcTemplateDO template = templateMapper.selectById(id);
  90 + if (template == null) {
89 91 throw exception(QC_TEMPLATE_NOT_EXISTS);
90 92 }
  93 + return template;
91 94 }
92 95  
93 96 private void validateTemplateCodeUnique(Long id, String code) {
... ... @@ -101,6 +104,11 @@ public class MesQcTemplateServiceImpl implements MesQcTemplateService {
101 104 }
102 105  
103 106 @Override
  107 + public MesQcTemplateItemDO getTemplateItemByTemplateIdAndItemId(Long templateId, Long itemId) {
  108 + return templateItemMapper.selectByTemplateIdAndItemId(templateId, itemId);
  109 + }
  110 +
  111 + @Override
104 112 public MesQcTemplateDO getTemplate(Long id) {
105 113 return templateMapper.selectById(id);
106 114 }
... ...