@@ -10,6 +10,7 @@ import { createStructuredSelector } from "reselect";
|
||||
import { INSERT_NEW_JOB } from "../../graphql/jobs.queries";
|
||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -156,104 +157,127 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract, disabled
|
||||
joblines: {
|
||||
data: billingLines
|
||||
},
|
||||
parts_tax_rates: {
|
||||
PAA: {
|
||||
prt_type: "PAA",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
...InstanceRenderManager({
|
||||
imex: {
|
||||
parts_tax_rates: {
|
||||
PAA: {
|
||||
prt_type: "PAA",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAC: {
|
||||
prt_type: "PAC",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAL: {
|
||||
prt_type: "PAL",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAM: {
|
||||
prt_type: "PAM",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAN: {
|
||||
prt_type: "PAN",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAR: {
|
||||
prt_type: "PAR",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAS: {
|
||||
prt_type: "PAS",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCDR: {
|
||||
prt_type: "CCDR",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCF: {
|
||||
prt_type: "CCF",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCM: {
|
||||
prt_type: "CCM",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCC: {
|
||||
prt_type: "CCC",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCD: {
|
||||
prt_type: "CCD",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
}
|
||||
}
|
||||
},
|
||||
PAC: {
|
||||
prt_type: "PAC",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAL: {
|
||||
prt_type: "PAL",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAM: {
|
||||
prt_type: "PAM",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAN: {
|
||||
prt_type: "PAN",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAR: {
|
||||
prt_type: "PAR",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
PAS: {
|
||||
prt_type: "PAS",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCDR: {
|
||||
prt_type: "CCDR",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCF: {
|
||||
prt_type: "CCF",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCM: {
|
||||
prt_type: "CCM",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCC: {
|
||||
prt_type: "CCC",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
},
|
||||
CCD: {
|
||||
prt_type: "CCD",
|
||||
prt_discp: 0,
|
||||
prt_mktyp: false,
|
||||
prt_mkupp: 0,
|
||||
prt_tax_in: true,
|
||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100
|
||||
rome: {
|
||||
cieca_pft: {
|
||||
...bodyshop.md_responsibility_centers.taxes.tax_ty1,
|
||||
...bodyshop.md_responsibility_centers.taxes.tax_ty2,
|
||||
...bodyshop.md_responsibility_centers.taxes.tax_ty3,
|
||||
...bodyshop.md_responsibility_centers.taxes.tax_ty4,
|
||||
...bodyshop.md_responsibility_centers.taxes.tax_ty5
|
||||
},
|
||||
materials: bodyshop.md_responsibility_centers.cieca_pfm,
|
||||
cieca_pfl: bodyshop.md_responsibility_centers.cieca_pfl,
|
||||
parts_tax_rates: bodyshop.md_responsibility_centers.parts_tax_rates,
|
||||
tax_tow_rt: bodyshop.md_responsibility_centers.tax_tow_rt,
|
||||
tax_str_rt: bodyshop.md_responsibility_centers.tax_str_rt,
|
||||
tax_paint_mat_rt: bodyshop.md_responsibility_centers.tax_paint_mat_rt,
|
||||
tax_shop_mat_rt: bodyshop.md_responsibility_centers.tax_shop_mat_rt,
|
||||
tax_sub_rt: bodyshop.md_responsibility_centers.tax_sub_rt,
|
||||
tax_lbr_rt: bodyshop.md_responsibility_centers.tax_lbr_rt,
|
||||
tax_levies_rt: bodyshop.md_responsibility_centers.tax_levies_rt
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
if (currentUser?.email) {
|
||||
@@ -287,7 +311,7 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract, disabled
|
||||
notification.success({
|
||||
title: t("jobs.successes.created"),
|
||||
onClick: () => {
|
||||
history.push(`/manage/jobs/${result.data.insert_jobs.returning[0].id}`);
|
||||
history(`/manage/jobs/${result.data.insert_jobs.returning[0].id}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -116,6 +116,32 @@ async function TotalsServerSide(req, res) {
|
||||
ret.totals.ttl_tax_adjustment = Dinero({ amount: Math.round(ttlTaxDifference * 100) });
|
||||
ret.totals.total_repairs = ret.totals.total_repairs.add(ret.totals.ttl_tax_adjustment);
|
||||
ret.totals.net_repairs = ret.totals.net_repairs.add(ret.totals.ttl_tax_adjustment);
|
||||
|
||||
if (Math.abs(totalUsTaxes) === 0) {
|
||||
const laborRates = Object.values(job.cieca_pfl)
|
||||
.map((v) => v.lbr_taxp)
|
||||
.filter((v) => v != null);
|
||||
const materialRates = Object.values(job.materials)
|
||||
.map((v) => v.mat_taxp)
|
||||
.filter((v) => v != null);
|
||||
const partsRates = Object.values(job.parts_tax_rates)
|
||||
.map((v) => {
|
||||
const field = v.prt_tax_rt ?? v.part_tax_rt;
|
||||
if (field == null) return null;
|
||||
const raw = typeof field === "object" ? field.parsedValue : field;
|
||||
return raw != null ? raw * 100 : null;
|
||||
})
|
||||
.filter((v) => v != null);
|
||||
const taxRate = Math.max(...laborRates, ...materialRates, ...partsRates);
|
||||
|
||||
const totalTaxes = ret.totals.taxableAmounts.total.multiply(taxRate > 1 ? taxRate / 100 : taxRate);
|
||||
ret.totals.taxableAmounts.total = ret.totals.taxableAmounts.total
|
||||
.multiply(emsTaxTotal)
|
||||
.divide(totalTaxes.toUnit());
|
||||
} else {
|
||||
ret.totals.taxableAmounts.total = ret.totals.taxableAmounts.total.multiply(emsTaxTotal).divide(totalUsTaxes);
|
||||
}
|
||||
|
||||
logger.log("job-totals-USA-ttl-tax-adj", "debug", null, job.id, {
|
||||
adjAmount: ttlTaxDifference
|
||||
});
|
||||
@@ -885,6 +911,8 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
STOR: Dinero()
|
||||
};
|
||||
|
||||
const pfp = job.parts_tax_rates;
|
||||
|
||||
//For each line, determine if it's taxable, and if it is, add the line amount to the taxable amounts total.
|
||||
job.joblines
|
||||
.filter((jl) => !jl.removed)
|
||||
@@ -916,7 +944,17 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
})
|
||||
.multiply(val.part_qty || 0)
|
||||
.add(discMarkupAmount);
|
||||
taxableAmounts[typeOfPart] = taxableAmounts[typeOfPart].add(partAmount);
|
||||
if (taxableAmounts[typeOfPart]) {
|
||||
taxableAmounts[typeOfPart] = taxableAmounts[typeOfPart].add(partAmount);
|
||||
} else {
|
||||
const isTaxableCustomType =
|
||||
IsTrueOrYes(pfp?.[typeOfPart]?.prt_tax_in) || pfp?.[typeOfPart]?.prt_tax_in === true;
|
||||
|
||||
if (isTaxableCustomType) {
|
||||
if (!taxableAmounts[typeOfPart]) taxableAmounts[typeOfPart] = Dinero();
|
||||
taxableAmounts[typeOfPart] = taxableAmounts[typeOfPart].add(partAmount);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -969,16 +1007,20 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
})
|
||||
);
|
||||
|
||||
const pfp = job.parts_tax_rates;
|
||||
|
||||
//For any profile level markups/discounts, add them in now as well.
|
||||
Object.keys(otherTotals.parts.adjustments).forEach((key) => {
|
||||
const adjustmentAmount = otherTotals.parts.adjustments[key];
|
||||
if (adjustmentAmount.getAmount() !== 0 && pfp[key]?.prt_tax_in) {
|
||||
taxableAmounts[key] = taxableAmounts[key].add(adjustmentAmount);
|
||||
if (taxableAmounts[key]) {
|
||||
taxableAmounts[key] = taxableAmounts[key].add(adjustmentAmount);
|
||||
} else {
|
||||
taxableAmounts[key] = Dinero().add(adjustmentAmount);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
taxableAmounts.total = Object.values(taxableAmounts).reduce((acc, amount) => acc.add(amount), Dinero({ amount: 0 }));
|
||||
|
||||
// console.log("*** Taxable Amounts***");
|
||||
// console.table(JSON.parse(JSON.stringify(taxableAmounts)));
|
||||
|
||||
@@ -1072,6 +1114,21 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (pfp[key]) {
|
||||
//Custom part types (e.g. CC*) should flow through taxableAmountsByTier too.
|
||||
let assignedToTier = false;
|
||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
||||
if (IsTrueOrYes(pfp[key][`prt_tx_in${tyCounter}`])) {
|
||||
taxableAmountsByTier[`ty${tyCounter}Tax`] = taxableAmountsByTier[`ty${tyCounter}Tax`].add(
|
||||
taxableAmounts[key]
|
||||
);
|
||||
assignedToTier = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!assignedToTier && (IsTrueOrYes(pfp[key].prt_tax_in) || pfp[key].prt_tax_in === true)) {
|
||||
taxableAmountsByTier.ty1Tax = taxableAmountsByTier.ty1Tax.add(taxableAmounts[key]);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.log("job-totals-USA Key with issue", "warn", null, job.id, {
|
||||
@@ -1174,6 +1231,7 @@ function CalculateTaxesTotals(job, otherTotals) {
|
||||
|
||||
let ret = {
|
||||
subtotal: subtotal,
|
||||
taxableAmounts: taxableAmounts,
|
||||
federal_tax: subtotal
|
||||
.percentage((job.federal_tax_rate || 0) * 100)
|
||||
.add(otherTotals.additional.pvrt.percentage((job.federal_tax_rate || 0) * 100)),
|
||||
|
||||
Reference in New Issue
Block a user