Commit d8488e8393210649709a3670391adc689760eae5

Authored by YunaiV
1 parent c9ef6451

feat(mes): 添加生产任务选择器和工单选择器组件,支持前端过滤功能

yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/checkplan/MesDvCheckPlanDO.java
1 package cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan; 1 package cn.iocoder.yudao.module.mes.dal.dataobject.dv.checkplan;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
4 import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckPlanStatusEnum; 5 import cn.iocoder.yudao.module.mes.enums.dv.MesDvCheckPlanStatusEnum;
5 import com.baomidou.mybatisplus.annotation.KeySequence; 6 import com.baomidou.mybatisplus.annotation.KeySequence;
6 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
@@ -37,11 +38,10 @@ public class MesDvCheckPlanDO extends BaseDO { @@ -37,11 +38,10 @@ public class MesDvCheckPlanDO extends BaseDO {
37 * 方案名称 38 * 方案名称
38 */ 39 */
39 private String name; 40 private String name;
40 - // TODO @AI:需要在 dict constants 里枚举下,然后 @过去  
41 /** 41 /**
42 * 方案类型 42 * 方案类型
43 * 43 *
44 - * 字典类型 mes_dv_subject_type(1=设备点检,2=设备保养) 44 + * 字典 {@link DictTypeConstants#MES_DV_SUBJECT_TYPE}
45 */ 45 */
46 private Integer type; 46 private Integer type;
47 /** 47 /**
@@ -52,11 +52,10 @@ public class MesDvCheckPlanDO extends BaseDO { @@ -52,11 +52,10 @@ public class MesDvCheckPlanDO extends BaseDO {
52 * 结束日期 52 * 结束日期
53 */ 53 */
54 private LocalDateTime endDate; 54 private LocalDateTime endDate;
55 - // TODO @AI:需要在 dict constants 里枚举下,然后 @过去  
56 /** 55 /**
57 * 周期类型 56 * 周期类型
58 * 57 *
59 - * 字典类型 mes_dv_cycle_type(1=天,2=周,3=月,4=年) 58 + * 字典 {@link DictTypeConstants#MES_DV_CYCLE_TYPE}
60 */ 59 */
61 private Integer cycleType; 60 private Integer cycleType;
62 /** 61 /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/wm/materialstock/MesWmMaterialStockDO.java
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
5 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; 5 import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO;
6 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO; 6 import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
7 import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO; 7 import cn.iocoder.yudao.module.mes.dal.dataobject.md.vendor.MesMdVendorDO;
  8 +import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
8 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO; 9 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseAreaDO;
9 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO; 10 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseDO;
10 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO; 11 import cn.iocoder.yudao.module.mes.dal.dataobject.wm.warehouse.MesWmWarehouseLocationDO;
@@ -85,11 +86,10 @@ public class MesWmMaterialStockDO extends BaseDO { @@ -85,11 +86,10 @@ public class MesWmMaterialStockDO extends BaseDO {
85 * 关联 {@link MesMdVendorDO#getId()} 86 * 关联 {@link MesMdVendorDO#getId()}
86 */ 87 */
87 private Long vendorId; 88 private Long vendorId;
88 - // TODO @AI:去关联下;  
89 /** 89 /**
90 * 生产工单编号 90 * 生产工单编号
91 * 91 *
92 - * TODO @芋艿:待 mes_pro_work_order 模块完成后关联 92 + * 关联 {@link MesProWorkOrderDO#getId()}
93 */ 93 */
94 private Long workOrderId; 94 private Long workOrderId;
95 /** 95 /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -247,8 +247,7 @@ public interface ErrorCodeConstants { @@ -247,8 +247,7 @@ public interface ErrorCodeConstants {
247 // ========== MES 质量管理-来料检验 IQC(1-040-603-000) ========== 247 // ========== MES 质量管理-来料检验 IQC(1-040-603-000) ==========
248 ErrorCode QC_IQC_NOT_EXISTS = new ErrorCode(1_040_603_000, "来料检验单不存在"); 248 ErrorCode QC_IQC_NOT_EXISTS = new ErrorCode(1_040_603_000, "来料检验单不存在");
249 ErrorCode QC_IQC_CODE_DUPLICATE = new ErrorCode(1_040_603_001, "来料检验单编号已存在"); 249 ErrorCode QC_IQC_CODE_DUPLICATE = new ErrorCode(1_040_603_001, "来料检验单编号已存在");
250 - ErrorCode QC_IQC_ONLY_PREPARE_CAN_DELETE = new ErrorCode(1_040_603_002, "只能删除草稿状态的检验单");  
251 - ErrorCode QC_IQC_ONLY_PREPARE_CAN_COMPLETE = new ErrorCode(1_040_603_003, "只能完成草稿状态的检验单"); 250 + ErrorCode QC_IQC_NOT_PREPARE = new ErrorCode(1_040_603_002, "只有草稿状态的检验单才可操作");
252 ErrorCode QC_IQC_QUANTITY_MISMATCH = new ErrorCode(1_040_603_004, "合格品与不合格品数量之和须等于检测数量"); 251 ErrorCode QC_IQC_QUANTITY_MISMATCH = new ErrorCode(1_040_603_004, "合格品与不合格品数量之和须等于检测数量");
253 ErrorCode QC_IQC_NO_TEMPLATE = new ErrorCode(1_040_603_005, "当前产品未配置 IQC 检测模板"); 252 ErrorCode QC_IQC_NO_TEMPLATE = new ErrorCode(1_040_603_005, "当前产品未配置 IQC 检测模板");
254 // ========== MES 质量管理-来料检验行(1-040-603-100) ========== 253 // ========== MES 质量管理-来料检验行(1-040-603-100) ==========
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/process/MesProProcessServiceImpl.java
@@ -70,8 +70,7 @@ public class MesProProcessServiceImpl implements MesProProcessService { @@ -70,8 +70,7 @@ public class MesProProcessServiceImpl implements MesProProcessService {
70 // 1.1 校验存在 70 // 1.1 校验存在
71 validateProcessExists(id); 71 validateProcessExists(id);
72 // 1.2 校验是否被工艺路线引用 72 // 1.2 校验是否被工艺路线引用
73 - // TODO @AI:CollUtil.isNotEmpty() 可能更好  
74 - if (!routeProcessMapper.selectListByProcessId(id).isEmpty()) { 73 + if (CollUtil.isNotEmpty(routeProcessMapper.selectListByProcessId(id))) {
75 throw exception(PRO_PROCESS_USED_BY_ROUTE); 74 throw exception(PRO_PROCESS_USED_BY_ROUTE);
76 } 75 }
77 76
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderService.java
@@ -112,4 +112,11 @@ public interface MesProWorkOrderService { @@ -112,4 +112,11 @@ public interface MesProWorkOrderService {
112 */ 112 */
113 void cancelWorkOrder(Long id); 113 void cancelWorkOrder(Long id);
114 114
  115 + /**
  116 + * 获得工单精简列表(用于下拉选项)
  117 + *
  118 + * @return 工单列表
  119 + */
  120 + List<MesProWorkOrderDO> getWorkOrderSimpleList();
  121 +
115 } 122 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/workorder/MesProWorkorderServiceImpl.java
@@ -222,6 +222,11 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService { @@ -222,6 +222,11 @@ public class MesProWorkOrderServiceImpl implements MesProWorkOrderService {
222 } 222 }
223 } 223 }
224 224
  225 + @Override
  226 + public List<MesProWorkOrderDO> getWorkOrderSimpleList() {
  227 + return workOrderMapper.selectList();
  228 + }
  229 +
