From 7132465945d137ee3720e40593f3d6dd6b87f358 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Fri, 6 Mar 2026 17:56:21 -0800 Subject: [PATCH] IO-3605 Material Threshold Calculations Signed-off-by: Allan Carr --- .../job-totals.table.labor.component.jsx | 30 +++--------- server/job/job-totals.js | 49 +++++++++---------- 2 files changed, 31 insertions(+), 48 deletions(-) diff --git a/client/src/components/job-totals-table/job-totals.table.labor.component.jsx b/client/src/components/job-totals-table/job-totals.table.labor.component.jsx index 4da437b95..4078737ef 100644 --- a/client/src/components/job-totals-table/job-totals.table.labor.component.jsx +++ b/client/src/components/job-totals-table/job-totals.table.labor.component.jsx @@ -144,18 +144,11 @@ export default function JobTotalsTableLabor({ job }) { {t("jobs.labels.mapa")} {InstanceRenderManager({ imex: - job.materials?.mapa && - job.materials.mapa.cal_maxdlr && - job.materials.mapa.cal_maxdlr > 0 && - t("jobs.labels.threshhold", { - amount: job.materials.mapa.cal_maxdlr - }), + (job.materials?.mapa ?? job.materials?.MAPA)?.cal_maxdlr > 0 && + t("jobs.labels.threshhold", { amount: (job.materials.mapa ?? job.materials.MAPA).cal_maxdlr }), rome: - job.materials?.MAPA && - job.materials.MAPA.cal_maxdlr !== undefined && - t("jobs.labels.threshhold", { - amount: job.materials.MAPA.cal_maxdlr - }) + job.materials?.MAPA?.cal_maxdlr !== undefined && + t("jobs.labels.threshhold", { amount: job.materials.MAPA.cal_maxdlr }) })} @@ -190,18 +183,11 @@ export default function JobTotalsTableLabor({ job }) { {t("jobs.labels.mash")} {InstanceRenderManager({ imex: - job.materials?.mash && - job.materials.mash.cal_maxdlr && - job.materials.mash.cal_maxdlr > 0 && - t("jobs.labels.threshhold", { - amount: job.materials.mash.cal_maxdlr - }), + (job.materials?.mash ?? job.materials?.MASH)?.cal_maxdlr > 0 && + t("jobs.labels.threshhold", { amount: (job.materials.mash ?? job.materials.MASH).cal_maxdlr }), rome: - job.materials?.MASH && - job.materials.MASH.cal_maxdlr !== undefined && - t("jobs.labels.threshhold", { - amount: job.materials.MASH.cal_maxdlr - }) + job.materials?.MASH?.cal_maxdlr !== undefined && + t("jobs.labels.threshhold", { amount: job.materials.MASH.cal_maxdlr }) })} diff --git a/server/job/job-totals.js b/server/job/job-totals.js index 35cc4e6c1..1a578c724 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -315,7 +315,12 @@ function CalculateRatesTotals(ratesList) { if (item.mod_lbr_ty) { //Check to see if it has 0 hours and a price instead. //Extend for when there are hours and a price. - if (item.lbr_op === "OP14" && item.act_price > 0 && (!item.part_type || item.mod_lb_hrs === 0) && !IsAdditionalCost(item)) { + if ( + item.lbr_op === "OP14" && + item.act_price > 0 && + (!item.part_type || item.mod_lb_hrs === 0) && + !IsAdditionalCost(item) + ) { //Scenario where SGI may pay out hours using a part price. if (!ret[item.mod_lbr_ty.toLowerCase()].total) { ret[item.mod_lbr_ty.toLowerCase()].total = Dinero(); @@ -339,38 +344,30 @@ function CalculateRatesTotals(ratesList) { let subtotal = Dinero({ amount: 0 }); let rates_subtotal = Dinero({ amount: 0 }); - for (const property in ret) { + for (const [property, values] of Object.entries(ret)) { //Skip calculating mapa and mash if we got the amounts. - if (!((property === "mapa" && hasMapaLine) || (property === "mash" && hasMashLine))) { - if (!ret[property].total) { - ret[property].total = Dinero(); - } - let threshold; - //Check if there is a max for this type. - if (ratesList.materials && ratesList.materials[property]) { - // - if (ratesList.materials[property].cal_maxdlr && ratesList.materials[property].cal_maxdlr > 0) { - //It has an upper threshhold. - threshold = Dinero({ - amount: Math.round(ratesList.materials[property].cal_maxdlr * 100) - }); - } - } + const shouldSkipCalculation = (property === "mapa" && hasMapaLine) || (property === "mash" && hasMashLine); + + if (!shouldSkipCalculation) { + values.total ??= Dinero(); + + //Check if there is a max for this type and apply it. + const maxDollar = + ratesList.materials?.[property]?.cal_maxdlr || ratesList.materials?.[property.toUpperCase()]?.cal_maxdlr; + const threshold = maxDollar > 0 ? Dinero({ amount: Math.round(maxDollar * 100) }) : null; const total = Dinero({ - amount: Math.round((ret[property].rate || 0) * 100) - }).multiply(ret[property].hours); + amount: Math.round((values.rate || 0) * 100) + }).multiply(values.hours); - if (threshold && total.greaterThanOrEqual(threshold)) { - ret[property].total = ret[property].total.add(threshold); - } else { - ret[property].total = ret[property].total.add(total); - } + values.total = values.total.add(threshold && total.greaterThanOrEqual(threshold) ? threshold : total); } - subtotal = subtotal.add(ret[property].total); + subtotal = subtotal.add(values.total); - if (property !== "mapa" && property !== "mash") rates_subtotal = rates_subtotal.add(ret[property].total); + if (property !== "mapa" && property !== "mash") { + rates_subtotal = rates_subtotal.add(values.total); + } } ret.subtotal = subtotal;