From 614420d7d223301652535849082e6dac22343503 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Tue, 28 Apr 2026 18:06:11 -0700 Subject: [PATCH] IO-3562 Visual Production Board Statistics - Exclude Suspended Jobs Signed-off-by: Allan Carr --- .../production-board-kanban.statistics.jsx | 94 ++++++++++++------- .../settings/StatisticsSettings.jsx | 11 ++- .../settings/defaultKanbanSettings.js | 3 +- client/src/translations/en_us/common.json | 1 + client/src/translations/es/common.json | 1 + client/src/translations/fr/common.json | 1 + 6 files changed, 76 insertions(+), 35 deletions(-) diff --git a/client/src/components/production-board-kanban/production-board-kanban.statistics.jsx b/client/src/components/production-board-kanban/production-board-kanban.statistics.jsx index cc8c46332..b31d58b84 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.statistics.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.statistics.jsx @@ -28,11 +28,14 @@ const ProductionStatistics = ({ data, cardSettings, reducerData }) => { const { t } = useTranslation(); const calculateTotal = (items, key, subKey) => { - return items.reduce((acc, item) => acc + (item[key]?.aggregate?.sum?.[subKey] || 0), 0); + return items.reduce((acc, item) => acc + (item?.[key]?.aggregate?.sum?.[subKey] ?? 0), 0); }; const calculateTotalAmount = (items, key) => { - return items.reduce((acc, item) => acc.add(Dinero(item[key]?.totals?.subtotal ?? Dinero())), Dinero({ amount: 0 })); + return items.reduce( + (acc, item) => acc.add(Dinero(item?.[key]?.totals?.subtotal ?? Dinero())), + Dinero({ amount: 0 }) + ); }; const calculateReducerTotalAmount = (lanes, key) => { @@ -67,58 +70,83 @@ const ProductionStatistics = ({ data, cardSettings, reducerData }) => { return value; }; + const filteredData = cardSettings.excludeSuspended === true ? data.filter((item) => item.suspended !== true) : data; + const filteredReducerData = + cardSettings.excludeSuspended === true + ? { + ...reducerData, + lanes: reducerData.lanes.map((lane) => ({ + ...lane, + cards: lane.cards.filter((card) => card.metadata.suspended !== true) + })) + } + : reducerData; + const totalHrs = cardSettings.totalHrs - ? parseFloat((calculateTotal(data, "labhrs", "mod_lb_hrs") + calculateTotal(data, "larhrs", "mod_lb_hrs")).toFixed(2)) + ? parseFloat( + ( + calculateTotal(filteredData, "labhrs", "mod_lb_hrs") + calculateTotal(filteredData, "larhrs", "mod_lb_hrs") + ).toFixed(2) + ) : null; const totalLAB = cardSettings.totalLAB - ? parseFloat(calculateTotal(data, "labhrs", "mod_lb_hrs").toFixed(2)) + ? parseFloat(calculateTotal(filteredData, "labhrs", "mod_lb_hrs").toFixed(2)) : null; const totalLAR = cardSettings.totalLAR - ? parseFloat(calculateTotal(data, "larhrs", "mod_lb_hrs").toFixed(2)) + ? parseFloat(calculateTotal(filteredData, "larhrs", "mod_lb_hrs").toFixed(2)) : null; - const jobsInProduction = cardSettings.jobsInProduction ? data.length : null; + const jobsInProduction = cardSettings.jobsInProduction ? filteredData.length : null; const totalAmountInProduction = cardSettings.totalAmountInProduction - ? calculateTotalAmount(data, "job_totals").toFormat("$0,0.00") + ? calculateTotalAmount(filteredData, "job_totals").toFormat("$0,0.00") : null; - const totalAmountOnBoard = reducerData && cardSettings.totalAmountOnBoard - ? calculateReducerTotalAmount(reducerData.lanes, "job_totals").toFormat("$0,0.00") - : null; + const totalAmountOnBoard = + filteredReducerData && cardSettings.totalAmountOnBoard + ? calculateReducerTotalAmount(filteredReducerData.lanes, "job_totals").toFormat("$0,0.00") + : null; - const totalHrsOnBoard = reducerData && cardSettings.totalHrsOnBoard - ? parseFloat(( - calculateReducerTotal(reducerData.lanes, "labhrs", "mod_lb_hrs") + - calculateReducerTotal(reducerData.lanes, "larhrs", "mod_lb_hrs") - ).toFixed(2)) - : null; + const totalHrsOnBoard = + filteredReducerData && cardSettings.totalHrsOnBoard + ? parseFloat( + ( + calculateReducerTotal(filteredReducerData.lanes, "labhrs", "mod_lb_hrs") + + calculateReducerTotal(filteredReducerData.lanes, "larhrs", "mod_lb_hrs") + ).toFixed(2) + ) + : null; - const totalLABOnBoard = reducerData && cardSettings.totalLABOnBoard - ? parseFloat(calculateReducerTotal(reducerData.lanes, "labhrs", "mod_lb_hrs").toFixed(2)) - : null; + const totalLABOnBoard = + filteredReducerData && cardSettings.totalLABOnBoard + ? parseFloat(calculateReducerTotal(filteredReducerData.lanes, "labhrs", "mod_lb_hrs").toFixed(2)) + : null; - const totalLAROnBoard = reducerData && cardSettings.totalLAROnBoard - ? parseFloat(calculateReducerTotal(reducerData.lanes, "larhrs", "mod_lb_hrs").toFixed(2)) - : null; + const totalLAROnBoard = + filteredReducerData && cardSettings.totalLAROnBoard + ? parseFloat(calculateReducerTotal(filteredReducerData.lanes, "larhrs", "mod_lb_hrs").toFixed(2)) + : null; - const jobsOnBoard = reducerData && cardSettings.jobsOnBoard - ? reducerData.lanes.reduce((acc, lane) => acc + lane.cards.length, 0) - : null; + const jobsOnBoard = + filteredReducerData && cardSettings.jobsOnBoard + ? filteredReducerData.lanes.reduce((acc, lane) => acc + lane.cards.length, 0) + : null; const tasksInProduction = cardSettings.tasksInProduction - ? data.reduce((acc, item) => acc + (item.tasks_aggregate?.aggregate?.count || 0), 0) + ? filteredData.reduce((acc, item) => acc + (item.tasks_aggregate?.aggregate?.count || 0), 0) : null; - const tasksOnBoard = reducerData && cardSettings.tasksOnBoard - ? reducerData.lanes.reduce((acc, lane) => { - return ( - acc + lane.cards.reduce((laneAcc, card) => laneAcc + (card.metadata.tasks_aggregate?.aggregate?.count || 0), 0) - ); - }, 0) - : null; + const tasksOnBoard = + filteredReducerData && cardSettings.tasksOnBoard + ? filteredReducerData.lanes.reduce((acc, lane) => { + return ( + acc + + lane.cards.reduce((laneAcc, card) => laneAcc + (card.metadata.tasks_aggregate?.aggregate?.count || 0), 0) + ); + }, 0) + : null; const statistics = mergeStatistics(statisticsItems, [ { id: 0, value: totalHrs, type: StatisticType.HOURS }, diff --git a/client/src/components/production-board-kanban/settings/StatisticsSettings.jsx b/client/src/components/production-board-kanban/settings/StatisticsSettings.jsx index 1645bc05d..d283f6122 100644 --- a/client/src/components/production-board-kanban/settings/StatisticsSettings.jsx +++ b/client/src/components/production-board-kanban/settings/StatisticsSettings.jsx @@ -14,7 +14,16 @@ const StatisticsSettings = ({ t, statisticsOrder, setStatisticsOrder, setHasChan }; return ( - + + + {t("production.settings.statistics.exclude_suspended")} + + + } + > {(provided) => ( diff --git a/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js b/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js index 1c7a264b7..93486a11d 100644 --- a/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js +++ b/client/src/components/production-board-kanban/settings/defaultKanbanSettings.js @@ -91,7 +91,8 @@ const defaultKanbanSettings = { subtotal: false, statisticsOrder: statisticsItems.map((item) => item.id), selectedMdInsCos: [], - selectedEstimators: [] + selectedEstimators: [], + excludeSuspended: false }; const defaultFilters = { search: "", employeeId: null, alert: false }; diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 976222c46..9e41f90d8 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -3265,6 +3265,7 @@ "information": "Information", "layout": "Layout", "statistics": { + "exclude_suspended": "Exclude Suspended Jobs", "jobs_in_production": "Jobs in Production", "tasks_in_production": "Tasks in Production", "tasks_in_view": "Tasks in View", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 619b7f0b1..987149079 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -3259,6 +3259,7 @@ "information": "", "layout": "", "statistics": { + "exclude_suspended": "", "jobs_in_production": "", "tasks_in_production": "", "tasks_in_view": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index a0c5be98e..357d6aa4b 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -3259,6 +3259,7 @@ "information": "", "layout": "", "statistics": { + "exclude_suspended": "", "jobs_in_production": "", "tasks_in_production": "", "tasks_in_view": "",