IO-3239 QBO Logging and integration log schema changes.

This commit is contained in:
Patrick Fic
2025-05-22 11:54:17 -07:00
parent 16a91c772a
commit 2c508cf1a1
9 changed files with 202 additions and 66 deletions

View File

@@ -16,7 +16,6 @@ const oauthClient = new OAuthClient({
redirectUri: process.env.QBO_REDIRECT_URI,
});
//TODO:AIO Add in QBO callbacks.
const url = InstanceEndpoints();
exports.default = async (req, res) => {

View File

@@ -150,11 +150,11 @@ async function QueryVendorRecord(oauthClient, qbo_realmId, req, bill) {
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "QueryVendorRecord",
method: "POST",
name: "QueryVendorRecord",
billid: bill.id,
statusCode: result.status,
bodyshopid: req.user.bodyshopid,
status: result.response?.status,
bodyshopid: bill.job.shopid,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
@@ -188,11 +188,11 @@ async function InsertVendorRecord(oauthClient, qbo_realmId, req, bill) {
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "InsertVendorRecord",
method: "POST",
name: "InsertVendorRecord",
billid: bill.id,
statusCode: result.status,
bodyshopid: req.user.bodyshopid,
status: result.response?.status,
bodyshopid: bill.job.shopid,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
@@ -207,7 +207,7 @@ async function InsertVendorRecord(oauthClient, qbo_realmId, req, bill) {
}
async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop) {
const { accounts, taxCodes, classes } = await QueryMetaData(oauthClient, qbo_realmId, req);
const { accounts, taxCodes, classes } = await QueryMetaData(oauthClient, qbo_realmId, req, bill.job.shopid);
const lines = bill.billlines.map((il) =>
generateBillLine(
@@ -299,11 +299,11 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor, bodyshop)
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "InsertBill",
method: "POST",
name: "InsertBill",
billid: bill.id,
statusCode: result.status,
bodyshopid: req.user.bodyshopid,
status: result.response?.status,
bodyshopid: bill.job.shopid,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
@@ -368,7 +368,7 @@ const generateBillLine = (
};
};
async function QueryMetaData(oauthClient, qbo_realmId, req) {
async function QueryMetaData(oauthClient, qbo_realmId, req, bodyshopid) {
const accounts = await oauthClient.makeApiCall({
url: urlBuilder(
qbo_realmId,
@@ -382,10 +382,10 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "QueryAccountType",
statusCode: accounts.status,
bodyshopid: req.user.bodyshopid,
method: "POST",
name: "QueryAccountType",
status: accounts.response?.status,
bodyshopid,
email: req.user.email
})
setNewRefreshToken(req.user.email, accounts);
@@ -398,10 +398,10 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "QueryTaxCode",
statusCode: taxCodes.status,
bodyshopid: req.user.bodyshopid,
method: "POST",
name: "QueryTaxCode",
status: taxCodes.status,
bodyshopid,
email: req.user.email
})
const classes = await oauthClient.makeApiCall({
@@ -413,10 +413,10 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "QueryClasses",
statusCode: classes.status,
bodyshopid: req.user.bodyshopid,
method: "POST",
name: "QueryClasses",
status: classes.status,
bodyshopid,
email: req.user.email
})
const taxCodeMapping = {};

View File

@@ -197,7 +197,8 @@ async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef,
req,
payment.job.ro_number,
false,
parentRef
parentRef,
payment.job.shopid
);
if (invoices && invoices.length !== 1) {
@@ -256,11 +257,11 @@ async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef,
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "InsertPayment",
method: "POST",
name: "InsertPayment",
paymentid: payment.id,
statusCode: result.status,
bodyshopid: req.user.bodyshopid,
status: result.response?.status,
bodyshopid: payment.job.shopid,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
@@ -274,7 +275,7 @@ async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef,
}
}
async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditMemo, parentTierRef) {
async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditMemo, parentTierRef, bodyshopid) {
const invoice = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From Invoice where DocNumber like '${ro_number}%'`),
method: "POST",
@@ -284,11 +285,11 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "QueryInvoice",
method: "POST",
name: "QueryInvoice",
statusCode: invoice.status,
bodyshopid: req.user.bodyshopid,
status: invoice.response?.status,
bodyshopid,
email: req.user.email
})
const paymentMethods = await oauthClient.makeApiCall({
@@ -300,10 +301,10 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "QueryPaymentMethod",
statusCode: paymentMethods.status,
bodyshopid: req.user.bodyshopid,
method: "POST",
name: "QueryPaymentMethod",
status: paymentMethods.response?.status,
bodyshopid,
email: req.user.email
})
setNewRefreshToken(req.user.email, paymentMethods);
@@ -351,11 +352,11 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "QueryTaxCode",
method: "POST",
name: "QueryTaxCode",
statusCode: taxCodes.status,
bodyshopid: req.user.bodyshopid,
status: taxCodes.response?.status,
bodyshopid,
email: req.user.email
})
const items = await oauthClient.makeApiCall({
@@ -367,10 +368,10 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "QueryItems",
statusCode: items.status,
bodyshopid: req.user.bodyshopid,
method: "POST",
name: "QueryItems",
status: items.response?.status,
bodyshopid,
email: req.user.email
})
setNewRefreshToken(req.user.email, items);
@@ -418,7 +419,8 @@ async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRe
req,
payment.job.ro_number,
true,
parentRef
parentRef,
payment.job.shopid
);
if (invoices && invoices.length !== 1) {
@@ -475,10 +477,10 @@ async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRe
});
logger.LogIntegrationCall({
platform: "QBO",
methodType: "POST",
methodName: "InsertCreditMemo",
method: "POST",
name: "InsertCreditMemo",
paymentid: payment.id,
statusCode: result.status,
status: result.response?.status,
bodyshopid: req.user.bodyshopid,
email: req.user.email
})

View File

@@ -233,6 +233,15 @@ async function QueryInsuranceCo(oauthClient, qbo_realmId, req, job) {
"Content-Type": "application/json"
}
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "QueryCustomer",
status: result.response?.status,
bodyshopid: job.shopid,
jobid: job.id,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
return (
result.json &&
@@ -279,6 +288,15 @@ async function InsertInsuranceCo(oauthClient, qbo_realmId, req, job, bodyshop) {
},
body: JSON.stringify(Customer)
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "InsertCustomer",
status: result.response.status,
bodyshopid: job.shopid,
jobid: job.id,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
return result && result.json.Customer;
} catch (error) {
@@ -305,6 +323,15 @@ async function QueryOwner(oauthClient, qbo_realmId, req, job, isThreeTier, paren
"Content-Type": "application/json"
}
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "QueryCustomer",
status: result.response?.status,
bodyshopid: job.shopid,
jobid: job.id,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
return (
result.json &&
@@ -347,6 +374,15 @@ async function InsertOwner(oauthClient, qbo_realmId, req, job, isThreeTier, pare
},
body: JSON.stringify(Customer)
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "InsertCustomer",
status: result.response?.status,
bodyshopid: job.shopid,
jobid: job.id,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
return result && result.json.Customer;
} catch (error) {
@@ -372,6 +408,15 @@ async function QueryJob(oauthClient, qbo_realmId, req, job, parentTierRef) {
"Content-Type": "application/json"
}
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "QueryCustomer",
status: result.response?.status,
bodyshopid: job.shopid,
jobid: job.id,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
return (
result.json &&
@@ -411,6 +456,15 @@ async function InsertJob(oauthClient, qbo_realmId, req, job, parentTierRef) {
},
body: JSON.stringify(Customer)
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "InsertCustomer",
status: result.response?.status,
bodyshopid: job.shopid,
jobid: job.id,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
return result && result.json.Customer;
} catch (error) {
@@ -424,7 +478,7 @@ async function InsertJob(oauthClient, qbo_realmId, req, job, parentTierRef) {
exports.InsertJob = InsertJob;
async function QueryMetaData(oauthClient, qbo_realmId, req) {
async function QueryMetaData(oauthClient, qbo_realmId, req, bodyshopid) {
const items = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From Item where active=true maxresults 1000`),
method: "POST",
@@ -432,6 +486,14 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
"Content-Type": "application/json"
}
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "QueryItems",
status: items.response?.status,
bodyshopid,
email: req.user.email
})
setNewRefreshToken(req.user.email, items);
const taxCodes = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From TaxCode where active=true`),
@@ -440,7 +502,14 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
"Content-Type": "application/json"
}
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "QueryTaxCodes",
status: taxCodes.response?.status,
bodyshopid,
email: req.user.email
})
const classes = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From Class`),
method: "POST",
@@ -448,7 +517,14 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
"Content-Type": "application/json"
}
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "QueryClasses",
status: classes.response?.status,
bodyshopid,
email: req.user.email
})
const taxCodeMapping = {};
taxCodes.json &&
@@ -483,7 +559,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
}
async function InsertInvoice(oauthClient, qbo_realmId, req, job, bodyshop, parentTierRef) {
const { items, taxCodes, classes } = await QueryMetaData(oauthClient, qbo_realmId, req);
const { items, taxCodes, classes } = await QueryMetaData(oauthClient, qbo_realmId, req, job.shopid);
const InvoiceLineAdd = CreateInvoiceLines({
bodyshop,
jobs_by_pk: job,
@@ -573,6 +649,15 @@ async function InsertInvoice(oauthClient, qbo_realmId, req, job, bodyshop, paren
},
body: JSON.stringify(invoiceObj)
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "InsertInvoice",
status: result.status,
bodyshopid: job.shopid,
jobid: job.id,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
return result && result.json && result.json.Invoice;
} catch (error) {
@@ -596,7 +681,7 @@ async function InsertInvoiceMultiPayerInvoice(
payer,
suffix
) {
const { items, taxCodes, classes } = await QueryMetaData(oauthClient, qbo_realmId, req);
const { items, taxCodes, classes } = await QueryMetaData(oauthClient, qbo_realmId, req, job.shopid);
const InvoiceLineAdd = createMultiQbPayerLines({
bodyshop,
jobs_by_pk: job,
@@ -689,6 +774,15 @@ async function InsertInvoiceMultiPayerInvoice(
},
body: JSON.stringify(invoiceObj)
});
logger.LogIntegrationCall({
platform: "QBO",
method: "POST",
name: "InsertInvoice",
status: result.response.status,
bodyshopid: job.shopid,
jobid: job.id,
email: req.user.email
})
setNewRefreshToken(req.user.email, result);
return result && result.json && result.json.Invoice;
} catch (error) {

View File

@@ -222,6 +222,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
rate_mash
rate_matd
class
shopid
ca_bc_pvrt
ca_customer_gst
towing_payable
@@ -480,6 +481,7 @@ query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) {
ownr_ln
ownr_co_nm
class
shopid
}
billlines{
id
@@ -530,6 +532,7 @@ exports.QUERY_PAYMENTS_FOR_EXPORT = `
ownr_fn
ownr_ln
ownr_co_nm
shopid
bodyshop {
accountingconfig
md_responsibility_centers

View File

@@ -195,21 +195,37 @@ const createLogger = () => {
winstonLogger.log(logEntry);
};
const LogIntegrationCall = async ({ platform, methodType, methodName, jobid, paymentid, billid, statusCode, bodyshopid, email }) => {
const LogIntegrationCall = async ({ platform, method, name, jobid, paymentid, billid, status, bodyshopid, email }) => {
try {
//Insert the record.
await client.request(queries.INSERT_INTEGRATION_LOG, {
platform,
methodType,
methodName, jobid, paymentid, billid,
statusCode,
bodyshopid,
email
log: {
platform,
method,
name,
jobid,
paymentid,
billid,
status: status.toString() ?? "0",
bodyshopid,
email
}
});
} catch (error) {
console.trace("Stack", error?.stack);
log("integration-log-error", "ERROR", email, null, {
error
message: error?.message,
stack: error?.stack,
platform,
method,
name,
jobid,
paymentid,
billid,
status,
bodyshopid,
email
});
}
};