Add opcode and bodyshop query to main

This commit is contained in:
Patrick Fic
2025-03-21 08:33:41 -07:00
parent 6345b5a9a8
commit 6da5822197
9 changed files with 199 additions and 40 deletions

View File

@@ -2,8 +2,9 @@ import { DBFFile } from "dbffile";
import log from "electron-log/main";
import _ from "lodash";
import deepLowerCaseKeys from "../../util/deepLowercaseKeys";
import { DecodedLin, DecodedLinLine } from "./decode-lin.interface";
import errorTypeCheck from "../../util/errorTypeCheck";
import store from "../store/store";
import { DecodedLin, DecodedLinLine } from "./decode-lin.interface";
const DecodeLin = async (
extensionlessFilePath: string
@@ -25,6 +26,7 @@ const DecodeLin = async (
//AD2 will always have only 1 row.
//Commented lines have been cross referenced with existing partner fields.
const opCodeData = store.get("app.masterdata.opcodes"); //TODO: Type the op codes
const rawLinData: DecodedLinLine[] = rawDBFRecord.map((record) => {
const singleLineData: DecodedLinLine = deepLowerCaseKeys(
@@ -81,17 +83,7 @@ const DecodeLin = async (
])
);
//Apply line by line adjustments.
singleLineData.op_code_desc = ""; //TODO: Implement the OP Code Lookup.
//Partner previously queried this on login and stored it. Then referenced it and added here.
// Sample Code:
// try
// {
// lin.op_code_desc = Utils.AppMetaData.CiecaOpCodes[lin.lbr_op.Value]["desc"].Value;
// }
// catch (Exception Ex)
// {
// logger.Warn(Ex, "Couldnt find OpCodeDesc from {0} ", lin.lbr_op.Value);
// }
singleLineData.op_code_desc = opCodeData[singleLineData.lbr_op]?.desc;
return singleLineData;
});

View File

@@ -28,6 +28,8 @@ import { DecodedVeh } from "./decode-veh.interface";
import { DecodedEnv } from "./decode-env.interface";
import DecodeEnv from "./decode-env";
import fs from "fs";
import store from "../store/store";
import client from "../graphql/graphql-client";
async function ImportJob(filepath: string): Promise<void> {
const parsedFilePath = path.parse(filepath);
@@ -90,6 +92,52 @@ async function ImportJob(filepath: string): Promise<void> {
log.debug("Job Object", {
jobObject,
});
//Build the request object
//Insert it
const newAvailableJob = {
// newJob.uploaded_by = Auth.authlink.User.Email;
// newJob.bodyshopid = AppMetaData.ActiveShopId;
// newJob.cieca_id = item.Job.ciecaid;
// newJob.est_data = item.Job;
// newJob.ownr_name = item.Job.ownr_fn?.Value + " " + item.Job.ownr_ln?.Value + " " + item.Job.ownr_co_nm?.Value;
// newJob.ins_co_nm = item.Job.ins_co_nm?.Value;
// newJob.vehicle_info = item.Job.vehicle.data.v_model_yr?.Value + " " + item.Job.vehicle.data.v_make_desc?.Value + " " + item.Job.vehicle.data.v_model_desc?.Value;
// newJob.clm_no = item.Job.clm_no?.Value;
// newJob.clm_amt = item.Job.clm_total?.Value;
// newJob.source_system = item.Job.source_system?.Value;
uploaded_by: store.get("app.user.email"),
bodyshopid: store.get("app.bodyshop.id"),
cieca_id: jobObject.ciecaid,
est_data: jobObject,
ownr_name: `${jobObject.ownr_fn} ${jobObject.ownr_ln} ${jobObject.ownr_co_nm}`,
ins_co_nm: jobObject.ins_co_nm,
vehicle_info: `${jobObject.v_model_yr} ${jobObject.v_make_desc} ${jobObject.v_model_desc}`,
clm_no: jobObject.clm_no,
clm_amt: jobObject.clm_total,
// source_system: jobObject.source_system, //TODO: Add back source system if needed.
};
const existingVehicleId: uuid = await client.query ()
// var vehuuid = await Utils.Queries.VehicleQueries.GetVehicleUuidByVin(item?.Job?.vehicle?.data?.v_vin?.Value ?? "");
// if (!string.IsNullOrEmpty(vehuuid))
// {
// newJob.est_data.vehicle = null;
// newJob.est_data.vehicleid = vehuuid;
// }
// string jobId = await Utils.Queries.JobsQueries.CheckSupplementByClaimNo(item.Job.clm_no?.Value ?? "");
// if (!string.IsNullOrEmpty(jobId))
// {
// newJob.issupplement = true;
// newJob.jobid = jobId;
// };
//Check if the vehicle exists, if it does, use that UUID, if not, keep it to insert it.
} catch (error) {
log.error("Error encountered while decoding job. ", errorTypeCheck(error));
}

View File

@@ -6,6 +6,13 @@ import ipcTypes from "../../util/ipcTypes.json";
const requestMiddleware: RequestMiddleware = async (request) => {
const token = await getTokenFromRenderer();
log.info(
`%c[Graphql Request]%c${request.operationName}`,
"color: red",
"color: green",
request
);
return {
...request,
headers: { ...request.headers, Authorization: `Bearer ${token}` },

View File

@@ -0,0 +1,73 @@
import { parse, TypedQueryDocumentNode } from "graphql";
import { gql } from "graphql-request";
// Define types for the query result and variables
export interface ActiveBodyshopQueryResult {
bodyshops: Array<{
id: string;
shopname: string;
region_config: string;
}>;
}
// No variables needed for this query
interface ActiveBodyshopQueryVariables {}
// Transform the string query into a TypedQueryDocumentNode
export const QUERY_ACTIVE_BODYSHOP_TYPED: TypedQueryDocumentNode<
ActiveBodyshopQueryResult,
ActiveBodyshopQueryVariables
> = parse(gql`
query QUERY_ACTIVE_BODYSHOP {
bodyshops(where: { associations: { active: { _eq: true } } }) {
id
shopname
region_config
}
}
`);
export interface MasterdataQueryResult {
masterdata: Array<{
value: string;
key: string;
}>;
}
interface MasterdataQueryVariables {
key: string;
}
export const QUERY_MASTERDATA_TYPED: TypedQueryDocumentNode<
MasterdataQueryResult,
MasterdataQueryVariables
> = parse(gql`
query QUERY_MASTERDATA($key: String!) {
masterdata(where: { key: { _eq: $key } }) {
value
key
}
}
`);
export interface VehicleQueryResult {
masterdata: Array<{
value: string;
key: string;
}>;
}
interface VehicleQueryVariables {
vin: string;
}
export const QUERY_VEHICLE_BY_VIN_TYPED: TypedQueryDocumentNode<
VehicleQueryResult,
VehicleQueryVariables
> = parse(gql`
query QUERY_VEHICLE_BY_VIN($vin: String!) {
vehicles(where: { v_vin: { _eq: $vin } }) {
id
}
}
`);

View File

@@ -150,6 +150,14 @@ function createWindow(): void {
shell.openPath(path.dirname(store.path));
},
},
{
label: "Log the Store",
click: (): void => {
log.debug(
"Store Contents" + JSON.stringify(store.store, null, 4)
);
},
},
{
type: "separator",
},

View File

@@ -49,17 +49,15 @@ if (import.meta.env.DEV) {
log.debug("[IPC Debug Functions] Adding Debug Handlers");
ipcMain.on(ipcTypes.toMain.debug.decodeEstimate, async (): Promise<void> => {
// const relativeEmsFilepath = `_reference/ems/MPI_1/3698420.ENV`;
// // Get the app's root directory and create an absolute path
// const rootDir = app.getAppPath();
// const absoluteFilepath = path.join(rootDir, relativeEmsFilepath);
// console.log("*** ~ ipcMain.on ~ absoluteFilepath:", absoluteFilepath);
const relativeEmsFilepath = `_reference/ems/MPI_1/3698420.ENV`;
// Get the app's root directory and create an absolute path
const rootDir = app.getAppPath();
const absoluteFilepath = path.join(rootDir, relativeEmsFilepath);
// log.debug("[IPC Debug Function] Decode test Estimate", absoluteFilepath);
// await ImportJob(absoluteFilepath);
log.debug("[IPC Debug Function] Decode test Estimate", absoluteFilepath);
await ImportJob(absoluteFilepath);
const job2 = `/Users/pfic/Downloads/12285264/2285264.ENV`;
const job3 = `/Users/pfic/Downloads/14033376/4033376.ENV`;
await ImportJob(job2);
await ImportJob(job3);

View File

@@ -1,12 +1,38 @@
import { IpcMainEvent } from "electron";
import { User } from "firebase/auth";
import client from "../graphql/graphql-client";
import {
ActiveBodyshopQueryResult,
MasterdataQueryResult,
QUERY_ACTIVE_BODYSHOP_TYPED,
QUERY_MASTERDATA_TYPED,
} from "../graphql/queries";
import Store from "../store/store";
import log from "electron-log/main";
const ipcMainHandleAuthStateChanged = async (
event: IpcMainEvent,
user: User | null
): Promise<void> => {
Store.set("user", user);
//Need to query the currently active shop, and store the metadata as well.
//Also need to query the OP Codes for decoding reference.
const activeBodyshop: ActiveBodyshopQueryResult = await client.request(
QUERY_ACTIVE_BODYSHOP_TYPED
);
Store.set("app.bodyshop", activeBodyshop.bodyshops[0]);
const OpCodes: MasterdataQueryResult = await client.request(
QUERY_MASTERDATA_TYPED,
{
key: `${activeBodyshop.bodyshops[0].region_config}_ciecaopcodes`,
}
);
Store.set("app.masterdata.opcodes", JSON.parse(OpCodes.masterdata[0]?.value));
log.debug("Received authentication state change from Renderer.", user);
log.debug("Requery shop information & master data.");
};
export { ipcMainHandleAuthStateChanged };

View File

@@ -17,8 +17,9 @@ const store = new Store({
y: undefined,
},
user: null,
bodyshop: {
id: "6089913a-7522-49e7-8c96-786a488b738d", //TODO: Remove hard coded default.
bodyshop: {},
masterdata: {
opcodes: null,
},
},
},

View File

@@ -1,33 +1,39 @@
import "@ant-design/v5-patch-for-react-19";
import { Layout } from "antd";
import { User } from "firebase/auth";
import { useState } from "react";
import { BrowserRouter, Route, Routes } from "react-router";
import ipcTypes from "../../util/ipcTypes.json";
import NavigationHeader from "./components/NavigationHeader/Navigationheader";
import SignInForm from "./components/SignInForm/SignInForm";
import { auth } from "./util/firebase";
import { useEffect, useState } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { Provider } from "react-redux";
import { BrowserRouter, Route, Routes } from "react-router";
import ipcTypes from "../../util/ipcTypes";
import ErrorBoundaryFallback from "./components/ErrorBoundaryFallback/ErrorBoundaryFallback";
import Home from "./components/Home/Home";
import NavigationHeader from "./components/NavigationHeader/Navigationheader";
import Settings from "./components/Settings/Settings";
import { Provider } from "react-redux";
import SignInForm from "./components/SignInForm/SignInForm";
import reduxStore from "./redux/redux-store";
import { auth } from "./util/firebase";
const App: React.FC = () => {
const [user, setUser] = useState<User | null>(null);
auth.onAuthStateChanged((user: User | null) => {
setUser(user);
//Send back to the main process so that it knows we are authenticated.
if (user) {
window.electron.ipcRenderer.send(
ipcTypes.toMain.authStateChanged,
user.toJSON()
);
window.electron.ipcRenderer.send(ipcTypes.toMain.watcher.start);
}
});
useEffect(() => {
// Only set up the listener once when component mounts
const unsubscribe = auth.onAuthStateChanged((user: User | null) => {
setUser(user);
//Send back to the main process so that it knows we are authenticated.
if (user) {
window.electron.ipcRenderer.send(
ipcTypes.toMain.authStateChanged,
user.toJSON()
);
window.electron.ipcRenderer.send(ipcTypes.toMain.watcher.start);
}
});
// Clean up the listener when component unmounts
return (): void => unsubscribe();
}, []);
return (
<Provider store={reduxStore}>