eo-services/src/api/routes/interactions-flow.js
Peter.Morton 6c1b3f8b20 Added handling for OUTBOUND and fractional links.
Also removed filtering (too complex for now)
2023-08-07 20:53:08 -05:00

180 lines
5.1 KiB
JavaScript

import { Router } from "express";
import axios from "axios";
import localStorage from "local-storage";
import sampleFlow from "../../utils/sampleFlow.js";
const router = Router();
import { logger } from "../../utils/index.js";
import { referenceIdQuery } from "../../utils/graphQueries.js";
router.get("/", (req, res) => {
const data = {
nodes: [],
links: [],
};
const filter = req.query.filter;
var chain = {
"Direction-Channel": true,
"Channel-SubChannel": true,
"Channel-Queue": true,
"SubChannel-Queue": true,
"Queue-Outcome": true,
"Channel-Outcome": true, // special case for outbound that does not go throught queue
};
// TODO: Chain will be hardcoded until I can work out filter logic
// var filterNames = filter.split(",");
// for (let index = 0; index < filterNames.length - 1; index++) {
// chain[filterNames[index] + "-" + filterNames[index + 1]] = true;
// }
const startTime = new Date(
new Date().setFullYear(new Date().getFullYear() - 2)
);
var endTime = new Date();
// FIX for 'endTime' parameter cannot be later than one minute prior to now.
endTime.setMinutes(endTime.getMinutes() - 1);
const { host, tenant, token } = localStorage(req.query.authKey);
axios
.post(
`${host}/unified-data-gateway/${tenant}/graphql`,
JSON.stringify({
query: referenceIdQuery,
variables: { startTime, endTime },
}),
{
headers: {
Authorization: `OIDC_id_token ${token}`,
"Content-Type": "application/json",
},
}
)
.then((result) => {
if (result.data.errors && result.data.errors.length > 0) {
result.data.errors.forEach(function (error) {
logger.error("ERROR: Errors in results - " + error.message);
});
// TODO: Should keep errors for filteredContacts
result.data.errors = [];
}
if (!result.data.data.findContactsCompletedBetween) {
logger.debug("No findContactsCompletedBetween returned.");
res.send(data);
return;
}
result.data.data.findContactsCompletedBetween.edges.forEach((value) => {
// TODO: Should add INBOUND and OUTBOUND Nodes before Channel
addNode(filter, "Direction", value.node.direction, data);
addNode(filter, "Channel", value.node.interaction.__typename, data);
if (chain["Direction-Channel"]) {
addLink(
data,
value.node.direction,
value.node.interaction.__typename
);
}
if (value.node.interaction.subChannel) {
addNode(
filter,
"SubChannel",
value.node.interaction.subChannel,
data
);
if (chain["Channel-SubChannel"]) {
addLink(
data,
value.node.interaction.__typename,
value.node.interaction.subChannel
);
}
}
if (value.node.queue) {
const queueName = `${value.node.queue.name}(${value.node.queue.orgScope})`;
addNode(filter, "Queue", queueName, data);
if (
chain["SubChannel-Queue"] &&
!!value.node.interaction.subChannel
) {
addLink(data, value.node.interaction.subChannel, queueName);
} else if (chain["Channel-Queue"]) {
addLink(data, value.node.interaction.__typename, queueName);
}
}
if (value.node.outcome) {
value.node.outcome.edges.forEach((element) => {
addNode(filter, "Outcome", element.node.text, data);
if (chain["Queue-Outcome"] && !!value.node.queue) {
const queueName = `${value.node.queue.name}(${value.node.queue.orgScope})`;
addLink(
data,
queueName,
element.node.text,
1 / value.node.outcome.edges.length
);
}
if (chain["Channel-Outcome"] && !value.node.queue) {
addLink(
data,
value.node.interaction.__typename,
element.node.text,
1 / value.node.outcome.edges.length
);
}
});
}
});
logger.debug(`Sending data: ${JSON.stringify(data, null, 2)}`);
res.send(data);
});
if (req.query.useSampleData) {
const data = sampleFlow(filter);
res.send(data);
return;
}
});
function addLink(data, source, target, _fraction) {
var fraction = _fraction ? _fraction : 1;
var index = data.links.findIndex((i) => {
return i.source == source && i.target == target;
});
if (index != -1) {
data.links[index].value++;
} else {
data.links.push({
source: source,
target: target,
value: fraction,
});
}
}
function addNode(filter, category, name, data) {
if (
filter.split(",").indexOf(category) != -1 &&
!!name &&
data.nodes.findIndex(
(value) => value.name === name && value.category === category
) == -1
) {
data.nodes.push({
name: name,
category: category,
});
}
}
export default router;