From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-dms/jnpf-dms-biz/src/test/java/jnpf/dmsService/DmsFileUploadServiceTest.java |  173 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 173 insertions(+), 0 deletions(-)

diff --git a/jnpf-dms/jnpf-dms-biz/src/test/java/jnpf/dmsService/DmsFileUploadServiceTest.java b/jnpf-dms/jnpf-dms-biz/src/test/java/jnpf/dmsService/DmsFileUploadServiceTest.java
new file mode 100644
index 0000000..e62a5ee
--- /dev/null
+++ b/jnpf-dms/jnpf-dms-biz/src/test/java/jnpf/dmsService/DmsFileUploadServiceTest.java
@@ -0,0 +1,173 @@
+package jnpf.dmsService;
+
+import jnpf.base.UserInfo;
+import jnpf.dmsEntity.permission.entity.DmsDocumentEntity;
+import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity;
+import jnpf.dmsEntity.permission.entity.DmsPermissionResourceEntity;
+import jnpf.dmsEntity.storage.entity.DmsFileObjectEntity;
+import jnpf.dmsEntity.storage.form.DmsFileUploadRegisterForm;
+import jnpf.dmsEntity.storage.vo.DmsFileUploadVO;
+import jnpf.dmsIntegration.audit.DmsAuditAdapter;
+import jnpf.dmsMapper.DmsDocumentMapper;
+import jnpf.dmsMapper.DmsFileObjectMapper;
+import jnpf.dmsMapper.DmsFileVersionMapper;
+import jnpf.dmsMapper.DmsPermissionResourceMapper;
+import jnpf.dmsMapper.DmsVersionStateMapper;
+import jnpf.dmsPermission.DmsCurrentIdentity;
+import jnpf.dmsPermission.DmsPermissionException;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+
+import java.time.LocalDate;
+import java.util.UUID;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class DmsFileUploadServiceTest {
+
+    @Test
+    void registersDocumentVersionResourcesAndObjectInOneServiceCall() {
+        Fixture fixture = new Fixture();
+        DmsFileUploadRegisterForm form = fixture.form();
+        DmsFileUploadVO created = fixture.view(form);
+        when(fixture.fileObjectMapper.selectUploadBySource("tenant-1", "jnpf-file", "source-1"))
+                .thenReturn(null, created);
+
+        DmsFileUploadVO result = fixture.service.register(form, "jnpf-file");
+
+        assertSame(created, result);
+        verify(fixture.decisionService).requireAllowed(any(), any(), any());
+        ArgumentCaptor<DmsDocumentEntity> documentCaptor = ArgumentCaptor.forClass(DmsDocumentEntity.class);
+        verify(fixture.documentMapper).insert(documentCaptor.capture());
+        assertEquals("MM-R02", documentCaptor.getValue().getDocumentNo());
+        assertEquals("QUALITY_MANUAL", documentCaptor.getValue().getDocumentType());
+        assertEquals("dept-quality", documentCaptor.getValue().getResponsibleDeptId());
+
+        ArgumentCaptor<DmsFileVersionEntity> versionCaptor = ArgumentCaptor.forClass(DmsFileVersionEntity.class);
+        verify(fixture.fileVersionMapper).insert(versionCaptor.capture());
+        assertEquals("D(00)", versionCaptor.getValue().getVersionLabel());
+        assertEquals("author-1", versionCaptor.getValue().getPreparedBy());
+        assertEquals(LocalDate.of(2026, 8, 21), versionCaptor.getValue().getPreparedOn());
+        verify(fixture.resourceMapper, org.mockito.Mockito.times(2)).insert(any(DmsPermissionResourceEntity.class));
+        verify(fixture.versionStateMapper).insertDirectEffective("tenant-1", form.getDocumentId(),
+                form.getFileVersionId(), "user-1");
+        verify(fixture.fileObjectMapper).insert(any(DmsFileObjectEntity.class));
+    }
+
+    @Test
+    void returnsExistingUploadWithoutDuplicateWrites() {
+        Fixture fixture = new Fixture();
+        DmsFileUploadRegisterForm form = fixture.form();
+        DmsFileUploadVO existing = fixture.view(form);
+        when(fixture.fileObjectMapper.selectUploadBySource("tenant-1", "jnpf-file", "source-1"))
+                .thenReturn(existing);
+
+        DmsFileUploadVO result = fixture.service.register(form, "jnpf-file");
+
+        assertSame(existing, result);
+        verify(fixture.documentMapper, never()).insert(any(DmsDocumentEntity.class));
+        verify(fixture.fileVersionMapper, never()).insert(any(DmsFileVersionEntity.class));
+        verify(fixture.versionStateMapper, never()).insertDirectEffective(any(), any(), any(), any());
+        verify(fixture.fileObjectMapper, never()).insert(any(DmsFileObjectEntity.class));
+    }
+
+    @Test
+    void rejectsIdempotentRetryWhenDocumentNumberChanges() {
+        Fixture fixture = new Fixture();
+        DmsFileUploadRegisterForm form = fixture.form();
+        DmsFileUploadVO existing = fixture.view(form);
+        form.setDocumentNo("MM-R03");
+        when(fixture.fileObjectMapper.selectUploadBySource("tenant-1", "jnpf-file", "source-1"))
+                .thenReturn(existing);
+
+        assertThrows(DmsPermissionException.class,
+                () -> fixture.service.register(form, "jnpf-file"));
+
+        verify(fixture.documentMapper, never()).insert(any(DmsDocumentEntity.class));
+        verify(fixture.fileVersionMapper, never()).insert(any(DmsFileVersionEntity.class));
+        verify(fixture.versionStateMapper, never()).insertDirectEffective(any(), any(), any(), any());
+        verify(fixture.fileObjectMapper, never()).insert(any(DmsFileObjectEntity.class));
+    }
+
+    private static class Fixture {
+        private final DmsCurrentIdentity currentIdentity = mock(DmsCurrentIdentity.class);
+        private final DmsPermissionDecisionService decisionService = mock(DmsPermissionDecisionService.class);
+        private final DmsDocumentMapper documentMapper = mock(DmsDocumentMapper.class);
+        private final DmsFileVersionMapper fileVersionMapper = mock(DmsFileVersionMapper.class);
+        private final DmsPermissionResourceMapper resourceMapper = mock(DmsPermissionResourceMapper.class);
+        private final DmsFileObjectMapper fileObjectMapper = mock(DmsFileObjectMapper.class);
+        private final DmsVersionStateMapper versionStateMapper = mock(DmsVersionStateMapper.class);
+        private final DmsAuditAdapter auditAdapter = mock(DmsAuditAdapter.class);
+        private final DmsFileUploadService service = new DmsFileUploadService(currentIdentity, decisionService,
+                documentMapper, fileVersionMapper, resourceMapper, fileObjectMapper, versionStateMapper,
+                auditAdapter);
+
+        private Fixture() {
+            UserInfo user = new UserInfo();
+            user.setUserId("user-1");
+            user.setTenantId("tenant-1");
+            when(currentIdentity.requireUser()).thenReturn(user);
+            when(currentIdentity.tenantId(user)).thenReturn("tenant-1");
+        }
+
+        private DmsFileUploadRegisterForm form() {
+            DmsFileUploadRegisterForm form = new DmsFileUploadRegisterForm();
+            form.setDocumentId(UUID.fromString("018f0000-0000-7000-8000-000000000301"));
+            form.setFileVersionId(UUID.fromString("018f0000-0000-7000-8000-000000000302"));
+            form.setFileObjectId(UUID.fromString("018f0000-0000-7000-8000-000000000303"));
+            form.setFolderId(UUID.fromString("018f0000-0000-7000-8000-000000000304"));
+            form.setDocumentNo("MM-R02");
+            form.setDocumentName("璐ㄩ噺鎵嬪唽");
+            form.setDocumentType("QUALITY_MANUAL");
+            form.setResponsibleDeptId("dept-quality");
+            form.setVersionLabel("D(00)");
+            form.setFileName("report.txt");
+            form.setMimeType("text/plain");
+            form.setSizeBytes(12L);
+            form.setChecksumSha256("a".repeat(64));
+            form.setPreparedBy("author-1");
+            form.setPreparedOn(LocalDate.of(2026, 8, 21));
+            form.setStoragePlatform("seaweedfs-1");
+            form.setBucketName("jnpf-dms");
+            form.setBasePath("dms/");
+            form.setObjectPath("2026/08/17/document/");
+            form.setObjectName("version.txt");
+            form.setSourceId("source-1");
+            return form;
+        }
+
+        private DmsFileUploadVO view(DmsFileUploadRegisterForm form) {
+            DmsFileUploadVO view = new DmsFileUploadVO();
+            view.setDocumentId(form.getDocumentId());
+            view.setFileVersionId(form.getFileVersionId());
+            view.setFileObjectId(form.getFileObjectId());
+            view.setFolderId(form.getFolderId());
+            view.setDocumentNo(form.getDocumentNo());
+            view.setDocumentName(form.getDocumentName());
+            view.setDocumentType(form.getDocumentType());
+            view.setResponsibleDeptId(form.getResponsibleDeptId());
+            view.setVersionNo(1L);
+            view.setVersionLabel(form.getVersionLabel());
+            view.setFileName(form.getFileName());
+            view.setMimeType(form.getMimeType());
+            view.setSizeBytes(form.getSizeBytes());
+            view.setChecksumSha256(form.getChecksumSha256());
+            view.setPreparedBy(form.getPreparedBy());
+            view.setPreparedOn(form.getPreparedOn());
+            view.setStoragePlatform(form.getStoragePlatform());
+            view.setBucketName(form.getBucketName());
+            view.setBasePath(form.getBasePath());
+            view.setObjectPath(form.getObjectPath());
+            view.setObjectName(form.getObjectName());
+            view.setSourceId(form.getSourceId());
+            return view;
+        }
+    }
+}

--
Gitblit v1.8.0