const GraphQLClient = require("graphql-request").GraphQLClient; const path = require("path"); const DineroQbFormat = require("../accounting-constants").DineroQbFormat; const queries = require("../../graphql-client/queries"); const Dinero = require("dinero.js"); var builder = require("xmlbuilder2"); const QbXmlUtils = require("./qbxml-utils"); const moment = require("moment"); require("dotenv").config({ path: path.resolve( process.cwd(), `.env.${process.env.NODE_ENV || "development"}` ), }); exports.default = async (req, res) => { const BearerToken = req.headers.authorization; const { bills: billsToQuery } = req.body; const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, { headers: { Authorization: BearerToken, }, }); try { const result = await client .setHeaders({ Authorization: BearerToken }) .request(queries.QUERY_BILLS_FOR_PAYABLES_EXPORT, { bills: billsToQuery, }); const { bills } = result; const QbXmlToExecute = []; bills.map((i) => { QbXmlToExecute.push({ id: i.id, okStatusCodes: ["0"], qbxml: generateBill(i), }); }); //For each invoice. res.status(200).json(QbXmlToExecute); } catch (error) { console.log("error", error); res.status(400).send(JSON.stringify(error)); } }; const generateBill = (bill) => { const billQbxmlObj = { QBXML: { QBXMLMsgsRq: { "@onError": "continueOnError", [`${bill.is_credit_memo ? "VendorCreditAddRq" : "BillAddRq"}`]: { [`${bill.is_credit_memo ? "VendorCreditAdd" : "BillAdd"}`]: { VendorRef: { FullName: bill.vendor.name, }, TxnDate: moment(bill.date).format("YYYY-MM-DD"), DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"), RefNumber: bill.invoice_number, Memo: `RO ${bill.job.ro_number || ""} OWNER ${ bill.job.ownr_fn || "" } ${bill.job.ownr_ln || ""} ${bill.job.ownr_co_nm || ""}`, ExpenseLineAdd: bill.billlines.map((il) => generateBillLine( il, bill.job.bodyshop.md_responsibility_centers, bill.job.class ) ), }, }, }, }, }; var billQbxml_partial = builder .create(billQbxmlObj, { version: "1.30", encoding: "UTF-8", headless: true, }) .end({ pretty: true }); const billQbxml_Full = QbXmlUtils.addQbxmlHeader(billQbxml_partial); console.log("generateBill -> billQbxml_Full", billQbxml_Full); return billQbxml_Full; }; const generateBillLine = (billLine, responsibilityCenters, jobClass) => { return { AccountRef: { FullName: responsibilityCenters.costs.find( (c) => c.name === billLine.cost_center ).accountname, }, Amount: Dinero({ amount: Math.round(billLine.actual_cost * 100), }) .multiply(billLine.quantity || 1) .toFormat(DineroQbFormat), ...(jobClass ? { ClassRef: { FullName: jobClass } } : {}), SalesTaxCodeRef: { FullName: findTaxCode(billLine, responsibilityCenters.sales_tax_codes), }, }; }; // [ // { // AccountRef: { FullName: "BODY SHOP COST:SUBLET" }, // Amount: invoice.amount, // }, // ], const findTaxCode = (billLine, taxcode) => { const { applicable_taxes: { local, state, federal }, } = billLine; const t = taxcode.filter( (t) => !!t.local === !!local && !!t.state === !!state && !!t.federal === !!federal ); if (t.length === 1) { console.log(t); return t[0].code; } else if (t.length > 1) { return "Multiple Tax Codes Match"; } else { return "No Tax Code Matches"; } };