Last updated September 8, 2019
Add multiple workflows to an order when product selections are made.
Some order types are designed to let users select multiple single products for a single order. Fulfilling each product typically requires a unique workflow, and usually this mapping follows some consistent logic.
Make sure you have loaded axios
const axios = require('axios');
const URL_BASE = 'https://api.factoryfour.com';
/*
* Return an array of workflows that should be added
* entries [{
* type: string, Product manifest type of selection
* options: object, Options selected in manifest
* stage_id: string, ID of the stage that was added
* model: object, Options selected in the stage
* title: string Title assigned to the manifest
* }]
* */
const getWorkflows = (entries) => {
const workflows = [];
entries.forEach((entry) => {
if (entry.type === 'Tw') {
workflows.push({
name: entry.title,
code: 'workflow_a',
});
} else {
workflows.push({
name: entry.title,
code: 'workflow_b',
});
}
});
return workflows;
};
// ======================================================================================================================
/*
* Retrieve a valid FactoryFour token from the headers in the context
*/
const getToken = (ctx) => {
const token = ctx.headers['x-factoryfour-token'];
if (!token) {
throw new Error('Unable to find token in context');
}
return token;
};
/*
* Fetch the order this form was submitted on from the context
*/
const getOrderId = (ctx) => {
const orderId = ctx.body.order.id;
if (!orderId) {
throw new Error('Could not find an order for this form');
}
return orderId;
};
/*
* Make calls to the FactoryFour API using the token passed to this rule and the workflowCode specified
*/
const addAndInitWorkflow = (data, token) => {
// Format the headers for the request
const headers = {
Authorization: `Bearer ${token}`,
};
// Create a new workflow object
return axios({
method: 'POST',
url: `${URL_BASE}/workflows/`,
headers,
data,
})
.then((res) => {
const workflowId = res.data.data.workflow.id;
// Initialize the newly created workflow to create tasks
const optionsInit = {
method: 'POST',
url: `${URL_BASE}/workflows/${workflowId}/initiate`,
headers,
json: true,
};
return axios(optionsInit);
});
};
const getManifestEntries = (context) => {
const { formData } = context.body;
if (!formData) {
console.error('No form data found');
return [];
}
if (!formData.Manifest || !formData.Manifest.manifest || !formData.Manifest.manifest.entries) {
console.error('Could not find manifest information');
return [];
}
const { entries } = formData.Manifest.manifest;
const entriesOut = entries.map((e) => ({
type: e.type,
options: e.options.model,
model: formData[e.id],
title: e.title,
stage_id: e.stage_id,
}));
return entriesOut;
};
module.exports = (context, cb) => {
const token = getToken(context);
const orderId = getOrderId(context);
const workflowsToAdd = getWorkflows(getManifestEntries(context));
const workflowCreationPromises = [];
if (workflowsToAdd) {
// if no workflow was found, exit with no further action
if (!Array.isArray(workflowsToAdd)) {
console.error('Workflow creation requires an array');
return cb('Workflow creation requires an array');
}
workflowsToAdd.forEach((wf) => {
workflowCreationPromises.push(addAndInitWorkflow({
format: 'order',
parent: `f4::order::${orderId}`,
code: wf.code,
name: wf.name ? wf.name : undefined,
}, token));
});
}
return Promise.all(workflowCreationPromises)
.then(() => cb(null, 'Created workflows'))
.catch((err) => {
console.error(err);
return cb('Could not add workflows successfully');
});
};