225 // ==================== BOM 自动生成 ==================== 230 // ==================== BOM 自动生成 ====================
226 231
227 /** 232 /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcDefectServiceImpl.java
@@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO; @@ -9,7 +9,6 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcDO;
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.dal.dataobject.qc.lqc.MesQcIqcLineDO; 10 import cn.iocoder.yudao.module.mes.dal.dataobject.qc.lqc.MesQcIqcLineDO;
11 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcDefectMapper; 11 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcDefectMapper;
12 -import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcLineMapper;  
13 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper; 12 import cn.iocoder.yudao.module.mes.dal.mysql.qc.lqc.MesQcIqcMapper;
14 import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum; 13 import cn.iocoder.yudao.module.mes.enums.qc.MesQcDefectLevelEnum;
15 import jakarta.annotation.Resource; 14 import jakarta.annotation.Resource;
@@ -20,6 +19,7 @@ import org.springframework.validation.annotation.Validated; @@ -20,6 +19,7 @@ import org.springframework.validation.annotation.Validated;
20 19
21 import java.math.BigDecimal; 20 import java.math.BigDecimal;
22 import java.math.RoundingMode; 21 import java.math.RoundingMode;
  22 +import java.util.ArrayList;
23 import java.util.List; 23 import java.util.List;
24 import java.util.Objects; 24 import java.util.Objects;
25 25
@@ -38,8 +38,6 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService { @@ -38,8 +38,6 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService {
38 @Resource 38 @Resource
39 private MesQcIqcDefectMapper iqcDefectMapper; 39 private MesQcIqcDefectMapper iqcDefectMapper;
40 @Resource 40 @Resource
41 - private MesQcIqcLineMapper iqcLineMapper;  
42 - @Resource  
43 private MesQcIqcMapper iqcMapper; 41 private MesQcIqcMapper iqcMapper;
44 @Resource 42 @Resource
45 @Lazy 43 @Lazy
@@ -130,8 +128,9 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService { @@ -130,8 +128,9 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService {
130 // 1. 查询所有缺陷记录 128 // 1. 查询所有缺陷记录
131 List<MesQcIqcDefectDO> defects = iqcDefectMapper.selectListByIqcId(iqcId); 129 List<MesQcIqcDefectDO> defects = iqcDefectMapper.selectListByIqcId(iqcId);
132 130
133 - // 2. 更新每行的缺陷数量 131 + // 2. 按行汇总缺陷数量,批量更新
134 List<MesQcIqcLineDO> lines = iqcLineService.selectListByIqcId(iqcId); 132 List<MesQcIqcLineDO> lines = iqcLineService.selectListByIqcId(iqcId);
  133 + List<MesQcIqcLineDO> updateLines = new ArrayList<>();
135 for (MesQcIqcLineDO line : lines) { 134 for (MesQcIqcLineDO line : lines) {
136 int critical = 0, major = 0, minor = 0; 135 int critical = 0, major = 0, minor = 0;
137 for (MesQcIqcDefectDO defect : defects) { 136 for (MesQcIqcDefectDO defect : defects) {
@@ -149,8 +148,10 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService { @@ -149,8 +148,10 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService {
149 throw exception(QC_IQC_DEFECT_LEVEL_UNKNOWN); 148 throw exception(QC_IQC_DEFECT_LEVEL_UNKNOWN);
150 } 149 }
151 } 150 }
152 - updateLineDefectStats(line.getId(), critical, major, minor); 151 + updateLines.add(new MesQcIqcLineDO().setId(line.getId())
  152 + .setCriticalQuantity(critical).setMajorQuantity(major).setMinorQuantity(minor));
153 } 153 }
  154 + iqcLineService.batchUpdateDefectStats(updateLines);
154 155
155 // 3.1 汇总主表的缺陷数量 156 // 3.1 汇总主表的缺陷数量
156 int totalCritical = 0, totalMajor = 0, totalMinor = 0; 157 int totalCritical = 0, totalMajor = 0, totalMinor = 0;
@@ -187,14 +188,4 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService { @@ -187,14 +188,4 @@ public class MesQcIqcDefectServiceImpl implements MesQcIqcDefectService {
187 iqcMapper.updateById(updateIqc); 188 iqcMapper.updateById(updateIqc);
188 } 189 }
189 190
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 -  
200 } 191 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcLineService.java
@@ -46,6 +46,13 @@ public interface MesQcIqcLineService { @@ -46,6 +46,13 @@ public interface MesQcIqcLineService {
46 void createLinesFromTemplate(Long iqcId, Long templateId); 46 void createLinesFromTemplate(Long iqcId, Long templateId);
47 47
48 /** 48 /**
  49 + * 批量更新行的缺陷统计数量
  50 + *
  51 + * @param lines 待更新的行列表(只需设置 id、criticalQuantity、majorQuantity、minorQuantity)
  52 + */
  53 + void batchUpdateDefectStats(List<MesQcIqcLineDO> lines);
  54 +
  55 + /**
49 * 根据来料检验单 ID 级联删除所有行 56 * 根据来料检验单 ID 级联删除所有行
50 * 57 *
51 * @param iqcId 来料检验单 ID 58 * @param iqcId 来料检验单 ID
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcLineServiceImpl.java
@@ -57,6 +57,13 @@ public class MesQcIqcLineServiceImpl implements MesQcIqcLineService { @@ -57,6 +57,13 @@ public class MesQcIqcLineServiceImpl implements MesQcIqcLineService {
57 } 57 }
58 58
59 @Override 59 @Override
  60 + public void batchUpdateDefectStats(List<MesQcIqcLineDO> lines) {
  61 + for (MesQcIqcLineDO line : lines) {
  62 + iqcLineMapper.updateById(line);
  63 + }
  64 + }
  65 +
  66 + @Override
60 public void deleteByIqcId(Long iqcId) { 67 public void deleteByIqcId(Long iqcId) {
61 iqcLineMapper.deleteByIqcId(iqcId); 68 iqcLineMapper.deleteByIqcId(iqcId);
62 } 69 }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/lqc/MesQcIqcServiceImpl.java
@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.mes.service.qc.lqc; @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.mes.service.qc.lqc;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
5 -import cn.iocoder.yudao.framework.common.exception.ErrorCode;  
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 6 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
8 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO; 7 import cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo.MesQcIqcPageReqVO;
@@ -76,11 +75,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -76,11 +75,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
76 75
77 @Override 76 @Override
78 public void updateIqc(MesQcIqcSaveReqVO updateReqVO) { 77 public void updateIqc(MesQcIqcSaveReqVO updateReqVO) {
79 - // 1.1 校验存在  
80 - MesQcIqcDO iqc = validateIqcExists(updateReqVO.getId());  
81 - // 1.2 校验状态为草稿  
82 - validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_COMPLETE);  
83 - // 1.3 校验编号唯一 78 + // 1.1 校验存在 + 草稿状态
  79 + validateIqcStatusPrepare(updateReqVO.getId());
  80 + // 1.2 校验编号唯一
84 validateIqcCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); 81 validateIqcCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
85 82
86 // 2. 更新 83 // 2. 更新
@@ -90,11 +87,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -90,11 +87,9 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
90 87
91 @Override 88 @Override
92 public void completeIqc(Long id) { 89 public void completeIqc(Long id) {
93 - // 1.1 校验存在  
94 - MesQcIqcDO iqc = validateIqcExists(id);  
95 - // 1.2 校验状态为草稿  
96 - validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_COMPLETE);  
97 - // 1.3 校验合格品 + 不合格品 = 检测数量 90 + // 1.1 校验存在 + 草稿状态
  91 + MesQcIqcDO iqc = validateIqcStatusPrepare(id);
  92 + // 1.2 校验合格品 + 不合格品 = 检测数量
98 if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) { 93 if (iqc.getCheckQuantity() != null && iqc.getCheckQuantity() > 0) {
99 int total = (iqc.getQualifiedQuantity() != null ? iqc.getQualifiedQuantity() : 0) 94 int total = (iqc.getQualifiedQuantity() != null ? iqc.getQualifiedQuantity() : 0)
100 + (iqc.getUnqualifiedQuantity() != null ? iqc.getUnqualifiedQuantity() : 0); 95 + (iqc.getUnqualifiedQuantity() != null ? iqc.getUnqualifiedQuantity() : 0);
@@ -114,10 +109,8 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -114,10 +109,8 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
114 @Override 109 @Override
115 @Transactional(rollbackFor = Exception.class) 110 @Transactional(rollbackFor = Exception.class)
116 public void deleteIqc(Long id) { 111 public void deleteIqc(Long id) {
117 - // 1.1 校验存在  
118 - MesQcIqcDO iqc = validateIqcExists(id);  
119 - // 1.2 仅草稿可删  
120 - validatePrepareStatus(iqc, QC_IQC_ONLY_PREPARE_CAN_DELETE); 112 + // 1. 校验存在 + 草稿状态
  113 + validateIqcStatusPrepare(id);
121 114
122 // 2.1 删除主表 115 // 2.1 删除主表
123 iqcMapper.deleteById(id); 116 iqcMapper.deleteById(id);
@@ -127,19 +120,21 @@ public class MesQcIqcServiceImpl implements MesQcIqcService { @@ -127,19 +120,21 @@ public class MesQcIqcServiceImpl implements MesQcIqcService {
127 iqcDefectService.deleteByIqcId(id); 120 iqcDefectService.deleteByIqcId(id);
128 } 121 }
129 122
130 - private MesQcIqcDO validateIqcExists(Long id) { 123 + /**
  124 + * 校验来料检验单存在且为草稿状态
  125 + *
  126 + * @param id 来料检验单 ID
  127 + * @return 来料检验单
  128 + */
  129 + private MesQcIqcDO validateIqcStatusPrepare(Long id) {
131 MesQcIqcDO iqc = iqcMapper.selectById(id); 130 MesQcIqcDO iqc = iqcMapper.selectById(id);
132 if (iqc == null) { 131 if (iqc == null) {
133 throw exception(QC_IQC_NOT_EXISTS); 132 throw exception(QC_IQC_NOT_EXISTS);
134 } 133 }
135 - return iqc;  
136 - }  
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())) { 134 if (ObjUtil.notEqual(iqc.getStatus(), MesQcIqcStatusEnum.PREPARE.getType())) {
141 - throw exception(errorCode); 135 + throw exception(QC_IQC_NOT_PREPARE);
142 } 136 }
  137 + return iqc;
143 } 138 }
144 139
145 private void validateIqcCodeUnique(Long id, String code) { 140 private void validateIqcCodeUnique(Long id, String code) {