diff --git a/.gitignore b/.gitignore
index 3e33d8a2b..590787f08 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,7 +114,7 @@ firebase/.env
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml
logs/oAuthClient-log.log
-
+logs/*
.node-persist/**
diff --git a/client/src/components/dms-cdk-makes/dms-cdk-makes.refetch.component.jsx b/client/src/components/dms-cdk-makes/dms-cdk-makes.refetch.component.jsx
index 641f0e8c1..0020cbfd5 100644
--- a/client/src/components/dms-cdk-makes/dms-cdk-makes.refetch.component.jsx
+++ b/client/src/components/dms-cdk-makes/dms-cdk-makes.refetch.component.jsx
@@ -1,4 +1,4 @@
-import { Button } from "antd";
+import { Button, Space } from "antd";
import axios from "axios";
import { useState } from "react";
import { useTranslation } from "react-i18next";
@@ -42,9 +42,29 @@ export function DmsCdkMakesRefetch({ currentUser, bodyshop }) {
setLoading(false);
};
+
+ const handleGetCOA = async () => {
+ try {
+ setLoading(true);
+ await axios.post(`cdk/fortellis/getCOA`, {
+ cdk_dealerid: bodyshop.cdk_dealerid,
+ bodyshopid: bodyshop.id
+ });
+ } catch (error) {
+ console.error(error);
+ }
+
+ setLoading(false);
+ };
+
return (
-
+
+
+
+
);
}
diff --git a/server/cdk/cdk-get-makes.js b/server/cdk/cdk-get-makes.js
index 962a1af9d..319ecd131 100644
--- a/server/cdk/cdk-get-makes.js
+++ b/server/cdk/cdk-get-makes.js
@@ -131,6 +131,7 @@ async function GetFortellisMakes(req, cdk_dealerid) {
socket: { emit: () => null },
jobid: null,
body: {},
+ debug: true,
SubscriptionObject: {
SubscriptionID: cdk_dealerid
}
@@ -147,6 +148,45 @@ async function GetFortellisMakes(req, cdk_dealerid) {
}
}
+async function GetFortellisCOA(req) {
+ const { cdk_dealerid } = req.body;
+ try {
+ logger.log("fortellis-get-COA", "DEBUG", req.user?.email, null, {
+ cdk_dealerid
+ });
+ const result = await MakeFortellisCall({
+ ...FortellisActions.GetCOA,
+ headers: {},
+ redisHelpers: {
+ setSessionTransactionData: () => {
+ return null;
+ },
+ getSessionTransactionData: () => {
+ return null;
+ }
+ },
+ socket: { emit: () => null },
+ jobid: null,
+ body: {},
+ debug: true,
+ SubscriptionObject: {
+ SubscriptionID: cdk_dealerid
+ }
+ });
+
+ return result.data?.data;
+ } catch (error) {
+ logger.log("fortellis-get-COA-error", "ERROR", req.user?.email, null, {
+ cdk_dealerid,
+ error: error.message,
+ stack: error.stack
+ });
+
+ throw new Error(error);
+ }
+}
+exports.fortellisCOA = GetFortellisCOA
+
exports.fortellis = async function ReloadFortellisMakes(req, res) {
const { bodyshopid, cdk_dealerid } = req.body;
try {
diff --git a/server/fortellis/fortellis-helpers.js b/server/fortellis/fortellis-helpers.js
index 5020fa337..62ac1c0e2 100644
--- a/server/fortellis/fortellis-helpers.js
+++ b/server/fortellis/fortellis-helpers.js
@@ -312,6 +312,27 @@ function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
+async function writeFortellisLogToFile(logObject) {
+ try {
+ const logsDir = path.join(process.cwd(), 'logs');
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
+ const filename = `fortellis-${timestamp}.json`;
+ const filepath = path.join(logsDir, filename);
+
+ console.log(`[writeFortellisLogToFile] Writing to: ${filepath}`);
+ console.log(`[writeFortellisLogToFile] process.cwd(): ${process.cwd()}`);
+
+ // Ensure logs directory exists
+ await fs.mkdir(logsDir, { recursive: true });
+
+ // Write log object to file
+ await fs.writeFile(filepath, JSON.stringify(logObject, null, 2), 'utf8');
+
+ console.log(`Fortellis log written to: ${filepath}`,);
+ } catch (err) {
+ console.error('Failed to write Fortellis log to file:', err);
+ }
+}
async function WriteToIOEventLog({ apiName, type, fullUrl, bodyshopid, useremail, logger, socket }) {
try {
@@ -351,6 +372,7 @@ async function WriteToIOEventLog({ apiName, type, fullUrl, bodyshopid, useremail
}
}
+
const isProduction = process.env.NODE_ENV === "production";
//Get requests should have the trailing slash as they are used that way in the calls.
@@ -427,8 +449,10 @@ const FortellisActions = {
},
GetCOA: {
type: "get",
- apiName: "CDK Drive Post Accounts GL WIP",
- url: `https://api.fortellis.io/cdk-test/drive/chartofaccounts/v2/bulk/`,
+ apiName: "CDK Drive Get Chart of Accounts",
+ url: isProduction
+ ? "https://api.fortellis.io/cdk/drive/chartofaccounts/v2/bulk"
+ : "https://api.fortellis.io/cdk-test/drive/chartofaccounts/v2/bulk",
waitForResult: true
},
StartWip: {
diff --git a/server/fortellis/fortellis.js b/server/fortellis/fortellis.js
index 7862dbda8..bb808e36b 100644
--- a/server/fortellis/fortellis.js
+++ b/server/fortellis/fortellis.js
@@ -189,7 +189,17 @@ async function FortellisSelectedCustomer({ socket, redisHelpers, selectedCustome
let DMSCust;
if (selectedCustomerId) {
CreateFortellisLogEvent(socket, "DEBUG", `{3.1} Querying the Customer using Customer ID: ${selectedCustomerId}`);
- DMSCust = await QueryDmsCustomerById({ socket, redisHelpers, JobData, CustomerId: selectedCustomerId }); //TODO: Optimize here - if selected ID, we already have the customer information. Prevent an extra call to Fortellis.
+
+ //Get cust list from Redis. Return the item
+ const DMSCustList = await getSessionTransactionData(
+ socket.id,
+ getTransactionType(jobid),
+ FortellisCacheEnums.DMSCustList
+ );
+ const existingCustomerInDMSCustList = DMSCustList.find((c) => c.customerId === selectedCustomerId);
+ DMSCust = existingCustomerInDMSCustList || {
+ customerId: selectedCustomerId //This is the fall back in case it is the generic customer.
+ };
await setSessionTransactionData(
socket.id,
getTransactionType(jobid),
@@ -197,6 +207,8 @@ async function FortellisSelectedCustomer({ socket, redisHelpers, selectedCustome
DMSCust,
defaultFortellisTTL
);
+
+
} else {
CreateFortellisLogEvent(socket, "DEBUG", `{3.2} Creating new customer.`);
const DMSCustomerInsertResponse = await InsertDmsCustomer({ socket, redisHelpers, JobData });
@@ -215,26 +227,32 @@ async function FortellisSelectedCustomer({ socket, redisHelpers, selectedCustome
CreateFortellisLogEvent(socket, "DEBUG", `{4.1} Inserting new vehicle with ID: ID ${DMSVid.vehiclesVehId}`);
DMSVeh = await InsertDmsVehicle({ socket, redisHelpers, JobData, txEnvelope, DMSVid, DMSCust });
} else {
- CreateFortellisLogEvent(socket, "DEBUG", `{4.2} Querying Existing Vehicle using ID ${DMSVid.vehiclesVehId}`);
- DMSVeh = await QueryDmsVehicleById({ socket, redisHelpers, JobData, DMSVid });
-
- CreateFortellisLogEvent(socket, "DEBUG", `{4.3} Updating Existing Vehicle to associate to owner.`);
- DMSVeh = await UpdateDmsVehicle({
- socket,
- redisHelpers,
- JobData,
- DMSVeh,
- DMSCust,
- selectedCustomerId,
- txEnvelope
- });
- await setSessionTransactionData(
+ DMSVeh = await getSessionTransactionData(
socket.id,
getTransactionType(jobid),
- FortellisCacheEnums.DMSVeh,
- DMSVeh,
- defaultFortellisTTL
- ); //TODO: This should be immutable probably.F
+ FortellisCacheEnums.DMSVeh
+ )
+ CreateFortellisLogEvent(socket, "DEBUG", `{4.3} Updating Existing Vehicle to associate to owner.`);
+
+ //Check to see if the vehicle needs to be updated - i.e. the owner is not the selected customer.
+ if (!DMSVeh?.owners.find((o) => o.id.value === DMSCust.customerId && o.id.assigningPartyId === "CURRENT")) {
+ DMSVeh = await UpdateDmsVehicle({
+ socket,
+ redisHelpers,
+ JobData,
+ DMSVeh,
+ DMSCust,
+ selectedCustomerId,
+ txEnvelope
+ });
+ await setSessionTransactionData(
+ socket.id,
+ getTransactionType(jobid),
+ FortellisCacheEnums.DMSVeh,
+ DMSVeh,
+ defaultFortellisTTL
+ );
+ }
}
// const DMSVehHistory = await InsertServiceVehicleHistory({ socket, redisHelpers, JobData });
// await setSessionTransactionData(socket.id, getTransactionType(jobid), FortellisCacheEnums.DMSVehHistory, DMSVehHistory, defaultFortellisTTL);
@@ -293,7 +311,6 @@ async function FortellisSelectedCustomer({ socket, redisHelpers, selectedCustome
// //Get the error code
CreateFortellisLogEvent(socket, "DEBUG", `{6.1} Getting errors for Transaction ID ${DMSTransHeader.transID}`);
- await QueryDmsErrWip({ socket, redisHelpers, JobData });
const DmsError = await QueryDmsErrWip({ socket, redisHelpers, JobData });
// //Delete the transaction
@@ -301,7 +318,7 @@ async function FortellisSelectedCustomer({ socket, redisHelpers, selectedCustome
await DeleteDmsWip({ socket, redisHelpers, JobData });
- DmsError.errLine.map(
+ DmsError.errMsg.map(
(e) =>
e !== null &&
e !== "" &&
@@ -310,7 +327,7 @@ async function FortellisSelectedCustomer({ socket, redisHelpers, selectedCustome
await InsertFailedExportLog({
socket,
JobData,
- error: DmsError.errLine
+ error: DmsError.errMsg
});
}
}
@@ -1027,7 +1044,6 @@ async function InsertDmsStartWip({ socket, redisHelpers, JobData }) {
// userID: "partprgm",
// userName: "PROGRAM, PARTNER"
},
- //overrideDepartmentId: "D100152198" //TODO: REMOVE AFTER TESTING
});
return result;
} catch (error) {
diff --git a/server/routes/cdkRoutes.js b/server/routes/cdkRoutes.js
index 056142842..6a32a3af2 100644
--- a/server/routes/cdkRoutes.js
+++ b/server/routes/cdkRoutes.js
@@ -9,6 +9,7 @@ router.use(validateFirebaseIdTokenMiddleware);
router.post("/getvehicles", withUserGraphQLClientMiddleware, cdkGetMake.default);
router.post("/fortellis/getvehicles", withUserGraphQLClientMiddleware, cdkGetMake.fortellis);
+router.post("/fortellis/getCOA", withUserGraphQLClientMiddleware, cdkGetMake.fortellisCOA);
router.post("/calculate-allocations", withUserGraphQLClientMiddleware, cdkCalculateAllocations.defaultRoute);
module.exports = router;