Learn how to manage a contract validation workflow using the REST API. Log in as different users to see the whole process and process tasks.
The contract validation workflow follows the following steps:
- When the workflow starts, the contract state changes to the
approval
and the system verifies that the amount property is filled in. If not, the workflow initiator must fill it in. - A manager reviews the contract to approve it. If they reject it, the workflow initiator must fix it.
- When the manager approves the contract, the state changes to
running
.
Starting the Workflow
Goal
Start a workflow on a contract, leveraging the contract validation workflow provided by the addon Getting started with the Nuxeo Platform.
Prerequisites
- Install the addon Getting started with the Nuxeo Platform. See Setting up Your Nuxeo Environment.
- Create users on your Nuxeo instance. See Setting up Your JavaScript Environment.
- Create the
skynet-ai-maintenance
contract. See Manipulating Documents
Procedure
Create a file called
startContractValidationWorkflow.js
with the following content.#!/usr/bin/env node let Nuxeo = require('nuxeo'); let nuxeo = new Nuxeo({ auth: { method: 'basic', username: 'afraser', password: 'afraser' } }); let contractToFetch = '/default-domain/workspaces/North America/awesome-tech/skynet-ai-maintenance'; nuxeo.repository() .fetch(contractToFetch) .then(contract => { if (contract.state !== 'draft') { console.log('\nSorry, the contract needs to be in the draft state to launch a validation workflow on it.\nCurrent state is: ' + contract.state + '\n'); return; } contract.startWorkflow('BCContractValidationWf') .then(wf => { console.log('Workflow is now started!'); console.log('id: ' + wf.id); console.log('workflow state: ' + wf.state); console.log('initiated by: ' + wf.initiator); }) .catch(error => { console.log('Apologies, an error occurred while starting the workflow.'); console.log(error); }); return; }) .catch(error => { console.log('Apologies, an error occurred while fetching the contract.'); console.log(error); });
Save and run:
$ node startContractValidationWorkflow.js
Completing Tasks
Goal
Complete the Fill Amount task.
The workflow looks like this:
When the workflow started, a verification was performed that determined no amount was given in the contract properties. Therefore, a task has been assigned to the workflow initiator (Alicia Fraser in this case) so that she may fill it in before having it reviewed by a manager.
Procedure
Create a file called
handleUserWorkflowTasks.js
with the following content. While completing a task, you can send the information filled in by a user (Alicia Fraser in this case). Here, send the contract amount.#!/usr/bin/env node let Nuxeo = require('nuxeo'); let nuxeo = new Nuxeo({ auth: { method: 'basic', username: 'afraser', password: 'afraser' } }); // Fetch the current user's contract validation tasks nuxeo.workflows().fetchTasks({ 'workflowModelName': 'BCContractValidationWf' }) .then(function(tasks) { // Display tasks if (tasks.length === 0) { console.log('No task to do! Cool!\n'); return; } tasks.entries.forEach(currentTask => { console.log('Name: ' + currentTask.name); console.log('Status: ' + currentTask.state); console.log('What to do: ' + currentTask.directive); console.log('Before: ' + currentTask.dueDate); console.log('On document id: ' + currentTask.targetDocumentIds[0].id); console.log('Task form can be downloaded at: ' + currentTask.taskInfo.layoutResource.url); console.log('\nPossible actions for this task:'); currentTask.taskInfo.taskActions.forEach(currentAction => { console.log('Name: ' + currentAction.name); }); // Fill in the contract's amount and confirm currentTask .variable('contractAmount', '67890.99') .complete('confirm') .then(completedTask => { console.log('\nWe will fill in an amount and confirm to send the contract for validation.'); console.log(`Task ${completedTask.name} is now ${completedTask.state}.`); // Check contract state now that the task is completed nuxeo.repository().fetch(completedTask.targetDocumentIds[0].id, { schemas: ['bcsalescommon'] }) .then(contract => { console.log(`Contract ${contract.title} is now in the following state: ${contract.state}.`); console.log(`Its amount has been set to ${contract.properties['bcsalescommon:amount']}.`); }); }) .catch(error => { console.log('Apologies, an error occurred while completing a task.'); console.log(error); }); }) }) .catch(error => { console.log('Apologies, an error occurred while fetching the tasks.'); console.log(error); });
Save and run:
$ node handleUserWorkflowTasks.js
Note that the contract's amount has been updated.
Ending the Workflow
Goal
Review and validate the contract.
The contract should now be reviewed by a manager:
This time a task has been assigned to the managers
group (represented by Sarah Connor). Validating the contract will trigger some logic and end the workflow, rejecting it will ask the workflow initiator to update it.
Procedure
Create a file called
handleManagerWorkflowTasks.js
with the following content. Log in asSarah Connor
this time since she is a manager, and as such the one that needs to complete this task.#!/usr/bin/env node let Nuxeo = require('nuxeo'); let nuxeo = new Nuxeo({ auth: { method: 'basic', username: 'sconnor', password: 'sconnor' } }); // Fetch the current user's contract validation tasks nuxeo.workflows().fetchTasks({ 'workflowModelName': 'BCContractValidationWf' }) .then(function(tasks) { // Display tasks if (tasks.length === 0) { console.log('No task to do! Cool!\n'); return; } tasks.entries.forEach(currentTask => { console.log('Name: ' + currentTask.name); console.log('Status: ' + currentTask.state); console.log('What to do: ' + currentTask.directive); console.log('Before: ' + currentTask.dueDate); console.log('On document id: ' + currentTask.targetDocumentIds[0].id); console.log('Task form can be downloaded at: ' + currentTask.taskInfo.layoutResource.url); console.log('\nPossible actions for this task:\n'); currentTask.taskInfo.taskActions.forEach(currentAction => { console.log('Name: ' + currentAction.name + '\nCan be triggered using code or by following this link:\n' + currentAction.url); }); // Validate contract(s) currentTask.complete('validate') .then(completedTask => { console.log('\nWe will validate the contract.'); console.log('Task ' + completedTask.name + ' is now ' + completedTask.state + '.'); // Check contract state now that the task is completed nuxeo.repository().fetch(completedTask.targetDocumentIds[0].id, { schemas: ['bccontract'] }) .then(contract => { console.log('Contract ' + contract.title + ' is now in the following state: ' + contract.state + '.'); console.log('Contract\'s expiration date has automatically been set to one year from now: ' + contract.properties['bccontract:expirationDate'] + '.'); }); }) .catch(error => { console.log('Apologies, an error occurred while completing a task.'); console.log(error); }); }) }) .catch(error => { console.log('Apologies, an error occurred while fetching the tasks.'); console.log(error); });
Save and run:
$ node handleManagerWorkflowTasks.js
The workflow is now finished.
Notes:
- Validating the contract triggered some logic automatically: the contract's expiration date has been set to one year from now, the contract's state is now
running
. - Instead of completing the task programmatically, you could have used direct links instead. Keep in mind that these links need to be sent using a POST call.