const DineroQbFormat = require("../accounting-constants").DineroQbFormat; const queries = require("../../graphql-client/queries"); const Dinero = require("dinero.js"); const builder = require("xmlbuilder2"); const moment = require("moment-timezone"); const QbXmlUtils = require("./qbxml-utils"); const QbxmlReceivables = require("./qbxml-receivables"); const logger = require("../../utils/logger"); const { generateJobTier, generateOwnerTier, generateSourceTier } = QbXmlUtils; exports.default = async (req, res) => { const { payments: paymentsToQuery } = req.body; const BearerToken = req.BearerToken; const client = req.userGraphQLClient; try { logger.log("qbxml-payments-create", "DEBUG", req?.user?.email, null, { paymentsToQuery: req.body?.paymentsToQuery }); const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.QUERY_PAYMENTS_FOR_EXPORT, { payments: paymentsToQuery }); const { payments, bodyshops } = result; const bodyshop = bodyshops[0]; const isThreeTier = bodyshop.accountingconfig.tiers === 3; const twoTierPref = bodyshop.accountingconfig.twotierpref; const QbXmlToExecute = []; payments.map((i) => { if (isThreeTier) { QbXmlToExecute.push({ id: i.id, okStatusCodes: ["0", "3100"], qbxml: QbxmlReceivables.generateSourceCustomerQbxml(i.job, bodyshop) // Create the source customer. }); } QbXmlToExecute.push({ id: i.id, okStatusCodes: ["0", "3100"], qbxml: QbxmlReceivables.generateJobQbxml(i.job, bodyshop, isThreeTier, 2, twoTierPref) }); QbXmlToExecute.push({ id: i.id, okStatusCodes: ["0", "3100"], qbxml: QbxmlReceivables.generateJobQbxml(i.job, bodyshop, isThreeTier, 3, twoTierPref) }); QbXmlToExecute.push({ id: i.id, okStatusCodes: ["0"], qbxml: generatePayment(i, isThreeTier, twoTierPref, bodyshop) }); }); res.status(200).json(QbXmlToExecute); } catch (error) { logger.log("qbxml-payments-error", "error", req?.user?.email, null, { paymentsToQuery: req.body?.paymentsToQuery, error: error.message, stack: error.stack }); res.status(400).send(JSON.stringify(error)); } }; const generatePayment = (payment, isThreeTier, twoTierPref, bodyshop) => { let paymentQbxmlObj; if (payment.amount > 0) { paymentQbxmlObj = { QBXML: { QBXMLMsgsRq: { "@onError": "continueOnError", ReceivePaymentAddRq: { ReceivePaymentAdd: { CustomerRef: { FullName: (payment.job.bodyshop.accountingconfig.tiers === 3 ? `${generateSourceTier(payment.job)}:${generateOwnerTier( payment.job, isThreeTier, twoTierPref )}:${generateJobTier(payment.job)}` : `${generateOwnerTier(payment.job, isThreeTier, twoTierPref)}:${generateJobTier(payment.job)}` ).trim() }, ARAccountRef: { FullName: payment.job.bodyshop.md_responsibility_centers.ar.accountname }, TxnDate: moment(payment.date) // .tz(bodyshop.timezone) .format("YYYY-MM-DD"), //Trim String RefNumber: payment.paymentnum || payment.transactionid, TotalAmount: Dinero({ amount: Math.round(payment.amount * 100) }).toFormat(DineroQbFormat), PaymentMethodRef: { FullName: payment.type }, Memo: `RO ${payment.job.ro_number || ""} OWNER ${ payment.job.ownr_fn || "" } ${payment.job.ownr_ln || ""} ${payment.job.ownr_co_nm || ""} ${ payment.stripeid || "" } ${payment.payer ? ` PAID BY ${payment.payer}` : ""}`, IsAutoApply: true } } } } }; } else { paymentQbxmlObj = { QBXML: { QBXMLMsgsRq: { "@onError": "continueOnError", CreditMemoAddRq: { CreditMemoAdd: { CustomerRef: { FullName: (payment.job.bodyshop.accountingconfig.tiers === 3 ? `${generateSourceTier(payment.job)}:${generateOwnerTier( payment.job, isThreeTier, twoTierPref )}:${generateJobTier(payment.job)}` : `${generateOwnerTier(payment.job, isThreeTier, twoTierPref)}:${generateJobTier(payment.job)}` ).trim() }, ARAccountRef: { FullName: payment.job.bodyshop.md_responsibility_centers.ar.accountname }, TxnDate: moment(payment.date) //.tz(bodyshop.timezone) .format("YYYY-MM-DD"), //Trim String RefNumber: payment.paymentnum || payment.stripeid || payment.transactionid, CreditMemoLineAdd: [ { ItemRef: { FullName: payment.job.bodyshop.md_responsibility_centers.refund.accountitem }, Desc: payment.memo, Amount: Dinero({ amount: Math.round(payment.amount * 100 * -1) }).toFormat(DineroQbFormat), SalesTaxCodeRef: { FullName: "E" } } ] } } } } }; } var paymentQbxmlPartial = builder .create(paymentQbxmlObj, { version: "1.30", encoding: "UTF-8", headless: true }) .end({ pretty: true }); const paymentQbxmlFull = QbXmlUtils.addQbxmlHeader(paymentQbxmlPartial); return paymentQbxmlFull; };