From 5f621e1ae0e8d47ee1514a9eaea567f515bfc1dd Mon Sep 17 00:00:00 2001 From: Dave Richer Date: Mon, 14 Jul 2025 19:28:29 -0400 Subject: [PATCH] feature/IO-3303-logging - Logging --- server/job/job-costing.js | 10 +- server/job/job-lifecycle.js | 195 ++++++++++++++++++++---------------- 2 files changed, 111 insertions(+), 94 deletions(-) diff --git a/server/job/job-costing.js b/server/job/job-costing.js index 29c9dbfce..d1fe8b3d7 100644 --- a/server/job/job-costing.js +++ b/server/job/job-costing.js @@ -19,7 +19,7 @@ async function JobCosting(req, res) { const client = req.userGraphQLClient; //Uncomment for further testing - // logger.log("job-costing-start", "DEBUG", req.user.email, jobid, null); + logger.log("job-costing-start", "DEBUG", req.user.email, jobid, null); try { const resp = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_JOB_COSTING_DETAILS, { @@ -47,9 +47,9 @@ async function JobCostingMulti(req, res) { const client = req.userGraphQLClient; //Uncomment for further testing - // logger.log("job-costing-multi-start", "DEBUG", req?.user?.email, null, { - // jobids - // }); + logger.log("job-costing-multi-start", "DEBUG", req?.user?.email, null, { + jobids + }); try { const resp = await client @@ -589,7 +589,7 @@ function GenerateCostingData(job) { amount: Math.round((job.storage_payable || 0) * 100) }); } - + //Is it a DMS Setup? const selectedDmsAllocationConfig = (job.bodyshop.md_responsibility_centers.dms_defaults && diff --git a/server/job/job-lifecycle.js b/server/job/job-lifecycle.js index 7076069f6..209a8c4a0 100644 --- a/server/job/job-lifecycle.js +++ b/server/job/job-lifecycle.js @@ -8,6 +8,7 @@ const getLifecycleStatusColor = require("../utils/getLifecycleStatusColor"); const jobLifecycle = async (req, res) => { // Grab the jobids and statuses from the request body const { jobids, statuses } = req.body; + const { logger } = req; if (!jobids) { return res.status(400).json({ @@ -16,102 +17,118 @@ const jobLifecycle = async (req, res) => { } const jobIDs = _.isArray(jobids) ? jobids : [jobids]; - const client = req.userGraphQLClient; - const resp = await client.request(queries.QUERY_TRANSITIONS_BY_JOBID, { jobids: jobIDs }); - const transitions = resp.transitions; + logger.log("job-lifecycle-start", "DEBUG", req?.user?.email, null, { + jobids: jobIDs + }); + + try { + const client = req.userGraphQLClient; + const resp = await client.request(queries.QUERY_TRANSITIONS_BY_JOBID, { jobids: jobIDs }); + + const transitions = resp.transitions; + + if (!transitions) { + return res.status(200).json({ + jobIDs, + transitions: [] + }); + } + + const transitionsByJobId = _.groupBy(resp.transitions, "jobid"); + + const groupedTransitions = {}; + const allDurations = []; + + for (let jobId in transitionsByJobId) { + let lifecycle = transitionsByJobId[jobId].map((transition) => { + transition.start_readable = transition.start ? moment(transition.start).fromNow() : "N/A"; + transition.end_readable = transition.end ? moment(transition.end).fromNow() : "N/A"; + + if (transition.duration) { + transition.duration_seconds = Math.round(transition.duration / 1000); + transition.duration_minutes = Math.round(transition.duration_seconds / 60); + let duration = moment.duration(transition.duration); + transition.duration_readable = durationToHumanReadable(duration); + } else { + transition.duration_seconds = 0; + transition.duration_minutes = 0; + transition.duration_readable = "N/A"; + } + return transition; + }); + + const durations = calculateStatusDuration(lifecycle, statuses); + + groupedTransitions[jobId] = { + lifecycle, + durations + }; + + if (durations?.summations) { + allDurations.push(durations.summations); + } + } + + const finalSummations = []; + const flatGroupedAllDurations = _.groupBy(allDurations.flat(), "status"); + + const finalStatusCounts = Object.keys(flatGroupedAllDurations).reduce((acc, status) => { + acc[status] = flatGroupedAllDurations[status].length; + return acc; + }, {}); + // Calculate total value of all statuses + const finalTotal = Object.values(flatGroupedAllDurations).reduce((total, statusArr) => { + return total + statusArr.reduce((acc, curr) => acc + curr.value, 0); + }, 0); + + Object.keys(flatGroupedAllDurations).forEach((status) => { + const value = flatGroupedAllDurations[status].reduce((acc, curr) => acc + curr.value, 0); + const humanReadable = durationToHumanReadable(moment.duration(value)); + const percentage = finalTotal > 0 ? (value / finalTotal) * 100 : 0; + const color = getLifecycleStatusColor(status); + const roundedPercentage = `${Math.round(percentage)}%`; + const averageValue = _.size(jobIDs) > 0 ? value / jobIDs.length : 0; + const averageHumanReadable = durationToHumanReadable(moment.duration(averageValue)); + finalSummations.push({ + status, + value, + humanReadable, + percentage, + color, + roundedPercentage, + averageValue, + averageHumanReadable + }); + }); - if (!transitions) { return res.status(200).json({ jobIDs, - transitions: [] - }); - } - - const transitionsByJobId = _.groupBy(resp.transitions, "jobid"); - - const groupedTransitions = {}; - const allDurations = []; - - for (let jobId in transitionsByJobId) { - let lifecycle = transitionsByJobId[jobId].map((transition) => { - transition.start_readable = transition.start ? moment(transition.start).fromNow() : "N/A"; - transition.end_readable = transition.end ? moment(transition.end).fromNow() : "N/A"; - - if (transition.duration) { - transition.duration_seconds = Math.round(transition.duration / 1000); - transition.duration_minutes = Math.round(transition.duration_seconds / 60); - let duration = moment.duration(transition.duration); - transition.duration_readable = durationToHumanReadable(duration); - } else { - transition.duration_seconds = 0; - transition.duration_minutes = 0; - transition.duration_readable = "N/A"; + transition: groupedTransitions, + durations: { + jobs: jobIDs.length, + summations: finalSummations, + totalStatuses: finalSummations.length, + total: finalTotal, + statusCounts: finalStatusCounts, + humanReadable: durationToHumanReadable(moment.duration(finalTotal)), + averageValue: _.size(jobIDs) > 0 ? finalTotal / jobIDs.length : 0, + averageHumanReadable: + _.size(jobIDs) > 0 + ? durationToHumanReadable(moment.duration(finalTotal / jobIDs.length)) + : durationToHumanReadable(moment.duration(0)) } - return transition; }); - - const durations = calculateStatusDuration(lifecycle, statuses); - - groupedTransitions[jobId] = { - lifecycle, - durations - }; - - if (durations?.summations) { - allDurations.push(durations.summations); - } + } catch (error) { + logger.log("job-lifecycle-error", "ERROR", req?.user?.email, null, { + jobids: jobIDs, + statuses: statuses ? JSON.stringify(statuses) : "N/A", + error: error.message + }); + return res.status(500).json({ + error: "Internal server error" + }); } - - const finalSummations = []; - const flatGroupedAllDurations = _.groupBy(allDurations.flat(), "status"); - - const finalStatusCounts = Object.keys(flatGroupedAllDurations).reduce((acc, status) => { - acc[status] = flatGroupedAllDurations[status].length; - return acc; - }, {}); - // Calculate total value of all statuses - const finalTotal = Object.values(flatGroupedAllDurations).reduce((total, statusArr) => { - return total + statusArr.reduce((acc, curr) => acc + curr.value, 0); - }, 0); - - Object.keys(flatGroupedAllDurations).forEach((status) => { - const value = flatGroupedAllDurations[status].reduce((acc, curr) => acc + curr.value, 0); - const humanReadable = durationToHumanReadable(moment.duration(value)); - const percentage = finalTotal > 0 ? (value / finalTotal) * 100 : 0; - const color = getLifecycleStatusColor(status); - const roundedPercentage = `${Math.round(percentage)}%`; - const averageValue = _.size(jobIDs) > 0 ? value / jobIDs.length : 0; - const averageHumanReadable = durationToHumanReadable(moment.duration(averageValue)); - finalSummations.push({ - status, - value, - humanReadable, - percentage, - color, - roundedPercentage, - averageValue, - averageHumanReadable - }); - }); - - return res.status(200).json({ - jobIDs, - transition: groupedTransitions, - durations: { - jobs: jobIDs.length, - summations: finalSummations, - totalStatuses: finalSummations.length, - total: finalTotal, - statusCounts: finalStatusCounts, - humanReadable: durationToHumanReadable(moment.duration(finalTotal)), - averageValue: _.size(jobIDs) > 0 ? finalTotal / jobIDs.length : 0, - averageHumanReadable: - _.size(jobIDs) > 0 - ? durationToHumanReadable(moment.duration(finalTotal / jobIDs.length)) - : durationToHumanReadable(moment.duration(0)) - } - }); }; module.exports = jobLifecycle;