From a347943b68595902809f67578fdf5cca84b7f8af Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 21 Feb 2026 08:10:54 +0800 Subject: [PATCH] feat(mes): 优化缺陷统计计算逻辑,重构模板校验方法,增强代码可读性 --- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectServiceImpl.java | 58 ++++++++++++++++++++++++++++++++-------------------------- yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java | 41 +++++++++++++++++------------------------ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java | 17 +++++++++++++++++ yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java | 12 ++++++++++-- 4 files changed, 76 insertions(+), 52 deletions(-) diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectServiceImpl.java index 85e23e2..fe9bce3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.mes.service.qc.lqc; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.defect.MesQcIqcDefectPageReqVO; @@ -124,6 +125,7 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService { * * @param iqcId 来料检验单 ID */ + @SuppressWarnings("DuplicatedCode") private void recalculateDefectStats(Long iqcId) { // 1. 查询所有缺陷记录 List defects = iqcDefectMapper.selectListByIqcId(iqcId); @@ -131,44 +133,38 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService { // 2. 更新每行的缺陷数量 List lines = iqcLineService.selectListByIqcId(iqcId); for (MesQcIqcLineDO line : lines) { - int critical = 0; - int major = 0; - int minor = 0; + int critical = 0, major = 0, minor = 0; for (MesQcIqcDefectDO defect : defects) { - // TODO @AI:notEquals continue;减少括号层级; - if (Objects.equals(defect.getLineId(), line.getId())) { - // TODO @AI:defaultIfNull;变量改成 quantity - int qty = defect.getDefectQuantity() != null ? defect.getDefectQuantity() : 1; - if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { - critical += qty; - } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { - major += qty; - } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MINOR.getType())) { - minor += qty; - } - // TODO @AI:抛出异常;未知的缺陷等级 + if (ObjUtil.notEqual(defect.getLineId(), line.getId())) { + continue; + } + int quantity = ObjUtil.defaultIfNull(defect.getDefectQuantity(), 1); + if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { + critical += quantity; + } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { + major += quantity; + } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MINOR.getType())) { + minor += quantity; + } else { + throw exception(QC_IQC_DEFECT_LEVEL_UNKNOWN); } } - MesQcIqcLineDO updateLine = new MesQcIqcLineDO().setId(line.getId()) - .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor); - // 直接通过 lineService 内部更新(避免循环依赖,使用 mapper) - // TODO @AI:单独搞个 updateLineDefectStats 方法;减少 updateLine 变量的作用域; - iqcLineMapper.updateById(updateLine); + updateLineDefectStats(line.getId(), critical, major, minor); } // 3.1 汇总主表的缺陷数量 int totalCritical = 0, totalMajor = 0, totalMinor = 0; for (MesQcIqcDefectDO defect : defects) { - // TODO @AI:defaultIfNull;变量改成 quantity - int qty = defect.getDefectQuantity() != null ? defect.getDefectQuantity() : 1; + int quantity = ObjUtil.defaultIfNull(defect.getDefectQuantity(), 1); if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.CRITICAL.getType())) { - totalCritical += qty; + totalCritical += quantity; } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MAJOR.getType())) { - totalMajor += qty; + totalMajor += quantity; } else if (Objects.equals(defect.getDefectLevel(), MesQcDefectLevelEnum.MINOR.getType())) { - totalMinor += qty; + totalMinor += quantity; + } else { + throw exception(QC_IQC_DEFECT_LEVEL_UNKNOWN); } - // TODO @AI:抛出异常;未知的缺陷等级 } // 3.2 计算缺陷率 MesQcIqcDO iqc = iqcMapper.selectById(iqcId); @@ -191,4 +187,14 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService { iqcMapper.updateById(updateIqc); } + // TODO @AI:在 iqclineservice 里,提供一个方法,直接根据行 ID 列表,批量更新缺陷统计数量。然后这里直接调用即可,避免循环更新数据库。 + /** + * 更新检验行的缺陷统计数量 + */ + private void updateLineDefectStats(Long lineId, int critical, int major, int minor) { + MesQcIqcLineDO updateLine = new MesQcIqcLineDO().setId(lineId) + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor); + iqcLineMapper.updateById(updateLine); + } + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java index 4535934..5627cfb 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.mes.service.qc.lqc; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateDO; import cn.iocoder.yudao.module.mes.dal.dataobject.qc.template.MesQcTemplateItemDO; import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateItemMapper; -import cn.iocoder.yudao.module.mes.dal.mysql.qc.template.MesQcTemplateMapper; import cn.iocoder.yudao.module.mes.enums.qc.MesQcIqcStatusEnum; import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; +import cn.iocoder.yudao.module.mes.service.qc.template.MesQcTemplateService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.util.Objects; - import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; @@ -35,9 +34,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @Resource private MesQcIqcMapper iqcMapper; @Resource - private MesQcTemplateMapper templateMapper; - @Resource - private MesQcTemplateItemMapper templateItemMapper; + private MesQcTemplateService templateService; @Resource private MesQcIqcLineService iqcLineService; @@ -51,16 +48,13 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { validateIqcCodeUnique(null, createReqVO.getCode()); // 1.2 查找物料关联的 IQC 检测模板 Long templateId = createReqVO.getTemplateId(); - // TODO @AI:直接使用 templateService 的 validateTemplateExists() 方法,后续如果有更多模板相关的校验,也可以放在该方法中 - MesQcTemplateDO template = templateMapper.selectById(templateId); - // TODO @AI:CollUtil.contains 这样更合适; - if (template == null || template.getTypes() == null || !template.getTypes().contains(MesQcTypeEnum.IQC.getType())) { + MesQcTemplateDO template = templateService.validateTemplateExists(templateId); + if (!CollUtil.contains(template.getTypes(), MesQcTypeEnum.IQC.getType())) { throw exception(QC_IQC_NO_TEMPLATE); } // 3.1 从模板的产品关联中获取检测参数(min_check_quantity、max_unqualified_quantity) - // TODO @AI:使用 templateItemService 方法,不要直接使用对方的 mapper; - MesQcTemplateItemDO templateItem = templateItemMapper.selectByTemplateIdAndItemId( + MesQcTemplateItemDO templateItem = templateService.getTemplateItemByTemplateIdAndItemId( templateId, createReqVO.getItemId()); if (templateItem != null) { if (createReqVO.getMinCheckQuantity() == null) { @@ -85,11 +79,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { // 1.1 校验存在 MesQcIqcDO iqc = validateIqcExists(updateReqVO.getId()); // 1.2 校验状态为草稿 - // TODO @AI:notEquals; - // TODO @AI:抽成一个方法,这样 completeIqc 和 deleteIqc 也可以复用,避免重复代码; - if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) { - throw exception(QC_IQC_ONLY_PREPARE_CAN_COMPLETE); - } + validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_COMPLETE); // 1.3 校验编号唯一 validateIqcCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); @@ -103,9 +93,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { // 1.1 校验存在 MesQcIqcDO iqc = validateIqcExists(id); // 1.2 校验状态为草稿 - if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) { - throw exception(QC_IQC_ONLY_PREPARE_CAN_COMPLETE); - } + validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_COMPLETE); // 1.3 校验合格品 + 不合格品 = 检测数量 if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) { int total = (iqc.getQualifiedQuantity() != null ? iqc.getQualifiedQuantity() : 0) @@ -129,9 +117,7 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { // 1.1 校验存在 MesQcIqcDO iqc = validateIqcExists(id); // 1.2 仅草稿可删 - if (!Objects.equals(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) { - throw exception(QC_IQC_ONLY_PREPARE_CAN_DELETE); - } + validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_DELETE); // 2.1 删除主表 iqcMapper.deleteById(id); @@ -149,6 +135,13 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { return iqc; } + // TODO @AI:就搞个方法,传递 id 进去;抛出不为 草稿状态的异常;然后在 update/delete/complete 方法中调用这个方法(不用专门 errorCode) + private void validatePrepareStatus(MesQcIqcDO iqc, ErrorCode errorCode) { + if (ObjUtil.notEqual(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) { + throw exception(errorCode); + } + } + private void validateIqcCodeUnique(Long id, String code) { MesQcIqcDO iqc = iqcMapper.selectByCode(code); if (iqc == null) { diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java index 55af914..940091b 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateService.java @@ -90,6 +90,23 @@ public interface MesQcTemplateService { return convertMap(getTemplateList(ids), MesQcTemplateDO::getId); } + /** + * 校验质检方案存在 + * + * @param id 编号 + * @return 质检方案 + */ + MesQcTemplateDO validateTemplateExists(Long id); + + /** + * 根据方案 ID + 产品 ID 获取产品关联 + * + * @param templateId 方案 ID + * @param itemId 产品 ID + * @return 产品关联(可能为 null) + */ + MesQcTemplateItemDO getTemplateItemByTemplateIdAndItemId(Long templateId, Long itemId); + // ========== 质检方案-检测指标项 ========== /** diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java index 1cf8486..6fc0f5f 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/template/MesQcTemplateServiceImpl.java +++ b/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 { templateItemMapper.deleteByTemplateId(id); } - private void validateTemplateExists(Long id) { - if (templateMapper.selectById(id) == null) { + @Override + public MesQcTemplateDO validateTemplateExists(Long id) { + MesQcTemplateDO template = templateMapper.selectById(id); + if (template == null) { throw exception(QC_TEMPLATE_NOT_EXISTS); } + return template; } private void validateTemplateCodeUnique(Long id, String code) { @@ -101,6 +104,11 @@ public class MesQcTemplateServiceImpl implements MesQcTemplateService { } @Override + public MesQcTemplateItemDO getTemplateItemByTemplateIdAndItemId(Long templateId, Long itemId) { + return templateItemMapper.selectByTemplateIdAndItemId(templateId, itemId); + } + + @Override public MesQcTemplateDO getTemplate(Long id) { return templateMapper.selectById(id); } -- libgit2 0.21.4