Skip to main content

Workflow templates

Bare minimum​

The following template shows the minimum required code to execute a workflow.

export async function run() {
console.log('Hello World');
return true;
}

Parameters​

This template combines all different kind of parameters and console outputs.

import { isEnabled, count, articleName, bundle, file } from '@workflow/parameters';

export async function run() {
try {
console.group();
console.debug('Print all parameters...');
console.info('isEnabled: ' + isEnabled);
console.log('count: ' + count);
console.warn('articleName: ' + articleName);
console.debug('bundle: ' + bundle);
console.info('file: ' + file);
console.groupEnd();
} catch (e) {
console.error('Unexpected error: ' + e);
}
return true;
}

Update assets​

It is possible to update file or datasource assets within a workflow.

info

If a file asset is linked to data sources, then all data sources are also updated automatically.

The update of a datasource and a subsequent publish of the corresponding asset bundle is shown in this template.
Following steps are performed:

  1. create a new asset bundle draft
  2. get an existing data source
  3. update the data source
  4. publish the asset bundle
  5. update related configurators
import { bundle, file } from '@workflow/parameters';

// ATTENTION: NEVER forget to await asynchronous calls
export async function run() {
// 1. create a new asset bundle draft based on the asset bundle parameter
const draft = await bundle.createDraft();

// 2. get the data source asset which should be updated
const dataSourceName = 'articles';
const folderName = 'data';
const dataSourceAsset = draft.getAsset(dataSourceName, folderName);

// 3. update the data source asset
await dataSourceAsset.update(file);

// 4. publish the asset bundle draft
await draft.publish(configurator => {
// In this block you can decide what should happen to each configurator (or draft) which is using this asset bundle version
// you have to return an object with the following format: { update: true|false, publish: true|false } for each configurator

// 5.a) We can, for instance, choose to update but not publish a specific configurator.
// the 'configurator' argument contains details about the current configurator, such as its name or version, or whether it is a draft
if (configurator.name === 'MyOtherConfigurator') {
return { update: true, publish: false };
}

// 5.b) We can also return a bool value as a shorthand; returning 'true' is the same as returning { update: true, publish: true }
return true;
});
}

Workflow triggers​

As mentioned here the workflow run argument provides different data depending on the trigger type. This is shown in the example below. Quote and configuration data properties may change in the future—please contact us if you require additional properties.

/**
* @param {WorkflowRunArgument} arg
*/
export async function run(arg) {
// Argument always contains the workflow run type
console.debug('Trigger Type: ' + arg.type); // manual, scheduled, api, finishCfgn, ...

// check for the type to see which trigger started the workflow run
if (arg.type == 'manual') {
console.debug('A manual run triggered by a user - no additional information available');
} else if (arg.type == 'scheduled') {
console.debug('A scheduled run - no additional information available');
} else if (arg.type == 'api') {
console.debug('An api call - not supported currently, will be released soon');
} else if (arg.type == 'finishCfgn') {
// triggered when a configuration is finished

arg.configurator; // name of the configurator
arg.stage; // stage name of the configurator
var cfgnJson = JSON.parse(arg.configuration.raw); // configuration data needs to parsed to be process in the workflow
console.debug('configuration (id): ' + cfgnJson.id);
console.debug('configuration (cfgr name): ' + cfgnJson.cfgrName);
console.debug('configuration (created at): ' + cfgnJson.createdAt);
} else if (arg.type == 'quoteStateChanged') {
// triggered when the state of a quote is changed

// arg.quote.data can be used to retrieve a quote within the workflow
var quoteData = arg.quote.data;
console.log(quoteData.hubName);
console.log(quoteData.quoteNumber);
console.debug('quote (items): ' + quoteData.items.length);
quoteData.items.forEach(item => {
if (item.type === 'Item') {
console.log(' * ' + item.quantity + item.unit + " '" + item.name + "' - " + item.netUnitPriceFinal + quoteData.currency);
} else if (item.type === 'Section') {
console.log(" * Section '" + item.name + "'");
} else {
console.log('Unknown type:', item.type);
}
});

// change and publish a quote
quoteData.state = 'processing';
return await arg.quote.publish();
} else {
console.debug('Unkown workflow run type');
}
return true;
}

Send quote mail upon quote change trigger​

/**
* @param {WorkflowRunArgument} arg
*/
export async function run(arg) {
if (arg.type == 'quoteStateChanged') {
// first create the quote pdf for this quote with the desired pdfTemplate
const quotePdfUrl = await arg.quote.createPdf('pdfTemplatePath');

// after the quote pdf has been created send a mail
await mail.send({
sender: 'noreply@example.com',
to: 'recipient@example.com',
subject: 'Your Quote is ready',
body: 'Please find the attached Quote.',
attachments: [
{
filename: 'Quote.pdf',
url: quotePdfUrl,
mediaType: 'application/pdf'
}
]
});
} else {
console.debug('Nothing to do');
}
}