package jnpf.dmsService; import jnpf.dmsEntity.storage.enums.DmsWorkflowFileType; import jnpf.dmsEntity.storage.form.DmsWorkflowFileForm; import jnpf.dmsEntity.storage.form.DmsWorkflowUploadRegisterForm; import jnpf.dmsEntity.storage.form.DmsWorkflowRevisionRegisterForm; import jnpf.dmsEntity.storage.vo.DmsFileUploadVO; import jnpf.dmsEntity.storage.vo.DmsWorkflowFilePrepareVO; import jnpf.exception.DataException; import jnpf.flowable.WorkFlowApi; import jnpf.flowable.entity.TaskEntity; import org.junit.jupiter.api.Test; import org.springframework.aop.framework.ProxyFactory; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource; import org.springframework.transaction.interceptor.TransactionInterceptor; import java.time.LocalDate; import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; class DmsWorkflowFileRegistrationServiceTest { private final DmsWorkflowFilePrepareService prepare = mock(DmsWorkflowFilePrepareService.class); private final DmsFileUploadService upload = mock(DmsFileUploadService.class); private final DmsFileRevisionService revise = mock(DmsFileRevisionService.class); private final WorkFlowApi workflowApi = mock(WorkFlowApi.class); private final DmsWorkflowFileRegistrationService service = new DmsWorkflowFileRegistrationService( prepare, upload, revise, workflowApi); @Test void revokedWhileFileWasTransferredNeverRegisters() { DmsWorkflowUploadRegisterForm form = uploadForm(); when(workflowApi.getInfoSubmit("task")).thenReturn(task(7)); assertThrows(DataException.class, () -> service.upload(form, "jnpf-file")); verifyNoInteractions(prepare, upload, revise); } @Test void passedTaskCannotUseThePreApprovalRegistrationApi() { DmsWorkflowUploadRegisterForm form = uploadForm(); when(workflowApi.getInfoSubmit("task")).thenReturn(task(2)); assertThrows(DataException.class, () -> service.upload(form, "jnpf-file")); verifyNoInteractions(prepare, upload, revise); } @Test void rejectsTaskFromDifferentFlowEvenWhenPassed() { DmsWorkflowUploadRegisterForm form = uploadForm(); TaskEntity task = task(1); task.setFlowId("other-flow"); when(workflowApi.getInfoSubmit("task")).thenReturn(task); assertThrows(DataException.class, () -> service.upload(form, "jnpf-file")); verifyNoInteractions(prepare, upload, revise); } @Test void changedApprovalAttachmentStopsRegistration() { DmsWorkflowUploadRegisterForm form = uploadForm(); stubStageable(); form.setApprovedFileJson("changed-file"); assertThrows(DataException.class, () -> service.upload(form, "jnpf-file")); verifyNoInteractions(upload, revise); } @Test void revokedBeforeCommitRollsBackTheRegistrationTransaction() { DmsWorkflowUploadRegisterForm form = uploadForm(); stubStageable(); when(workflowApi.getInfoSubmit("task")).thenReturn(task(1), task(7)); PlatformTransactionManager transactions = mock(PlatformTransactionManager.class); TransactionStatus status = mock(TransactionStatus.class); when(transactions.getTransaction(any())).thenReturn(status); ProxyFactory proxyFactory = new ProxyFactory(service); proxyFactory.addAdvice(new TransactionInterceptor(transactions, new AnnotationTransactionAttributeSource())); DmsWorkflowFileRegistrationService transactional = (DmsWorkflowFileRegistrationService) proxyFactory.getProxy(); assertThrows(DataException.class, () -> transactional.upload(form, "jnpf-file")); verify(upload).registerWorkflowPending(form, "jnpf-file", "flow", "task"); verify(transactions).rollback(status); verify(transactions, never()).commit(any()); } @Test void stageableRegistrationUsesFreshContextAndChecksTaskAgain() { DmsWorkflowUploadRegisterForm form = uploadForm(); stubStageable(); DmsFileUploadVO expected = new DmsFileUploadVO(); when(upload.registerWorkflowPending(form, "jnpf-file", "flow", "task")) .thenReturn(expected); assertSame(expected, service.upload(form, "jnpf-file")); verify(workflowApi, times(2)).getInfoSubmit("task"); verify(upload).registerWorkflowPending(form, "jnpf-file", "flow", "task"); } @Test void revisionCannotSubstituteTheApprovedDocument() { stubStageable(); DmsWorkflowRevisionRegisterForm form = new DmsWorkflowRevisionRegisterForm(); DmsWorkflowFileForm workflow = uploadForm().getWorkflow(); workflow.setFileType(DmsWorkflowFileType.REVISE); form.setWorkflow(workflow); form.setSourceId("workflow:key"); form.setApprovedFileJson("approved-file"); form.setDocumentId(UUID.randomUUID()); assertThrows(DataException.class, () -> service.revise(form, "jnpf-file")); verifyNoInteractions(upload, revise); } private void stubStageable() { when(workflowApi.getInfoSubmit("task")).thenReturn(task(1)); DmsWorkflowFilePrepareVO context = new DmsWorkflowFilePrepareVO(); context.setSourceKey("workflow:key"); context.setApprovedFileJson("approved-file"); context.setVersionLabel("D(00)"); when(prepare.prepare(any(), eq("jnpf-file"))).thenReturn(context); } private TaskEntity task(int status) { TaskEntity task = new TaskEntity(); task.setId("task"); task.setFlowId("flow"); task.setStatus(status); return task; } private DmsWorkflowUploadRegisterForm uploadForm() { DmsWorkflowFileForm workflow = new DmsWorkflowFileForm(); workflow.setSourceId("flow"); workflow.setTaskId("task"); workflow.setFileType(DmsWorkflowFileType.CREATE); workflow.setFolderId(UUID.randomUUID()); workflow.setDocumentNo("DOC-1"); workflow.setDocumentName("manual"); workflow.setResponsibleDeptId("quality"); workflow.setPreparedBy("user"); workflow.setPreparedOn(LocalDate.of(2026, 9, 7)); DmsWorkflowUploadRegisterForm form = new DmsWorkflowUploadRegisterForm(); form.setWorkflow(workflow); form.setSourceId("workflow:key"); form.setApprovedFileJson("approved-file"); form.setVersionLabel("D(00)"); form.setFolderId(workflow.getFolderId()); form.setDocumentNo(workflow.getDocumentNo()); form.setDocumentName(workflow.getDocumentName()); form.setResponsibleDeptId(workflow.getResponsibleDeptId()); form.setPreparedBy(workflow.getPreparedBy()); form.setPreparedOn(workflow.getPreparedOn()); return form; } }