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/impl/DmsWenjianBanbenServiceImplTest.java |  223 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 223 insertions(+), 0 deletions(-)

diff --git a/jnpf-dms/jnpf-dms-biz/src/test/java/jnpf/dmsService/impl/DmsWenjianBanbenServiceImplTest.java b/jnpf-dms/jnpf-dms-biz/src/test/java/jnpf/dmsService/impl/DmsWenjianBanbenServiceImplTest.java
new file mode 100644
index 0000000..ed6c9c7
--- /dev/null
+++ b/jnpf-dms/jnpf-dms-biz/src/test/java/jnpf/dmsService/impl/DmsWenjianBanbenServiceImplTest.java
@@ -0,0 +1,223 @@
+package jnpf.dmsService.impl;
+
+import jnpf.base.UserInfo;
+import jnpf.dmsEntity.DmsWenjianBanbenKongzhiEntity;
+import jnpf.dmsEntity.DmsWenjianXinzengGuanliEntity;
+import jnpf.dmsEntity.DmsWenjianXinzengShenheEntity;
+import jnpf.dmsEntity.DmsWenjianXiudingShenheEntity;
+import jnpf.dmsEntity.DmsWenjianXiudingShenqingEntity;
+import jnpf.dmsEntity.wenjianbianhao.DmsFlowEventType;
+import jnpf.dmsMapper.DmsWenjianBanbenKongzhiMapper;
+import jnpf.dmsMapper.DmsWenjianXinzengGuanliMapper;
+import jnpf.dmsMapper.DmsWenjianXinzengShenheMapper;
+import jnpf.dmsMapper.DmsWenjianXiudingShenheMapper;
+import jnpf.dmsMapper.DmsWenjianXiudingShenqingMapper;
+import jnpf.dmsPermission.DmsCurrentIdentity;
+import jnpf.exception.DataException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.Collections;
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class DmsWenjianBanbenServiceImplTest {
+
+    private static final String TENANT_ID = "tenant-1";
+    private static final String FLOW_ID = "flow-1";
+    private static final String TASK_ID = "task-1";
+
+    @Mock private DmsCurrentIdentity identity;
+    @Mock private DmsWenjianBanbenKongzhiMapper controlMapper;
+    @Mock private DmsWenjianXinzengGuanliMapper newRequestMapper;
+    @Mock private DmsWenjianXinzengShenheMapper newAuditMapper;
+    @Mock private DmsWenjianXiudingShenqingMapper revisionRequestMapper;
+    @Mock private DmsWenjianXiudingShenheMapper revisionAuditMapper;
+
+    @InjectMocks
+    private DmsWenjianBanbenServiceImpl service;
+
+    @BeforeEach
+    void setUpIdentity() {
+        UserInfo user = new UserInfo();
+        user.setUserId("operator-1");
+        user.setTenantId(TENANT_ID);
+        when(identity.requireUser()).thenReturn(user);
+        when(identity.tenantId(user)).thenReturn(TENANT_ID);
+    }
+
+    @Test
+    void newAuditPassInitializesD00AndWritesAuditResult() {
+        DmsWenjianXinzengShenheEntity audit = newAudit(2);
+        DmsWenjianXinzengGuanliEntity request = newRequest();
+        when(newAuditMapper.selectByFlowForUpdate(TENANT_ID, FLOW_ID, TASK_ID))
+                .thenReturn(Collections.singletonList(audit));
+        when(newRequestMapper.selectByIdForUpdate(TENANT_ID, "new-request-1"))
+                .thenReturn(request);
+        when(controlMapper.selectByFileForUpdate(TENANT_ID, "new-request-1"))
+                .thenReturn(null);
+        when(controlMapper.insertControl(any())).thenReturn(1);
+        when(newAuditMapper.updateEffectiveVersion(audit)).thenReturn(1);
+
+        service.syncNewAuditFlow(FLOW_ID, TASK_ID, 2, DmsFlowEventType.END);
+
+        ArgumentCaptor<DmsWenjianBanbenKongzhiEntity> captor =
+                ArgumentCaptor.forClass(DmsWenjianBanbenKongzhiEntity.class);
+        verify(controlMapper).insertControl(captor.capture());
+        DmsWenjianBanbenKongzhiEntity control = captor.getValue();
+        assertEquals("new-request-1", control.getWenjianId());
+        assertEquals(0, control.getBanbenXuhao());
+        assertEquals(0L, control.getBiangengXuhao());
+        assertEquals("xinzeng", control.getZuihouShengxiaoLeixing());
+        assertEquals("D(00)", audit.getShengxiaoBanbenhao());
+        assertNotNull(audit.getBanbenShengxiaoShijian());
+    }
+
+    @Test
+    void upgradeRevisionAdvancesVersionAndChangeSequence() {
+        DmsWenjianXiudingShenheEntity audit = revisionAudit(2, "shengji");
+        DmsWenjianXiudingShenqingEntity request = revisionRequest(2, 4L);
+        DmsWenjianBanbenKongzhiEntity control = control(2, 4L);
+        when(revisionAuditMapper.selectByFlowForUpdate(TENANT_ID, FLOW_ID, TASK_ID))
+                .thenReturn(Collections.singletonList(audit));
+        when(revisionRequestMapper.selectByIdForUpdate(TENANT_ID, "revision-request-1"))
+                .thenReturn(request);
+        when(controlMapper.selectByFileForUpdate(TENANT_ID, "file-1")).thenReturn(control);
+        when(controlMapper.advance(any(), any(), any())).thenReturn(1);
+        when(revisionAuditMapper.updateEffectiveVersion(audit)).thenReturn(1);
+
+        service.syncRevisionAuditFlow(FLOW_ID, TASK_ID, 2, DmsFlowEventType.END);
+
+        assertEquals(3, control.getBanbenXuhao());
+        assertEquals(5L, control.getBiangengXuhao());
+        assertEquals("D(03)", audit.getShengxiaoBanbenhao());
+        assertEquals(5L, audit.getShengxiaoBiangengXuhao());
+        verify(controlMapper).advance(control, 2, 4L);
+    }
+
+    @Test
+    void unchangedRevisionKeepsVersionButAdvancesChangeSequence() {
+        DmsWenjianXiudingShenheEntity audit = revisionAudit(2, "wubianhua");
+        DmsWenjianXiudingShenqingEntity request = revisionRequest(2, 4L);
+        DmsWenjianBanbenKongzhiEntity control = control(2, 4L);
+        when(revisionAuditMapper.selectByFlowForUpdate(TENANT_ID, FLOW_ID, TASK_ID))
+                .thenReturn(Collections.singletonList(audit));
+        when(revisionRequestMapper.selectByIdForUpdate(TENANT_ID, "revision-request-1"))
+                .thenReturn(request);
+        when(controlMapper.selectByFileForUpdate(TENANT_ID, "file-1")).thenReturn(control);
+        when(controlMapper.advance(any(), any(), any())).thenReturn(1);
+        when(revisionAuditMapper.updateEffectiveVersion(audit)).thenReturn(1);
+
+        service.syncRevisionAuditFlow(FLOW_ID, TASK_ID, 2, DmsFlowEventType.END);
+
+        assertEquals(2, control.getBanbenXuhao());
+        assertEquals(5L, control.getBiangengXuhao());
+        assertEquals("D(02)", audit.getShengxiaoBanbenhao());
+    }
+
+    @Test
+    void staleRevisionSnapshotIsRejectedBeforeAnyUpdate() {
+        DmsWenjianXiudingShenheEntity audit = revisionAudit(2, "shengji");
+        DmsWenjianXiudingShenqingEntity request = revisionRequest(2, 3L);
+        DmsWenjianBanbenKongzhiEntity control = control(2, 4L);
+        when(revisionAuditMapper.selectByFlowForUpdate(TENANT_ID, FLOW_ID, TASK_ID))
+                .thenReturn(Collections.singletonList(audit));
+        when(revisionRequestMapper.selectByIdForUpdate(TENANT_ID, "revision-request-1"))
+                .thenReturn(request);
+        when(controlMapper.selectByFileForUpdate(TENANT_ID, "file-1")).thenReturn(control);
+
+        DataException exception = assertThrows(DataException.class,
+                () -> service.syncRevisionAuditFlow(
+                        FLOW_ID, TASK_ID, 2, DmsFlowEventType.END));
+
+        assertEquals("鏉ユ簮鏂囦欢宸叉湁鍏朵粬淇鐢熸晥锛岃閲嶆柊鍙戣捣淇鐢宠", exception.getMessage());
+        verify(controlMapper, never()).advance(any(), any(), any());
+        verify(revisionAuditMapper, never()).updateEffectiveVersion(any());
+    }
+
+    @Test
+    void repeatedRevisionEndIsIdempotentAfterLaterVersionsExist() {
+        DmsWenjianXiudingShenheEntity audit = revisionAudit(2, "shengji");
+        audit.setShengxiaoBanbenXuhao(3);
+        audit.setShengxiaoBanbenhao("D(03)");
+        audit.setShengxiaoBiangengXuhao(5L);
+        audit.setBanbenShengxiaoShijian(new Date());
+        when(revisionAuditMapper.selectByFlowForUpdate(TENANT_ID, FLOW_ID, TASK_ID))
+                .thenReturn(Collections.singletonList(audit));
+
+        service.syncRevisionAuditFlow(FLOW_ID, TASK_ID, 2, DmsFlowEventType.END);
+
+        verify(revisionRequestMapper, never()).selectByIdForUpdate(any(), any());
+        verify(controlMapper, never()).advance(any(), any(), any());
+    }
+
+    private DmsWenjianXinzengShenheEntity newAudit(int state) {
+        DmsWenjianXinzengShenheEntity audit = new DmsWenjianXinzengShenheEntity();
+        audit.setId("new-audit-1");
+        audit.setTenantId(TENANT_ID);
+        audit.setFlowId(FLOW_ID);
+        audit.setFlowTaskId(TASK_ID);
+        audit.setFlowState(state);
+        audit.setShenqingdanId("new-request-1");
+        return audit;
+    }
+
+    private DmsWenjianXinzengGuanliEntity newRequest() {
+        DmsWenjianXinzengGuanliEntity request = new DmsWenjianXinzengGuanliEntity();
+        request.setId("new-request-1");
+        request.setTenantId(TENANT_ID);
+        request.setFlowState(2);
+        request.setXinxiuding("xinding");
+        request.setBanbenXuhao(0);
+        request.setBanbenhao("D(00)");
+        return request;
+    }
+
+    private DmsWenjianXiudingShenheEntity revisionAudit(int state, String type) {
+        DmsWenjianXiudingShenheEntity audit = new DmsWenjianXiudingShenheEntity();
+        audit.setId("revision-audit-1");
+        audit.setTenantId(TENANT_ID);
+        audit.setFlowId(FLOW_ID);
+        audit.setFlowTaskId(TASK_ID);
+        audit.setFlowState(state);
+        audit.setXiudingShenqingId("revision-request-1");
+        audit.setBiangengFangshi(type);
+        return audit;
+    }
+
+    private DmsWenjianXiudingShenqingEntity revisionRequest(int version, long change) {
+        DmsWenjianXiudingShenqingEntity request = new DmsWenjianXiudingShenqingEntity();
+        request.setId("revision-request-1");
+        request.setTenantId(TENANT_ID);
+        request.setFlowState(2);
+        request.setWenjianId("file-1");
+        request.setBanbenXuhao(version);
+        request.setBanbenhao(DmsWenjianBanbenServiceImpl.formatVersion(version));
+        request.setYuanBiangengXuhao(change);
+        return request;
+    }
+
+    private DmsWenjianBanbenKongzhiEntity control(int version, long change) {
+        DmsWenjianBanbenKongzhiEntity control = new DmsWenjianBanbenKongzhiEntity();
+        control.setId("control-1");
+        control.setTenantId(TENANT_ID);
+        control.setWenjianId("file-1");
+        control.setBanbenXuhao(version);
+        control.setBiangengXuhao(change);
+        control.setBizStatus("effective");
+        return control;
+    }
+}

--
Gitblit v1.8.0