Skip to content

Guide

Overview

Workflow configuration is split into named workflow steps. Routes define which step will be executed when matching transaction criteria are met.

Workflow steps are maintained using the Portal. Read the Workflow user interface guide for more information about the interface use.

Workflow steps are defined using an XML model. The XML elements and attributes are a mix of mandatory and conditional values that define the behaviour of the workflow steps service.

Workflow step invocation

The service is typically called via the Routes service as the result of a p6route route evaluation. Possible headers values are:

Header value Description
step The workflow step’s name (required)
appkey The workflow step’s application key
flowName Fixed value for flow name. Use %UUID% to auto generated uuid formatted flow name.
status The initial status of the message (required)
script The name of the step template script
pipelineVar The input pipeline content to script, a pipeline is a map to share variables between scripts

Here is an example of a workflow step invocation via a route deployment script.

from("seda:wfroute.test")
    .when(xpath("/TransactionMetaData/TechnicalStatusCode='Pending'"))
        .setHeader("platform6.request.action").constant("invoke")
        .setHeader("status").constant("PENDING")
        .setHeader("step").constant("Dispatch Field Ticket")
        .setHeader("flowname").constant("%UUID%")
        .to("p6route://workflowsteps")   
    .otherwise()
        .throwException(io.platform6.common.util.P6Exception, "No matching rule found for item!")
    .end()
    .routeId("WF_Route.Test")            

Note

Item Primary Key component headers are auto generated by the P6route component.

Header value: script

The script header allows a script to generate the workflow step definition XML.

This is useful when, for example, a transaction containing a cost centre is received and depending upon the value of this field, different workflow assignees are required.

Using the script header allows a steps XML configuration to be templated.

Script input pipeline

Header’s key Description
platform6.request.dataPartition The partition (primary key component)
platform6.request.dataType The item type (primary key component)
platform6.request.ids The ids as a comma separated list (primary key component)
templateStepXml The content of the current step XML defined by the step parameter as type text/xml

Script output pipeline

Header’s key Description
stepXml The new step XML configuration generated by the script (required)

Note

A step XML generated via a script is not stored as a service’s configuration. However, it is stored in the generated workflow task for the lifetime of this workflow step.

Workflow custom forms

It is possible to use custom forms triggered by Workflow.

Workflow step modification

Inside the Action that is going to call the custom form, add a FormGenerator element with the name of the custom form.

 <Actions>
     <Action id="review" status="REVIEWED" type="FORM" transformer="AWF_Review">
         <Style>icon:fa-check,btn:btn-success</Style>
         <Label>
             <EN>Review</EN>
             <FR>Vérifier</FR>
         </Label>

         <FormGenerator>MyCustomForm</FormGenerator>
      ...
     </Action>
 ...
 </Actions>

The FormGenerator name must match that of a script in the Scripts service.

Parameters passed to the script

Four parameters are passed to the script from the pipeline:

  • pk: a JSON string containing the primary key of the workflow task.
{
    "dataPartition": "TRANSACTION",
    "dataType": "WorkflowTask",
    "ids": ["64cb15dafd0a11e699620242ac120005"]
}
  • xml: an XML string with the content of the workflow task.
  • user: the user’s email (id).
  • itemLinks: a JSON Array (string) with the list of Items Links (name, pk and type) of the workflow task.

[
    {
        "name": "MessageLink",
        "pk": {
            "dataPartition": "TRANSACTION",
            "dataType": "TransactionInfo",
            "ids": ["WFTestForm-2017-02-27 04:32:54 GMT"]
        },
        "type": ""
    }
]
Recovering the underlying Transaction (typically a TransactionInfo)

Two solutions:

  1. Directly from the workflow task XML.

    def xml = p6.pipeline.getXml "xml"
    def mpk = p6.transaction.buildPK(xml.itemDataType.text(), xml.itemIds.text().split('\\.'))
    def message = p6.transaction.get(mpk)
    
  2. From the Item Links (the Transaction is the first link).

    def itemLinks = p6.pipeline.get "itemLinks"
    def ils = new JsonSlurper().parseText(itemLinks)
    def mpk = p6.transaction.buildPK(ils[0].pk.concept, ils[0].pk.ids.toArray(new String[ils[0].pk.ids.size()]))
    def message = p6.transaction.get(mpk)
    

Sending the actual form

The form must be developed in JavaScript (or TypeScript) and available in the Scripts service.

The form can be passed a JSON model with data to be displayed in the form.

def model = [
    user: 'John Doe',
    companySiret: "48432937000049",
    latestProduct: [
        name: "b2box",
        url: "http://www.amalto.com"
    ]
]
p6.pipeline.put "model", JsonOutput.toJson(model)
p6.pipeline.put "form", p6.resource.getCompiled("MyCustomForm")

Implementing a custom workflow form

To get you started quickly on how to create your first custom workflow form, you can find a demo project in the platform6-custom-workflow-form repository.

It will allow you to generate a JavaScript bundled file which can be simply copy-pasted to any Script of your Platform 6 instance.

Please follow the instructions in the README.md of the repository to create, test and deploy your form on your instance.

Scripting

You can manage workflow steps with the Scripts service using the workflow DSL.

Actions

When a user takes an action defined in a workflow step (either built-in or custom form based) any script that is defined to be run upon that action will receive the following pipeline variable:

  • _wf_ui_action_origin

This variable indicates where in the portal user interface the action submission was made. The following string values are supported:

  • WORKFLOWTASKS_LIST
  • TRANSACTION_LINK
  • WORKFLOWTASK_LINK

Given this information a workflow step action script can make a decision regarding where the user should be directed following the sucessfull processing of the action submission.

To influence where the user is directed after action submission the action script should set the pipeline variable:

  • _wf_ui_action_destination

The following string values are supported:

  • WORKFLOWTASKS_LIST
  • WORKFLOWTASKS_LIST_REFRESHED
  • TRANSACTIONS_LIST
  • TRANSACTIONS_LIST_REFRESHED
  • LINK_ITEM
  • LINK_ITEM_REFRESHED

The REFRESHED modifier will cause the LIST or ITEM to be re-evaluated

Assignee Resolution via SCRIPT

It is possible to evaluate workflow step assignees using a script instead of the default organizational tree.

When an implementation requires a very large organizational tree to express assignee distribution and this involves hundreds or thousands of associations it is recommended that assignee resolution is performed using a table based cross-reference list.

Not only will this greatly improve performance and place less load on the central organization tree infrastructure but will make assignee updates easier.

As company employees change, only local table updates are required and synchronization of current and previous assignees workflow tasks can all be under the control of the local instance.

Example SCRIPT Assignee Resolution Workflow Step

<Assignee  name="Invoice_REVIEWERS" path="/${INSTANCE_ID}" type="SCRIPT" scope="WF_AssigneesGenerator" >
    <Label>
        <EN>Invoice Review Team</EN>
        <FR>Équipe de revue des factures</FR>
    </Label>
</Assignee>

WF_AssigneesGenerator

import groovy.json.JsonOutput 

println p6.pipeline.get('name')
println p6.pipeline.get('path')
println p6.pipeline.get('stepId')

def assignees = []

for ( i in 0..65 ) {
    assignees.add([
        email: 'simon.temple+' + i + '@amalto.com',
        firstname: 'Simon',
        lastname: 'Temple' + i
    ])
}

p6.pipeline.put('assignees', JsonOutput.toJson(assignees))
The script must return an assignees pipeline variable containing a JSON array of MAPs

Each Map must contain at least email and optionally firstname and/or lastname

Note

The assignees returned will be cached inside the service so this script will only be called when the assignee cache TTL expires or the cache is empty