Compare commits

..

2 Commits

Author SHA1 Message Date
Patrick Fic
3775789e9d Merged in feature/IO-3322-intellipay-refund (pull request #2457)
IO-3332 Add error message to intellipay refund error.

Approved-by: Dave Richer
2025-08-11 17:46:24 +00:00
Patrick Fic
75de177b7b IO-3332 Add error message to intellipay refund error. 2025-08-08 09:11:48 -07:00
4 changed files with 79 additions and 57 deletions

View File

@@ -1,4 +1,4 @@
<babeledit_project be_version="2.7.1" version="1.2">
<babeledit_project version="1.2" be_version="2.7.1">
<!--
BabelEdit project file
@@ -8472,6 +8472,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>responsibilitycenter</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>templates</name>
<definition_loaded>false</definition_loaded>
@@ -65702,7 +65723,7 @@
<primary_language>en-US</primary_language>
<configuration>
<definitions>.</definitions>
<indent>tab</indent>
<indent>space2</indent>
<format>namespaced-json</format>
<support_arrays>true</support_arrays>
</configuration>

View File

@@ -16,10 +16,10 @@ import { useNotification } from "../../contexts/Notifications/notificationContex
const { confirm } = Modal;
const openNotificationWithIcon = (type, t, notification) => {
const openNotificationWithIcon = (type, t, notification, message) => {
notification[type]({
message: t("job_payments.notifications.error.title"),
description: t("job_payments.notifications.error.description")
description: t("job_payments.notifications.error.description", { message: message || "Unknown error." })
});
};
@@ -99,7 +99,7 @@ const PaymentExpandedRowComponent = ({ record, bodyshop }) => {
});
if (refundResponse.data.status < 0) {
openNotificationWithIcon("error", t, notification);
openNotificationWithIcon("error", t, notification, refundResponse.data.message);
return;
}

View File

@@ -1455,9 +1455,9 @@
},
"notifications": {
"error": {
"description": "Please try again. Make sure the refund amount does not exceeds the payment amount.",
"description": "An error has occurred processing the refund: {{message}}",
"openingip": "Error connecting to IntelliPay service.",
"title": "Error placing refund"
"title": "Error issuing refund"
}
},
"titles": {

View File

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