IO-1503 QBO Credit Memos

This commit is contained in:
Patrick Fic
2021-10-28 09:56:59 -07:00
parent 2c00e5ee79
commit 53394efebf
2 changed files with 146 additions and 4 deletions

View File

@@ -27,6 +27,7 @@ const {
} = require("../qbo/qbo-receivables");
const { urlBuilder } = require("./qbo");
const { DineroQbFormat } = require("../accounting-constants");
const { findTaxCode } = require("../qb-receivables-lines");
exports.default = async (req, res) => {
const oauthClient = new OAuthClient({
@@ -135,7 +136,17 @@ exports.default = async (req, res) => {
);
}
await InsertPayment(oauthClient, qbo_realmId, req, payment, jobTier);
if (payment.amount > 0) {
await InsertPayment(oauthClient, qbo_realmId, req, payment, jobTier);
} else {
await InsertCreditMemo(
oauthClient,
qbo_realmId,
req,
payment,
jobTier
);
}
ret.push({ paymentid: payment.id, success: true });
} catch (error) {
logger.log("qbo-payment-create-error", "ERROR", req.user.email, {
@@ -173,7 +184,8 @@ async function InsertPayment(
oauthClient,
qbo_realmId,
req,
payment.job.ro_number
payment.job.ro_number,
false
);
if (invoices && invoices.length !== 1) {
@@ -235,7 +247,13 @@ async function InsertPayment(
throw error;
}
}
async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number) {
async function QueryMetaData(
oauthClient,
qbo_realmId,
req,
ro_number,
isCreditMemo
) {
const invoice = await oauthClient.makeApiCall({
url: urlBuilder(
qbo_realmId,
@@ -288,8 +306,50 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number) {
// classes.json.QueryResponse.Class.forEach((t) => {
// accountMapping[t.Name] = t.Id;
// });
let ret = {};
if (isCreditMemo) {
const taxCodes = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From TaxCode`),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const items = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From Item`),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
setNewRefreshToken(req.user.email, items);
const itemMapping = {};
items.json &&
items.json.QueryResponse &&
items.json.QueryResponse.Item &&
items.json.QueryResponse.Item.forEach((t) => {
itemMapping[t.Name] = t.Id;
});
const taxCodeMapping = {};
taxCodes.json &&
taxCodes.json.QueryResponse &&
taxCodes.json.QueryResponse.TaxCode &&
taxCodes.json.QueryResponse.TaxCode.forEach((t) => {
taxCodeMapping[t.Name] = t.Id;
});
ret = {
...ret,
items: itemMapping,
taxCodes: taxCodeMapping,
};
}
return {
...ret,
paymentMethods: paymentMethodMapping,
invoices:
invoice.json &&
@@ -297,3 +357,85 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number) {
invoice.json.QueryResponse.Invoice,
};
}
async function InsertCreditMemo(
oauthClient,
qbo_realmId,
req,
payment,
parentRef
) {
const { paymentMethods, invoices, items, taxCodes } = await QueryMetaData(
oauthClient,
qbo_realmId,
req,
payment.job.ro_number,
true
);
if (invoices && invoices.length !== 1) {
throw new Error(
`More than 1 invoice with DocNumber ${payment.ro_number} found.`
);
}
const paymentQbo = {
CustomerRef: {
value: parentRef.Id,
},
TxnDate: moment(payment.date).format("YYYY-MM-DD"),
DocNumber: payment.paymentnum,
...(invoices[0] ? { InvoiceRef: { value: invoices[0].Id } } : {}),
Line: [
{
DetailType: "SalesItemLineDetail",
Amount: Dinero({ amount: Math.round(payment.amount * -100) }).toFormat(
DineroQbFormat
),
SalesItemLineDetail: {
ItemRef: {
value:
items[
payment.job.bodyshop.md_responsibility_centers.refund
.accountitem
],
},
Qty: 1,
TaxCodeRef: {
value:
taxCodes[
findTaxCode(
{
local: false,
federal: false,
state: false,
},
payment.job.bodyshop.md_responsibility_centers.sales_tax_codes
)
],
},
},
},
],
};
logger.log("qbo-payments-objectlog", "DEBUG", req.user.email, payment.id, {
paymentQbo,
});
try {
const result = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "creditmemo"),
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(paymentQbo),
});
setNewRefreshToken(req.user.email, result);
return result && result.Bill;
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, payment.id, {
error: error && error.message,
method: "InsertCreditMemo",
});
throw error;
}
}

View File

@@ -152,7 +152,7 @@ const generatePayment = (payment, isThreeTier, twoTierPref) => {
QBXML: {
QBXMLMsgsRq: {
"@onError": "continueOnError",
CreditMemoAddRq: {
wMemoAddRq: {
CreditMemoAdd: {
CustomerRef: {
FullName: (payment.job.bodyshop.accountingconfig.tiers === 3