package jnpf.dmsService; import jnpf.base.UserInfo; import jnpf.dmsEntity.DmsWenjianXinzengShenheEntity; import jnpf.dmsEntity.DmsWenjianXiudingShenheEntity; import jnpf.dmsEntity.permission.entity.DmsFileVersionEntity; import jnpf.dmsEntity.storage.enums.DmsWorkflowFileType; import jnpf.dmsEntity.storage.DmsWorkflowSourceKey; import jnpf.dmsEntity.storage.form.DmsWorkflowFilePrepareForm; import jnpf.dmsEntity.storage.vo.DmsWorkflowFilePrepareVO; import jnpf.dmsEntity.storage.vo.DmsFileUploadVO; import jnpf.dmsMapper.DmsFileObjectMapper; import jnpf.dmsMapper.DmsFileVersionMapper; import jnpf.dmsMapper.DmsWenjianXinzengShenheMapper; import jnpf.dmsMapper.DmsWenjianXiudingShenheMapper; import jnpf.dmsPermission.DmsCurrentIdentity; import jnpf.dmsPermission.DmsPermissionException; import jnpf.exception.DataException; import org.junit.jupiter.api.Test; import java.util.Collections; import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; 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.verifyNoInteractions; import static org.mockito.Mockito.when; class DmsWorkflowFilePrepareServiceTest { private static final String SOURCE_ID = "flow-1"; private static final String TASK_ID = "task-1"; private static final UUID VERSION_ID = UUID.fromString("018f0000-0000-7000-8000-000000000701"); private static final UUID DOCUMENT_ID = UUID.fromString("018f0000-0000-7000-8000-000000000702"); @Test void refusesToGuessTaskOwnershipOfLegacyFlowOnlyRegistration() { Fixture fixture = new Fixture(); DmsWenjianXinzengShenheEntity audit = new DmsWenjianXinzengShenheEntity(); audit.setFlowState(1); when(fixture.newAuditMapper.selectByFlowForUpdate("tenant-1", SOURCE_ID, TASK_ID)) .thenReturn(Collections.singletonList(audit)); when(fixture.fileObjectMapper.selectUploadBySource("tenant-1", "jnpf-file", SOURCE_ID)) .thenReturn(new DmsFileUploadVO()); assertThrows(DataException.class, () -> fixture.prepare(fixture.form(DmsWorkflowFileType.CREATE, null))); verifyNoInteractions(fixture.fileVersionMapper); } @Test void runningNewWorkflowReturnsInitialVersionContext() { Fixture fixture = new Fixture(); DmsWenjianXinzengShenheEntity audit = new DmsWenjianXinzengShenheEntity(); audit.setFlowState(1); when(fixture.newAuditMapper.selectByFlowForUpdate( "tenant-1", SOURCE_ID, TASK_ID)).thenReturn(Collections.singletonList(audit)); DmsWorkflowFilePrepareVO result = fixture.prepare( fixture.form(DmsWorkflowFileType.CREATE, null)); assertEquals("D(00)", result.getVersionLabel()); assertNull(result.getDocumentId()); verifyNoInteractions(fixture.revisionAuditMapper, fixture.fileVersionMapper, fixture.decisionService); } @Test void runningWorkflowCanPrepareAFileBeforeApproval() { Fixture fixture = new Fixture(); DmsWenjianXinzengShenheEntity audit = new DmsWenjianXinzengShenheEntity(); audit.setFlowState(1); when(fixture.newAuditMapper.selectByFlowForUpdate( "tenant-1", SOURCE_ID, TASK_ID)).thenReturn(Collections.singletonList(audit)); DmsWorkflowFilePrepareVO result = fixture.prepare( fixture.form(DmsWorkflowFileType.CREATE, null)); assertEquals("D(00)", result.getVersionLabel()); verifyNoInteractions(fixture.fileVersionMapper, fixture.decisionService); } @Test void passedBusinessWorkflowCannotBeRegisteredAgain() { Fixture fixture = new Fixture(); DmsWenjianXinzengShenheEntity audit = new DmsWenjianXinzengShenheEntity(); audit.setFlowState(2); when(fixture.newAuditMapper.selectByFlowForUpdate( "tenant-1", SOURCE_ID, TASK_ID)).thenReturn(Collections.singletonList(audit)); assertThrows(DataException.class, () -> fixture.prepare( fixture.form(DmsWorkflowFileType.CREATE, null))); verifyNoInteractions(fixture.fileVersionMapper, fixture.decisionService); } @Test void sourceAndTaskMustIdentifyOneBusinessWorkflow() { Fixture fixture = new Fixture(); when(fixture.newAuditMapper.selectByFlowForUpdate( "tenant-1", SOURCE_ID, TASK_ID)).thenReturn(Collections.emptyList()); assertThrows(DataException.class, () -> fixture.prepare( fixture.form(DmsWorkflowFileType.CREATE, null))); verifyNoInteractions(fixture.fileVersionMapper, fixture.decisionService); } @Test void runningRevisionResolvesDocumentAndNextVersionFromCurrentVersion() { Fixture fixture = new Fixture(); DmsWenjianXiudingShenheEntity audit = new DmsWenjianXiudingShenheEntity(); audit.setFlowState(1); when(fixture.revisionAuditMapper.selectByFlowForUpdate( "tenant-1", SOURCE_ID, TASK_ID)).thenReturn(Collections.singletonList(audit)); DmsFileVersionEntity base = version(VERSION_ID, DOCUMENT_ID); when(fixture.fileVersionMapper.selectByTenantAndId("tenant-1", VERSION_ID)) .thenReturn(base); when(fixture.fileVersionMapper.selectCurrentEffective("tenant-1", DOCUMENT_ID)) .thenReturn(base); when(fixture.fileVersionMapper.selectNextVersionNo("tenant-1", DOCUMENT_ID)) .thenReturn(2L); DmsWorkflowFilePrepareVO result = fixture.prepare( fixture.form(DmsWorkflowFileType.REVISE, VERSION_ID)); assertEquals(DOCUMENT_ID, result.getDocumentId()); assertEquals("D(01)", result.getVersionLabel()); assertEquals("工作流审核通过", result.getRevisionReason()); verify(fixture.decisionService).requireAllowed(any(), any(), any()); } @Test void revisionRequiresCurrentEffectiveVersion() { Fixture fixture = new Fixture(); DmsWenjianXiudingShenheEntity audit = new DmsWenjianXiudingShenheEntity(); audit.setFlowState(1); when(fixture.revisionAuditMapper.selectByFlowForUpdate( "tenant-1", SOURCE_ID, TASK_ID)).thenReturn(Collections.singletonList(audit)); when(fixture.fileVersionMapper.selectByTenantAndId("tenant-1", VERSION_ID)) .thenReturn(version(VERSION_ID, DOCUMENT_ID)); when(fixture.fileVersionMapper.selectCurrentEffective("tenant-1", DOCUMENT_ID)) .thenReturn(version(UUID.randomUUID(), DOCUMENT_ID)); assertThrows(DmsPermissionException.class, () -> fixture.prepare( fixture.form(DmsWorkflowFileType.REVISE, VERSION_ID))); verify(fixture.fileVersionMapper, never()).selectNextVersionNo(any(), any()); } @Test void exactRevisionRetryCanUseItsSupersededBaseVersion() { Fixture fixture = new Fixture(); DmsWenjianXiudingShenheEntity audit = new DmsWenjianXiudingShenheEntity(); audit.setFlowState(1); when(fixture.revisionAuditMapper.selectByFlowForUpdate( "tenant-1", SOURCE_ID, TASK_ID)).thenReturn(Collections.singletonList(audit)); DmsFileUploadVO existing = new DmsFileUploadVO(); existing.setDocumentId(DOCUMENT_ID); existing.setBaseFileVersionId(VERSION_ID); existing.setVersionLabel("D(01)"); existing.setRevisionReason("工作流审核通过"); when(fixture.fileObjectMapper.selectUploadBySource( "tenant-1", "jnpf-file", DmsWorkflowSourceKey.of(SOURCE_ID, TASK_ID, DmsWorkflowFileType.REVISE))).thenReturn(existing); DmsWorkflowFilePrepareVO result = fixture.prepare( fixture.form(DmsWorkflowFileType.REVISE, VERSION_ID)); assertEquals(DOCUMENT_ID, result.getDocumentId()); assertEquals("D(01)", result.getVersionLabel()); verify(fixture.fileVersionMapper, never()).selectByTenantAndId(any(), any()); } private static DmsFileVersionEntity version(UUID id, UUID documentId) { DmsFileVersionEntity version = new DmsFileVersionEntity(); version.setId(id); version.setDocumentId(documentId); return version; } private static class Fixture { private final DmsCurrentIdentity currentIdentity = mock(DmsCurrentIdentity.class); private final DmsPermissionDecisionService decisionService = mock(DmsPermissionDecisionService.class); private final DmsWenjianXinzengShenheMapper newAuditMapper = mock(DmsWenjianXinzengShenheMapper.class); private final DmsWenjianXiudingShenheMapper revisionAuditMapper = mock(DmsWenjianXiudingShenheMapper.class); private final DmsFileVersionMapper fileVersionMapper = mock(DmsFileVersionMapper.class); private final DmsFileObjectMapper fileObjectMapper = mock(DmsFileObjectMapper.class); private final DmsWorkflowApprovalValidator approvalValidator = mock(DmsWorkflowApprovalValidator.class); private final DmsWorkflowFilePrepareService service = new DmsWorkflowFilePrepareService( currentIdentity, decisionService, newAuditMapper, revisionAuditMapper, fileVersionMapper, fileObjectMapper, approvalValidator); 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 DmsWorkflowFilePrepareForm form(DmsWorkflowFileType type, UUID versionId) { DmsWorkflowFilePrepareForm form = new DmsWorkflowFilePrepareForm(); form.setSourceId(SOURCE_ID); form.setTaskId(TASK_ID); form.setFileType(type); form.setVersionId(versionId); return form; } private DmsWorkflowFilePrepareVO prepare(DmsWorkflowFilePrepareForm form) { return service.prepare(form, "jnpf-file"); } } }