WIP PBS AP.

This commit is contained in:
Patrick Fic
2022-10-31 15:59:00 -07:00
parent cd96de3a96
commit ede1cdb89b
16 changed files with 418 additions and 174 deletions

View File

@@ -11,8 +11,47 @@ const queries = require("../../graphql-client/queries");
const CdkBase = require("../../web-sockets/web-socket");
const moment = require("moment");
const Dinero = require("dinero.js");
const AxiosLib = require("axios").default;
const axios = AxiosLib.create();
const { PBS_ENDPOINTS, PBS_CREDENTIALS } = require("./pbs-constants");
const { CheckForErrors } = require("./pbs-job-export");
const uuid = require("uuid").v4;
axios.interceptors.request.use((x) => {
const socket = x.socket;
exports.default = async function (socket, billids) {
const headers = {
...x.headers.common,
...x.headers[x.method],
...x.headers,
};
const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${
x.url
} | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`;
console.log(printable);
CdkBase.createJsonEvent(socket, "TRACE", `Raw Request: ${printable}`, x.data);
return x;
});
axios.interceptors.response.use((x) => {
const socket = x.config.socket;
const printable = `${new Date()} | Response: ${x.status} | ${JSON.stringify(
x.data
)}`;
console.log(printable);
CdkBase.createJsonEvent(
socket,
"TRACE",
`Raw Response: ${printable}`,
x.data
);
return x;
});
async function PbsCalculateAllocationsAp(socket, billids) {
try {
CdkBase.createLogEvent(
socket,
@@ -21,28 +60,48 @@ exports.default = async function (socket, billids) {
);
const { bills, bodyshops } = await QueryBillData(socket, billids);
const bodyshop = bodyshops[0];
const transactionLines = [];
socket.bodyshop = bodyshop;
socket.bills = bills;
//Each bill will enter it's own top level transaction.
const transactionlist = [];
bills.forEach((bill) => {
//Keep the allocations at the bill level.
const transactionObject = {
SerialNumber: socket.bodyshop.pbs_serialnumber,
billid: bill.id,
Posting: {
Reference: bill.job.ro_number,
JournalCode: socket.txEnvelope ? socket.txEnvelope.journal : null,
TransactionDate: moment().tz(socket.bodyshop.timezone).toISOString(), //"0001-01-01T00:00:00.0000000Z",
//Description: "Bulk AP posting.",
//AdditionalInfo: "String",
Source: "ImEX Online",
Lines: [], //socket.apAllocations,
},
};
const billHash = {
[bodyshop.md_responsibility_centers.taxes.federal_itc.name]: {
Account:
bodyshop.md_responsibility_centers.taxes.federal_itc.dms_acctnumber,
//ControlNumber: "String", //need to figure this out still?
ControlNumber: bill.vendor.dmsid,
Amount: Dinero(),
// Comment: "String",
//AdditionalInfo: "String",
AdditionalInfo: bill.vendor.name,
InvoiceNumber: bill.invoice_number,
InvoiceDate: moment(bill.date).tz(bodyshop.timezone).toISOString(),
},
[bodyshop.md_responsibility_centers.taxes.state.name]: {
Account:
bodyshop.md_responsibility_centers.taxes.state.dms_acctnumber,
//ControlNumber: "String", //need to figure this out still?
ControlNumber: bill.vendor.dmsid,
Amount: Dinero(),
// Comment: "String",
//AdditionalInfo: "String",
AdditionalInfo: bill.vendor.name,
InvoiceNumber: bill.invoice_number,
InvoiceDate: moment(bill.date).tz(bodyshop.timezone).toISOString(),
},
@@ -59,17 +118,16 @@ exports.default = async function (socket, billids) {
if (!billHash[cc.name]) {
billHash[cc.name] = {
Account: cc.dms_acctnumber,
//ControlNumber: "String", //need to figure this out still?
ControlNumber: bill.vendor.dmsid,
Amount: Dinero(),
// Comment: "String",
//AdditionalInfo: "String",
AdditionalInfo: bill.vendor.name,
InvoiceNumber: bill.invoice_number,
InvoiceDate: moment(bill.date).tz(bodyshop.timezone).toISOString(),
};
}
//Add the line amount.
billHash[cc.name] = {
...billHash[cc.name],
Amount: billHash[cc.name].Amount.add(lineDinero),
@@ -79,36 +137,57 @@ exports.default = async function (socket, billids) {
if (bl.applicable_taxes.federal) {
billHash[bodyshop.md_responsibility_centers.taxes.federal_itc.name] =
{
...bodyshop.md_responsibility_centers.taxes.federal_itc.name,
...billHash[
bodyshop.md_responsibility_centers.taxes.federal_itc.name
],
Amount: billHash[
bodyshop.md_responsibility_centers.taxes.federal_itc.name
].Amount.add(lineDinero.percentage(bl.federal_tax_rate || 0)),
].Amount.add(lineDinero.percentage(bill.federal_tax_rate || 0)),
};
}
if (bl.applicable_taxes.state) {
billHash[bodyshop.md_responsibility_centers.taxes.state.name] = {
...bodyshop.md_responsibility_centers.taxes.state.name,
...billHash[bodyshop.md_responsibility_centers.taxes.state.name],
Amount: billHash[
bodyshop.md_responsibility_centers.taxes.state.name
].Amount.add(lineDinero.percentage(bl.state_tax_rate || 0)),
].Amount.add(lineDinero.percentage(bill.state_tax_rate || 0)),
};
}
//End tax check
});
let APAmount = Dinero();
Object.keys(billHash).map((key) => {
if (billHash[key].Amount.getAmount() > 0) {
transactionObject.Posting.Lines.push(billHash[key]);
APAmount = APAmount.add(billHash[key].Amount); //Calculate the total expense for the bill iteratively to create the corresponding credit to AP.
}
});
Object.keys(billHash).map((key) => {
transactionLines.push(billHash[key]);
transactionObject.Posting.Lines.push({
Account: bodyshop.md_responsibility_centers.ap.dms_acctnumber,
ControlNumber: bill.vendor.dmsid,
Amount: APAmount.multiply(-1),
// Comment: "String",
AdditionalInfo: bill.vendor.name,
InvoiceNumber: bill.invoice_number,
InvoiceDate: moment(bill.date).tz(bodyshop.timezone).toISOString(),
});
transactionlist.push(transactionObject);
});
return transactionLines;
return transactionlist;
} catch (error) {
CdkBase.createLogEvent(
socket,
"ERROR",
`Error encountered in CdkCalculateAllocations. ${error}`
`Error encountered in PbsCalculateAllocationsAp. ${error}`
);
}
};
}
exports.PbsCalculateAllocationsAp = PbsCalculateAllocationsAp;
async function QueryBillData(socket, billids) {
CdkBase.createLogEvent(
@@ -125,6 +204,7 @@ async function QueryBillData(socket, billids) {
"TRACE",
`Bill data query result ${JSON.stringify(result, null, 2)}`
);
return result;
}
@@ -136,3 +216,56 @@ function getCostAccount(billline, respcenters) {
return respcenters.costs.find((c) => c.name === acctName);
}
exports.PbsExportAp = async function (socket, { billids, txEnvelope }) {
CdkBase.createLogEvent(socket, "DEBUG", `Exporting selected AP.`);
//apAllocations has the same shap as the lines key for the accounting posting to PBS.
socket.apAllocations = await PbsCalculateAllocationsAp(socket, billids);
socket.txEnvelope = txEnvelope;
for (const allocation of socket.apAllocations) {
const { billid, ...restAllocation } = allocation;
const { data: AccountPostingChange } = await axios.post(
PBS_ENDPOINTS.AccountingPostingChange,
restAllocation,
{ auth: PBS_CREDENTIALS, socket }
);
CheckForErrors(socket, AccountPostingChange);
if (AccountPostingChange.WasSuccessful) {
CdkBase.createLogEvent(socket, "DEBUG", `Marking bill as exported.`);
await MarkApExported(socket, [billid]);
// socket.emit("export-success", billids);
} else {
CdkBase.createLogEvent(socket, "ERROR", `Export was not succesful.`);
}
}
};
async function MarkApExported(socket, billids) {
CdkBase.createLogEvent(
socket,
"DEBUG",
`Marking bills as exported for id ${billids}`
);
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
const result = await client
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
.request(queries.MARK_BILLS_EXPORTED, {
billids,
bill: {
exported: true,
exported_at: new Date(),
},
logs: socket.bills.map((bill) => ({
bodyshopid: socket.bodyshop.id,
billid: bill.id,
successful: true,
useremail: socket.user.email,
})),
});
return result;
}

View File

@@ -182,6 +182,8 @@ async function CheckForErrors(socket, response) {
}
}
exports.CheckForErrors = CheckForErrors;
async function QueryJobData(socket, jobid) {
CdkBase.createLogEvent(socket, "DEBUG", `Querying job data for id ${jobid}`);
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});

View File

@@ -1506,6 +1506,23 @@ mutation MARK_JOB_EXPORTED($jobId: uuid!, $job: jobs_set_input!, $log: exportlog
}
`;
exports.MARK_BILLS_EXPORTED = `
mutation UPDATE_BILLS($billids: [uuid!]!, $bill: bills_set_input!, $logs: [exportlog_insert_input!]!) {
update_bills(where: {id: {_in: $billids}}, _set: $bill) {
returning {
id
exported
exported_at
}
}
insert_exportlog(objects: $logs) {
returning{
id
}
}
}
`;
exports.INSERT_EXPORT_LOG = `
mutation INSERT_EXPORT_LOG($log: exportlog_insert_input!) {
insert_exportlog_one(object: $log) {
@@ -1639,6 +1656,8 @@ query GET_PBS_AP_ALLOCATIONS($billids: [uuid!]) {
bodyshops(where: {associations: {active: {_eq: true}}}) {
md_responsibility_centers
timezone
pbs_serialnumber
id
}
bills(where: {id: {_in: $billids}}) {
id
@@ -1659,6 +1678,7 @@ query GET_PBS_AP_ALLOCATIONS($billids: [uuid!]) {
vendor {
id
name
dmsid
}
billlines {
id

View File

@@ -22,8 +22,10 @@ const {
PbsSelectedCustomer,
} = require("../accounting/pbs/pbs-job-export");
const PbsCalculateAllocationsAp =
require("../accounting/pbs/pbs-ap-allocations").default;
const {
PbsCalculateAllocationsAp,
PbsExportAp,
} = require("../accounting/pbs/pbs-ap-allocations");
io.use(function (socket, next) {
try {
@@ -139,9 +141,15 @@ io.on("connection", (socket) => {
"TRACE",
`Allocations calculated. ${JSON.stringify(allocations, null, 2)}`
);
socket.apAllocations = allocations;
callback(allocations);
});
socket.on("pbs-export-ap", ({ billids, txEnvelope }) => {
socket.txEnvelope = txEnvelope;
PbsExportAp(socket, { billids, txEnvelope });
});
//END PBS AP
socket.on("disconnect", () => {