From fff9073f9d02c9a338333f7610f37e13206bae4c Mon Sep 17 00:00:00 2001
From: Patrick Fic <>
Date: Tue, 12 Oct 2021 16:54:28 -0700
Subject: [PATCH 01/23] IO-256 Add vendor credits.
---
server/accounting/qbo/qbo-payables.js | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js
index ffe60b373..c68531b49 100644
--- a/server/accounting/qbo/qbo-payables.js
+++ b/server/accounting/qbo/qbo-payables.js
@@ -72,6 +72,7 @@ exports.default = async (req, res) => {
bill,
vendorRecord
);
+
ret.push({ billid: bill.id, success: true });
} catch (error) {
ret.push({
@@ -112,7 +113,7 @@ async function QueryVendorRecord(oauthClient, req, bill) {
);
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, bill.id, {
- error,
+ error: JSON.stringify(error),
method: "QueryVendorRecord",
});
throw error;
@@ -135,7 +136,7 @@ async function InsertVendorRecord(oauthClient, req, bill) {
return result && result.Vendor;
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, bill.id, {
- error,
+ error: JSON.stringify(error),
method: "InsertVendorRecord",
});
throw error;
@@ -150,7 +151,7 @@ async function InsertBill(oauthClient, req, bill, vendor) {
value: vendor.Id,
},
TxnDate: moment(bill.date).format("YYYY-MM-DD"),
- DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
+ //DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
DocNumber: bill.invoice_number,
...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
@@ -170,7 +171,10 @@ async function InsertBill(oauthClient, req, bill, vendor) {
};
try {
const result = await oauthClient.makeApiCall({
- url: urlBuilder(req.cookies.qbo_realmId, "bill"),
+ url: urlBuilder(
+ req.cookies.qbo_realmId,
+ bill.is_credit_memo ? "vendorcredit" : "bill"
+ ),
method: "POST",
headers: {
"Content-Type": "application/json",
@@ -181,7 +185,7 @@ async function InsertBill(oauthClient, req, bill, vendor) {
return result && result.Bill;
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, bill.id, {
- error,
+ error: JSON.stringify(error),
method: "InsertBill",
});
throw error;
@@ -231,6 +235,7 @@ const generateBillLine = (
.toFormat(DineroQbFormat),
};
};
+
async function QueryMetaData(oauthClient, req) {
const accounts = await oauthClient.makeApiCall({
url: urlBuilder(
From 4d52a5c44a9bfcde871975a013da5d0ef2d69f07 Mon Sep 17 00:00:00 2001
From: Patrick Fic <>
Date: Tue, 12 Oct 2021 19:07:43 -0700
Subject: [PATCH 02/23] IO-256 Exporting of payments
---
.../accounting-payments-table.component.jsx | 23 +-
.../owner-find-modal.container.jsx | 4 +-
.../payment-export-button.component.jsx | 102 ++++---
.../payments-export-all-button.component.jsx | 72 +++--
server.js | 1 +
server/accounting/qbo/qbo-payables.js | 9 +-
server/accounting/qbo/qbo-payments.js | 274 ++++++++++++++++++
server/accounting/qbo/qbo-receivables.js | 20 +-
server/accounting/qbo/qbo.js | 1 +
server/accounting/qbxml/qbxml-payments.js | 3 -
10 files changed, 415 insertions(+), 94 deletions(-)
diff --git a/client/src/components/accounting-payments-table/accounting-payments-table.component.jsx b/client/src/components/accounting-payments-table/accounting-payments-table.component.jsx
index 2edc4a0a4..53a51bdae 100644
--- a/client/src/components/accounting-payments-table/accounting-payments-table.component.jsx
+++ b/client/src/components/accounting-payments-table/accounting-payments-table.component.jsx
@@ -8,8 +8,26 @@ import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
import { alphaSort, dateSort } from "../../utils/sorters";
import PaymentExportButton from "../payment-export-button/payment-export-button.component";
import PaymentsExportAllButton from "../payments-export-all-button/payments-export-all-button.component";
+import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectBodyshop } from "../../redux/user/user.selectors";
-export default function AccountingPayablesTableComponent({
+const mapStateToProps = createStructuredSelector({
+ bodyshop: selectBodyshop,
+});
+
+const mapDispatchToProps = (dispatch) => ({
+ //setUserLanguage: language => dispatch(setUserLanguage(language))
+});
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(AccountingPayablesTableComponent);
+
+export function AccountingPayablesTableComponent({
+ bodyshop,
loading,
payments,
}) {
@@ -163,6 +181,9 @@ export default function AccountingPayablesTableComponent({
loadingCallback={setTransInProgress}
completedCallback={setSelectedPayments}
/>
+ {bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
+
+ )}
{
logImEXEvent("accounting_payment_export");
-
setLoading(true);
- if (!!loadingCallback) loadingCallback(true);
-
- let QbXmlResponse;
- try {
- QbXmlResponse = await axios.post(
- "/accounting/qbxml/payments",
- { payments: [paymentId] },
- {
- headers: {
- Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
- },
- }
- );
- console.log("handle -> XML", QbXmlResponse);
- } catch (error) {
- console.log("Error getting QBXML from Server.", error);
- notification["error"]({
- message: t("payments.errors.exporting", {
- error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
- }),
- });
- if (loadingCallback) loadingCallback(false);
- setLoading(false);
- return;
- }
-
+ //Check if it's a QBO Setup.
let PartnerResponse;
-
- try {
- PartnerResponse = await axios.post(
- "http://localhost:1337/qb/",
- //"http://609feaeae986.ngrok.io/qb/",
- QbXmlResponse.data
- );
- } catch (error) {
- console.log("Error connecting to quickbooks or partner.", error);
- notification["error"]({
- message: t("payments.errors.exporting-partner"),
+ if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
+ PartnerResponse = await axios.post(`/qbo/payments`, {
+ withCredentials: true,
+ payments: [paymentId],
});
- if (!!loadingCallback) loadingCallback(false);
- setLoading(false);
- return;
+ } else {
+ //Default is QBD
+
+ if (!!loadingCallback) loadingCallback(true);
+
+ let QbXmlResponse;
+ try {
+ QbXmlResponse = await axios.post(
+ "/accounting/qbxml/payments",
+ { payments: [paymentId] },
+ {
+ headers: {
+ Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
+ },
+ }
+ );
+ console.log("handle -> XML", QbXmlResponse);
+ } catch (error) {
+ console.log("Error getting QBXML from Server.", error);
+ notification["error"]({
+ message: t("payments.errors.exporting", {
+ error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
+ }),
+ });
+ if (loadingCallback) loadingCallback(false);
+ setLoading(false);
+ return;
+ }
+
+ try {
+ PartnerResponse = await axios.post(
+ "http://localhost:1337/qb/",
+ QbXmlResponse.data
+ );
+ } catch (error) {
+ console.log("Error connecting to quickbooks or partner.", error);
+ notification["error"]({
+ message: t("payments.errors.exporting-partner"),
+ });
+ if (!!loadingCallback) loadingCallback(false);
+ setLoading(false);
+ return;
+ }
}
console.log("handleQbxml -> PartnerResponse", PartnerResponse);
const failedTransactions = PartnerResponse.data.filter((r) => !r.success);
-
+ const successfulTransactions = PartnerResponse.data.filter(
+ (r) => r.success
+ );
if (failedTransactions.length > 0) {
//Uh oh. At least one was no good.
failedTransactions.map((ft) =>
@@ -123,7 +132,14 @@ export function PaymentExportButton({
const paymentUpdateResponse = await updatePayment({
variables: {
- paymentIdList: [paymentId],
+ paymentIdList: successfulTransactions.map(
+ (st) =>
+ st[
+ bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
+ ? "paymentid"
+ : "id"
+ ]
+ ),
payment: {
exportedat: new Date(),
},
diff --git a/client/src/components/payments-export-all-button/payments-export-all-button.component.jsx b/client/src/components/payments-export-all-button/payments-export-all-button.component.jsx
index 693a14339..3e4085c44 100644
--- a/client/src/components/payments-export-all-button/payments-export-all-button.component.jsx
+++ b/client/src/components/payments-export-all-button/payments-export-all-button.component.jsx
@@ -33,42 +33,50 @@ export function PaymentsExportAllButton({
const handleQbxml = async () => {
setLoading(true);
if (!!loadingCallback) loadingCallback(true);
-
- let QbXmlResponse;
- try {
- QbXmlResponse = await axios.post("/accounting/qbxml/payments", {
+ let PartnerResponse;
+ if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
+ PartnerResponse = await axios.post(`/qbo/payments`, {
+ withCredentials: true,
payments: paymentIds,
});
- } catch (error) {
- console.log("Error getting QBXML from Server.", error);
- notification["error"]({
- message: t("payments.errors.exporting", {
- error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
- }),
- });
- if (loadingCallback) loadingCallback(false);
- setLoading(false);
- return;
+ } else {
+ let QbXmlResponse;
+ try {
+ QbXmlResponse = await axios.post("/accounting/qbxml/payments", {
+ payments: paymentIds,
+ });
+ } catch (error) {
+ console.log("Error getting QBXML from Server.", error);
+ notification["error"]({
+ message: t("payments.errors.exporting", {
+ error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
+ }),
+ });
+ if (loadingCallback) loadingCallback(false);
+ setLoading(false);
+ return;
+ }
+
+ try {
+ PartnerResponse = await axios.post(
+ "http://localhost:1337/qb/",
+ QbXmlResponse.data
+ );
+ } catch (error) {
+ console.log("Error connecting to quickbooks or partner.", error);
+ notification["error"]({
+ message: t("payments.errors.exporting-partner"),
+ });
+ if (!!loadingCallback) loadingCallback(false);
+ setLoading(false);
+ return;
+ }
}
- let PartnerResponse;
-
- try {
- PartnerResponse = await axios.post(
- "http://localhost:1337/qb/",
- QbXmlResponse.data
- );
- } catch (error) {
- console.log("Error connecting to quickbooks or partner.", error);
- notification["error"]({
- message: t("payments.errors.exporting-partner"),
- });
- if (!!loadingCallback) loadingCallback(false);
- setLoading(false);
- return;
- }
-
- const groupedData = _.groupBy(PartnerResponse.data, "id");
+ const groupedData = _.groupBy(
+ PartnerResponse.data,
+ bodyshop.accountingconfig.qbo ? "paymentid" : "id"
+ );
const proms = [];
Object.keys(groupedData).forEach((key) => {
proms.push(
diff --git a/server.js b/server.js
index 368fdf632..28a7da70a 100644
--- a/server.js
+++ b/server.js
@@ -150,6 +150,7 @@ app.post("/qbo/authorize", fb.validateFirebaseIdToken, qbo.authorize);
app.get("/qbo/callback", qbo.callback);
app.post("/qbo/receivables", fb.validateFirebaseIdToken, qbo.receivables);
app.post("/qbo/payables", fb.validateFirebaseIdToken, qbo.payables);
+app.post("/qbo/payments", fb.validateFirebaseIdToken, qbo.payments);
var data = require("./server/data/data");
app.post("/data/ah", data.autohouse);
diff --git a/server/accounting/qbo/qbo-payables.js b/server/accounting/qbo/qbo-payables.js
index c68531b49..57d357c50 100644
--- a/server/accounting/qbo/qbo-payables.js
+++ b/server/accounting/qbo/qbo-payables.js
@@ -78,7 +78,8 @@ exports.default = async (req, res) => {
ret.push({
billid: bill.id,
success: false,
- errorMessage: error.message,
+ errorMessage:
+ (error && error.authResponse.body) || JSON.stringify(error),
});
}
}
@@ -113,7 +114,7 @@ async function QueryVendorRecord(oauthClient, req, bill) {
);
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, bill.id, {
- error: JSON.stringify(error),
+ error: (error && error.authResponse.body) || JSON.stringify(error),
method: "QueryVendorRecord",
});
throw error;
@@ -136,7 +137,7 @@ async function InsertVendorRecord(oauthClient, req, bill) {
return result && result.Vendor;
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, bill.id, {
- error: JSON.stringify(error),
+ error: (error && error.authResponse.body) || JSON.stringify(error),
method: "InsertVendorRecord",
});
throw error;
@@ -185,7 +186,7 @@ async function InsertBill(oauthClient, req, bill, vendor) {
return result && result.Bill;
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, bill.id, {
- error: JSON.stringify(error),
+ error: (error && error.authResponse.body) || JSON.stringify(error),
method: "InsertBill",
});
throw error;
diff --git a/server/accounting/qbo/qbo-payments.js b/server/accounting/qbo/qbo-payments.js
index e69de29bb..99ae12fc9 100644
--- a/server/accounting/qbo/qbo-payments.js
+++ b/server/accounting/qbo/qbo-payments.js
@@ -0,0 +1,274 @@
+const path = require("path");
+require("dotenv").config({
+ path: path.resolve(
+ process.cwd(),
+ `.env.${process.env.NODE_ENV || "development"}`
+ ),
+});
+const logger = require("../../utils/logger");
+const Dinero = require("dinero.js");
+
+const apiGqlClient = require("../../graphql-client/graphql-client").client;
+const queries = require("../../graphql-client/queries");
+const {
+ refresh: refreshOauthToken,
+ setNewRefreshToken,
+} = require("./qbo-callback");
+const OAuthClient = require("intuit-oauth");
+const moment = require("moment");
+const GraphQLClient = require("graphql-request").GraphQLClient;
+const {
+ QueryInsuranceCo,
+ InsertInsuranceCo,
+ InsertJob,
+ InsertOwner,
+ QueryJob,
+ QueryOwner,
+} = require("../qbo/qbo-receivables");
+const { urlBuilder } = require("./qbo");
+const { DineroQbFormat } = require("../accounting-constants");
+
+exports.default = async (req, res) => {
+ const oauthClient = new OAuthClient({
+ 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,
+ logging: true,
+ });
+ try {
+ //Fetch the API Access Tokens & Set them for the session.
+ const response = await apiGqlClient.request(queries.GET_QBO_AUTH, {
+ email: req.user.email,
+ });
+
+ oauthClient.setToken(response.associations[0].qbo_auth);
+
+ await refreshOauthToken(oauthClient, req);
+
+ const BearerToken = req.headers.authorization;
+ const { payments: paymentsToQuery } = req.body;
+ //Query Job Info
+ const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
+ headers: {
+ Authorization: BearerToken,
+ },
+ });
+ logger.log("qbo-payment-create", "DEBUG", req.user.email, 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 ret = [];
+
+ for (const payment of payments) {
+ try {
+ const isThreeTier = bodyshop.accountingconfig.tiers === 3;
+ const twoTierPref = bodyshop.accountingconfig.twotierpref;
+
+ //Replace this with a for-each loop to check every single Job that's included in the list.
+
+ let insCoCustomerTier, ownerCustomerTier, jobTier;
+ if (isThreeTier || twoTierPref === "source") {
+ //Insert the insurance company tier.
+ //Query for top level customer, the insurance company name.
+ insCoCustomerTier = await QueryInsuranceCo(
+ oauthClient,
+ req,
+ payment.job
+ );
+ if (!insCoCustomerTier) {
+ //Creating the Insurance Customer.
+ insCoCustomerTier = await InsertInsuranceCo(
+ oauthClient,
+ req,
+ payment.job,
+ bodyshop
+ );
+ }
+ }
+
+ if (isThreeTier || twoTierPref === "name") {
+ //Insert the name/owner and account for whether the source should be the ins co in 3 tier..
+ ownerCustomerTier = await QueryOwner(oauthClient, req, payment.job);
+ //Query for the owner itself.
+ if (!ownerCustomerTier) {
+ ownerCustomerTier = await InsertOwner(
+ oauthClient,
+ req,
+ payment.job,
+ isThreeTier,
+ insCoCustomerTier
+ );
+ }
+ }
+
+ //Query for the Job or Create it.
+ jobTier = await QueryJob(oauthClient, req, payment.job);
+
+ // Need to validate that the job tier is associated to the right individual?
+
+ if (!jobTier) {
+ jobTier = await InsertJob(
+ oauthClient,
+ req,
+ payment.job,
+ isThreeTier,
+ ownerCustomerTier
+ );
+ }
+
+ await InsertPayment(oauthClient, req, payment, jobTier);
+ ret.push({ paymentid: payment.id, success: true });
+ } catch (error) {
+ logger.log("qbo-payment-create-error", "ERROR", req.user.email, {
+ error: (error && error.authResponse.body) || JSON.stringify(error),
+ });
+
+ ret.push({
+ paymentid: payment.id,
+ success: false,
+ errorMessage:
+ (error && error.authResponse.body) || JSON.stringify(error),
+ });
+ }
+ }
+
+ res.status(200).json(ret);
+ } catch (error) {
+ console.log(error);
+ logger.log("qbo-payment-create-error", "ERROR", req.user.email, { error });
+ res.status(400).json(error);
+ }
+};
+
+async function InsertPayment(oauthClient, req, payment, parentRef) {
+ const { paymentMethods, invoices } = await QueryMetaData(
+ oauthClient,
+ req,
+ payment.job.ro_number
+ );
+
+ if (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"),
+ //DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
+ DocNumber: payment.paymentnum,
+ TotalAmt: Dinero({
+ amount: Math.round(payment.amount * 100),
+ }).toFormat(DineroQbFormat),
+ PaymentMethodRef: {
+ value: paymentMethods[payment.type],
+ },
+ Line: [
+ {
+ Amount: Dinero({
+ amount: Math.round(payment.amount * 100),
+ }).toFormat(DineroQbFormat),
+ LinkedTxn: [
+ {
+ TxnId: invoices[0].Id,
+ TxnType: "Invoice",
+ },
+ ],
+ },
+ ],
+ };
+ try {
+ const result = await oauthClient.makeApiCall({
+ url: urlBuilder(req.cookies.qbo_realmId, "payment"),
+ 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: JSON.stringify(error),
+ method: "InsertPayment",
+ });
+ throw error;
+ }
+}
+async function QueryMetaData(oauthClient, req, ro_number) {
+ const invoice = await oauthClient.makeApiCall({
+ url: urlBuilder(
+ req.cookies.qbo_realmId,
+ "query",
+ `select * From Invoice where DocNumber = '${ro_number}'`
+ ),
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+
+ const paymentMethods = await oauthClient.makeApiCall({
+ url: urlBuilder(
+ req.cookies.qbo_realmId,
+ "query",
+ `select * From PaymentMethod`
+ ),
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ setNewRefreshToken(req.user.email, paymentMethods);
+
+ // const classes = await oauthClient.makeApiCall({
+ // url: urlBuilder(req.cookies.qbo_realmId, "query", `select * From Class`),
+ // method: "POST",
+ // headers: {
+ // "Content-Type": "application/json",
+ // },
+ // });
+
+ const paymentMethodMapping = {};
+
+ paymentMethods.json &&
+ paymentMethods.json.QueryResponse &&
+ paymentMethods.json.QueryResponse.PaymentMethod.forEach((t) => {
+ paymentMethodMapping[t.Name] = t.Id;
+ });
+
+ // const accountMapping = {};
+
+ // accounts.json &&
+ // accounts.json.QueryResponse &&
+ // accounts.json.QueryResponse.Account.forEach((t) => {
+ // accountMapping[t.Name] = t.Id;
+ // });
+
+ // const classMapping = {};
+ // classes.json &&
+ // classes.json.QueryResponse &&
+ // classes.json.QueryResponse.Class.forEach((t) => {
+ // accountMapping[t.Name] = t.Id;
+ // });
+
+ return {
+ paymentMethods: paymentMethodMapping,
+ invoices:
+ invoice.json &&
+ invoice.json.QueryResponse &&
+ invoice.json.QueryResponse.Invoice,
+ };
+}
diff --git a/server/accounting/qbo/qbo-receivables.js b/server/accounting/qbo/qbo-receivables.js
index f23873544..3a9eafb31 100644
--- a/server/accounting/qbo/qbo-receivables.js
+++ b/server/accounting/qbo/qbo-receivables.js
@@ -80,7 +80,7 @@ exports.default = async (req, res) => {
);
}
}
- console.log(insCoCustomerTier);
+
if (isThreeTier || twoTierPref === "name") {
//Insert the name/owner and account for whether the source should be the ins co in 3 tier..
ownerCustomerTier = await QueryOwner(oauthClient, req, job);
@@ -95,7 +95,7 @@ exports.default = async (req, res) => {
);
}
}
- console.log(ownerCustomerTier);
+
//Query for the Job or Create it.
jobTier = await QueryJob(oauthClient, req, job);
@@ -110,14 +110,15 @@ exports.default = async (req, res) => {
ownerCustomerTier
);
}
- console.log(jobTier);
+
await InsertInvoice(oauthClient, req, job, bodyshop, jobTier);
ret.push({ jobid: job.id, success: true });
} catch (error) {
ret.push({
jobid: job.id,
success: false,
- errorMessage: error.message,
+ errorMessage:
+ (error && error.authResponse.body) || JSON.stringify(error),
});
}
}
@@ -160,6 +161,7 @@ async function QueryInsuranceCo(oauthClient, req, job) {
throw error;
}
}
+exports.QueryInsuranceCo = QueryInsuranceCo;
async function InsertInsuranceCo(oauthClient, req, job, bodyshop) {
const insCo = bodyshop.md_ins_cos.find((i) => i.name === job.ins_co_nm);
@@ -192,7 +194,7 @@ async function InsertInsuranceCo(oauthClient, req, job, bodyshop) {
throw error;
}
}
-
+exports.InsertInsuranceCo = InsertInsuranceCo;
async function QueryOwner(oauthClient, req, job) {
const ownerName = generateOwnerTier(job, true, null);
const result = await oauthClient.makeApiCall({
@@ -214,7 +216,7 @@ async function QueryOwner(oauthClient, req, job) {
result.json.QueryResponse.Customer[0]
);
}
-
+exports.QueryOwner = QueryOwner;
async function InsertOwner(oauthClient, req, job, isThreeTier, parentTierRef) {
const ownerName = generateOwnerTier(job, true, null);
const Customer = {
@@ -254,7 +256,7 @@ async function InsertOwner(oauthClient, req, job, isThreeTier, parentTierRef) {
throw error;
}
}
-
+exports.InsertOwner = InsertOwner;
async function QueryJob(oauthClient, req, job) {
const result = await oauthClient.makeApiCall({
url: urlBuilder(
@@ -275,7 +277,7 @@ async function QueryJob(oauthClient, req, job) {
result.json.QueryResponse.Customer[0]
);
}
-
+exports.QueryJob = QueryJob;
async function InsertJob(oauthClient, req, job, isThreeTier, parentTierRef) {
const Customer = {
DisplayName: job.ro_number,
@@ -314,7 +316,7 @@ async function InsertJob(oauthClient, req, job, isThreeTier, parentTierRef) {
throw error;
}
}
-
+exports.InsertJob = InsertJob;
async function QueryMetaData(oauthClient, req) {
const items = await oauthClient.makeApiCall({
url: urlBuilder(req.cookies.qbo_realmId, "query", `select * From Item`),
diff --git a/server/accounting/qbo/qbo.js b/server/accounting/qbo/qbo.js
index 190e5aa07..ab46a86c0 100644
--- a/server/accounting/qbo/qbo.js
+++ b/server/accounting/qbo/qbo.js
@@ -22,3 +22,4 @@ exports.authorize = require("./qbo-authorize").default;
exports.refresh = require("./qbo-callback").refresh;
exports.receivables = require("./qbo-receivables").default;
exports.payables = require("./qbo-payables").default;
+exports.payments = require("./qbo-payments").default;
diff --git a/server/accounting/qbxml/qbxml-payments.js b/server/accounting/qbxml/qbxml-payments.js
index ef53099cf..ec429aa86 100644
--- a/server/accounting/qbxml/qbxml-payments.js
+++ b/server/accounting/qbxml/qbxml-payments.js
@@ -142,9 +142,6 @@ const generatePayment = (payment, isThreeTier, twoTierPref) => {
payment.stripeid || ""
} ${payment.payer ? ` PAID BY ${payment.payer}` : ""}`,
IsAutoApply: true,
- // AppliedToTxnAdd:{
- // T
- // }
},
},
},
From 9ee8e9007a11cb23182e84337a357a8b75ad2a52 Mon Sep 17 00:00:00 2001
From: Patrick Fic <>
Date: Tue, 12 Oct 2021 20:18:06 -0700
Subject: [PATCH 03/23] IO-256 Add Payables Posting.
---
.../components/dms-post-form/dms-post-form.component.jsx | 1 -
.../jobs-export-all-button.component.jsx | 7 +------
.../payable-export-all-button.component.jsx | 7 +------
.../payable-export-button.component.jsx | 7 +------
.../payment-export-button.component.jsx | 7 +------
.../payments-export-all-button.component.jsx | 7 +------
6 files changed, 5 insertions(+), 31 deletions(-)
diff --git a/client/src/components/dms-post-form/dms-post-form.component.jsx b/client/src/components/dms-post-form/dms-post-form.component.jsx
index 637a858af..c3bc99333 100644
--- a/client/src/components/dms-post-form/dms-post-form.component.jsx
+++ b/client/src/components/dms-post-form/dms-post-form.component.jsx
@@ -259,7 +259,6 @@ export function DmsPostForm({ bodyshop, socket, job }) {
))}