From 43aab58c9ecb1203770ba382efbdbae299ca87ec Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期一, 26 十月 2026 15:12:31 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_business' into dev_business
---
yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/md/item/MesBomImportAdapterTest.java | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 174 insertions(+), 0 deletions(-)
diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/md/item/MesBomImportAdapterTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/md/item/MesBomImportAdapterTest.java
new file mode 100644
index 0000000..763628c
--- /dev/null
+++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/md/item/MesBomImportAdapterTest.java
@@ -0,0 +1,174 @@
+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;
+ }
+}
--
Gitblit v1.9.3