168 lines
5.2 KiB
JavaScript
168 lines
5.2 KiB
JavaScript
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;
|
|
}
|