const urlBuilder = require("./qbo").urlBuilder; const path = require("path"); require("dotenv").config({ path: path.resolve( process.cwd(), `.env.${process.env.NODE_ENV || "development"}` ), }); const logger = require("../../utils/logger"); 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"); 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, clientSecret: process.env.QBO_SECRET, environment: process.env.NODE_ENV === "production" ? "production" : "sandbox", redirectUri: process.env.QBO_REDIRECT_URI, logging: true, }); exports.default = async (req, res) => { try { //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 BearerToken = req.headers.authorization; const { jobIds } = req.body; //Query Job Info const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, { headers: { Authorization: BearerToken, }, }); 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), // });