IO-256 Further work on QBO Receivables.

This commit is contained in:
Patrick Fic
2021-08-30 10:50:56 -07:00
parent 5284ee2ef9
commit c72ef97b82
6 changed files with 3801 additions and 66 deletions

View File

@@ -1,7 +1,7 @@
import { Button, Space } from "antd";
import Axios from "axios";
import React, { useEffect } from "react";
import QboImg from "./qbo_signin.png";
//import QboImg from "./qbo_signin.png";
import queryString from "query-string";
import { useLocation } from "react-router-dom";
import { useCookies } from "react-cookie";

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,6 @@ exports.default = async (req, res) => {
scope: [OAuthClient.scopes.Accounting, OAuthClient.scopes.OpenId],
state: req.user.email,
}); // can be an array of multiple scopes ex : {scope:[OAuthClient.scopes.Accounting,OAuthClient.scopes.OpenId]}
// Redirect the authUri
res.send(authUri);
} catch (error) {

View File

@@ -6,7 +6,9 @@ require("dotenv").config({
`.env.${process.env.NODE_ENV || "development"}`
),
});
const client = require("../../graphql-client/graphql-client").client;
const logger = require("../../utils/logger");
const apiGqlClient = require("../../graphql-client/graphql-client").client;
const queries = require("../../graphql-client/queries");
const {
refresh: refreshOauthToken,
@@ -14,6 +16,8 @@ const {
} = require("./qbo-callback");
const OAuthClient = require("intuit-oauth");
var QuickBooks = require("node-quickbooks");
const GraphQLClient = require("graphql-request").GraphQLClient;
const { generateOwnerTier } = require("../qbxml/qbxml-utils");
const oauthClient = new OAuthClient({
clientId: process.env.QBO_CLIENT_ID,
@@ -25,83 +29,284 @@ const oauthClient = new OAuthClient({
exports.default = async (req, res) => {
try {
const response = await client.request(queries.GET_QBO_AUTH, {
//Fetch the API Access Tokens & Set them for the session.
const response = await apiGqlClient.request(queries.GET_QBO_AUTH, {
email: req.user.email,
});
response.associations[0].qbo_auth;
oauthClient.setToken(response.associations[0].qbo_auth);
if (!oauthClient.token.isAccessTokenValid()) {
await refreshOauthToken(oauthClient, req);
if (!oauthClient.token.isAccessTokenValid()) {
res.sendStatus(401);
}
}
const customerCreate = {
FullyQualifiedName: "A Test Customer",
DisplayName: "A test Customer",
};
// const ret = await oauthClient.makeApiCall({
// url: urlBuilder(req.cookies.qbo_realmId, "customer"),
// method: "POST",
// headers: {
// "Content-Type": "application/json",
// },
// body: JSON.stringify(customerCreate),
// });
// const invoice = {
// Line: [
// {
// DetailType: "SalesItemLineDetail",
// Amount: 100,
// SalesItemLineDetail: {
// ItemRef: {
// name: "Services",
// value: "1",
// },
// TaxCodeRef: {
// value: "2",
// },
// Qty: 1,
// UnitPrice: 100,
// },
// },
// ],
// CustomerRef: {
// name: "A test Customer",
// },
// };
// const ret2 = await oauthClient.makeApiCall({
// url: urlBuilder(req.cookies.qbo_realmId, "invoice"),
// method: "POST",
// headers: {
// "Content-Type": "application/json",
// },
// body: JSON.stringify(invoice),
// });
const ret2 = await oauthClient.makeApiCall({
url: urlBuilder(
req.cookies.qbo_realmId,
"query",
`select * From TaxCode where Active = true`
),
method: "POST",
const BearerToken = req.headers.authorization;
const { jobIds } = req.body;
//Query Job Info
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
headers: {
"Content-Type": "application/json",
Authorization: BearerToken,
},
// body: JSON.stringify(invoice),
});
setNewRefreshToken(req.user.email, ret2);
console.log(ret2);
res.send(ret2);
const result = await client
.setHeaders({ Authorization: BearerToken })
.request(queries.QUERY_JOBS_FOR_RECEIVABLES_EXPORT, {
ids: ["966dc7f9-2acd-44dc-9df5-d07c5578070a"],
//jobIds
});
const { jobs, bodyshops } = result;
const job = jobs[0];
const bodyshop = bodyshops[0];
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;
if (isThreeTier || twoTierPref === "source") {
//Insert the insurance company tier.
//Query for top level customer, the insurance company name.
insCoCustomerTier = await QueryInsuranceCo(oauthClient, req, job);
if (!insCoCustomerTier) {
//Creating the Insurance Customer.
insCoCustomerTier = await InsertInsuranceCo(
oauthClient,
req,
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, job);
//Query for the owner itself.
if (!ownerCustomerTier) {
ownerCustomerTier = await InsertOwner(
oauthClient,
req,
job,
isThreeTier,
insCoCustomerTier
);
}
}
//Query for the Job or Create it.
const jobrecord = await InsertJob(
oauthClient,
req,
job,
isThreeTier,
ownerCustomerTier
);
//Is there a job associated to the owner? If so, get the ID and move on.
//Otherwise create it.
res.sendStatus(200);
} catch (error) {
console.log(error);
res.status(400).json(error);
}
};
async function QueryInsuranceCo(oauthClient, req, job) {
const result = await oauthClient.makeApiCall({
url: urlBuilder(
req.cookies.qbo_realmId,
"query",
`select * From Customer where DisplayName = '${job.ins_co_nm}'`
),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
setNewRefreshToken(req.user.email, result);
return (
result.json &&
result.json.QueryResponse &&
result.json.QueryResponse.Customer &&
result.json.QueryResponse.Customer[0]
);
}
async function InsertInsuranceCo(oauthClient, req, job, bodyshop) {
const insCo = bodyshop.md_ins_cos.find((i) => i.name === job.ins_co_nm);
const Customer = {
DisplayName: job.ins_co_nm,
BillAddr: {
City: job.ownr_city,
Line1: insCo.street1,
Line2: insCo.street2,
PostalCode: insCo.zip,
CountrySubDivisionCode: insCo.state,
},
};
try {
const result = await oauthClient.makeApiCall({
url: urlBuilder(req.cookies.qbo_realmId, "customer"),
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(Customer),
});
setNewRefreshToken(req.user.email, result);
return result && result.Customer;
} catch (error) {
logger.log("qbo-receivables-error", "DEBUG", req.user.email, job.id, {
error,
method: "InsertInsuranceCo",
});
throw error;
}
}
async function QueryOwner(oauthClient, req, job) {
const ownerName = generateOwnerTier(job, true, null);
const result = await oauthClient.makeApiCall({
url: urlBuilder(
req.cookies.qbo_realmId,
"query",
`select * From Customer where DisplayName = '${ownerName}'`
),
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
setNewRefreshToken(req.user.email, result);
return (
result.json &&
result.json.QueryResponse &&
result.json.QueryResponse.Customer &&
result.json.QueryResponse.Customer[0]
);
}
async function InsertOwner(oauthClient, req, job, isThreeTier, parentTierRef) {
const ownerName = generateOwnerTier(job, true, null);
const Customer = {
DisplayName: ownerName,
BillAddr: {
City: job.ownr_city,
Line1: job.ownr_addr1,
Line2: job.ownr_addr2,
PostalCode: job.ownr_zip,
CountrySubDivisionCode: job.ownr_st,
},
...(isThreeTier
? {
Job: true,
ParentRef: {
value: parentTierRef.Id,
},
}
: {}),
};
try {
const result = await oauthClient.makeApiCall({
url: urlBuilder(req.cookies.qbo_realmId, "customer"),
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(Customer),
});
setNewRefreshToken(req.user.email, result);
return result && result.Customer;
} catch (error) {
logger.log("qbo-receivables-error", "DEBUG", req.user.email, job.id, {
error,
method: "InsertOwner",
});
throw error;
}
}
async function InsertJob(oauthClient, req, job, isThreeTier, parentTierRef) {
const Customer = {
DisplayName: job.ro_number,
BillAddr: {
City: job.ownr_city,
Line1: job.ownr_addr1,
Line2: job.ownr_addr2,
PostalCode: job.ownr_zip,
CountrySubDivisionCode: job.ownr_st,
},
...(isThreeTier
? {
Job: true,
ParentRef: {
value: parentTierRef.Id,
},
}
: {}),
};
try {
const result = await oauthClient.makeApiCall({
url: urlBuilder(req.cookies.qbo_realmId, "customer"),
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(Customer),
});
setNewRefreshToken(req.user.email, result);
return result && result.Customer;
} catch (error) {
logger.log("qbo-receivables-error", "DEBUG", req.user.email, job.id, {
error,
method: "InsertOwner",
});
throw error;
}
}
// const customerCreate = {
// FullyQualifiedName: "A Test Customer",
// DisplayName: "A test Customer",
// };
// const ret = await oauthClient.makeApiCall({
// url: urlBuilder(req.cookies.qbo_realmId, "customer"),
// method: "POST",
// headers: {
// "Content-Type": "application/json",
// },
// body: JSON.stringify(customerCreate),
// });
// const invoice = {
// Line: [
// {
// DetailType: "SalesItemLineDetail",
// Amount: 100,
// SalesItemLineDetail: {
// ItemRef: {
// name: "Services",
// value: "1",
// },
// TaxCodeRef: {
// value: "2",
// },
// Qty: 1,
// UnitPrice: 100,
// },
// },
// ],
// CustomerRef: {
// name: "A test Customer",
// },
// };
// const ret2 = await oauthClient.makeApiCall({
// url: urlBuilder(req.cookies.qbo_realmId, "invoice"),
// method: "POST",
// headers: {
// "Content-Type": "application/json",
// },
// body: JSON.stringify(invoice),
// });

View File

@@ -1,4 +1,3 @@
const OAuthClient = require("intuit-oauth");
const path = require("path");
require("dotenv").config({
path: path.resolve(

View File

@@ -114,6 +114,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
id
md_responsibility_centers
accountingconfig
md_ins_cos
}
}
`;