diff --git a/server/accounting/qb-receivables-lines.js b/server/accounting/qb-receivables-lines.js index e2437dca1..0ef97135a 100644 --- a/server/accounting/qb-receivables-lines.js +++ b/server/accounting/qb-receivables-lines.js @@ -664,7 +664,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes }); } } else { - //Handle insurance profile adjustments + //Handle insurance profile adjustments for Parts Object.keys(job_totals.parts.adjustments).forEach((key) => { if (qbo) { //Going to always assume that we need to apply GST and PST for labor. @@ -718,6 +718,67 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes } }); + //Handle insurance profile adjustments for Labor and Materials + Object.keys(job_totals.rate).forEach((key) => { + if ( + job_totals.rate[key] && + job_totals.rate[key].adjustment && + job_totals.rate[key].adjustment.isZero() === false + ) { + if (qbo) { + //Going to always assume that we need to apply GST and PST for labor. + const taxAccountCode = findTaxCode( + { + local: false, + federal: process.env.COUNTRY === "USA" ? false : true, + state: jobs_by_pk.state_tax_rate === 0 ? false : true + }, + bodyshop.md_responsibility_centers.sales_tax_codes + ); + const account = responsibilityCenters.profits.find( + (c) => c.name === responsibilityCenters.defaults.profits[key.toUpperCase()] + ); + const QboTaxId = + process.env.COUNTRY === "USA" + ? CheckQBOUSATaxID({ + // jobline: jobline, + job: jobs_by_pk, + type: "storage" + }) + : taxCodes[taxAccountCode]; + InvoiceLineAdd.push({ + DetailType: "SalesItemLineDetail", + Amount: Dinero(job_totals.rate[key]).adjustment.toFormat(DineroQbFormat), + Description: `${account.accountdesc} - Adjustment`, + SalesItemLineDetail: { + ...(jobs_by_pk.class ? { ClassRef: { value: classes[jobs_by_pk.class] } } : {}), + ItemRef: { + value: items[account.accountitem] + }, + TaxCodeRef: { + value: QboTaxId + }, + Qty: 1 + } + }); + } else { + InvoiceLineAdd.push({ + ItemRef: { + FullName: responsibilityCenters.profits.find( + (c) => c.name === responsibilityCenters.defaults.profits[key.toUpperCase()] + ).accountitem + }, + Desc: "Storage", + Quantity: 1, + Amount: Dinero(job_totals.rate[key]).adjustment.toFormat(DineroQbFormat), + SalesTaxCodeRef: { + FullName: bodyshop.md_responsibility_centers.taxes.itemexemptcode || "NON" + } + }); + } + } + }); + const QboTaxId = process.env.COUNTRY === "USA" ? CheckQBOUSATaxID({ diff --git a/server/cdk/cdk-calculate-allocations.js b/server/cdk/cdk-calculate-allocations.js index c47addbfe..8e92c76a9 100644 --- a/server/cdk/cdk-calculate-allocations.js +++ b/server/cdk/cdk-calculate-allocations.js @@ -360,12 +360,10 @@ function calculateAllocations(connectionData, job) { } } if (InstanceManager({ rome: true })) { - //profile level adjustments + //profile level adjustments for parts Object.keys(job.job_totals.parts.adjustments).forEach((key) => { const accountName = selectedDmsAllocationConfig.profits[key]; - const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName); - if (otherAccount) { if (!profitCenterHash[accountName]) profitCenterHash[accountName] = Dinero(); @@ -380,6 +378,24 @@ function calculateAllocations(connectionData, job) { ); } }); + //profile level adjustments for labor and materials + Object.keys(job.job_totals.rates).forEach((key) => { + if (job.job_totals.rate[key] && job.job_totals.rate[key].adjustment && job.job_totals.rate[key].adjustment.isZero() === false) { + const accountName = selectedDmsAllocationConfig.profits[key.toUpperCase()]; + const otherAccount = bodyshop.md_responsibility_centers.profits.find((c) => c.name === accountName); + if (otherAccount) { + if (!profitCenterHash[accountName]) profitCenterHash[accountName] = Dinero(); + + profitCenterHash[accountName] = profitCenterHash[accountName].add(Dinero(job.job_totals.rates[key].adjustments)); + } else { + CdkBase.createLogEvent( + connectionData, + "ERROR", + `Error encountered in CdkCalculateAllocations. Unable to find adjustment account. ${error}` + ); + } + } + }); } const jobAllocations = _.union(Object.keys(profitCenterHash), Object.keys(costCenterHash)).map((key) => { diff --git a/server/job/job-costing.js b/server/job/job-costing.js index ecdc9dde3..9ce65f71d 100644 --- a/server/job/job-costing.js +++ b/server/job/job-costing.js @@ -375,7 +375,7 @@ function GenerateCostingData(job) { : Dinero() ); - // Profile Discount for Parts + // 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 && @@ -476,6 +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( @@ -483,10 +484,26 @@ function GenerateCostingData(job) { amount: Math.round((job.rate_mapa || 0) * 100) }).multiply(materialsHours.mapaHrs || 0) ); + let adjp = 0; + if (job.materials["MAPA"] && job.materials["MAPA"].mat_adjp) { + adjp = + Math.abs(job.materials["MAPA"].mat_adjp) > 1 + ? job.materials["MAPA"].mat_adjp + : job.materials["MAPA"].mat_adjp * 100; //Adjust mat_adjp to whole number + } + + jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] = jobLineTotalsByProfitCenter.additional[ + defaultProfits["MAPA"] + ].add( + jobLineTotalsByProfitCenter.additional[defaultProfits["MAPA"]] + .percentage(adjp < 0 ? adjp * -1 : adjp) + .multiply(adjp < 0 ? -1 : 1) + ); } if (!hasMashLine) { if (!jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]]) jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]] = Dinero(); + jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]] = jobLineTotalsByProfitCenter.additional[ defaultProfits["MASH"] ].add( @@ -494,6 +511,21 @@ function GenerateCostingData(job) { amount: Math.round((job.rate_mash || 0) * 100) }).multiply(materialsHours.mashHrs || 0) ); + let adjp = 0; + if (job.materials["MASH"] && job.materials["MASH"].mat_adjp) { + adjp = + Math.abs(job.materials["MASH"].mat_adjp) > 1 + ? job.materials["MASH"].mat_adjp + : job.materials["MASH"].mat_adjp * 100; //Adjust mat_adjp to whole number + } + + jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]] = jobLineTotalsByProfitCenter.additional[ + defaultProfits["MASH"] + ].add( + jobLineTotalsByProfitCenter.additional[defaultProfits["MASH"]] + .percentage(adjp < 0 ? adjp * -1 : adjp) + .multiply(adjp < 0 ? -1 : 1) + ); } //Is it a DMS Setup?