protected void finalizeOnlineReviewDocument( ProtocolOnlineReviewDocumentBase protocolOnlineReviewDocument, ProtocolSubmissionBase submission, String annotation) { try { final String principalId = identityManagementService .getPrincipalByPrincipalName(KRADConstants.SYSTEM_USER) .getPrincipalId(); WorkflowDocument workflowDocument = WorkflowDocumentFactory.loadDocument( principalId, protocolOnlineReviewDocument.getDocumentNumber()); ProtocolOnlineReviewBase review = protocolOnlineReviewDocument.getProtocolOnlineReview(); review.addActionPerformed( "Finalize:" + workflowDocument.getStatus().getCode() + ":" + review.getProtocolOnlineReviewStatusCode()); if (workflowDocument.isEnroute() || workflowDocument.isInitiated() || workflowDocument.isSaved()) { workflowDocument.superUserBlanketApprove(annotation); } } catch (Exception e) { String errorMessage = String.format( "Workflow exception generated while executing superUserApprove on document %s in finalizeOnlineReviewDocument. Message:%s", protocolOnlineReviewDocument.getDocumentNumber(), e.getMessage()); LOG.error(errorMessage); throw new RuntimeException(errorMessage, e); } }
protected void cancelOnlineReviewDocument( ProtocolOnlineReviewDocumentBase protocolOnlineReviewDocument, ProtocolSubmissionBase submission, String annotation) { try { final String principalId = identityManagementService .getPrincipalByPrincipalName(KRADConstants.SYSTEM_USER) .getPrincipalId(); WorkflowDocument workflowDocument = WorkflowDocumentFactory.loadDocument( principalId, protocolOnlineReviewDocument.getDocumentNumber()); if (workflowDocument.isEnroute() || workflowDocument.isInitiated() || workflowDocument.isSaved()) { workflowDocument.superUserCancel( String.format( "Review Cancelled from assign reviewers action by %s", GlobalVariables.getUserSession().getPrincipalId())); } } catch (Exception e) { String errorMessage = String.format( "Exception generated while executing superUserCancel on document %s in removeOnlineReviewDocument. Message: %s", protocolOnlineReviewDocument.getDocumentNumber(), e.getMessage()); LOG.error(errorMessage); throw new RuntimeException(errorMessage, e); } }
/** * Tests that an exception is thrown if you try to execute a "route" command on an already routed * document. */ @Test public void testRouteAlreadyRoutedDocument() throws Exception { WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), DOCUMENT_TYPE_NAME); document.route(""); assertTrue("Document should be ENROUTE.", document.isEnroute()); assertFalse("There should not be a request to ewestfal.", document.isApprovalRequested()); // verify that only 1 action taken has been performed Collection<ActionTakenValue> actionTakens = KEWServiceLocator.getActionTakenService().findByDocumentId(document.getDocumentId()); assertEquals("There should be only 1 action taken.", 1, actionTakens.size()); // now try and route the document again, an exception should be thrown try { document.route(""); fail("A WorkflowException should have been thrown."); } catch (InvalidActionTakenException e) { e.printStackTrace(); } // verify that there is still only 1 action taken (the transaction above should have rolled // back) actionTakens = KEWServiceLocator.getActionTakenService().findByDocumentId(document.getDocumentId()); assertEquals("There should still be only 1 action taken.", 1, actionTakens.size()); }
@Test public void testAdhocApproversJoinScenario() throws Exception { WorkflowDocument document = WorkflowDocumentFactory.createDocument( getPrincipalIdForName("ewestfal"), "AdHocApproversDocType"); document.route(""); // should send an approve to bmcgough document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("bmcgough"), document.getDocumentId()); assertTrue("Bmcgough should have approve request.", document.isApprovalRequested()); document.approve(""); // at this point the document should pass the split, and end up at the WorkflowDocument2 node // and the AdHocApproversJoin node // after bypassing the AdHocJoinPoint Set<String> nodeNames = document.getNodeNames(); assertEquals("There should be two node names.", 2, nodeNames.size()); assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("WorkflowDocument2")); assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("AdHocApproversJoin")); // pmckown has the request at the adhoc approvers node, if we approve as him then the document // should _not_ transition out // of it's current nodes document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("pmckown"), document.getDocumentId()); assertTrue("Pmckown should have approve request.", document.isApprovalRequested()); document.approve(""); // the document should still be at the same nodes nodeNames = document.getNodeNames(); assertEquals("There should be two node names.", 2, nodeNames.size()); assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("WorkflowDocument2")); assertTrue("Should be at WorkflowDocument2 node.", nodeNames.contains("AdHocApproversJoin")); // at WorkflowDocument2, rkirkend is the approver, if we approve as him we should end up at the // WorkflowDocumentFinal node document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("rkirkend"), document.getDocumentId()); assertTrue("Rkirkend should have approve request.", document.isApprovalRequested()); document.approve(""); // the document should now be at WorkflowDocumentFinal with a request to xqi nodeNames = document.getNodeNames(); assertEquals("There should be one node name.", 1, nodeNames.size()); assertTrue( "Should be at WorkflowDocumentFinal node.", nodeNames.contains("WorkflowDocumentFinal")); document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("xqi"), document.getDocumentId()); assertTrue("Document should still be enroute.", document.isEnroute()); document.approve(""); assertTrue("Document should now be final.", document.isFinal()); }
@Override public boolean canEditDocumentOverview(Document document) { WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument(); Set<String> nodeNames = workflowDocument.getCurrentNodeNames(); return workflowDocument.isEnroute() && CollectionUtils.isNotEmpty(nodeNames) && nodeNames.contains(KFSConstants.RouteLevelNames.ACCOUNT_REVIEW_FULL_EDIT) && workflowDocument.isApprovalRequested() && !workflowDocument.isAcknowledgeRequested(); }
/** * Tests that the document route past the join properly when there are parallel branches that * don't generate requests. This was coded in response to a bug found while testing with ERA in * order to track it down and fix it. */ @Test public void testEmptyParallelBranches() throws Exception { WorkflowDocument document = WorkflowDocumentFactory.createDocument( getPrincipalIdForName("ewestfal"), PARALLEL_EMPTY_DOCUMENT_TYPE_NAME); document.saveDocumentData(); assertTrue("Document should be initiated", document.isInitiated()); assertEquals("Should be no action requests.", 0, document.getRootActionRequests().size()); Collection<? extends Object> nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()); assertEquals("Wrong number of active nodes.", 1, nodeInstances.size()); document.route(""); // should have generated a request to "bmcgough" document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("bmcgough"), document.getDocumentId()); assertTrue("Document should be enroute", document.isEnroute()); List<ActionRequestValue> actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); assertEquals("Incorrect pending action requests.", 1, actionRequests.size()); ActionRequestValue bRequest = actionRequests.get(0); assertNotNull("Should have been routed through node instance.", bRequest.getNodeInstance()); assertTrue(document.isApprovalRequested()); document.approve(""); // now the document should have split, passed through nodes in each branch which didn't generate // requests, // and then passed the join node and generated requests at WorkflowDocumentFinal document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("xqi"), document.getDocumentId()); assertTrue("Document should be enroute", document.isEnroute()); assertTrue(document.isApprovalRequested()); }
/** * Cancel that calls superUserCancel if the document is in route and the current user is the * routed by user of the document. * * @see * org.kuali.rice.kns.web.struts.action.KualiDocumentActionBase#cancel(org.apache.struts.action.ActionMapping, * org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, * javax.servlet.http.HttpServletResponse) */ @Override public ActionForward cancel( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { AwardBudgetDocument awardBudgetDocument = ((AwardBudgetForm) form).getAwardBudgetDocument(); WorkflowDocument workflowDoc = awardBudgetDocument.getDocumentHeader().getWorkflowDocument(); if (workflowDoc.isEnroute() && StringUtils.equals( GlobalVariables.getUserSession().getPrincipalId(), workflowDoc.getRoutedByPrincipalId())) { workflowDoc.superUserCancel("Cancelled by Routed By User"); return mapping.findForward(Constants.MAPPING_BASIC); } else { return super.cancel(mapping, form, request, response); } }
/** * Tests that an exception is not thrown if you try to execute a "route" command on a document you * did not initiate. */ @Test public void testRouteDefaultDocumentAsNonInitiatorUser() throws Exception { WorkflowDocument firstDocument = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), DOCUMENT_TYPE_NAME); WorkflowDocument document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("user2"), firstDocument.getDocumentId()); try { document.route(""); fail("Exception should have been thrown."); } catch (Exception e) { e.printStackTrace(); } assertFalse("Document should not be ENROUTE.", document.isEnroute()); // assertFalse("There should not be a request to user2.", // document.isApprovalRequested()); // // // verify that there are no actions taken // Collection actionTakens = // KEWServiceLocator.getActionTakenService().findByDocumentId(document.getDocumentId()); // assertEquals("There should be 0 actions taken.", 0, actionTakens.size()); }
@Test public void testParallelRoute() throws Exception { WorkflowDocument document = WorkflowDocumentFactory.createDocument( getPrincipalIdForName("ewestfal"), DOCUMENT_TYPE_NAME); document.saveDocumentData(); assertTrue("Document should be initiated", document.isInitiated()); assertEquals("Should be no action requests.", 0, document.getRootActionRequests().size()); Collection<RouteNodeInstance> nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()); assertEquals("Wrong number of active nodes.", 1, nodeInstances.size()); document.route("Routing for parallel"); // should have generated a request to "bmcgough" document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("bmcgough"), document.getDocumentId()); assertTrue("Document should be enroute", document.isEnroute()); List<ActionRequestValue> actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); assertEquals("Incorrect pending action requests.", 1, actionRequests.size()); ActionRequestValue bRequest = actionRequests.get(0); assertNotNull("Should have been routed through node instance.", bRequest.getNodeInstance()); assertTrue(document.isApprovalRequested()); document.approve("Approving test"); // document should split at this point and generate an ack to temay and approves to rkirkend and // pmckown document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("rkirkend"), document.getDocumentId()); assertTrue("Document should be enroute", document.isEnroute()); actionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()); assertEquals("Incorrect pending action requests.", 3, actionRequests.size()); boolean isToTemay = false; boolean isToPmckown = false; boolean isToRkirkend = false; for (Iterator iterator = actionRequests.iterator(); iterator.hasNext(); ) { ActionRequestValue actionRequest = (ActionRequestValue) iterator.next(); if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("temay"))) { isToTemay = true; assertEquals( "Request should be activated.", ActionRequestStatus.ACTIVATED.getCode(), actionRequest.getStatus()); assertEquals( "Wrong action requested.", KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, actionRequest.getActionRequested()); assertNotNull( "Should have been routed through node instance.", actionRequest.getNodeInstance()); assertEquals( "Invalid node.", ACKNOWLEDGE_1_NODE, actionRequest.getNodeInstance().getRouteNode().getRouteNodeName()); } if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("rkirkend"))) { isToRkirkend = true; assertEquals( "Request should be activated.", ActionRequestStatus.ACTIVATED.getCode(), actionRequest.getStatus()); assertEquals( "Wrong action requested.", KewApiConstants.ACTION_REQUEST_APPROVE_REQ, actionRequest.getActionRequested()); assertNotNull( "Should have been routed through node instance.", actionRequest.getNodeInstance()); assertEquals( "Invalid node.", WORKFLOW_DOCUMENT_2_NODE, actionRequest.getNodeInstance().getRouteNode().getRouteNodeName()); } if (actionRequest.getPrincipalId().equals(getPrincipalIdForName("pmckown"))) { isToPmckown = true; assertEquals( "Request should be activated.", ActionRequestStatus.ACTIVATED.getCode(), actionRequest.getStatus()); assertEquals( "Wrong action requested.", KewApiConstants.ACTION_REQUEST_APPROVE_REQ, actionRequest.getActionRequested()); assertNotNull( "Should have been routed through node instance.", actionRequest.getNodeInstance()); assertEquals( "Invalid node.", WORKFLOW_DOCUMENT_3_NODE, actionRequest.getNodeInstance().getRouteNode().getRouteNodeName()); } } assertTrue("No request to temay.", isToTemay); assertTrue("No request to pmckown.", isToPmckown); assertTrue("No request to rkirkend.", isToRkirkend); // check that we are at both nodes, one in each branch Set<String> nodeNames = document.getNodeNames(); assertEquals("Wrong number of node names.", 2, nodeNames.size()); boolean isNode2 = false; boolean isNode3 = false; for (String name : nodeNames) { if (name.equals(WORKFLOW_DOCUMENT_2_NODE)) { isNode2 = true; } if (name.equals(WORKFLOW_DOCUMENT_3_NODE)) { isNode3 = true; } } assertTrue("Not at node2.", isNode2); assertTrue("Not at node3.", isNode3); nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()); assertEquals("Wrong number of active nodes.", 2, nodeInstances.size()); Iterator<RouteNodeInstance> iterator = nodeInstances.iterator(); RouteNodeInstance instance1 = (RouteNodeInstance) iterator.next(); RouteNodeInstance instance2 = (RouteNodeInstance) iterator.next(); assertNotNull("Node should be in branch.", instance1.getBranch()); assertNotNull("Node should be in branch.", instance2.getBranch()); assertTrue( "Branches should be different.", !instance1.getBranch().getBranchId().equals(instance2.getBranch().getBranchId())); document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("rkirkend"), document.getDocumentId()); assertTrue("Should have request.", document.isApprovalRequested()); document.approve("Git-r-dun"); nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()); assertEquals("Wrong number of active nodes.", 2, nodeInstances.size()); boolean isAtJoin = false; boolean isAtWD3 = false; for (RouteNodeInstance nodeInstance : nodeInstances) { if (nodeInstance.getRouteNode().getRouteNodeName().equals(JOIN_NODE)) { assertEquals( "Join branch should be split branch.", instance1.getBranch().getParentBranch().getBranchId(), nodeInstance.getBranch().getBranchId()); isAtJoin = true; } if (nodeInstance.getRouteNode().getRouteNodeName().equals(WORKFLOW_DOCUMENT_3_NODE)) { isAtWD3 = true; } } assertTrue("Not at join", isAtJoin); assertTrue("Not at WD3", isAtWD3); document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("pmckown"), document.getDocumentId()); assertTrue("Should have request.", document.isApprovalRequested()); document.approve("Do it."); nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()); assertEquals("Wrong number of active nodes.", 1, nodeInstances.size()); boolean isAtWDF = false; for (RouteNodeInstance nodeInstance : nodeInstances) { if (nodeInstance.getRouteNode().getRouteNodeName().equals(WORKFLOW_DOCUMENT_FINAL_NODE)) { isAtWDF = true; } } assertTrue("Not at WDF", isAtWDF); document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("xqi"), document.getDocumentId()); assertTrue("Should still be enroute.", document.isEnroute()); assertTrue("Should have request.", document.isApprovalRequested()); document.approve("I'm the last approver"); assertTrue("Document should be processed.", document.isProcessed()); nodeInstances = KEWServiceLocator.getRouteNodeService().getActiveNodeInstances(document.getDocumentId()); assertEquals( "The doc is processed so no node instances should be active", 0, nodeInstances.size()); document = WorkflowDocumentFactory.loadDocument( getPrincipalIdForName("temay"), document.getDocumentId()); assertTrue("Should have request.", document.isAcknowledgeRequested()); document.acknowledge(""); assertTrue(document.isFinal()); }