| 对比新文件 |
| | |
| | | package cn.iocoder.yudao.module.mes.service.md.item; |
| | | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.bom.MesMdProductBomSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdProductBomDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.md.item.MesMdProductBomMapper; |
| | | import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportCommitReqVO; |
| | | import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportPreflightReqVO; |
| | | import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportPreflightRespVO; |
| | | import cn.iocoder.yudao.module.system.api.agent.imports.AgentImportRowReceipt; |
| | | import cn.iocoder.yudao.module.system.framework.agent.AgentPrincipal; |
| | | import org.junit.jupiter.api.BeforeEach; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.test.util.ReflectionTestUtils; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.*; |
| | | import static org.mockito.ArgumentMatchers.any; |
| | | import static org.mockito.Mockito.*; |
| | | |
| | | class MesBomImportAdapterTest { |
| | | |
| | | private static final AgentPrincipal PRINCIPAL = new AgentPrincipal(1L, "live"); |
| | | |
| | | private MesBomImportAdapter adapter; |
| | | private MesMdItemService itemService; |
| | | private MesMdProductBomService productBomService; |
| | | private MesMdProductBomMapper productBomMapper; |
| | | |
| | | @BeforeEach |
| | | void setUp() { |
| | | adapter = new MesBomImportAdapter(); |
| | | itemService = mock(MesMdItemService.class); |
| | | productBomService = mock(MesMdProductBomService.class); |
| | | productBomMapper = mock(MesMdProductBomMapper.class); |
| | | ReflectionTestUtils.setField(adapter, "itemService", itemService); |
| | | ReflectionTestUtils.setField(adapter, "productBomService", productBomService); |
| | | ReflectionTestUtils.setField(adapter, "productBomMapper", productBomMapper); |
| | | when(itemService.getItemByCode("P")).thenReturn(item(1L, "P")); |
| | | when(itemService.getItemByCode("C")).thenReturn(item(2L, "C")); |
| | | when(itemService.getItemByCode("A")).thenReturn(item(3L, "A")); |
| | | when(itemService.getItemByCode("X")).thenReturn(null); |
| | | when(productBomMapper.selectAll()).thenReturn(List.of()); |
| | | } |
| | | |
| | | @Test |
| | | void preflightCreatesWhenItemsAreSynced() { |
| | | AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "2"))); |
| | | |
| | | assertEquals("CREATE", plan.getRows().get(0).getAction()); |
| | | assertEquals(1, plan.getSummary().getCreate()); |
| | | assertTrue(plan.getCanCommit()); |
| | | assertNotNull(plan.getPreflightHash()); |
| | | } |
| | | |
| | | @Test |
| | | void existingCombinationIsSkippedWithWarning() { |
| | | when(productBomMapper.selectAll()).thenReturn(List.of(bom(50L, 1L, 2L))); |
| | | |
| | | AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "2"))); |
| | | |
| | | assertEquals("SKIP", plan.getRows().get(0).getAction()); |
| | | assertEquals(50L, plan.getRows().get(0).getTargetId()); |
| | | assertEquals(1, plan.getSummary().getSkip()); |
| | | assertTrue(plan.getRows().get(0).getWarnings().stream() |
| | | .anyMatch(item -> "BOM_EXISTS".equals(item.getCode()))); |
| | | } |
| | | |
| | | @Test |
| | | void unsyncedComponentBlocksRow() { |
| | | AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "X", "1"))); |
| | | |
| | | assertEquals("BLOCKED", plan.getRows().get(0).getAction()); |
| | | assertTrue(plan.getRows().get(0).getBlockers().stream() |
| | | .anyMatch(item -> "MES_ITEM_NOT_SYNCED".equals(item.getCode()))); |
| | | assertFalse(plan.getCanCommit()); |
| | | } |
| | | |
| | | @Test |
| | | void selfReferenceBlocksRow() { |
| | | AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "P", "1"))); |
| | | |
| | | assertEquals("BLOCKED", plan.getRows().get(0).getAction()); |
| | | assertTrue(plan.getRows().get(0).getBlockers().stream() |
| | | .anyMatch(item -> "BOM_SELF_REFERENCE".equals(item.getCode()))); |
| | | } |
| | | |
| | | @Test |
| | | void duplicateCombinationInFileBlocksSecondRow() { |
| | | AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request( |
| | | row("r1", "P", "C", "1"), |
| | | row("r2", "P", "C", "2"))); |
| | | |
| | | assertEquals("CREATE", plan.getRows().get(0).getAction()); |
| | | assertEquals("BLOCKED", plan.getRows().get(1).getAction()); |
| | | assertTrue(plan.getRows().get(1).getBlockers().stream() |
| | | .anyMatch(item -> "DUPLICATE_IN_FILE".equals(item.getCode()))); |
| | | } |
| | | |
| | | @Test |
| | | void cycleAgainstExistingGraphBlocksRow() { |
| | | when(productBomMapper.selectAll()).thenReturn(List.of(bom(60L, 3L, 1L))); |
| | | |
| | | AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "A", "1"))); |
| | | |
| | | assertEquals("BLOCKED", plan.getRows().get(0).getAction()); |
| | | assertTrue(plan.getRows().get(0).getBlockers().stream() |
| | | .anyMatch(item -> "BOM_CYCLE".equals(item.getCode()))); |
| | | } |
| | | |
| | | @Test |
| | | void invalidQuantityBlocksRow() { |
| | | AgentImportPreflightRespVO plan = adapter.preflight(PRINCIPAL, request(row("r1", "P", "C", "0"))); |
| | | |
| | | assertEquals("BLOCKED", plan.getRows().get(0).getAction()); |
| | | assertTrue(plan.getRows().get(0).getBlockers().stream() |
| | | .anyMatch(item -> "INVALID_QUANTITY".equals(item.getCode()))); |
| | | } |
| | | |
| | | @Test |
| | | void commitCreatesBomWithResolvedItemIds() { |
| | | when(productBomService.createProductBom(any())).thenReturn(88L); |
| | | |
| | | AgentImportRowReceipt receipt = adapter.commitRow(PRINCIPAL, new AgentImportCommitReqVO(), |
| | | AgentImportPreflightRespVO.Row.builder().candidateId("r1").action("CREATE").build(), |
| | | row("r1", "P", "C", "2")); |
| | | |
| | | assertEquals(88L, receipt.targetId()); |
| | | assertEquals("P", receipt.code()); |
| | | verify(productBomService).createProductBom(any(MesMdProductBomSaveReqVO.class)); |
| | | } |
| | | |
| | | private static MesMdItemDO item(Long id, String code) { |
| | | MesMdItemDO item = new MesMdItemDO(); |
| | | item.setId(id); |
| | | item.setCode(code); |
| | | return item; |
| | | } |
| | | |
| | | private static MesMdProductBomDO bom(Long id, Long itemId, Long bomItemId) { |
| | | MesMdProductBomDO bom = new MesMdProductBomDO(); |
| | | bom.setId(id); |
| | | bom.setItemId(itemId); |
| | | bom.setBomItemId(bomItemId); |
| | | bom.setQuantity(BigDecimal.ONE); |
| | | return bom; |
| | | } |
| | | |
| | | private static AgentImportPreflightReqVO request(AgentImportPreflightReqVO.Row... rows) { |
| | | AgentImportPreflightReqVO request = new AgentImportPreflightReqVO(); |
| | | request.setAttachmentId(1L); |
| | | request.setSourceSha256("a".repeat(64)); |
| | | request.setProposalRevision("0"); |
| | | request.setRows(List.of(rows)); |
| | | return request; |
| | | } |
| | | |
| | | private static AgentImportPreflightReqVO.Row row(String candidateId, String parent, String component, |
| | | String quantity) { |
| | | Map<String, String> values = new LinkedHashMap<>(); |
| | | values.put("parentCode", parent); |
| | | values.put("componentCode", component); |
| | | values.put("quantity", quantity); |
| | | AgentImportPreflightReqVO.Row row = new AgentImportPreflightReqVO.Row(); |
| | | row.setCandidateId(candidateId); |
| | | row.setRowNo(1); |
| | | row.setValues(values); |
| | | return row; |
| | | } |
| | | } |