Commit 80183a18a625eba8512430f6bfdfb41aaf17c479
1 parent
a1a35aa5
✨ feat(qc): 增加到货通知单状态校验及文件 URL 格式验证
新增 validateArrivalNoticeReadyForReceipt 方法,确保到货通知单状态为待入库,并校验所有需检行已完成 IQC。同时,增强了文件 URL 格式验证,确保文件值为有效的 http/https URL。
Showing
7 changed files
with
355 additions
and
7 deletions
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImpl.java
| ... | ... | @@ -29,6 +29,7 @@ import org.springframework.transaction.annotation.Transactional; |
| 29 | 29 | import org.springframework.validation.annotation.Validated; |
| 30 | 30 | |
| 31 | 31 | import java.math.BigDecimal; |
| 32 | +import java.net.URI; | |
| 32 | 33 | import java.util.*; |
| 33 | 34 | |
| 34 | 35 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| ... | ... | @@ -181,7 +182,7 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ |
| 181 | 182 | * 按检测项的 resultType 校验明细值格式 |
| 182 | 183 | * |
| 183 | 184 | * <p>FLOAT → 必须可解析为 BigDecimal;INTEGER → 必须可解析为整数; |
| 184 | - * TEXT / DICT / FILE → 放行 | |
| 185 | + * DICT → 必须属于字典值域;FILE → 必须为 http/https URL;TEXT → 放行 | |
| 185 | 186 | */ |
| 186 | 187 | private void validateDetailValues(List<MesQcIndicatorResultSaveReqVO.Item> items, |
| 187 | 188 | Map<Long, MesQcIndicatorDO> indicatorMap) { |
| ... | ... | @@ -219,7 +220,23 @@ public class MesQcIndicatorResultServiceImpl implements MesQcIndicatorResultServ |
| 219 | 220 | dictDataApi.validateDictDataList(dictType, Collections.singleton(item.getValue())); |
| 220 | 221 | } |
| 221 | 222 | } |
| 222 | - // FILE / TEXT 不做格式校验 | |
| 223 | + if (Objects.equals(resultType, MesQcResultValueTypeEnum.FILE.getType()) | |
| 224 | + && !isHttpUrl(item.getValue())) { | |
| 225 | + throw exception(QC_RESULT_VALUE_FORMAT_INVALID, | |
| 226 | + "检测项[" + indicator.getName() + "]要求文件 URL,实际值=" + item.getValue()); | |
| 227 | + } | |
| 228 | + // TEXT 不做格式校验 | |
| 229 | + } | |
| 230 | + } | |
| 231 | + | |
| 232 | + private boolean isHttpUrl(String value) { | |
| 233 | + try { | |
| 234 | + URI uri = URI.create(value); | |
| 235 | + String scheme = uri.getScheme(); | |
| 236 | + return StrUtil.isNotBlank(uri.getHost()) | |
| 237 | + && ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)); | |
| 238 | + } catch (IllegalArgumentException e) { | |
| 239 | + return false; | |
| 223 | 240 | } |
| 224 | 241 | } |
| 225 | 242 | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeService.java
| ... | ... | @@ -117,6 +117,15 @@ public interface MesWmArrivalNoticeService { |
| 117 | 117 | void validateArrivalNoticeAndLineExists(Long noticeId, Long lineId); |
| 118 | 118 | |
| 119 | 119 | /** |
| 120 | + * 校验到货通知单已就绪可被采购入库引用 | |
| 121 | + * <p>校验状态为待入库 + 所有需检行都已完成 IQC</p> | |
| 122 | + * | |
| 123 | + * @param id 到货通知单编号 | |
| 124 | + * @return 到货通知单 | |
| 125 | + */ | |
| 126 | + MesWmArrivalNoticeDO validateArrivalNoticeReadyForReceipt(Long id); | |
| 127 | + | |
| 128 | + /** | |
| 120 | 129 | * 查询指定供应商的到货通知单数量 |
| 121 | 130 | * |
| 122 | 131 | * @param vendorId 供应商编号 | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/arrivalnotice/MesWmArrivalNoticeServiceImpl.java
| ... | ... | @@ -210,6 +210,23 @@ public class MesWmArrivalNoticeServiceImpl implements MesWmArrivalNoticeService |
| 210 | 210 | return notice; |
| 211 | 211 | } |
| 212 | 212 | |
| 213 | + @Override | |
| 214 | + public MesWmArrivalNoticeDO validateArrivalNoticeReadyForReceipt(Long id) { | |
| 215 | + // 1. 校验到货通知单存在且状态为待入库 | |
| 216 | + MesWmArrivalNoticeDO notice = validateArrivalNoticeExists(id); | |
| 217 | + if (ObjUtil.notEqual(MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus(), notice.getStatus())) { | |
| 218 | + throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT); | |
| 219 | + } | |
| 220 | + // 2. 行级防御校验:确保所有需检行都已完成 IQC | |
| 221 | + List<MesWmArrivalNoticeLineDO> lines = arrivalNoticeLineService.getArrivalNoticeLineListByNoticeId(id); | |
| 222 | + boolean hasUnchecked = CollectionUtils.anyMatch(lines, | |
| 223 | + line -> Boolean.TRUE.equals(line.getIqcCheckFlag()) && line.getIqcId() == null); | |
| 224 | + if (hasUnchecked) { | |
| 225 | + throw exception(WM_ARRIVAL_NOTICE_IQC_PENDING); | |
| 226 | + } | |
| 227 | + return notice; | |
| 228 | + } | |
| 229 | + | |
| 213 | 230 | private void validateCodeUnique(Long id, String code) { |
| 214 | 231 | MesWmArrivalNoticeDO notice = arrivalNoticeMapper.selectByCode(code); |
| 215 | 232 | if (notice == null) { | ... | ... |
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/itemreceipt/MesWmItemReceiptServiceImpl.java
| ... | ... | @@ -14,7 +14,6 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceip |
| 14 | 14 | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.itemreceipt.MesWmItemReceiptLineDO; |
| 15 | 15 | import cn.iocoder.yudao.module.mes.dal.mysql.wm.itemreceipt.MesWmItemReceiptMapper; |
| 16 | 16 | import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants; |
| 17 | -import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; | |
| 18 | 17 | import cn.iocoder.yudao.module.mes.enums.wm.MesWmItemReceiptStatusEnum; |
| 19 | 18 | import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum; |
| 20 | 19 | import cn.iocoder.yudao.module.mes.service.md.vendor.MesMdVendorService; |
| ... | ... | @@ -92,10 +91,7 @@ public class MesWmItemReceiptServiceImpl implements MesWmItemReceiptService { |
| 92 | 91 | vendorService.validateVendorExistsAndEnable(reqVO.getVendorId()); |
| 93 | 92 | // 校验到货通知单存在 |
| 94 | 93 | if (reqVO.getNoticeId() != null) { |
| 95 | - MesWmArrivalNoticeDO notice = arrivalNoticeService.validateArrivalNoticeExists(reqVO.getNoticeId()); | |
| 96 | - if (ObjUtil.notEqual(notice.getStatus(), MesWmArrivalNoticeStatusEnum.PENDING_RECEIPT.getStatus())) { | |
| 97 | - throw exception(WM_ARRIVAL_NOTICE_STATUS_NOT_PENDING_RECEIPT); | |
| 98 | - } | |
| 94 | + MesWmArrivalNoticeDO notice = arrivalNoticeService.validateArrivalNoticeReadyForReceipt(reqVO.getNoticeId()); | |
| 99 | 95 | if (ObjUtil.notEqual(notice.getVendorId(), reqVO.getVendorId())) { |
| 100 | 96 | throw exception(WM_ARRIVAL_NOTICE_VENDOR_MISMATCH); |
| 101 | 97 | } | ... | ... |
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/qc/indicatorresult/MesQcIndicatorResultServiceImplTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.mes.service.qc.indicatorresult; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 5 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultPageReqVO; | |
| 6 | +import cn.iocoder.yudao.module.mes.controller.admin.qc.indicatorresult.vo.MesQcIndicatorResultSaveReqVO; | |
| 7 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicator.MesQcIndicatorDO; | |
| 8 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.indicatorresult.MesQcIndicatorResultDO; | |
| 9 | +import cn.iocoder.yudao.module.mes.dal.dataobject.qc.iqc.MesQcIqcDO; | |
| 10 | +import cn.iocoder.yudao.module.mes.dal.mysql.qc.indicatorresult.MesQcIndicatorResultMapper; | |
| 11 | +import cn.iocoder.yudao.module.mes.enums.qc.MesQcResultValueTypeEnum; | |
| 12 | +import cn.iocoder.yudao.module.mes.enums.qc.MesQcTypeEnum; | |
| 13 | +import cn.iocoder.yudao.module.mes.service.qc.indicator.MesQcIndicatorService; | |
| 14 | +import cn.iocoder.yudao.module.mes.service.qc.ipqc.MesQcIpqcService; | |
| 15 | +import cn.iocoder.yudao.module.mes.service.qc.iqc.MesQcIqcService; | |
| 16 | +import cn.iocoder.yudao.module.mes.service.qc.oqc.MesQcOqcService; | |
| 17 | +import cn.iocoder.yudao.module.mes.service.qc.rqc.MesQcRqcService; | |
| 18 | +import cn.iocoder.yudao.module.system.api.dict.DictDataApi; | |
| 19 | +import org.junit.jupiter.api.Test; | |
| 20 | +import org.springframework.context.annotation.Import; | |
| 21 | +import org.springframework.test.context.bean.override.mockito.MockitoBean; | |
| 22 | + | |
| 23 | +import jakarta.annotation.Resource; | |
| 24 | +import java.util.List; | |
| 25 | +import java.util.Map; | |
| 26 | + | |
| 27 | +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | |
| 28 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | |
| 29 | +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | |
| 30 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; | |
| 31 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 32 | +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; | |
| 33 | +import static org.junit.jupiter.api.Assertions.*; | |
| 34 | +import static org.mockito.ArgumentMatchers.*; | |
| 35 | +import static org.mockito.Mockito.*; | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * {@link MesQcIndicatorResultServiceImpl} 的单元测试 | |
| 39 | + * | |
| 40 | + * @author 芋道源码 | |
| 41 | + */ | |
| 42 | +@Import(MesQcIndicatorResultServiceImpl.class) | |
| 43 | +public class MesQcIndicatorResultServiceImplTest extends BaseDbUnitTest { | |
| 44 | + | |
| 45 | + @Resource | |
| 46 | + private MesQcIndicatorResultServiceImpl indicatorResultService; | |
| 47 | + | |
| 48 | + @Resource | |
| 49 | + private MesQcIndicatorResultMapper resultMapper; | |
| 50 | + | |
| 51 | + @MockitoBean | |
| 52 | + private MesQcIndicatorResultDetailService resultDetailService; | |
| 53 | + @MockitoBean | |
| 54 | + private MesQcIndicatorService indicatorService; | |
| 55 | + @MockitoBean | |
| 56 | + private MesQcIqcService iqcService; | |
| 57 | + @MockitoBean | |
| 58 | + private MesQcIpqcService ipqcService; | |
| 59 | + @MockitoBean | |
| 60 | + private MesQcOqcService oqcService; | |
| 61 | + @MockitoBean | |
| 62 | + private MesQcRqcService rqcService; | |
| 63 | + @MockitoBean | |
| 64 | + private DictDataApi dictDataApi; | |
| 65 | + | |
| 66 | + @Test | |
| 67 | + public void testCreateIndicatorResult_success() { | |
| 68 | + // 准备参数 | |
| 69 | + MesQcIndicatorResultSaveReqVO reqVO = buildReqVO("plain text value", MesQcResultValueTypeEnum.TEXT.getType()); | |
| 70 | + // mock 方法 | |
| 71 | + mockIqcAndIndicator(reqVO, MesQcResultValueTypeEnum.TEXT.getType()); | |
| 72 | + | |
| 73 | + // 调用 | |
| 74 | + Long resultId = indicatorResultService.createIndicatorResult(reqVO); | |
| 75 | + | |
| 76 | + // 断言 | |
| 77 | + assertNotNull(resultId); | |
| 78 | + MesQcIndicatorResultDO dbResult = resultMapper.selectById(resultId); | |
| 79 | + assertNotNull(dbResult); | |
| 80 | + assertEquals(reqVO.getCode(), dbResult.getCode()); | |
| 81 | + assertEquals(reqVO.getQcId(), dbResult.getQcId()); | |
| 82 | + assertEquals(reqVO.getQcType(), dbResult.getQcType()); | |
| 83 | + assertEquals(100L, dbResult.getItemId()); // 从 mock IQC 获取 | |
| 84 | + verify(resultDetailService).createDetailList(anyList()); | |
| 85 | + } | |
| 86 | + | |
| 87 | + @Test | |
| 88 | + public void testCreateIndicatorResult_fileValueInvalid() { | |
| 89 | + // 准备参数 | |
| 90 | + MesQcIndicatorResultSaveReqVO reqVO = buildReqVO("not-a-url", MesQcResultValueTypeEnum.FILE.getType()); | |
| 91 | + // mock 方法 | |
| 92 | + mockIqcAndIndicator(reqVO, MesQcResultValueTypeEnum.FILE.getType()); | |
| 93 | + | |
| 94 | + // 调用,并断言异常 | |
| 95 | + assertServiceException(() -> indicatorResultService.createIndicatorResult(reqVO), | |
| 96 | + QC_RESULT_VALUE_FORMAT_INVALID, "检测项[检测项A]要求文件 URL,实际值=not-a-url"); | |
| 97 | + | |
| 98 | + // 断言:未入库 | |
| 99 | + assertEquals(0, resultMapper.selectCount()); | |
| 100 | + verify(resultDetailService, never()).createDetailList(anyList()); | |
| 101 | + } | |
| 102 | + | |
| 103 | + @Test | |
| 104 | + public void testUpdateIndicatorResult_success() { | |
| 105 | + // mock 数据 | |
| 106 | + MesQcIndicatorResultDO dbResult = randomPojo(MesQcIndicatorResultDO.class, o -> { | |
| 107 | + o.setQcType(MesQcTypeEnum.IQC.getType()); | |
| 108 | + }); | |
| 109 | + resultMapper.insert(dbResult); | |
| 110 | + // 准备参数 | |
| 111 | + MesQcIndicatorResultSaveReqVO reqVO = buildReqVO("updated text", MesQcResultValueTypeEnum.TEXT.getType()); | |
| 112 | + reqVO.setId(dbResult.getId()); | |
| 113 | + // mock 方法 | |
| 114 | + MesQcIndicatorDO indicator = new MesQcIndicatorDO(); | |
| 115 | + indicator.setId(reqVO.getItems().get(0).getIndicatorId()); | |
| 116 | + indicator.setName("检测项A"); | |
| 117 | + indicator.setResultType(MesQcResultValueTypeEnum.TEXT.getType()); | |
| 118 | + when(indicatorService.validateIndicatorListExists(anySet())) | |
| 119 | + .thenReturn(Map.of(indicator.getId(), indicator)); | |
| 120 | + | |
| 121 | + // 调用 | |
| 122 | + indicatorResultService.updateIndicatorResult(reqVO); | |
| 123 | + | |
| 124 | + // 断言 | |
| 125 | + MesQcIndicatorResultDO updatedResult = resultMapper.selectById(dbResult.getId()); | |
| 126 | + assertEquals(reqVO.getCode(), updatedResult.getCode()); | |
| 127 | + // qcId/qcType/itemId 不允许改挂,应保持原值 | |
| 128 | + assertEquals(dbResult.getQcId(), updatedResult.getQcId()); | |
| 129 | + assertEquals(dbResult.getQcType(), updatedResult.getQcType()); | |
| 130 | + assertEquals(dbResult.getItemId(), updatedResult.getItemId()); | |
| 131 | + verify(resultDetailService).createOrUpdateDetailList(anyList()); | |
| 132 | + } | |
| 133 | + | |
| 134 | + @Test | |
| 135 | + public void testUpdateIndicatorResult_notExists() { | |
| 136 | + // 准备参数 | |
| 137 | + MesQcIndicatorResultSaveReqVO reqVO = buildReqVO("text", MesQcResultValueTypeEnum.TEXT.getType()); | |
| 138 | + reqVO.setId(randomLongId()); | |
| 139 | + | |
| 140 | + // 调用,并断言异常 | |
| 141 | + assertServiceException(() -> indicatorResultService.updateIndicatorResult(reqVO), | |
| 142 | + QC_RESULT_NOT_EXISTS); | |
| 143 | + } | |
| 144 | + | |
| 145 | + @Test | |
| 146 | + public void testDeleteIndicatorResult_success() { | |
| 147 | + // mock 数据 | |
| 148 | + MesQcIndicatorResultDO dbResult = randomPojo(MesQcIndicatorResultDO.class); | |
| 149 | + resultMapper.insert(dbResult); | |
| 150 | + | |
| 151 | + // 调用 | |
| 152 | + indicatorResultService.deleteIndicatorResult(dbResult.getId()); | |
| 153 | + | |
| 154 | + // 断言 | |
| 155 | + assertNull(resultMapper.selectById(dbResult.getId())); | |
| 156 | + verify(resultDetailService).deleteDetailByResultId(dbResult.getId()); | |
| 157 | + } | |
| 158 | + | |
| 159 | + @Test | |
| 160 | + public void testDeleteIndicatorResult_notExists() { | |
| 161 | + // 调用,并断言异常 | |
| 162 | + assertServiceException(() -> indicatorResultService.deleteIndicatorResult(randomLongId()), | |
| 163 | + QC_RESULT_NOT_EXISTS); | |
| 164 | + } | |
| 165 | + | |
| 166 | + @Test | |
| 167 | + public void testGetIndicatorResult() { | |
| 168 | + // mock 数据 | |
| 169 | + MesQcIndicatorResultDO dbResult = randomPojo(MesQcIndicatorResultDO.class); | |
| 170 | + resultMapper.insert(dbResult); | |
| 171 | + | |
| 172 | + // 调用 | |
| 173 | + MesQcIndicatorResultDO result = indicatorResultService.getIndicatorResult(dbResult.getId()); | |
| 174 | + | |
| 175 | + // 断言 | |
| 176 | + assertPojoEquals(dbResult, result); | |
| 177 | + } | |
| 178 | + | |
| 179 | + @Test | |
| 180 | + public void testGetIndicatorResultPage() { | |
| 181 | + // mock 数据 | |
| 182 | + MesQcIndicatorResultDO dbResult = randomPojo(MesQcIndicatorResultDO.class, o -> { | |
| 183 | + o.setQcId(1L); | |
| 184 | + o.setQcType(MesQcTypeEnum.IQC.getType()); | |
| 185 | + o.setCode("SPL-001"); | |
| 186 | + o.setItemId(100L); | |
| 187 | + }); | |
| 188 | + resultMapper.insert(dbResult); | |
| 189 | + // 测试 qcId 不匹配 | |
| 190 | + resultMapper.insert(cloneIgnoreId(dbResult, o -> o.setQcId(2L))); | |
| 191 | + // 测试 qcType 不匹配 | |
| 192 | + resultMapper.insert(cloneIgnoreId(dbResult, o -> o.setQcType(MesQcTypeEnum.IPQC.getType()))); | |
| 193 | + // 测试 code 不匹配 | |
| 194 | + resultMapper.insert(cloneIgnoreId(dbResult, o -> o.setCode("SPL-999"))); | |
| 195 | + // 测试 itemId 不匹配 | |
| 196 | + resultMapper.insert(cloneIgnoreId(dbResult, o -> o.setItemId(999L))); | |
| 197 | + // 准备参数 | |
| 198 | + MesQcIndicatorResultPageReqVO pageReqVO = new MesQcIndicatorResultPageReqVO(); | |
| 199 | + pageReqVO.setQcId(1L); | |
| 200 | + pageReqVO.setQcType(MesQcTypeEnum.IQC.getType()); | |
| 201 | + pageReqVO.setCode("SPL-001"); | |
| 202 | + pageReqVO.setItemId(100L); | |
| 203 | + | |
| 204 | + // 调用 | |
| 205 | + PageResult<MesQcIndicatorResultDO> pageResult = indicatorResultService.getIndicatorResultPage(pageReqVO); | |
| 206 | + | |
| 207 | + // 断言 | |
| 208 | + assertEquals(1, pageResult.getTotal()); | |
| 209 | + assertEquals(1, pageResult.getList().size()); | |
| 210 | + assertPojoEquals(dbResult, pageResult.getList().get(0)); | |
| 211 | + } | |
| 212 | + | |
| 213 | + @Test | |
| 214 | + public void testGetIndicatorResultCountByQcIdAndType() { | |
| 215 | + // mock 数据 | |
| 216 | + MesQcIndicatorResultDO result1 = randomPojo(MesQcIndicatorResultDO.class, o -> { | |
| 217 | + o.setQcId(1L); | |
| 218 | + o.setQcType(MesQcTypeEnum.IQC.getType()); | |
| 219 | + }); | |
| 220 | + resultMapper.insert(result1); | |
| 221 | + MesQcIndicatorResultDO result2 = randomPojo(MesQcIndicatorResultDO.class, o -> { | |
| 222 | + o.setQcId(1L); | |
| 223 | + o.setQcType(MesQcTypeEnum.IQC.getType()); | |
| 224 | + }); | |
| 225 | + resultMapper.insert(result2); | |
| 226 | + // 不匹配 | |
| 227 | + resultMapper.insert(randomPojo(MesQcIndicatorResultDO.class, o -> { | |
| 228 | + o.setQcId(2L); | |
| 229 | + o.setQcType(MesQcTypeEnum.IPQC.getType()); | |
| 230 | + })); | |
| 231 | + | |
| 232 | + // 调用 | |
| 233 | + Long count = indicatorResultService.getIndicatorResultCountByQcIdAndType(1L, MesQcTypeEnum.IQC.getType()); | |
| 234 | + | |
| 235 | + // 断言 | |
| 236 | + assertEquals(2L, count); | |
| 237 | + } | |
| 238 | + | |
| 239 | + @Test | |
| 240 | + public void testValidateIndicatorResultExistsByQcIdAndType_success() { | |
| 241 | + // mock 数据 | |
| 242 | + resultMapper.insert(randomPojo(MesQcIndicatorResultDO.class, o -> { | |
| 243 | + o.setQcId(1L); | |
| 244 | + o.setQcType(MesQcTypeEnum.IQC.getType()); | |
| 245 | + })); | |
| 246 | + | |
| 247 | + // 调用(不抛异常即通过) | |
| 248 | + indicatorResultService.validateIndicatorResultExistsByQcIdAndType(1L, MesQcTypeEnum.IQC.getType()); | |
| 249 | + } | |
| 250 | + | |
| 251 | + @Test | |
| 252 | + public void testValidateIndicatorResultExistsByQcIdAndType_notExists() { | |
| 253 | + // 调用,并断言异常 | |
| 254 | + assertServiceException( | |
| 255 | + () -> indicatorResultService.validateIndicatorResultExistsByQcIdAndType(randomLongId(), MesQcTypeEnum.IQC.getType()), | |
| 256 | + QC_FINISH_INDICATOR_RESULT_REQUIRED); | |
| 257 | + } | |
| 258 | + | |
| 259 | + // ==================== 辅助方法 ==================== | |
| 260 | + | |
| 261 | + private void mockIqcAndIndicator(MesQcIndicatorResultSaveReqVO reqVO, Integer resultType) { | |
| 262 | + MesQcIqcDO iqc = new MesQcIqcDO(); | |
| 263 | + iqc.setId(reqVO.getQcId()); | |
| 264 | + iqc.setItemId(100L); | |
| 265 | + when(iqcService.validateIqcExists(reqVO.getQcId())).thenReturn(iqc); | |
| 266 | + | |
| 267 | + MesQcIndicatorDO indicator = new MesQcIndicatorDO(); | |
| 268 | + indicator.setId(reqVO.getItems().get(0).getIndicatorId()); | |
| 269 | + indicator.setName("检测项A"); | |
| 270 | + indicator.setResultType(resultType); | |
| 271 | + when(indicatorService.validateIndicatorListExists(anySet())) | |
| 272 | + .thenReturn(Map.of(indicator.getId(), indicator)); | |
| 273 | + } | |
| 274 | + | |
| 275 | + private MesQcIndicatorResultSaveReqVO buildReqVO(String value, Integer resultType) { | |
| 276 | + MesQcIndicatorResultSaveReqVO.Item item = new MesQcIndicatorResultSaveReqVO.Item(); | |
| 277 | + item.setIndicatorId(10L); | |
| 278 | + item.setValue(value); | |
| 279 | + | |
| 280 | + MesQcIndicatorResultSaveReqVO reqVO = new MesQcIndicatorResultSaveReqVO(); | |
| 281 | + reqVO.setCode("SPL-001"); | |
| 282 | + reqVO.setQcId(1L); | |
| 283 | + reqVO.setQcType(MesQcTypeEnum.IQC.getType()); | |
| 284 | + reqVO.setItems(List.of(item)); | |
| 285 | + return reqVO; | |
| 286 | + } | |
| 287 | + | |
| 288 | +} | ... | ... |
yudao-module-mes/src/test/resources/sql/clean.sql
yudao-module-mes/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -810,3 +810,23 @@ CREATE TABLE IF NOT EXISTS "mes_wm_product_sales_detail" ( |
| 810 | 810 | "tenant_id" bigint NOT NULL DEFAULT 0, |
| 811 | 811 | PRIMARY KEY ("id") |
| 812 | 812 | ); |
| 813 | + | |
| 814 | +-- ---------------------------- | |
| 815 | +-- MES 检验结果记录 | |
| 816 | +-- ---------------------------- | |
| 817 | +CREATE TABLE IF NOT EXISTS "mes_qc_indicator_result" ( | |
| 818 | + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 819 | + "code" varchar(64) DEFAULT NULL, | |
| 820 | + "qc_id" bigint DEFAULT NULL, | |
| 821 | + "qc_type" int DEFAULT NULL, | |
| 822 | + "item_id" bigint DEFAULT NULL, | |
| 823 | + "sn" varchar(128) DEFAULT NULL, | |
| 824 | + "remark" varchar(500) DEFAULT NULL, | |
| 825 | + "creator" varchar(64) DEFAULT '', | |
| 826 | + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 827 | + "updater" varchar(64) DEFAULT '', | |
| 828 | + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 829 | + "deleted" bit NOT NULL DEFAULT FALSE, | |
| 830 | + "tenant_id" bigint NOT NULL DEFAULT 0, | |
| 831 | + PRIMARY KEY ("id") | |
| 832 | +); | ... | ... |