IO-2854 Profile Adjustments for LA and MA
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
This commit is contained in:
@@ -1527,6 +1527,7 @@ exports.QUERY_JOB_COSTING_DETAILS = ` query QUERY_JOB_COSTING_DETAILS($id: uuid!
|
||||
ca_bc_pvrt
|
||||
ca_customer_gst
|
||||
dms_allocation
|
||||
cieca_pfl
|
||||
joblines(where: { removed: { _eq: false } }) {
|
||||
id
|
||||
db_ref
|
||||
|
||||
@@ -286,9 +286,45 @@ function GenerateCostingData(job) {
|
||||
|
||||
const rateName = `rate_${(val.mod_lbr_ty || "").toLowerCase()}`;
|
||||
|
||||
const laborAmount = Dinero({
|
||||
let laborAmount = Dinero();
|
||||
laborAmount = Dinero({
|
||||
amount: Math.round((job[rateName] || 0) * 100)
|
||||
}).multiply(val.mod_lb_hrs || 0);
|
||||
|
||||
if (
|
||||
job.cieca_pfl &&
|
||||
job.cieca_pfl[val.mod_lbr_ty.toUpperCase()] &&
|
||||
job.cieca_pfl[val.mod_lbr_ty.toUpperCase()].lbr_adjp !== 0
|
||||
) {
|
||||
let adjp = 0;
|
||||
if (
|
||||
val.mod_lbr_ty === "la1" ||
|
||||
val.mod_lbr_ty === "la2" ||
|
||||
val.mod_lbr_ty === "la3" ||
|
||||
val.mod_lbr_ty === "la4"
|
||||
) {
|
||||
adjp =
|
||||
Math.abs(job.cieca_pfl["LAU"].lbr_adjp) > 1
|
||||
? job.cieca_pfl["LAU"].lbr_adjp
|
||||
: job.cieca_pfl["LAU"].lbr_adjp * 100; //Adjust lbr_adjp to whole number
|
||||
} else {
|
||||
if (job.cieca_pfl[val.mod_lbr_ty.toUpperCase()]) {
|
||||
adjp =
|
||||
Math.abs(job.cieca_pfl[val.mod_lbr_ty.toUpperCase()].lbr_adjp) > 1
|
||||
? job.cieca_pfl[val.mod_lbr_ty.toUpperCase()].lbr_adjp
|
||||
: job.cieca_pfl[val.mod_lbr_ty.toUpperCase()].lbr_adjp * 100; //Adjust lbr_adjp to whole number
|
||||
} else {
|
||||
adjp =
|
||||
Math.abs(job.cieca_pfl["LAB"].lbr_adjp) > 1
|
||||
? job.cieca_pfl["LAB"].lbr_adjp
|
||||
: job.cieca_pfl["LAB"].lbr_adjp * 100; //Adjust lbr_adjp to whole number
|
||||
}
|
||||
}
|
||||
laborAmount = laborAmount.add(
|
||||
laborAmount.percentage(adjp < 0 ? adjp * -1 : adjp).multiply(adjp < 0 ? -1 : 1)
|
||||
);
|
||||
}
|
||||
|
||||
if (!acc.labor[laborProfitCenter]) acc.labor[laborProfitCenter] = Dinero();
|
||||
acc.labor[laborProfitCenter] = acc.labor[laborProfitCenter].add(laborAmount);
|
||||
|
||||
@@ -317,7 +353,7 @@ function GenerateCostingData(job) {
|
||||
|
||||
if (!partsProfitCenter)
|
||||
console.log("Unknown cost/profit center mapping for parts.", val.line_desc, val.part_type);
|
||||
const partsAmount = Dinero({
|
||||
let partsAmount = Dinero({
|
||||
amount: val.act_price_before_ppc
|
||||
? Math.round(val.act_price_before_ppc * 100)
|
||||
: Math.round(val.act_price * 100)
|
||||
@@ -338,6 +374,33 @@ function GenerateCostingData(job) {
|
||||
.multiply(val.prt_dsmk_p > 0 ? 1 : -1)
|
||||
: Dinero()
|
||||
);
|
||||
|
||||
// Profile Discount for Parts
|
||||
if (job.parts_tax_rates && job.parts_tax_rates[val.part_type.toUpperCase()]) {
|
||||
if (
|
||||
job.parts_tax_rates[val.part_type.toUpperCase()].prt_discp !== undefined &&
|
||||
job.parts_tax_rates[val.part_type.toUpperCase()].prt_discp >= 0
|
||||
) {
|
||||
const discountRate =
|
||||
Math.abs(job.parts_tax_rates[val.part_type.toUpperCase()].prt_discp) > 1
|
||||
? parts_tajob.parts_tax_rates_rates[val.part_type.toUpperCase()].prt_discp
|
||||
: job.parts_tax_rates[val.part_type.toUpperCase()].prt_discp * 100;
|
||||
const disc = partsAmount.percentage(discountRate).multiply(-1);
|
||||
partsAmount = partsAmount.add(disc);
|
||||
}
|
||||
if (
|
||||
job.parts_tax_rates[val.part_type.toUpperCase()].prt_mkupp !== undefined &&
|
||||
job.parts_tax_rates[val.part_type.toUpperCase()].prt_mkupp >= 0
|
||||
) {
|
||||
const markupRate =
|
||||
Math.abs(job.parts_tax_rates[val.part_type.toUpperCase()].prt_mkupp) > 1
|
||||
? job.parts_tax_rates[val.part_type.toUpperCase()].prt_mkupp
|
||||
: job.parts_tax_rates[val.part_type.toUpperCase()].prt_mkupp * 100;
|
||||
const markup = partsAmount.percentage(markupRate);
|
||||
partsAmount = partsAmount.add(markup);
|
||||
}
|
||||
}
|
||||
|
||||
if (!acc.parts[partsProfitCenter]) acc.parts[partsProfitCenter] = Dinero();
|
||||
acc.parts[partsProfitCenter] = acc.parts[partsProfitCenter].add(partsAmount);
|
||||
}
|
||||
|
||||
@@ -331,6 +331,8 @@ async function CalculateRatesTotals({ job, client }) {
|
||||
//Skip calculating mapa and mash if we got the amounts.
|
||||
if (!((property === "mapa" && hasMapaLine) || (property === "mash" && hasMashLine))) {
|
||||
if (!ret[property].total) {
|
||||
ret[property].base = Dinero();
|
||||
ret[property].adjustment = Dinero();
|
||||
ret[property].total = Dinero();
|
||||
}
|
||||
let threshold;
|
||||
@@ -349,13 +351,44 @@ async function CalculateRatesTotals({ job, client }) {
|
||||
}
|
||||
}
|
||||
|
||||
const total = Dinero({
|
||||
const base = Dinero({
|
||||
amount: Math.round((ret[property].rate || 0) * 100)
|
||||
}).multiply(ret[property].hours);
|
||||
|
||||
let adjp = 0;
|
||||
if (property === "mapa" || property === "mash") {
|
||||
adjp =
|
||||
Math.abs(job.materials[property.toUpperCase()].mat_adjp) > 1
|
||||
? job.materials[property.toUpperCase()].mat_adjp
|
||||
: job.materials[property.toUpperCase()].mat_adjp * 100; //Adjust mat_adjp to whole number
|
||||
} else {
|
||||
if (property === "la1" || property === "la2" || property === "la3" || property === "la4") {
|
||||
adjp =
|
||||
Math.abs(job.cieca_pfl["LAU"].lbr_adjp) > 1
|
||||
? job.cieca_pfl["LAU"].lbr_adjp
|
||||
: job.cieca_pfl["LAU"].lbr_adjp * 100; //Adjust lbr_adjp to whole number
|
||||
} else {
|
||||
if (job.cieca_pfl[property.toUpperCase()]) {
|
||||
adjp =
|
||||
Math.abs(job.cieca_pfl[property.toUpperCase()].lbr_adjp) > 1
|
||||
? job.cieca_pfl[property.toUpperCase()].lbr_adjp
|
||||
: job.cieca_pfl[property.toUpperCase()].lbr_adjp * 100; //Adjust lbr_adjp to whole number
|
||||
} else {
|
||||
adjp =
|
||||
Math.abs(job.cieca_pfl["LAB"].lbr_adjp) > 1
|
||||
? job.cieca_pfl["LAB"].lbr_adjp
|
||||
: job.cieca_pfl["LAB"].lbr_adjp * 100; //Adjust lbr_adjp to whole number
|
||||
}
|
||||
}
|
||||
}
|
||||
const adjustment = base.percentage(adjp < 0 ? adjp * -1 : adjp).multiply(adjp < 0 ? -1 : 1);
|
||||
const total = base.add(adjustment);
|
||||
|
||||
if (threshold && total.greaterThanOrEqual(threshold)) {
|
||||
ret[property].total = ret[property].total.add(threshold);
|
||||
} else {
|
||||
ret[property].base = ret[property].base.add(base);
|
||||
ret[property].adjustment = ret[property].adjustment.add(adjustment);
|
||||
ret[property].total = ret[property].total.add(total);
|
||||
}
|
||||
}
|
||||
@@ -703,18 +736,19 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
//Potential issue here with Sublet Calculation. Sublets are calculated under labor in Mitchell, but it's done in IO
|
||||
//Under the parts rates.
|
||||
|
||||
let statePartsTax = Dinero();
|
||||
let additionalItemsTax = Dinero();
|
||||
let stateTax = Dinero();
|
||||
// let additionalItemsTax = Dinero(); //This is not used.
|
||||
let us_sales_tax_breakdown;
|
||||
|
||||
// This is not referenced in the code base.
|
||||
//Audatex sends additional glass part types. IO-774
|
||||
const BackupGlassTax =
|
||||
job.parts_tax_rates &&
|
||||
(job.parts_tax_rates.PAGD ||
|
||||
job.parts_tax_rates.PAGF ||
|
||||
job.parts_tax_rates.PAGP ||
|
||||
job.parts_tax_rates.PAGQ ||
|
||||
job.parts_tax_rates.PAGR);
|
||||
// const BackupGlassTax =
|
||||
// job.parts_tax_rates &&
|
||||
// (job.parts_tax_rates.PAGD ||
|
||||
// job.parts_tax_rates.PAGF ||
|
||||
// job.parts_tax_rates.PAGP ||
|
||||
// job.parts_tax_rates.PAGQ ||
|
||||
// job.parts_tax_rates.PAGR);
|
||||
|
||||
const taxableAmounts = {
|
||||
PAA: Dinero(),
|
||||
@@ -878,11 +912,27 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
} else if (key.startsWith("LA")) {
|
||||
//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]
|
||||
);
|
||||
if (key === "LA1" || key === "LA2" || key === "LA3" || key === "LA4") {
|
||||
if (IsTrueOrYes(pfl["LAU"][`lbr_tx_in${tyCounter}`])) {
|
||||
//This amount is taxable for this type.
|
||||
taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[`ty${tyCounter}Tax`].add(
|
||||
taxableAmounts[key]
|
||||
);
|
||||
}
|
||||
} else if (key === "LAA" && !pfl[key]) {
|
||||
if (IsTrueOrYes(pfl["LAB"][`lbr_tx_in${tyCounter}`])) {
|
||||
//This amount is taxable for this type.
|
||||
taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[`ty${tyCounter}Tax`].add(
|
||||
taxableAmounts[key]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
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]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (key === "TOW") {
|
||||
@@ -919,7 +969,6 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
|
||||
Object.keys(taxableAmountsByTier).forEach((taxTierKey) => {
|
||||
taxable_adjustment = taxableAmountsByTier[taxTierKey].multiply(percent_of_adjustment);
|
||||
console.log("🚀 ~ taxableAmountsByTier ~ taxable_adjustment:", taxable_adjustment);
|
||||
if (job.adjustment_bottom_line > 0) {
|
||||
taxableAmountsByTier[taxTierKey] = taxableAmountsByTier[taxTierKey].add(taxable_adjustment);
|
||||
} else {
|
||||
@@ -937,8 +986,8 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
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}`]);
|
||||
const thresholdAmount = parseFloat(job.cieca_pft[`ty${tyCounter}_thres${threshCounter}`]) || 0;
|
||||
const thresholdTaxRate = parseFloat(job.cieca_pft[`ty${tyCounter}_rate${threshCounter}`]) || 0;
|
||||
|
||||
let taxableAmountInThisThreshold;
|
||||
if (
|
||||
@@ -946,7 +995,7 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
InstanceMgr({
|
||||
imex: false,
|
||||
rome: thresholdAmount === 0 && parseInt(tyCounter) === 1,
|
||||
promanager: thresholdAmount === 0 && parseInt(tyCounter) === 1
|
||||
promanager: "USE_ROME"
|
||||
})
|
||||
) {
|
||||
//
|
||||
@@ -980,10 +1029,10 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
}
|
||||
});
|
||||
|
||||
// console.log("*** Total Tax by Tier Amounts***");
|
||||
// console.table(JSON.parse(JSON.stringify(totalTaxByTier)));
|
||||
console.log("*** Total Tax by Tier Amounts***");
|
||||
console.table(JSON.parse(JSON.stringify(totalTaxByTier)));
|
||||
|
||||
statePartsTax = statePartsTax
|
||||
stateTax = stateTax
|
||||
.add(totalTaxByTier.ty1Tax)
|
||||
.add(totalTaxByTier.ty2Tax)
|
||||
.add(totalTaxByTier.ty3Tax)
|
||||
@@ -991,17 +1040,18 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
.add(totalTaxByTier.ty5Tax)
|
||||
.add(totalTaxByTier.ty6Tax);
|
||||
us_sales_tax_breakdown = totalTaxByTier;
|
||||
//console.log("Tiered Taxes Total for Parts/Labor", statePartsTax.toFormat());
|
||||
//console.log("Tiered Taxes Total for Parts/Labor", stateTax.toFormat());
|
||||
|
||||
let laborTaxTotal = Dinero();
|
||||
// This is not in use as such commented out.
|
||||
// let laborTaxTotal = Dinero();
|
||||
|
||||
if (Object.keys(job.cieca_pfl).length > 0) {
|
||||
//Ignore it now, we have calculated it above.
|
||||
//This was previously used for JCS before parts were also calculated at a different rate.
|
||||
} else {
|
||||
//We don't have it, just add in how it was before.
|
||||
laborTaxTotal = otherTotals.rates.subtotal.percentage((job.tax_lbr_rt || 0) * 100); // THis is currently using the lbr tax rate from PFH not PFL.
|
||||
}
|
||||
// if (Object.keys(job.cieca_pfl).length > 0) {
|
||||
// //Ignore it now, we have calculated it above.
|
||||
// //This was previously used for JCS before parts were also calculated at a different rate.
|
||||
// } else {
|
||||
// //We don't have it, just add in how it was before.
|
||||
// laborTaxTotal = otherTotals.rates.subtotal.percentage((job.tax_lbr_rt || 0) * 100); // THis is currently using the lbr tax rate from PFH not PFL.
|
||||
// }
|
||||
|
||||
//console.log("Labor Tax Total", laborTaxTotal.toFormat());
|
||||
|
||||
@@ -1010,9 +1060,9 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
federal_tax: subtotal
|
||||
.percentage((job.federal_tax_rate || 0) * 100)
|
||||
.add(otherTotals.additional.pvrt.percentage((job.federal_tax_rate || 0) * 100)),
|
||||
statePartsTax,
|
||||
stateTax,
|
||||
us_sales_tax_breakdown,
|
||||
state_tax: statePartsTax,
|
||||
state_tax: stateTax,
|
||||
local_tax: subtotal.percentage((job.local_tax_rate || 0) * 100)
|
||||
};
|
||||
ret.total_repairs = ret.subtotal
|
||||
|
||||
Reference in New Issue
Block a user