Merged in feature/IO-3335-QBO-Payment-Logging (pull request #2470)

IO-3335 QBO Payment Logging

Approved-by: Dave Richer
This commit is contained in:
Allan Carr
2025-08-14 14:25:15 +00:00
committed by Dave Richer

View File

@@ -10,7 +10,6 @@ const queries = require("../../graphql-client/queries");
const { refresh: refreshOauthToken, setNewRefreshToken } = require("./qbo-callback"); const { refresh: refreshOauthToken, setNewRefreshToken } = require("./qbo-callback");
const OAuthClient = require("intuit-oauth"); const OAuthClient = require("intuit-oauth");
const moment = require("moment-timezone"); const moment = require("moment-timezone");
const GraphQLClient = require("graphql-request").GraphQLClient;
const { const {
QueryInsuranceCo, QueryInsuranceCo,
InsertInsuranceCo, InsertInsuranceCo,
@@ -28,7 +27,7 @@ exports.default = async (req, res) => {
clientId: process.env.QBO_CLIENT_ID, clientId: process.env.QBO_CLIENT_ID,
clientSecret: process.env.QBO_SECRET, clientSecret: process.env.QBO_SECRET,
environment: process.env.NODE_ENV === "production" ? "production" : "sandbox", environment: process.env.NODE_ENV === "production" ? "production" : "sandbox",
redirectUri: process.env.QBO_REDIRECT_URI, redirectUri: process.env.QBO_REDIRECT_URI
}); });
try { try {
//Fetch the API Access Tokens & Set them for the session. //Fetch the API Access Tokens & Set them for the session.
@@ -131,22 +130,20 @@ exports.default = async (req, res) => {
// //No error. Mark the payment exported & insert export log. // //No error. Mark the payment exported & insert export log.
if (elgen) { if (elgen) {
const result = await client await client.setHeaders({ Authorization: BearerToken }).request(queries.QBO_MARK_PAYMENT_EXPORTED, {
.setHeaders({ Authorization: BearerToken }) paymentId: payment.id,
.request(queries.QBO_MARK_PAYMENT_EXPORTED, { payment: {
paymentId: payment.id, exportedat: moment().tz(bodyshop.timezone)
payment: { },
exportedat: moment().tz(bodyshop.timezone) logs: [
}, {
logs: [ bodyshopid: bodyshop.id,
{ paymentid: payment.id,
bodyshopid: bodyshop.id, successful: true,
paymentid: payment.id, useremail: req.user.email
successful: true, }
useremail: req.user.email ]
} });
]
});
} }
ret.push({ paymentid: payment.id, success: true }); ret.push({ paymentid: payment.id, success: true });
@@ -156,7 +153,7 @@ exports.default = async (req, res) => {
}); });
//Add the export log error. //Add the export log error.
if (elgen) { if (elgen) {
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.INSERT_EXPORT_LOG, { await client.setHeaders({ Authorization: BearerToken }).request(queries.INSERT_EXPORT_LOG, {
logs: [ logs: [
{ {
bodyshopid: bodyshop.id, bodyshopid: bodyshop.id,
@@ -190,7 +187,7 @@ exports.default = async (req, res) => {
} }
}; };
async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef, bodyshop) { async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef) {
const { paymentMethods, invoices } = await QueryMetaData( const { paymentMethods, invoices } = await QueryMetaData(
oauthClient, oauthClient,
qbo_realmId, qbo_realmId,
@@ -227,20 +224,20 @@ async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef,
PaymentRefNum: payment.transactionid, PaymentRefNum: payment.transactionid,
...(invoices && invoices.length === 1 && invoices[0] ...(invoices && invoices.length === 1 && invoices[0]
? { ? {
Line: [ Line: [
{ {
Amount: Dinero({ Amount: Dinero({
amount: Math.round(payment.amount * 100) amount: Math.round(payment.amount * 100)
}).toFormat(DineroQbFormat), }).toFormat(DineroQbFormat),
LinkedTxn: [ LinkedTxn: [
{ {
TxnId: invoices[0].Id, TxnId: invoices[0].Id,
TxnType: "Invoice" TxnType: "Invoice"
} }
] ]
} }
] ]
} }
: {}) : {})
}; };
logger.log("qbo-payments-objectlog", "DEBUG", req.user.email, payment.id, { logger.log("qbo-payments-objectlog", "DEBUG", req.user.email, payment.id, {
@@ -263,7 +260,7 @@ async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef,
status: result.response?.status, status: result.response?.status,
bodyshopid: payment.job.shopid, bodyshopid: payment.job.shopid,
email: req.user.email email: req.user.email
}) });
setNewRefreshToken(req.user.email, result); setNewRefreshToken(req.user.email, result);
return result && result.Bill; return result && result.Bill;
} catch (error) { } catch (error) {
@@ -291,7 +288,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
status: invoice.response?.status, status: invoice.response?.status,
bodyshopid, bodyshopid,
email: req.user.email email: req.user.email
}) });
const paymentMethods = await oauthClient.makeApiCall({ const paymentMethods = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From PaymentMethod`), url: urlBuilder(qbo_realmId, "query", `select * From PaymentMethod`),
method: "POST", method: "POST",
@@ -306,7 +303,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
status: paymentMethods.response?.status, status: paymentMethods.response?.status,
bodyshopid, bodyshopid,
email: req.user.email email: req.user.email
}) });
setNewRefreshToken(req.user.email, paymentMethods); setNewRefreshToken(req.user.email, paymentMethods);
// const classes = await oauthClient.makeApiCall({ // const classes = await oauthClient.makeApiCall({
@@ -358,7 +355,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
status: taxCodes.response?.status, status: taxCodes.response?.status,
bodyshopid, bodyshopid,
email: req.user.email email: req.user.email
}) });
const items = await oauthClient.makeApiCall({ const items = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From Item`), url: urlBuilder(qbo_realmId, "query", `select * From Item`),
method: "POST", method: "POST",
@@ -373,7 +370,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
status: items.response?.status, status: items.response?.status,
bodyshopid, bodyshopid,
email: req.user.email email: req.user.email
}) });
setNewRefreshToken(req.user.email, items); setNewRefreshToken(req.user.email, items);
const itemMapping = {}; const itemMapping = {};
@@ -412,8 +409,8 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
}; };
} }
async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRef, bodyshop) { async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRef) {
const { paymentMethods, invoices, items, taxCodes } = await QueryMetaData( const { invoices, items, taxCodes } = await QueryMetaData(
oauthClient, oauthClient,
qbo_realmId, qbo_realmId,
req, req,
@@ -449,14 +446,14 @@ async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRe
TaxCodeRef: { TaxCodeRef: {
value: value:
taxCodes[ taxCodes[
findTaxCode( findTaxCode(
{ {
local: false, local: false,
federal: false, federal: false,
state: false state: false
}, },
payment.job.bodyshop.md_responsibility_centers.sales_tax_codes payment.job.bodyshop.md_responsibility_centers.sales_tax_codes
) )
] ]
} }
} }
@@ -483,12 +480,14 @@ async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRe
status: result.response?.status, status: result.response?.status,
bodyshopid: req.user.bodyshopid, bodyshopid: req.user.bodyshopid,
email: req.user.email email: req.user.email
}) });
setNewRefreshToken(req.user.email, result); setNewRefreshToken(req.user.email, result);
return result && result.Bill; return result && result.Bill;
} catch (error) { } catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, payment.id, { logger.log("qbo-payables-error", "DEBUG", req.user.email, payment.id, {
error: error && error.message, error: error,
validationError: JSON.stringify(error?.response?.data),
accountmeta: JSON.stringify({ items, taxCodes }),
method: "InsertCreditMemo" method: "InsertCreditMemo"
}); });
throw error; throw error;