Succesful test imports to IO.
This commit is contained in:
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"prettier.trailingComma": "all",
|
||||||
|
"editor.formatOnSave": true
|
||||||
|
}
|
||||||
@@ -33,18 +33,18 @@ const DecodePfh = async (
|
|||||||
//TODO: Several of these fields will fail. Should extend schema to capture them.
|
//TODO: Several of these fields will fail. Should extend schema to capture them.
|
||||||
//"ID_PRO_NAM", //Remove
|
//"ID_PRO_NAM", //Remove
|
||||||
"TAX_PRETHR",
|
"TAX_PRETHR",
|
||||||
"TAX_THRAMT", //Remove
|
//"TAX_THRAMT", //Remove
|
||||||
"TAX_PSTTHR",
|
"TAX_PSTTHR",
|
||||||
"TAX_TOW_IN", //Remove
|
//"TAX_TOW_IN", //Remove
|
||||||
"TAX_TOW_RT",
|
"TAX_TOW_RT",
|
||||||
"TAX_STR_IN", //Remove
|
//"TAX_STR_IN", //Remove
|
||||||
"TAX_STR_RT",
|
"TAX_STR_RT",
|
||||||
"TAX_SUB_IN", //Remove
|
//"TAX_SUB_IN", //Remove
|
||||||
"TAX_SUB_RT",
|
"TAX_SUB_RT",
|
||||||
"TAX_BTR_IN", //Remove
|
//"TAX_BTR_IN", //Remove
|
||||||
"TAX_LBR_RT",
|
"TAX_LBR_RT",
|
||||||
"TAX_GST_RT",
|
"TAX_GST_RT",
|
||||||
"TAX_GST_IN", //Remove
|
//"TAX_GST_IN", //Remove
|
||||||
"ADJ_G_DISC",
|
"ADJ_G_DISC",
|
||||||
"ADJ_TOWDIS",
|
"ADJ_TOWDIS",
|
||||||
"ADJ_STRDIS",
|
"ADJ_STRDIS",
|
||||||
|
|||||||
@@ -137,9 +137,9 @@ const DecodePfm = async (
|
|||||||
...jobMaterialRates,
|
...jobMaterialRates,
|
||||||
materials: {
|
materials: {
|
||||||
mash: mashLine,
|
mash: mashLine,
|
||||||
mapa: mapaLine,
|
mapa: mapaLine, //TODO: Need to verify if more fields are to come in here.
|
||||||
},
|
},
|
||||||
cieca_pfm: rawPfmData,
|
//cieca_pfm: rawPfmData, //TODO: Not currently captured. This may have valu in the future.
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import deepLowerCaseKeys from "../../util/deepLowercaseKeys";
|
|||||||
import { DecodedVeh, VehicleRecordInterface } from "./decode-veh.interface";
|
import { DecodedVeh, VehicleRecordInterface } from "./decode-veh.interface";
|
||||||
import errorTypeCheck from "../../util/errorTypeCheck";
|
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||||
import store from "../store/store";
|
import store from "../store/store";
|
||||||
|
import typeCaster from "../../util/typeCaster";
|
||||||
|
|
||||||
const DecodeVeh = async (
|
const DecodeVeh = async (
|
||||||
extensionlessFilePath: string,
|
extensionlessFilePath: string,
|
||||||
@@ -28,35 +29,43 @@ const DecodeVeh = async (
|
|||||||
//AD2 will always have only 1 row.
|
//AD2 will always have only 1 row.
|
||||||
//Commented lines have been cross referenced with existing partner fields.
|
//Commented lines have been cross referenced with existing partner fields.
|
||||||
|
|
||||||
const rawVehData: VehicleRecordInterface = deepLowerCaseKeys(
|
//typeCaster is required as the previous partner sent some of these values toString, and the database was made accordingly rather than keeping their original type.
|
||||||
_.pick(rawDBFRecord[0], [
|
//Alternative is to change the database schema to match the original type.
|
||||||
//TODO: Add typings for EMS File Formats.
|
const rawVehData: VehicleRecordInterface = typeCaster(
|
||||||
"IMPACT_1",
|
deepLowerCaseKeys(
|
||||||
"IMPACT_2",
|
_.pick(rawDBFRecord[0], [
|
||||||
"DB_V_CODE",
|
//TODO: Add typings for EMS File Formats.
|
||||||
"PLATE_NO",
|
"IMPACT_1",
|
||||||
"PLATE_ST",
|
"IMPACT_2",
|
||||||
"V_VIN",
|
"DB_V_CODE",
|
||||||
"V_COND",
|
"PLATE_NO",
|
||||||
"V_PROD_DT",
|
"PLATE_ST",
|
||||||
"V_MODEL_YR",
|
"V_VIN",
|
||||||
"V_MAKECODE",
|
"V_COND",
|
||||||
"V_MAKEDESC",
|
"V_PROD_DT",
|
||||||
"V_MODEL",
|
"V_MODEL_YR",
|
||||||
"V_TYPE",
|
"V_MAKECODE",
|
||||||
"V_BSTYLE",
|
"V_MAKEDESC",
|
||||||
"V_TRIMCODE",
|
"V_MODEL",
|
||||||
"TRIM_COLOR",
|
"V_TYPE",
|
||||||
"V_MLDGCODE",
|
"V_BSTYLE",
|
||||||
"V_ENGINE",
|
"V_TRIMCODE",
|
||||||
"V_MILEAGE",
|
"TRIM_COLOR",
|
||||||
"V_COLOR",
|
"V_MLDGCODE",
|
||||||
"V_TONE",
|
"V_ENGINE",
|
||||||
"V_STAGE",
|
"V_MILEAGE",
|
||||||
"PAINT_CD1",
|
"V_COLOR",
|
||||||
"PAINT_CD2",
|
"V_TONE",
|
||||||
"PAINT_CD3",
|
"V_STAGE",
|
||||||
]),
|
"PAINT_CD1",
|
||||||
|
"PAINT_CD2",
|
||||||
|
"PAINT_CD3",
|
||||||
|
]),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
v_tone: "string",
|
||||||
|
v_stage: "string",
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
//Apply business logic transfomrations.
|
//Apply business logic transfomrations.
|
||||||
@@ -69,13 +78,16 @@ const DecodeVeh = async (
|
|||||||
delete rawVehData.v_model;
|
delete rawVehData.v_model;
|
||||||
|
|
||||||
//Consolidate Area of Damage.
|
//Consolidate Area of Damage.
|
||||||
rawVehData.area_of_damage = {
|
const area_of_damage = {
|
||||||
impact1: rawVehData.impact_1 ?? "",
|
impact1: rawVehData.impact_1 ?? "",
|
||||||
impact2: rawVehData.impact_2 ?? "",
|
impact2: rawVehData.impact_2 ?? "",
|
||||||
};
|
};
|
||||||
delete rawVehData.impact_1;
|
delete rawVehData.impact_1;
|
||||||
delete rawVehData.impact_2;
|
delete rawVehData.impact_2;
|
||||||
|
|
||||||
|
const kmin = rawVehData.v_mileage ?? 0;
|
||||||
|
delete rawVehData.v_mileage;
|
||||||
|
|
||||||
//Consolidate Paint Code information.
|
//Consolidate Paint Code information.
|
||||||
rawVehData.v_paint_codes = {
|
rawVehData.v_paint_codes = {
|
||||||
paint_cd1: rawVehData.paint_cd1 ?? "",
|
paint_cd1: rawVehData.paint_cd1 ?? "",
|
||||||
@@ -97,8 +109,8 @@ const DecodeVeh = async (
|
|||||||
v_make_desc: rawVehData.v_make_desc,
|
v_make_desc: rawVehData.v_make_desc,
|
||||||
v_model_desc: rawVehData.v_model_desc,
|
v_model_desc: rawVehData.v_model_desc,
|
||||||
v_color: rawVehData.v_color,
|
v_color: rawVehData.v_color,
|
||||||
kmin: rawVehData.v_mileage,
|
kmin: kmin,
|
||||||
area_of_damage: rawVehData.area_of_damage,
|
area_of_damage: area_of_damage,
|
||||||
vehicle: {
|
vehicle: {
|
||||||
data: rawVehData,
|
data: rawVehData,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import { UUID } from "crypto";
|
import { UUID } from "crypto";
|
||||||
|
import { Notification } from "electron";
|
||||||
import log from "electron-log/main";
|
import log from "electron-log/main";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import errorTypeCheck from "../../util/errorTypeCheck";
|
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||||
import client from "../graphql/graphql-client";
|
import client from "../graphql/graphql-client";
|
||||||
import {
|
import {
|
||||||
|
INSERT_AVAILABLE_JOB_TYPED,
|
||||||
|
InsertAvailableJobResult,
|
||||||
QUERY_JOB_BY_CLM_NO_TYPED,
|
QUERY_JOB_BY_CLM_NO_TYPED,
|
||||||
QUERY_VEHICLE_BY_VIN_TYPED,
|
QUERY_VEHICLE_BY_VIN_TYPED,
|
||||||
QueryJobByClmNoResult,
|
QueryJobByClmNoResult,
|
||||||
@@ -77,6 +80,7 @@ async function ImportJob(filepath: string): Promise<void> {
|
|||||||
...stl,
|
...stl,
|
||||||
...ttl,
|
...ttl,
|
||||||
...pfp,
|
...pfp,
|
||||||
|
shopid: store.get("app.bodyshop.id") as UUID,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save jobObject to a timestamped JSON file
|
// Save jobObject to a timestamped JSON file
|
||||||
@@ -100,11 +104,8 @@ async function ImportJob(filepath: string): Promise<void> {
|
|||||||
jobObject,
|
jobObject,
|
||||||
});
|
});
|
||||||
|
|
||||||
//Build the request object
|
|
||||||
|
|
||||||
//Insert it
|
|
||||||
const newAvailableJob: AvailableJobSchema = {
|
const newAvailableJob: AvailableJobSchema = {
|
||||||
uploaded_by: store.get("app.user.email"),
|
uploaded_by: store.get("user.email"),
|
||||||
bodyshopid: store.get("app.bodyshop.id"),
|
bodyshopid: store.get("app.bodyshop.id"),
|
||||||
cieca_id: jobObject.ciecaid,
|
cieca_id: jobObject.ciecaid,
|
||||||
est_data: jobObject,
|
est_data: jobObject,
|
||||||
@@ -141,8 +142,28 @@ async function ImportJob(filepath: string): Promise<void> {
|
|||||||
newAvailableJob.issupplement = true;
|
newAvailableJob.issupplement = true;
|
||||||
newAvailableJob.jobid = existingJobRecord.jobs[0].id;
|
newAvailableJob.jobid = existingJobRecord.jobs[0].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const insertRecordResult: InsertAvailableJobResult = await client.request(
|
||||||
|
INSERT_AVAILABLE_JOB_TYPED,
|
||||||
|
{
|
||||||
|
jobInput: [newAvailableJob],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
new Notification({
|
||||||
|
title: "Job Imported",
|
||||||
|
body: `Job ${newAvailableJob.cieca_id} imported successfully`,
|
||||||
|
actions: [{ text: "View Job", type: "button" }],
|
||||||
|
subtitle: newAvailableJob.ownr_name,
|
||||||
|
}).show();
|
||||||
|
|
||||||
|
log.debug("Job inserted", insertRecordResult);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error("Error encountered while decoding job. ", errorTypeCheck(error));
|
log.error("Error encountered while decoding job. ", errorTypeCheck(error));
|
||||||
|
new Notification({
|
||||||
|
title: "Job Upload Failure",
|
||||||
|
body: errorTypeCheck(error).message, //TODO: Remove after debug.
|
||||||
|
actions: [{ text: "View Job", type: "button" }],
|
||||||
|
}).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,6 +184,7 @@ export interface RawJobDataObject
|
|||||||
DecodedTtl,
|
DecodedTtl,
|
||||||
DecodedPfp {
|
DecodedPfp {
|
||||||
vehicleid?: UUID;
|
vehicleid?: UUID;
|
||||||
|
shopid: UUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AvailableJobSchema {
|
export interface AvailableJobSchema {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"toolbar": {
|
"toolbar": {
|
||||||
"help": "Help"
|
"help": "Help"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"translation": {
|
"translation": {
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"home": "Home",
|
"home": "Home",
|
||||||
"settings": "Settings"
|
"settings": "Settings"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"addpath": "Add path",
|
"addpath": "Add path",
|
||||||
"startwatcher": "Start Watcher",
|
"startwatcher": "Start Watcher",
|
||||||
"stopwatcher": "Stop Watcher\n"
|
"stopwatcher": "Stop Watcher\n"
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"started": "Started",
|
"started": "Started",
|
||||||
"stopped": "Stopped",
|
"stopped": "Stopped",
|
||||||
"watcherstatus": "Watcher Status"
|
"watcherstatus": "Watcher Status"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
62
src/util/typeCaster.ts
Normal file
62
src/util/typeCaster.ts
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/**
|
||||||
|
* Casts specified properties of an object to the desired types
|
||||||
|
*
|
||||||
|
* @param obj The object whose properties need to be cast
|
||||||
|
* @param typeMappings An object where keys are property names from the source object
|
||||||
|
* and values are the type to cast to ('string', 'number', 'boolean', etc.)
|
||||||
|
* @returns A new object with the specified properties cast to their desired types
|
||||||
|
*/
|
||||||
|
function typeCaster<T extends object, K extends keyof T>(
|
||||||
|
obj: T,
|
||||||
|
typeMappings: Partial<
|
||||||
|
Record<K, "string" | "number" | "boolean" | "object" | "array">
|
||||||
|
>,
|
||||||
|
): T {
|
||||||
|
const result = { ...obj };
|
||||||
|
|
||||||
|
for (const key in typeMappings) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
||||||
|
const targetType = typeMappings[key];
|
||||||
|
const value = obj[key];
|
||||||
|
|
||||||
|
switch (targetType) {
|
||||||
|
case "string":
|
||||||
|
(result as any)[key] = String(value);
|
||||||
|
break;
|
||||||
|
case "number":
|
||||||
|
(result as any)[key] = Number(value);
|
||||||
|
break;
|
||||||
|
case "boolean":
|
||||||
|
(result as any)[key] = Boolean(value);
|
||||||
|
break;
|
||||||
|
case "object":
|
||||||
|
if (value && typeof value !== "object") {
|
||||||
|
try {
|
||||||
|
(result as any)[key] = JSON.parse(String(value));
|
||||||
|
} catch {
|
||||||
|
(result as any)[key] = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "array":
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
(result as any)[key] = value;
|
||||||
|
} else if (value && typeof value === "string") {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(value);
|
||||||
|
(result as any)[key] = Array.isArray(parsed) ? parsed : [parsed];
|
||||||
|
} catch {
|
||||||
|
(result as any)[key] = [value];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(result as any)[key] = value ? [value] : [];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default typeCaster;
|
||||||
Reference in New Issue
Block a user