diff --git a/job-totals-testing-util.js b/job-totals-testing-util.js index 53eea2552..b69ec111b 100644 --- a/job-totals-testing-util.js +++ b/job-totals-testing-util.js @@ -99,7 +99,7 @@ async function RunTheTest() { } } - console.table(results); + console.table(results.filter((r) => r.result !== "PASS")); const summary = results.reduce( (acc, val) => { if (val.result === "PASS") { diff --git a/server/job/job-totals.js b/server/job/job-totals.js index d80805e4e..16b5ca5bd 100644 --- a/server/job/job-totals.js +++ b/server/job/job-totals.js @@ -762,9 +762,6 @@ function CalculateTaxesTotals(job, otherTotals) { .add(otherTotals.rates.subtotal) //No longer using just rates subtotal to include mapa/mash. .add(otherTotals.additional.total); - // .add(Dinero({ amount: (job.towing_payable || 0) * 100 })) - // .add(Dinero({ amount: (job.storage_payable || 0) * 100 })); - //Potential issue here with Sublet Calculation. Sublets are calculated under labor in Mitchell, but it's done in IO //Under the parts rates. @@ -791,6 +788,21 @@ function CalculateTaxesTotals(job, otherTotals) { PAS: Dinero(), PAP: Dinero(), PAM: Dinero(), + + LA1: Dinero(), + LA2: Dinero(), + LA3: Dinero(), + LA4: Dinero(), + LAU: Dinero(), + LAA: Dinero(), + LAB: Dinero(), + LAD: Dinero(), + LAE: Dinero(), + LAF: Dinero(), + LAG: Dinero(), + LAM: Dinero(), + LAR: Dinero(), + LAS: Dinero(), }; if ( @@ -811,7 +823,7 @@ function CalculateTaxesTotals(job, otherTotals) { } else if (!val.part_type) { //Do nothing for now. } else { - const typeOfPart = val.part_type === "PAM" ? "PAC" : val.part_type; + const typeOfPart = val.part_type; // === "PAM" ? "PAC" : val.part_type; taxableAmounts[typeOfPart] = taxableAmounts[typeOfPart].add( Dinero({ amount: Math.round((val.act_price || 0) * 100) }) .multiply(val.part_qty || 0) @@ -833,10 +845,33 @@ function CalculateTaxesTotals(job, otherTotals) { } }); - //Taxable amounts should match with what is in the STL file. - //Now that we have the taxable amounts, apply the tax. + //Check in the PFL file which types of labor are taxable. Add the amount that is considered taxable to the taxable amounts total. + Object.keys(taxableAmounts) + .filter((key) => key.startsWith("LA")) + .map((key) => { + const isLaborTypeTaxable = job.cieca_pfl[key]?.lbr_tax_in; + if (isLaborTypeTaxable) { + taxableAmounts[key] = taxableAmounts[key].add( + otherTotals.rates[key.toLowerCase()].total + ); + } + }); - const tieredTaxAmounts = { + console.log("*** Taxable Amounts***"); + console.table(JSON.parse(JSON.stringify(taxableAmounts))); + + //For the taxable amounts, figure out which tax type applies. + //Then sum up the total of that tax type and then calculate the thresholds. + + const taxableAmountsByTier = { + ty1Tax: Dinero(), + ty2Tax: Dinero(), + ty3Tax: Dinero(), + ty4Tax: Dinero(), + ty5Tax: Dinero(), + ty6Tax: Dinero(), + }; + const totalTaxByTier = { ty1Tax: Dinero(), ty2Tax: Dinero(), ty3Tax: Dinero(), @@ -845,80 +880,104 @@ function CalculateTaxesTotals(job, otherTotals) { ty6Tax: Dinero(), }; - const remainingTaxableAmounts = taxableAmounts; - console.log("Taxable Amounts"); - console.table(JSON.parse(JSON.stringify(taxableAmounts))); - Object.keys(taxableAmounts).forEach((part_type) => { - //Check it's taxability in the PFP + const pfp = job.parts_tax_rates; + const pfl = job.cieca_pfl; + Object.keys(taxableAmounts).map((key) => { try { - const pfp = job.parts_tax_rates; - - const typeOfPart = part_type === "PAM" ? "PAC" : part_type; - if (IsTrueOrYes(pfp[typeOfPart].prt_tax_in)) { + if (key.startsWith("PA")) { + const typeOfPart = key; // === "PAM" ? "PAC" : key; //At least one of these scenarios must be taxable. for (let tyCounter = 1; tyCounter <= 5; tyCounter++) { if (IsTrueOrYes(pfp[typeOfPart][`prt_tx_in${tyCounter}`])) { - //i represents the tax number. If we got here, this type of tax is applicable. Now we need to add based on the thresholds. - for (let threshCounter = 1; threshCounter <= 5; threshCounter++) { - const thresholdAmount = parseFloat( - job.cieca_pft[`ty${tyCounter}_thres${threshCounter}`] - ); - const thresholdTaxRate = parseFloat( - job.cieca_pft[`ty${tyCounter}_rate${threshCounter}`] - ); - - let taxableAmountInThisThreshold; - if (thresholdAmount === 9999.99) { - // THis is the last threshold. Tax the entire remaining amount. - taxableAmountInThisThreshold = - remainingTaxableAmounts[typeOfPart]; - remainingTaxableAmounts[typeOfPart] = Dinero(); - } else { - if ( - thresholdAmount >= - remainingTaxableAmounts[typeOfPart].getAmount() / 100 - ) { - //This threshold is bigger than the remaining taxable balance. Add it all. - taxableAmountInThisThreshold = - remainingTaxableAmounts[typeOfPart]; - remainingTaxableAmounts[typeOfPart] = Dinero(); - } else { - //Take the size of the threshold from the remaining amount, tax it, and do it all over. - taxableAmountInThisThreshold = Dinero({ - amount: Math.round(thresholdAmount * 100), - }); - remainingTaxableAmounts[typeOfPart] = - remainingTaxableAmounts[typeOfPart].subtract( - Dinero({ - amount: Math.round( - taxableAmountInThisThreshold * 100 - ), - }) - ); - } - } - - const taxAmountToAdd = - taxableAmountInThisThreshold.percentage(thresholdTaxRate); - - tieredTaxAmounts[`ty${tyCounter}Tax`] = - tieredTaxAmounts[`ty${tyCounter}Tax`].add(taxAmountToAdd); - } + //This amount is taxable for this type. + taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[ + `ty${tyCounter}Tax` + ].add(taxableAmounts[typeOfPart]); + } + } + } else { + //Labor. + for (let tyCounter = 1; tyCounter <= 5; tyCounter++) { + if (IsTrueOrYes(pfl[key][`lbr_tx_in${tyCounter}`])) { + //This amount is taxable for this type. + taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[ + `ty${tyCounter}Tax` + ].add(taxableAmounts[key]); } } } } catch (error) { - console.error("Shit the bed."); + console.error("Key with issue", key); } }); + const remainingTaxableAmounts = taxableAmountsByTier; + console.log("*** Taxable Amounts by Tier***"); + console.table(JSON.parse(JSON.stringify(taxableAmountsByTier))); + + Object.keys(taxableAmountsByTier).forEach((taxTierKey) => { + try { + let tyCounter = taxTierKey[2]; //Get the number from the key. + //i represents the tax number. If we got here, this type of tax is applicable. Now we need to add based on the thresholds. + for (let threshCounter = 1; threshCounter <= 5; threshCounter++) { + const thresholdAmount = parseFloat( + job.cieca_pft[`ty${tyCounter}_thres${threshCounter}`] + ); + const thresholdTaxRate = parseFloat( + job.cieca_pft[`ty${tyCounter}_rate${threshCounter}`] + ); + + let taxableAmountInThisThreshold; + if (thresholdAmount === 9999.99) { + // THis is the last threshold. Tax the entire remaining amount. + taxableAmountInThisThreshold = remainingTaxableAmounts[taxTierKey]; + remainingTaxableAmounts[taxTierKey] = Dinero(); + } else { + if ( + thresholdAmount >= + remainingTaxableAmounts[taxTierKey].getAmount() / 100 + ) { + //This threshold is bigger than the remaining taxable balance. Add it all. + taxableAmountInThisThreshold = + remainingTaxableAmounts[taxTierKey]; + remainingTaxableAmounts[taxTierKey] = Dinero(); + } else { + //Take the size of the threshold from the remaining amount, tax it, and do it all over. + taxableAmountInThisThreshold = Dinero({ + amount: Math.round(thresholdAmount * 100), + }); + remainingTaxableAmounts[taxTierKey] = remainingTaxableAmounts[ + taxTierKey + ].subtract( + Dinero({ + amount: Math.round(taxableAmountInThisThreshold * 100), + }) + ); + } + } + + const taxAmountToAdd = + taxableAmountInThisThreshold.percentage(thresholdTaxRate); + + totalTaxByTier[taxTierKey] = + totalTaxByTier[taxTierKey].add(taxAmountToAdd); + } + } catch (error) { + console.error("PFP Calculation error", error); + } + }); + + console.log("*** Total Tax by Tier Amounts***"); + console.table(JSON.parse(JSON.stringify(totalTaxByTier))); + statePartsTax = statePartsTax - .add(tieredTaxAmounts.ty1Tax) - .add(tieredTaxAmounts.ty2Tax) - .add(tieredTaxAmounts.ty3Tax) - .add(tieredTaxAmounts.ty4Tax) - .add(tieredTaxAmounts.ty5Tax) - .add(tieredTaxAmounts.ty6Tax); + .add(totalTaxByTier.ty1Tax) + .add(totalTaxByTier.ty2Tax) + .add(totalTaxByTier.ty3Tax) + .add(totalTaxByTier.ty4Tax) + .add(totalTaxByTier.ty5Tax) + .add(totalTaxByTier.ty6Tax); + console.log("Tiered Taxes Total for Parts", statePartsTax.toFormat()); } else { //Use the old thing. @@ -978,32 +1037,6 @@ function CalculateTaxesTotals(job, otherTotals) { let laborTaxTotal = Dinero(); if (Object.keys(job.cieca_pfl).length > 0) { - //Do it by labor type - const types = [ - "la1", - "la2", - "la3", - "la4", - "lau", - "laa", - "lab", - "lad", - "lae", - "laf", - "lag", - "lam", - "lar", - "las", - ]; - types.forEach((type) => { - laborTaxTotal = laborTaxTotal.add( - otherTotals.rates[type].total.percentage( - job.cieca_pfl[type.toUpperCase()] - ? job.cieca_pfl[type.toUpperCase()].lbr_taxp - : (job.tax_lbr_rt || 0) * 100 - ) - ); - }); } else { //We don't have it, just add in how it was before. laborTaxTotal = otherTotals.rates.subtotal.percentage(