Step Expiry

   Journey Manager (JM) The transaction engine for the platform.  |    System Manager / DevOps  |  All versions This feature is related to all versions.

You can configure steps of a collaboration job to expire depending on customer requirements, such as a Service Level AgreementA service-level agreement (SLA) is a commitment between a service provider and a client. Particular aspects of the service – quality, availability, responsibilities – are agreed between the service provider and the service user.. For example, you can implement a Review step to assign a task to a group, such as Reviewers group, so they have two days to action the task. Otherwise, it expires and will be routed to an Escalation step for a manager to review it.

The step expiry workflow is shown below.

You can implement step expiration using one of the following mechanisms:

  1. The step's expiryRule attribute to specify the period of time, from its creation date, when the step will expire.
  2. Any action in a step can control the step expiry by returning an action result that sets an action expiry or returns the Expired status.

You can also configure the Expiry Action, see Job Expiry Service, within a step. This allows for the clean-up code to be run. Steps that expire must define an Expiry Route; that is, a route with the Route Name Expiry. When the step expires, it is routed to the Next Step defined in the Expiry Route.

Download

You can also download the application package with this example here.

Configure a Form

This example uses the AVT-3547 Test Expiry form, which is a copy of Job Example 1 form, initiates a job controller. You can download the example below.

Configure a Job Controller

You can update an existing job controller by adding an Application Escalated step, so when the Application Review step expires, it will be routed to the Application Escalated step.

The AVT-3547 Test Expiry B job controller is a modified copy of the 1 Step Review job controller, where the version B introduces a new Group Task Step.

The Application Review step is modified to:

  • Expire the step after 1 minute.  |  v4.3 & Higher   This feature is related to v4.3 and higher.
  • Call the job expiry service.
  • Call the expiryServiceName service.
  • Expiry routes to the net step Application Escalated.
  • Expiry route added with display set to false.

The Application Review and Application Escalated steps definition is shown below.

