WIP Fortellis work.
This commit is contained in:
@@ -11,6 +11,11 @@ Department ID
|
|||||||
- May have multiple departments. Appears that financial stuff goes to Accounting, History will go to Service.
|
- May have multiple departments. Appears that financial stuff goes to Accounting, History will go to Service.
|
||||||
- TODO: How do we handle the multiple departments that may come up.
|
- TODO: How do we handle the multiple departments that may come up.
|
||||||
|
|
||||||
|
###Internal Questions
|
||||||
|
|
||||||
|
* Overview of the redis storing mechanism to cache this data.
|
||||||
|
*
|
||||||
|
|
||||||
# GL Wip Posting
|
# GL Wip Posting
|
||||||
|
|
||||||
## Org Helper Return Data
|
## Org Helper Return Data
|
||||||
|
|||||||
8504
_reference/Fortellis COA.json
Normal file
8504
_reference/Fortellis COA.json
Normal file
File diff suppressed because it is too large
Load Diff
199
fortellis.js
199
fortellis.js
@@ -1,46 +1,34 @@
|
|||||||
const path = require('path');
|
const path = require("path");
|
||||||
const Dinero = require('dinero.js');
|
const AxiosLib = require("axios").default;
|
||||||
const { gql } = require('graphql-request');
|
|
||||||
const queries = require('./server/graphql-client/queries');
|
|
||||||
const GraphQLClient = require('graphql-request').GraphQLClient;
|
|
||||||
const logger = require('./server/utils/logger');
|
|
||||||
const { header } = require('./server/email/html');
|
|
||||||
const { Transaction } = require('firebase-admin/firestore');
|
|
||||||
const AxiosLib = require('axios').default;
|
|
||||||
const axios = AxiosLib.create();
|
const axios = AxiosLib.create();
|
||||||
const uuid = require('uuid').v4;
|
const uuid = require("uuid").v4;
|
||||||
|
|
||||||
const FORTELLIS_KEY = 'X1FxzLyOk3kjHvMbzdPQXFZShkdbgzuo';
|
const FORTELLIS_KEY = "X1FxzLyOk3kjHvMbzdPQXFZShkdbgzuo";
|
||||||
const FORTELLIS_SECRET = '7Yvs0wpQeHcUS5r95ht8pqOaAvBq7dHV';
|
const FORTELLIS_SECRET = "7Yvs0wpQeHcUS5r95ht8pqOaAvBq7dHV";
|
||||||
const FORTELLIS_AUTH_URL = 'https://identity.fortellis.io/oauth2/aus1p1ixy7YL8cMq02p7/v1/token';
|
const FORTELLIS_AUTH_URL = "https://identity.fortellis.io/oauth2/aus1p1ixy7YL8cMq02p7/v1/token";
|
||||||
const FORTELLIS_URL = 'https://api.fortellis.io';
|
const FORTELLIS_URL = "https://api.fortellis.io";
|
||||||
const ENVSubscriptionID = '5b527d7d-baf3-40bc-adae-e7a541e37363';
|
const ENVSubscriptionID = "5b527d7d-baf3-40bc-adae-e7a541e37363"; //Given to us by CDK it seems.
|
||||||
let SubscriptionMeta = null;
|
let SubscriptionMeta = null;
|
||||||
//const ENVSubscriptionID = 'cb59fa04-e53e-4b57-b071-80a48ebc346c';
|
//const ENVSubscriptionID = 'cb59fa04-e53e-4b57-b071-80a48ebc346c';
|
||||||
|
|
||||||
function sleep(time, callback) {
|
|
||||||
var stop = new Date().getTime();
|
|
||||||
while (new Date().getTime() < stop + time) {}
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
async function GetAuthToken() {
|
async function GetAuthToken() {
|
||||||
//Done with Authorization Code Flow
|
//Done with Authorization Code Flow
|
||||||
//https://docs.fortellis.io/docs/tutorials/solution-integration/authorization-code-flow/
|
//https://docs.fortellis.io/docs/tutorials/solution-integration/authorization-code-flow/
|
||||||
const {
|
const {
|
||||||
data: { access_token, expires_in, token_type },
|
data: { access_token, expires_in, token_type }
|
||||||
} = await axios.post(
|
} = await axios.post(
|
||||||
FORTELLIS_AUTH_URL,
|
FORTELLIS_AUTH_URL,
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
auth: {
|
auth: {
|
||||||
username: FORTELLIS_KEY,
|
username: FORTELLIS_KEY,
|
||||||
password: FORTELLIS_SECRET,
|
password: FORTELLIS_SECRET
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
grant_type: 'client_credentials',
|
grant_type: "client_credentials",
|
||||||
scope: 'anonymous',
|
scope: "anonymous"
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
return access_token;
|
return access_token;
|
||||||
}
|
}
|
||||||
@@ -48,52 +36,40 @@ async function GetAuthToken() {
|
|||||||
async function FetchSubscriptions() {
|
async function FetchSubscriptions() {
|
||||||
const access_token = await GetAuthToken();
|
const access_token = await GetAuthToken();
|
||||||
try {
|
try {
|
||||||
const subscriptions = await axios.get(
|
const subscriptions = await axios.get(`https://subscriptions.fortellis.io/v1/solution/subscriptions`, {
|
||||||
`https://subscriptions.fortellis.io/v1/solution/subscriptions`,
|
headers: { Authorization: `Bearer ${access_token}` }
|
||||||
{
|
});
|
||||||
headers: { Authorization: `Bearer ${access_token}` },
|
SubscriptionMeta = subscriptions.data.subscriptions.find((s) => s.subscriptionId === ENVSubscriptionID);
|
||||||
},
|
|
||||||
);
|
|
||||||
SubscriptionMeta = subscriptions.data.subscriptions.find(
|
|
||||||
(s) => s.subscriptionId === ENVSubscriptionID,
|
|
||||||
);
|
|
||||||
return SubscriptionMeta;
|
return SubscriptionMeta;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('🚀 ~ FetchSubscriptions ~ error:', error);
|
console.log("🚀 ~ FetchSubscriptions ~ error:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetDepartmentId({ apiName, debug = false }) {
|
async function GetDepartmentId({ apiName, debug = false }) {
|
||||||
if (!apiName) throw new Error('apiName not provided. Unable to get department without apiName.');
|
if (!apiName) throw new Error("apiName not provided. Unable to get department without apiName.");
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log('API Names & Departments ');
|
console.log("API Names & Departments ");
|
||||||
console.log('===========');
|
console.log("===========");
|
||||||
console.log(
|
console.log(
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
SubscriptionMeta.apiDmsInfo.map((a) => ({
|
SubscriptionMeta.apiDmsInfo.map((a) => ({
|
||||||
name: a.name,
|
name: a.name,
|
||||||
departments: a.departments.map((d) => d.id),
|
departments: a.departments.map((d) => d.id)
|
||||||
})),
|
})),
|
||||||
null,
|
null,
|
||||||
4,
|
4
|
||||||
),
|
)
|
||||||
);
|
);
|
||||||
console.log('===========');
|
console.log("===========");
|
||||||
}
|
}
|
||||||
const departmentIds2 = SubscriptionMeta.apiDmsInfo //Get the subscription object.
|
const departmentIds2 = SubscriptionMeta.apiDmsInfo //Get the subscription object.
|
||||||
.find((info) => info.name === apiName)?.departments; //Departments are categorized by API name and have an array of departments.
|
.find((info) => info.name === apiName)?.departments; //Departments are categorized by API name and have an array of departments.
|
||||||
|
|
||||||
return departmentIds2[0].id;
|
return departmentIds2[0].id; //TODO: This makes the assumption that there is only 1 department.
|
||||||
}
|
}
|
||||||
|
|
||||||
async function MakeFortellisCall({
|
async function MakeFortellisCall({ apiName, url, headers = {}, body = {}, type = "post", debug = false }) {
|
||||||
apiName,
|
|
||||||
url,
|
|
||||||
headers = {},
|
|
||||||
body = {},
|
|
||||||
type = 'post',
|
|
||||||
debug = false,
|
|
||||||
}) {
|
|
||||||
if (debug) console.log(`Executing ${type} to ${url}`);
|
if (debug) console.log(`Executing ${type} to ${url}`);
|
||||||
const ReqId = uuid();
|
const ReqId = uuid();
|
||||||
const access_token = await GetAuthToken();
|
const access_token = await GetAuthToken();
|
||||||
@@ -101,7 +77,7 @@ async function MakeFortellisCall({
|
|||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log(
|
console.log(
|
||||||
`ReqID: ${ReqId} | SubscriptionID: ${SubscriptionMeta.subscriptionId} | DepartmentId: ${DepartmentId}`,
|
`ReqID: ${ReqId} | SubscriptionID: ${SubscriptionMeta.subscriptionId} | DepartmentId: ${DepartmentId}`
|
||||||
);
|
);
|
||||||
console.log(`Body Contents: ${JSON.stringify(body, null, 4)}`);
|
console.log(`Body Contents: ${JSON.stringify(body, null, 4)}`);
|
||||||
}
|
}
|
||||||
@@ -109,27 +85,27 @@ async function MakeFortellisCall({
|
|||||||
try {
|
try {
|
||||||
let result;
|
let result;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'post':
|
case "post":
|
||||||
default:
|
default:
|
||||||
result = await axios.post(url, body, {
|
result = await axios.post(url, body, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${access_token}`,
|
Authorization: `Bearer ${access_token}`,
|
||||||
'Subscription-Id': SubscriptionMeta.subscriptionId,
|
"Subscription-Id": SubscriptionMeta.subscriptionId,
|
||||||
'Request-Id': ReqId,
|
"Request-Id": ReqId,
|
||||||
'Department-Id': DepartmentId,
|
"Department-Id": DepartmentId,
|
||||||
...headers,
|
...headers
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'get':
|
case "get":
|
||||||
result = await axios.get(url, {
|
result = await axios.get(url, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${access_token}`,
|
Authorization: `Bearer ${access_token}`,
|
||||||
'Subscription-Id': SubscriptionMeta.subscriptionId,
|
"Subscription-Id": SubscriptionMeta.subscriptionId,
|
||||||
'Request-Id': ReqId,
|
"Request-Id": ReqId,
|
||||||
'Department-Id': DepartmentId,
|
"Department-Id": DepartmentId,
|
||||||
...headers,
|
...headers
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -138,39 +114,84 @@ async function MakeFortellisCall({
|
|||||||
console.log(`ReqID: ${ReqId} Data`);
|
console.log(`ReqID: ${ReqId} Data`);
|
||||||
console.log(JSON.stringify(result.data, null, 4));
|
console.log(JSON.stringify(result.data, null, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.data.checkStatusAfterSeconds) {
|
||||||
|
return DelayedCallback({
|
||||||
|
delayMeta: result.data,
|
||||||
|
access_token,
|
||||||
|
SubscriptionID: SubscriptionMeta.subscriptionId,
|
||||||
|
ReqId,
|
||||||
|
departmentIds: DepartmentId
|
||||||
|
});
|
||||||
|
}
|
||||||
return result.data;
|
return result.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(`ReqID: ${ReqId} Error`, error.response?.data);
|
console.log(`ReqID: ${ReqId} Error`, error.response?.data);
|
||||||
//console.log(`ReqID: ${ReqId} Full Error`, JSON.stringify(error, null, 4));
|
//console.log(`ReqID: ${ReqId} Full Error`, JSON.stringify(error, null, 4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//Get the status meta, then keep checking and return the result.
|
||||||
|
async function DelayedCallback({ delayMeta, access_token, SubscriptionID, ReqId, departmentIds }) {
|
||||||
|
for (let index = 0; index < 5; index++) {
|
||||||
|
await sleep(delayMeta.checkStatusAfterSeconds * 1000);
|
||||||
|
//Check to see if the call is ready.
|
||||||
|
const statusResult = await axios.get(delayMeta._links.status.href, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${access_token}`,
|
||||||
|
"Subscription-Id": SubscriptionID,
|
||||||
|
"Request-Id": ReqId,
|
||||||
|
"Department-Id": departmentIds[0].id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//TODO: Add a check if the status result is not ready, to try again.
|
||||||
|
if (statusResult.data.status === "complete") {
|
||||||
|
//This may have to check again if it isn't ready.
|
||||||
|
const batchResult = await axios.get(statusResult.data._links.result.href, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${access_token}`,
|
||||||
|
"Subscription-Id": SubscriptionID,
|
||||||
|
"Request-Id": ReqId,
|
||||||
|
//"Department-Id": departmentIds[0].id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return batchResult;
|
||||||
|
} else {
|
||||||
|
return "Error!!! Still need to implement batch waiting.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function sleep(ms) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
}
|
||||||
|
|
||||||
async function GetCOA() {
|
async function GetCOA() {
|
||||||
console.log('Executing GetCOA');
|
console.log("Executing GetCOA");
|
||||||
await MakeFortellisCall({
|
await MakeFortellisCall({
|
||||||
debug: true,
|
debug: true,
|
||||||
type: 'get',
|
type: "get",
|
||||||
apiName: 'CDK Drive Post Accounts GL WIP',
|
apiName: "CDK Drive Post Accounts GL WIP",
|
||||||
url: `https://api.fortellis.io/cdk-test/drive/chartofaccounts/v2/bulk`,
|
url: `https://api.fortellis.io/cdk-test/drive/chartofaccounts/v2/bulk`,
|
||||||
|
waitForResult: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function StartWIP() {
|
async function StartWIP() {
|
||||||
const TransactionWip = MakeFortellisCall({
|
const TransactionWip = MakeFortellisCall({
|
||||||
url: 'https://api.fortellis.io/cdk-test/drive/glwippost/startWIP',
|
url: "https://api.fortellis.io/cdk-test/drive/glwippost/startWIP",
|
||||||
apiName: 'CDK Drive Post Accounts GL WIP',
|
apiName: "CDK Drive Post Accounts GL WIP",
|
||||||
body: {
|
body: {
|
||||||
acctgDate: '2023-09-26', //job.invoice
|
acctgDate: "2023-09-26", //job.invoice
|
||||||
desc: 'TEST TRANSACTION',
|
desc: "TEST TRANSACTION",
|
||||||
docType: '3', //pulled from Doc Type workbook
|
docType: "3", //pulled from Doc Type workbook
|
||||||
m13Flag: '0', // Is this a M13 entry. Presumanbly always 0
|
m13Flag: "0", // Is this a M13 entry. Presumanbly always 0
|
||||||
refer: 'RO12345', //Supposed to be a doc reference number. Presumably the RO?
|
refer: "RO12345", //Supposed to be a doc reference number. Presumably the RO?
|
||||||
srcCo: '77',
|
srcCo: "77",
|
||||||
srcJrnl: '80',
|
srcJrnl: "80",
|
||||||
userID: 'csr', //bodyshop user
|
userID: "csr", //bodyshop user
|
||||||
userName: 'PROGRAM, PARTNER*ADP', //Can leave blank to have this return to default.
|
userName: "PROGRAM, PARTNER*ADP" //Can leave blank to have this return to default.
|
||||||
},
|
},
|
||||||
debug: true,
|
debug: true
|
||||||
});
|
});
|
||||||
|
|
||||||
return TransactionWip;
|
return TransactionWip;
|
||||||
@@ -178,30 +199,30 @@ async function StartWIP() {
|
|||||||
|
|
||||||
async function InsertBatch({ transID }) {
|
async function InsertBatch({ transID }) {
|
||||||
const TransactionWip = MakeFortellisCall({
|
const TransactionWip = MakeFortellisCall({
|
||||||
url: 'https://api.fortellis.io/cdk-test/drive/glwippost/transWIP',
|
url: "https://api.fortellis.io/cdk-test/drive/glwippost/transWIP",
|
||||||
apiName: 'CDK Drive Post Accounts GL WIP',
|
apiName: "CDK Drive Post Accounts GL WIP",
|
||||||
body: [
|
body: [
|
||||||
{
|
{
|
||||||
acct: '',
|
acct: "",
|
||||||
cntl: '',
|
cntl: "",
|
||||||
cntl2: null,
|
cntl2: null,
|
||||||
credtMemoNo: null,
|
credtMemoNo: null,
|
||||||
postAmt: Math.round(payer.amount * 100),
|
postAmt: Math.round(payer.amount * 100),
|
||||||
postDesc: '', //Required if required by the DMS setup
|
postDesc: "", //Required if required by the DMS setup
|
||||||
prod: null, //Productivity Number
|
prod: null, //Productivity Number
|
||||||
statCnt: 1, //Auto count, leave as 1.
|
statCnt: 1, //Auto count, leave as 1.
|
||||||
transID: transID,
|
transID: transID,
|
||||||
trgtCoID: '77', //Add this to read from the header
|
trgtCoID: "77" //Add this to read from the header
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
debug: true,
|
debug: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function DoTheThings() {
|
async function DoTheThings() {
|
||||||
await FetchSubscriptions();
|
await FetchSubscriptions();
|
||||||
//What do we have access to?
|
//What do we have access to?
|
||||||
console.log('Sub Access : ', SubscriptionMeta.apiDmsInfo.map((i) => i.name).join(', '));
|
console.log("Sub Access : ", SubscriptionMeta.apiDmsInfo.map((i) => i.name).join(", "));
|
||||||
await GetCOA();
|
await GetCOA();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -16,9 +16,12 @@ const moment = require("moment-timezone");
|
|||||||
const replaceSpecialRegex = /[^a-zA-Z0-9 .,\n #]+/g;
|
const replaceSpecialRegex = /[^a-zA-Z0-9 .,\n #]+/g;
|
||||||
|
|
||||||
exports.default = async function (socket, { txEnvelope, jobid }) {
|
exports.default = async function (socket, { txEnvelope, jobid }) {
|
||||||
|
////Store the following information into the redis store for this transaction.
|
||||||
socket.logEvents = [];
|
socket.logEvents = [];
|
||||||
socket.recordid = jobid;
|
socket.recordid = jobid;
|
||||||
socket.txEnvelope = txEnvelope;
|
socket.txEnvelope = txEnvelope;
|
||||||
|
////
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CdkBase.createLogEvent(socket, "DEBUG", `Received Job export request for id ${jobid}`);
|
CdkBase.createLogEvent(socket, "DEBUG", `Received Job export request for id ${jobid}`);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user