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-mdm/src/test/java/cn/iocoder/yudao/module/mdm/service/agent/MdmAgentImportCommandServiceTest.java |  171 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 171 insertions(+), 0 deletions(-)

diff --git a/yudao-module-mdm/src/test/java/cn/iocoder/yudao/module/mdm/service/agent/MdmAgentImportCommandServiceTest.java b/yudao-module-mdm/src/test/java/cn/iocoder/yudao/module/mdm/service/agent/MdmAgentImportCommandServiceTest.java
new file mode 100644
index 0000000..fc0d17b
--- /dev/null
+++ b/yudao-module-mdm/src/test/java/cn/iocoder/yudao/module/mdm/service/agent/MdmAgentImportCommandServiceTest.java
@@ -0,0 +1,171 @@
+package cn.iocoder.yudao.module.mdm.service.agent;
+
+import cn.iocoder.yudao.module.mdm.controller.admin.agent.vo.MdmAgentImportCommitReqVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.agent.vo.MdmAgentImportPreflightReqVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.agent.vo.MdmAgentImportPreflightRespVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.agent.vo.MdmAgentImportReceiptRespVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemImportExcelVO;
+import cn.iocoder.yudao.module.mdm.controller.admin.item.vo.MdmItemSaveReqVO;
+import cn.iocoder.yudao.module.mdm.dal.dataobject.agent.MdmAgentImportCommandDO;
+import cn.iocoder.yudao.module.mdm.dal.mysql.agent.MdmAgentImportCommandMapper;
+import cn.iocoder.yudao.module.mdm.dal.mysql.agent.MdmAgentImportCommandRowMapper;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemImportContext;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemRowResolution;
+import cn.iocoder.yudao.module.mdm.service.item.MdmItemService;
+import cn.iocoder.yudao.module.system.framework.agent.AgentBridgeException;
+import cn.iocoder.yudao.module.system.framework.agent.AgentPrincipal;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.*;
+
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+class MdmAgentImportCommandServiceTest {
+
+    private static final String PREFLIGHT_HASH = "b".repeat(64);
+    private static final String SOURCE_SHA = "a".repeat(64);
+
+    @Mock private MdmAgentImportPreflightService preflightService;
+    @Mock private MdmItemService itemService;
+    @Mock private MdmAgentImportPolicy policy;
+    @Mock private MdmAgentImportCommandMapper commandMapper;
+    @Mock private MdmAgentImportCommandRowMapper commandRowMapper;
+    @Mock private PlatformTransactionManager transactionManager;
+    @InjectMocks private MdmAgentImportCommandService service;
+
+    private final AgentPrincipal principal = new AgentPrincipal(7L, "live");
+
+    @BeforeEach
+    void setUp() {
+        when(policy.isWriteEnabled()).thenReturn(true);
+        when(transactionManager.getTransaction(any(TransactionDefinition.class)))
+                .thenReturn(mock(TransactionStatus.class));
+        when(itemService.buildImportContext(any())).thenReturn(new MdmItemImportContext(
+                Map.of("RAW", 11L), Map.of("RAW", "鍘熸枡"),
+                Map.of("PCS", 22L), Map.of("PCS", "涓�")));
+        when(itemService.resolveImportRow(any(MdmItemImportExcelVO.class), any()))
+                .thenAnswer(invocation -> MdmItemRowResolution.success(new MdmItemSaveReqVO()));
+        when(itemService.getItemListByCode(any())).thenReturn(List.of());
+        when(itemService.createItem(any())).thenReturn(77L);
+        when(commandRowMapper.selectListByCommandId(any())).thenReturn(List.of());
+    }
+
+    @Test
+    void writeDisabledRejects() {
+        when(policy.isWriteEnabled()).thenReturn(false);
+        AgentBridgeException ex = assertThrows(AgentBridgeException.class,
+                () -> service.commit(request("鐗╂枡A"), principal));
+        assertEquals("WRITE_DISABLED", ex.getErrorCode());
+        verify(itemService, never()).createItem(any());
+    }
+
+    @Test
+    void repeatedCommitCreatesItemOnceAndReplaysReceipt() {
+        stubPreflight(PREFLIGHT_HASH);
+        AtomicReference<MdmAgentImportCommandDO> inserted = captureInsertedCommand();
+
+        MdmAgentImportReceiptRespVO first = service.commit(request("鐗╂枡A"), principal);
+        when(commandMapper.selectByCommandId(7L, "cmd-1")).thenReturn(inserted.get());
+        MdmAgentImportReceiptRespVO second = service.commit(request("鐗╂枡A"), principal);
+
+        assertEquals("SUCCEEDED", first.getStatus());
+        assertEquals("SUCCEEDED", second.getStatus());
+        assertEquals(first.getPreflightHash(), second.getPreflightHash());
+        verify(itemService, times(1)).createItem(any());
+    }
+
+    @Test
+    void sameCommandWithDifferentContentConflicts() {
+        when(preflightService.preflight(any(), any())).thenReturn(preflight(PREFLIGHT_HASH));
+        AtomicReference<MdmAgentImportCommandDO> inserted = captureInsertedCommand();
+        service.commit(request("鐗╂枡A"), principal);
+        when(commandMapper.selectByCommandId(7L, "cmd-1")).thenReturn(inserted.get());
+        when(commandMapper.selectByIdempotencyKey(7L, "idem-1")).thenReturn(null);
+
+        AgentBridgeException ex = assertThrows(AgentBridgeException.class,
+                () -> service.commit(request("鐗╂枡B"), principal));
+        assertEquals("COMMAND_ID_CONFLICT", ex.getErrorCode());
+    }
+
+    @Test
+    void stalePreflightIsRejected() {
+        stubPreflight("c".repeat(64));
+
+        AgentBridgeException ex = assertThrows(AgentBridgeException.class,
+                () -> service.commit(request("鐗╂枡A"), principal));
+        assertEquals("PLAN_STALE", ex.getErrorCode());
+        verify(commandMapper, never()).insert(any(MdmAgentImportCommandDO.class));
+    }
+
+    @Test
+    void missingCommandReturnsNotFound() {
+        when(commandMapper.selectByCommandId(7L, "cmd-x")).thenReturn(null);
+
+        AgentBridgeException ex = assertThrows(AgentBridgeException.class,
+                () -> service.getCommand("cmd-x", principal));
+        assertEquals("COMMAND_NOT_FOUND", ex.getErrorCode());
+    }
+
+    private void stubPreflight(String preflightHash) {
+        when(preflightService.preflight(any(), any())).thenReturn(preflight(preflightHash));
+    }
+
+    private static MdmAgentImportPreflightRespVO preflight(String hash) {
+        return MdmAgentImportPreflightRespVO.builder()
+                .preflightHash(hash)
+                .canCommit(true)
+                .rows(List.of(MdmAgentImportPreflightRespVO.Row.builder()
+                        .candidateId("c-0").action("CREATE").build()))
+                .summary(MdmAgentImportPreflightRespVO.Summary.builder()
+                        .total(1).create(1).skip(0).blocked(0).build())
+                .build();
+    }
+
+    private AtomicReference<MdmAgentImportCommandDO> captureInsertedCommand() {
+        AtomicReference<MdmAgentImportCommandDO> holder = new AtomicReference<>();
+        doAnswer(invocation -> {
+            MdmAgentImportCommandDO command = invocation.getArgument(0);
+            command.setId(1L);
+            holder.set(command);
+            return 1;
+        }).when(commandMapper).insert(any(MdmAgentImportCommandDO.class));
+        return holder;
+    }
+
+    private static MdmAgentImportCommitReqVO request(String name) {
+        MdmAgentImportPreflightReqVO.Row row = new MdmAgentImportPreflightReqVO.Row();
+        row.setCandidateId("c-0");
+        row.setRowNo(1);
+        row.setCode("AGENT-E2E-1");
+        row.setName(name);
+        row.setCategoryCode("RAW");
+        row.setUnitMeasureCode("PCS");
+
+        MdmAgentImportCommitReqVO reqVO = new MdmAgentImportCommitReqVO();
+        reqVO.setCommandId("cmd-1");
+        reqVO.setIdempotencyKey("idem-1");
+        reqVO.setAttachmentId(5L);
+        reqVO.setSessionId(21L);
+        reqVO.setSourceSha256(SOURCE_SHA);
+        reqVO.setPreflightHash(PREFLIGHT_HASH);
+        reqVO.setProposalRevision("rev-1");
+        reqVO.setRows(List.of(row));
+        return reqVO;
+    }
+}

--
Gitblit v1.9.3