diff --git a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx index be92d5994..b989a9dcf 100644 --- a/client/src/components/job-totals-table/job-totals.table.totals.component.jsx +++ b/client/src/components/job-totals-table/job-totals.table.totals.component.jsx @@ -22,6 +22,14 @@ export function JobTotalsTableTotals({ bodyshop, job }) { const data = useMemo(() => { return [ + ...(job.job_totals?.totals?.ttl_adjustment + ? [ + { + key: `Subtotal Adj.`, + total: job.job_totals?.totals?.ttl_adjustment + } + ] + : []), { key: t("jobs.labels.subtotal"), total: job.job_totals.totals.subtotal, @@ -116,7 +124,7 @@ export function JobTotalsTableTotals({ bodyshop, job }) { ...(job.job_totals?.totals?.ttl_tax_adjustment ? [ { - key: `Adj.`, + key: `Tax Adj.`, total: job.job_totals?.totals?.ttl_tax_adjustment } ] diff --git a/client/src/components/jobs-available-table/jobs-available-table.container.jsx b/client/src/components/jobs-available-table/jobs-available-table.container.jsx index 3a3b0d7e8..6266e2dc5 100644 --- a/client/src/components/jobs-available-table/jobs-available-table.container.jsx +++ b/client/src/components/jobs-available-table/jobs-available-table.container.jsx @@ -408,26 +408,23 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail updateSchComp={updateSchComp} setSchComp={setSchComp} /> - { - currentUser.email.includes("@rome.") || - currentUser.email.includes("@imex.") ? ( - - ) : null - } + {currentUser.email.includes("@rome.") || currentUser.email.includes("@imex.") ? ( + + ) : null} r.result !== "PASS").length}` - ); + const limit = pLimit(5); // Set concurrency limit to 3 - try { - await axios.post( - `http://localhost:4000/job/totalsssu`, - { id: job.id }, - { headers: { Authorization: bearerToken } } + const tasks = jobs.map((job, index) => { + return limit(async () => { + process.stdout.cursorTo(0); + process.stdout.write( + `Processing job ${index + 1} of ${jobs.length}. Failed jobs: ${results.filter((r) => r.overallTotalCorrect !== "PASS").length}. Correct jobs because of adjustment: ${results.filter((r) => r.correctJobsBecauseOfAdjustment).length}` ); - const { jobs_by_pk: newjob } = await client.request( - gql` - query GET_JOBS($id: uuid!) { - jobs_by_pk(id: $id) { - id - ro_number - cieca_ttl - job_totals - ownr_fn - ownr_ln - ownr_co_nm - ins_co_nm - comment + + try { + await axios.post( + `http://localhost:4000/job/totalsssu`, + { id: job.id }, + { headers: { Authorization: bearerToken } } + ); + const { jobs_by_pk: newjob } = await client.request( + gql` + query GET_JOBS($id: uuid!) { + jobs_by_pk(id: $id) { + id + ro_number + cieca_ttl + job_totals + ownr_fn + ownr_ln + ownr_co_nm + ins_co_nm + comment + } } + `, + { + id: job.id } - `, - { - id: job.id + ); + + const result = { + id: newjob.id, + owner: `${newjob.ownr_fn} ${newjob.ownr_ln} ${job.ownr_co_nm || ""}`, + ins_co: newjob.ins_co_nm, + comment: newjob.comment + }; + + const calcTotal = newjob.job_totals.totals.total_repairs.amount; + const ttlTotal = newjob.cieca_ttl.data.g_ttl_amt * 100; + result.difference = (calcTotal - ttlTotal) / 100; + + if (Math.abs(calcTotal - ttlTotal) > 3) { + result.overallTotalCorrect = "***FAIL***"; + } else { + result.overallTotalCorrect = "PASS"; } - ); + result.ttl_adjustment = Dinero(newjob.job_totals.totals.ttl_adjustment).toFormat(); + result.ttl_tax_adjustment = Dinero(newjob.job_totals.totals.ttl_tax_adjustment).toFormat(); - const result = { - id: newjob.id, - owner: `${newjob.ownr_fn} ${newjob.ownr_ln} ${job.ownr_co_nm || ""}`, - ins_co: newjob.ins_co_nm, - comment: newjob.comment - }; + const calcTax = + Dinero(newjob.job_totals.totals.us_sales_tax_breakdown.ty1Tax) + .add(Dinero(newjob.job_totals.totals.us_sales_tax_breakdown.ty2Tax)) + .add(Dinero(newjob.job_totals.totals.us_sales_tax_breakdown.ty3Tax)) + .add(Dinero(newjob.job_totals.totals.us_sales_tax_breakdown.ty4Tax)) + .add(Dinero(newjob.job_totals.totals.us_sales_tax_breakdown.ty5Tax)) + .add(Dinero(newjob.job_totals.totals.ttl_tax_adjustment)) + .getAmount() / 100; - const calcTotal = newjob.job_totals.totals.total_repairs.amount; - const ttlTotal = newjob.cieca_ttl.data.g_ttl_amt * 100; - result.difference = (calcTotal - ttlTotal) / 100; + const emsTax = newjob.cieca_ttl.data.g_tax; + result.taxDifference = calcTax - emsTax; - if (Math.abs(calcTotal - ttlTotal) > 3) { - //Diff is greater than 5 cents. Fail it. - result.result = "***FAIL***"; - } else { - result.result = "PASS"; + if (Math.abs(calcTax - emsTax) > 3) { + result.taxCorrect = "***FAIL***"; + } else { + result.taxCorrect = "PASS"; + } + + results.push(result); + } catch (error) { + results.push({ + ro_number: job.ro_number, + id: job.id, + result: "**503 FAILURE**" + }); } - const subcalcTotal = newjob.job_totals.totals.subtotal.amount; - const subttlTotal = newjob.cieca_ttl.data.n_ttl_amt * 100; - result.subdifference = (subcalcTotal - subttlTotal) / 100; + }); + }); - if (Math.abs(subcalcTotal - subttlTotal) > 3) { - //Diff is greater than 5 cents. Fail it. - result.subresult = "***FAIL***"; - } else { - result.subresult = "PASS"; - } - // console.log(`${result.result} => RO ${job.ro_number} - ${job.id} `); + await Promise.all(tasks); - results.push(result); - } catch (error) { - results.push({ - ro_number: job.ro_number, - id: job.id, - result: "**503 FAILURE**" - }); - } - } - - console.table(results.filter((r) => r.result !== "PASS")); + console.table(results.filter((r) => r.overallTotalCorrect !== "PASS")); + console.log("======================================="); const summary = results.reduce( (acc, val) => { if (val.result === "PASS") { @@ -119,18 +134,12 @@ async function RunTheTest() { { pass: 0, fail: 0 } ); console.log("Pass Rate: ", ((summary.pass / (summary.fail + summary.pass)) * 100).toFixed(1)); + + const ret = converter.json2csv(results, { emptyFieldValue: "" }); + + fs.writeFile(`./logs/totalstest-${Date.now()}.csv`, ret, (error) => console.log(error)); } -RunTheTest(); - -// mutation { -// delete_jobs(where: {shopid: {_eq: "a7ee1503-ee05-4a02-b80e-bdb11d1cc8ac"}}) { -// affected_rows -// } -// delete_owners(where: {shopid: {_eq: "a7ee1503-ee05-4a02-b80e-bdb11d1cc8ac"}}) { -// affected_rows -// } -// delete_vehicles(where: {shopid: {_eq: "a7ee1503-ee05-4a02-b80e-bdb11d1cc8ac"}}) { -// affected_rows -// } -// } +RunTheTest().catch((error) => { + console.log("Error in RunTheTest: ", error); +}); diff --git a/package-lock.json b/package-lock.json index 2f0edfad5..76f862a25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -64,6 +64,7 @@ "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", "concurrently": "^8.2.2", + "p-limit": "^3.1.0", "prettier": "^3.3.3", "source-map-explorer": "^2.5.2" }, @@ -6726,7 +6727,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "optional": true, + "devOptional": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -8720,7 +8722,8 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "optional": true, + "devOptional": true, + "license": "MIT", "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 2a3c24ded..954c5ec07 100644 --- a/package.json +++ b/package.json @@ -74,6 +74,7 @@ "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", "concurrently": "^8.2.2", + "p-limit": "^3.1.0", "prettier": "^3.3.3", "source-map-explorer": "^2.5.2" } diff --git a/server/job/job-costing.js b/server/job/job-costing.js index 9ce65f71d..d55af58a5 100644 --- a/server/job/job-costing.js +++ b/server/job/job-costing.js @@ -476,7 +476,7 @@ function GenerateCostingData(job) { if (!hasMapaLine) { if (!jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]]) jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = Dinero(); - + jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = jobLineTotalsByProfitCenter.additional[ defaultProfits["MAPA"] ].add( @@ -809,6 +809,41 @@ function GenerateCostingData(job) { gppercent: formatGpPercent(0) }); } + //Push adjustments to bottom line. + if (job.job_totals.totals.ttl_adjustment) { + //Add to totals. + const Adjustment = Dinero(job.job_totals.totals.ttl_adjustment); //Need to invert, since this is being assigned as a cost. + summaryData.totalAdditionalSales = summaryData.totalAdditionalSales.add(Adjustment); + summaryData.totalSales = summaryData.totalSales.add(Adjustment); + //Add to lines. + costCenterData.push({ + id: "Adj", + cost_center: "Adjustment", + sale_labor: Dinero().toFormat(), + sale_labor_dinero: Dinero(), + sale_parts: Dinero().toFormat(), + sale_parts_dinero: Dinero(), + sale_additional: Adjustment.toFormat(), + sale_additional_dinero: Adjustment, + sale_sublet: Dinero(), + sale_sublet_dinero: Dinero(), + sales: Adjustment.toFormat(), + sales_dinero: Adjustment, + cost_parts: Dinero().toFormat(), + cost_parts_dinero: Dinero(), + cost_labor: Dinero().toFormat(), //Adjustment.toFormat(), + cost_labor_dinero: Dinero(), // Adjustment, + cost_additional: Dinero(), + cost_additional_dinero: Dinero(), + cost_sublet: Dinero(), + cost_sublet_dinero: Dinero(), + costs: Dinero().toFormat(), + costs_dinero: Dinero(), + gpdollars_dinero: Dinero(), + gpdollars: Dinero().toFormat(), + gppercent: formatGpPercent(0) + }); + } //Final summary data massaging.