{
  "name": "Application Review",
  "type": "",
  "expiryRule": "+1m",
  "expiryServiceName": "Job Expiry - Expire Step Tasks",
  "actions": [
    {
      "name": "Assign Review",
      "type": "Job Task Assign",
      "properties": [
        { "name": "Task Assign Groups",  "value": "Job Reviewers" },
        { "name": "Task Form Code",  "value": "$func.startFormCode()" },
        { "name": "Task Message",  "value": "Please review the ${submission.formName} by ${formDataMap.firstName} ${formDataMap.lastName}." },
        { "name": "Task Review Previous Step",  "value": "true" },
        { "name": "Task Subject",  "value": "Review ${submission.formName} by by ${formDataMap.firstName} ${formDataMap.lastName}" },
        { "name": "Task Type",  "value": "Review" }
      ]
    },
    {
      "name": "Review Wait",
      "type": "Job Task Wait"
    }
  ],
  "routes": [
    { "name": "Approve",  "nextStep": "Application Delivery" },
    { "name": "Reject",  "nextStep": "Application Rejected" },
    { "name": "Expiry",  "nextStep": "Application Escalated",  "display": "false" }
  ]
},
{
  "name": "Application Escalated",
  "type": "",
  "actions": [
    {
      "name": "Assign Review",
      "type": "Job Task Assign",
      "properties": [
        { "name": "Task Assign Groups",  "value": "Job Managers" },
        { "name": "Task Form Code",  "value": "$func.startFormCode()" },
        { "name": "Task Message",  "value": "The ${submission.formName} by ${formDataMap.firstName} ${formDataMap.lastName} has been escalated." },
        { "name": "Task Review Previous Step",  "value": "true" },
        { "name": "Task Subject",  "value": "Review Escalated ${submission.formName} by ${formDataMap.firstName} ${formDataMap.lastName}." },
        { "name": "Task Type",  "value": "Review" }
      ]
    },
    {
      "name": "Review Wait",
      "type": "Job Task Wait"
    }
  ]

Configure a Job Expiry Service

This service cleans up an task that hasn't been submitted and returns the Expiry route name. If you are expiring a step that has tasks that have not been completed, then you will need to run a Job Expiry Action that cleans these up, as shown in the code below.

/* Groovy Job Expiry action service is a special type of job action service that is executed when a step expires.
   It is used to clean up items such as tasks created by the step runs its actions.
   Script parameters include:
       actionContext : com.avoka.fc.core.service.job.ActionContext
       actionStepProperties :  com.avoka.fc.core.service.job.ActionStepProperties
       serviceDefinition : com.avoka.fc.core.entity.ServiceDefinition
       serviceParameters : Map<String, String>
       job : com.avoka.fc.core.entity.Job
       submission : com.avoka.fc.core.entity.Submission
       formDataMap : Map<String, String>
   Script return:
       actionResult : com.avoka.fc.core.service.job.ActionResult
*/
 
import com.avoka.fc.core.dao.DaoFactory
import com.avoka.fc.core.entity.Job
import com.avoka.fc.core.entity.JobAction
import com.avoka.fc.core.entity.JobStep
import com.avoka.fc.core.entity.Submission
import com.avoka.fc.core.service.AbandonmentService
import com.avoka.fc.core.service.job.ActionResult
import com.avoka.fc.core.service.job.ActionResult.Status
import com.avoka.core.groovy.GroovyLogger as logger
final EXPIRY_ROUTE_NAME = "Expiry"
Date now = new Date()
 
JobAction expiryJobAction = actionContext.getJobAction()
JobStep step = expiryJobAction.jobStep
List<JobAction> jobActions = step.getOrderedJobActions();
jobActions.remove(expiryJobAction)
 
// the msg can't be longer than 2000 characters.
StringBuilder msg = new StringBuilder();
msg.append("The job step associated with this task has expired. ref Job: ")
        .append(job.referenceNumber)
        .append(" Step: ")
        .append(step.name)
 
for (JobAction jobAction in jobActions) {
    // Fix Job Actions that have not completed
    if (jobAction.isStatusInProgress()
            || jobAction.isStatusAssigned()
            || jobAction.isStatusInvoked()
            || jobAction.isStatusPending()
            || jobAction.isStatusReady()) {
        jobAction.setStatus(JobAction.STATUS_EXPIRED);
        jobAction.setTimeFinished(now);
    }
 
    // Fix Tasks / Submissions in progress
    Submission submission = jobAction.getSubmission()
    if (submission != null) {
        // Set For all Tasks in this step as the step has Expired we don't want to deliver the
        submission.setDeliveryStatus(Submission.STATUS_NotRequired);
        if (submission.isFormOpened()
                || submission.isFormAssigned()
                || submission.isFormSaved()
                || submission.isFormSubmitted()) {
            submission.setFormStatus(Submission.STATUS_Abandoned)
            submission.setAbandonmentType(AbandonmentService.ABANDONMENT_TYPE_SYSTEM)
            submission.setAbandonmentTimestamp(now)
            submission.setAbandonmentReason(msg.toString())
 
        } else {
            // For Tasks that were submitted
            submission.setDeliveryTime(now);
            submission.setAbandonmentReason(msg.toString())
        }
 
        if (submission.isDeliveryNotRequired()) {
            if (submission.getPurgeTimeDataDelivered() == null) {
                DaoFactory.submissionDao.setPurgeDatesForDeliveredAbandonedForms(submission);
            }
        }
    }
}
ActionResult actionResult = new ActionResult(Status.COMPLETED)
actionResult.setRoute(EXPIRY_ROUTE_NAME)
return actionResult

This example uses the Core Transact API, but we recommend using the Fluent API instead whenever possible. A simple example is shown below:

import com.avoka.tm.job.*
import com.avoka.tm.util.*
import com.avoka.tm.vo.*
import groovy.transform.TypeChecked
import java.util.*
import javax.servlet.http.*

@TypeChecked
class FluentJobExpiryActionService {
    
    /*
     * Perform a job expiry action service invocation
     *
     * return: the job action result
     */
    ActionResult invoke(SvcDef svcDef, Job job, JobAction jobAction, Map actionProperties, HttpServletRequest request, User user) {

        // TODO: perform your logic

        String xml = Jobs.getStartTxnXml(job)
        Path path = new Path(xml)
        String email = path.val('//Contact/Email')

        return new ActionResultBuilder()
            .setStatus('Completed')
            .setMessage('Action completed for: ' + email)
            .build()
    }
}

Now, you can run the example and see how collaboration job's step expiry works.

Form - Start

  1. Joe click on the AVT-3547 Step Expiry Form which opens.
  2. Joe's detail are prefilled so he clicks Submit.

Manager - Action Review Expiry

  1. The collaboration job creates a Application Review step with an Review Task Assign action link to a submission assigned to the Job Reviewers and Review. There is also a task Review Task Wait Actions.
  2. When the step expires these 2 actions are expired. The Application Review - Expiry action (Custom Groovy Service) runs to clean up the submissions for this step. For more details see the Job Expiry Service below.

Form Space - Application Escalated

  1. Log in as Mike, who is a Job Manager.
  2. Select the Tasks tab.
  3. Select the Job Managers from the Groups dropdown list and click Go to view the following task list.
  4. Click the CCM7TM task.
  5. Select the Approve or Reject from the Route Name dropdown list and click Submit.

This concludes the example.

Download

You can also download the application package with this example here.

Next, learn about one step anonymous review collaboration jobs.