This is the documentation for Clover Club 12.0.
Documentation for the upcoming version Rampur 13.0 can be found here.

Approval Steps Configuration

This section describes how to skip certain steps during a repeated run of a workflow and how to allow only admins to add extra approval steps.

Mark Approval Step as Satisfied

You can configure the workflow to pass through an approval step without any need for approval and still keep a record of the step itself.

Using the methods listed below, the workflow logic has access to the previous workflow run and can decide if the previous approvals are still valid regarding the changes (per approval node). If the changes do not impact the existing approvals the workflow will continue from the same place where it left off.

Useful methods:

  • api.findPreviousApprovableState() – This method can be used to fetch the previous entity (Quote / Agreement or Promotion / Rebate Agreement) state from the database.

  • api.findPreviousWorkflowInfo() – This method can be used to fetch previous entity's workflow information (i.e., the workflow history).

  • ALREADY SATISFIED – A workflow step state that can be used to mark steps at the workflow logic execution time as "satisfied". They will be skipped by the workflow engine but will be retained in the workflow.

Example
def currentState = quote def previousState = api.findPreviousApprovableState(currentState.typedId, "DENIED", "WITHDRAWN") def previousWorkflowInfo = api.findPreviousWorkflowInfo(currentState.typedId, "DENIED", "WITHDRAWN") api.logInfo("currentState", currentState) api.logInfo("previousState", previousState) api.logInfo("previousWorkflowInfo", previousWorkflowInfo) def canSkip1stApprovalComment if (previousWorkflowInfo && previousWorkflowInfo.steps && previousWorkflowInfo.steps.size() >= 1) { if (previousWorkflowInfo.steps[0].approved || previousWorkflowInfo.steps[0].alreadySatisfied) { def comment = previousWorkflowInfo.steps[0].comment if (!comment) comment = "already satisfied in previous workflow" canSkip1stApprovalComment = comment } } workflow .addApprovalStep("ApproverWithDefault") .withApprovers("admin") .withReasons("type your reason here") .withAlreadySatisfied(canSkip1stApprovalComment) workflow .addApprovalStep("Approver") .withApprovers("admin") .withReasons("type your reason here") def canSkip3rdApproval = previousState && previousState.workflowStatus == "DENIED" && quote.createdByName == "admin" def step3 = workflow .addApprovalStep("Approver2") .withApprovers("admin") .withReasons("type your reason here") if (canSkip3rdApproval) { step3.withAlreadySatisfied("Not needed anymore") }

You can also use an option that allows users to select to which workflow step the workflow will return when a document is rejected.

def previousWorkflowInfo = api.findPreviousWorkflowInfo(quote.typedId, "DENIED") def stepNames = ["Sales Manager", "Account Manager", "Regional Manager"] def satisfiedSteps = [:] if (previousWorkflowInfo?.selectedStepOnDeny) { def found = false for (s in stepNames) { found = found || (s == previousWorkflowInfo?.selectedStepOnDeny) satisfiedSteps.put(s, found ? null : "Already satisfied in previous workflow and requested to be skipped now by workflow logic.") } } api.logInfo("Workflow", satisfiedSteps.inspect()) workflow .withSelectStepOnDeny(true) .addApprovalStep("Sales Manager") .withApprovers("John Newman") .withReasons("Total Price is over threshold.") .withAlreadySatisfied(satisfiedSteps["Sales Manager"]) workflow .withSelectStepOnDeny(true) .addApprovalStep("Account Manager") .withApprovers("Cindy Smith") .withReasons("Total Price is over threshold.") .withAlreadySatisfied(satisfiedSteps["Account Manager"]) workflow .withSelectStepOnDeny(true) .addApprovalStep("Regional Manager") .withApprovers("Lin Yun") .withReasons("Total Price is over threshold.") .withAlreadySatisfied(satisfiedSteps["Regional Manager"])

The method withSelectStepOnDeny displays a dialog when the user denies the document and provides three options:

  • Select a step from the drop-down list and click Deny – the document is rejected and the selected step is flagged. The next time the above example logic is run, the workflow skips all previous approvers.

  • Leave the Select step box empty and click Deny – the behavior is the same as in a workflow without this method. No step is flagged and the next time the workflow is run, it starts with the first approver.

  • Click the Cancel button – the dialog is closed and no workflow action is performed.

Restriction on Adding Steps

It is possible to restrict adding the extra steps to Workflow Admins only. To do so, use the withAddStepRestrictedToWFAdmin method for generating the workflow:

workflow.withAddStepRestrictedToWFAdmin().addApprovalStep("Approver").withApprover("admin").setReason("Requires 'admin' approval")