const path = require("path"); require("dotenv").config({ path: path.resolve( process.cwd(), `.env.${process.env.NODE_ENV || "development"}` ), }); const GraphQLClient = require("graphql-request").GraphQLClient; const queries = require("../graphql-client/queries"); const CdkBase = require("../web-sockets/web-socket"); const Dinero = require("dinero.js"); const _ = require("lodash"); exports.default = async function (socket, jobid) { try { CdkBase.createLogEvent( socket, "DEBUG", `Received request to calculate allocations for ${jobid}` ); const job = await QueryJobData(socket, jobid); const { bodyshop } = job; const taxAllocations = { local: { center: bodyshop.md_responsibility_centers.taxes.local.name, sale: Dinero(job.job_totals.totals.local_tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.local, costCenter: bodyshop.md_responsibility_centers.taxes.local, }, state: { center: bodyshop.md_responsibility_centers.taxes.state.name, sale: Dinero(job.job_totals.totals.state_tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.state, costCenter: bodyshop.md_responsibility_centers.taxes.state, }, federal: { center: bodyshop.md_responsibility_centers.taxes.federal.name, sale: Dinero(job.job_totals.totals.federal_tax), cost: Dinero(), profitCenter: bodyshop.md_responsibility_centers.taxes.federal, costCenter: bodyshop.md_responsibility_centers.taxes.federal, }, }; const profitCenterHash = job.joblines.reduce((acc, val) => { //Check the Parts Assignment if (val.profitcenter_part) { if (!acc[val.profitcenter_part]) acc[val.profitcenter_part] = Dinero(); acc[val.profitcenter_part] = acc[val.profitcenter_part].add( Dinero({ amount: Math.round((val.act_price || 0) * 100), }).multiply(val.part_qty || 0) ); } if (val.profitcenter_labor) { //Check the Labor Assignment. if (!acc[val.profitcenter_labor]) acc[val.profitcenter_labor] = Dinero(); acc[val.profitcenter_labor] = acc[val.profitcenter_labor].add( Dinero({ amount: Math.round( job[`rate_${val.mod_lbr_ty.toLowerCase()}`] * 100 ), }).multiply(val.mod_lb_hrs) ); } return acc; }, {}); const costCenterHash = job.bills.reduce((bill_acc, bill_val) => { bill_val.billlines.map((line_val) => { if (!bill_acc[line_val.cost_center]) bill_acc[line_val.cost_center] = Dinero(); const lineDinero = Dinero({ amount: Math.round((line_val.actual_cost || 0) * 100), }) .multiply(line_val.quantity) .multiply(bill_val.is_credit_memo ? -1 : 1); bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add(lineDinero); //Add appropriate tax amounts. const { applicable_taxes: { local, state, federal }, } = line_val; if (local) { taxAllocations.local.cost = taxAllocations.local.cost.add( lineDinero.percentage(bill_val.local_tax_rate || 0) ); } if (state) { taxAllocations.state.cost = taxAllocations.state.cost.add( lineDinero.percentage(bill_val.state_tax_rate || 0) ); } if (federal) { taxAllocations.federal.cost = taxAllocations.federal.cost.add( lineDinero.percentage(bill_val.federal_tax_rate || 0) ); } return null; }); return bill_acc; }, {}); const jobAllocations = _.union( Object.keys(profitCenterHash), Object.keys(costCenterHash) ).map((key) => { const profitCenter = bodyshop.md_responsibility_centers.profits.find( (c) => c.name === key ); const costCenter = bodyshop.md_responsibility_centers.costs.find( (c) => c.name === key ); return { center: key, sale: profitCenterHash[key] ? profitCenterHash[key] : Dinero(), cost: costCenterHash[key] ? costCenterHash[key] : Dinero(), profitCenter, costCenter, }; }); return [ ...jobAllocations, ...Object.keys(taxAllocations) .filter( (key) => taxAllocations[key].sale.getAmount() > 0 || taxAllocations[key].cost.getAmount() > 0 ) .map((key) => taxAllocations[key]), ]; } catch (error) { CdkBase.createLogEvent( socket, "ERROR", `Error encountered in CdkCalculateAllocations. ${error}` ); } }; async function QueryJobData(socket, jobid) { CdkBase.createLogEvent(socket, "DEBUG", `Querying job data for id ${jobid}`); const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {}); const result = await client .setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` }) .request(queries.GET_CDK_ALLOCATIONS, { id: jobid }); CdkBase.createLogEvent( socket, "TRACE", `Job data query result ${JSON.stringify(result, null, 2)}` ); return result.jobs_by_pk; }