Refactor PPC to pull out reusable componenets.

This commit is contained in:
Patrick Fic
2025-04-04 09:12:38 -07:00
parent 85fcecf856
commit f3adc76574
17 changed files with 957 additions and 451 deletions

View File

@@ -0,0 +1,38 @@
import { DBFFile } from "dbffile";
import { envFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/env-field-descriptor";
import { deleteEmsFileIfExists, generatePpcFilePath } from "../util/ems-util";
import { EmsPartsOrder } from "./ems-parts-order-interfaces";
const EmsPartsOrderGenerateEnvFile = async (
partsOrder: EmsPartsOrder,
): Promise<boolean> => {
const records = [
{
EST_SYSTEM: "C",
RO_ID: partsOrder.job.ro_number,
ESTFILE_ID: partsOrder.job.ciecaid,
STATUS: false,
INCL_ADMIN: true,
INCL_VEH: true,
INCL_EST: true,
INCL_PROFL: true,
INCL_TOTAL: true,
INCL_VENDR: false,
},
];
await deleteEmsFileIfExists(
generatePpcFilePath(`${partsOrder.job.ciecaid}.ENV`),
);
const dbf = await DBFFile.create(
generatePpcFilePath(`${partsOrder.job.ciecaid}.ENV`),
envFieldLineDescriptors,
);
await dbf.appendRecords(records);
console.log(`${records.length} LIN file records added.`);
return true;
};
export default EmsPartsOrderGenerateEnvFile;

View File

@@ -0,0 +1,53 @@
import log from "electron-log/main";
import express from "express";
import _ from "lodash";
import errorTypeCheck from "../../util/errorTypeCheck";
import store from "../store/store";
import createdDirectoryIfNotExist from "../util/createDirectoryIfNotExist";
import EmsPartsOrderGenerateEnvFile from "./ems-parts-order-generate-env";
import { EmsPartsOrder } from "./ems-parts-order-interfaces";
const handleEMSPartsOrder = async (
req: express.Request,
res: express.Response,
): Promise<void> => {
//Route handler here only.
const partsOrderBody = req.body as EmsPartsOrder;
try {
await generateEMSPartsOrder(partsOrderBody);
res.status(200).json({ success: true });
} catch (error) {
log.error("Error generating parts price change", errorTypeCheck(error));
res.status(500).json({
success: false,
error: "Error generating parts price change.",
...errorTypeCheck(error),
});
}
return;
};
const generateEMSPartsOrder = async (
partsOrder: EmsPartsOrder,
): Promise<void> => {
log.debug(" Generating parts price change");
//Check to make sure that the EMS Output file path exists. If it doesn't, create it. If it's not set, abandon ship.
const emsOutFilePath: string | null = store.get("settings.emsOutFilePath");
if (_.isEmpty(emsOutFilePath) || emsOutFilePath === null) {
log.error("EMS Out file path is not set");
throw new Error("EMS Out file path is not set");
}
try {
createdDirectoryIfNotExist(emsOutFilePath);
//Generate all required files: ad1, ad2, veh, lin, pfh, pfl, pfm,pfo, pfp, pft, stl, ttl
await EmsPartsOrderGenerateEnvFile(partsOrder);
} catch (error) {
log.error("Error generating parts price change", errorTypeCheck(error));
throw error;
}
};
export { handleEMSPartsOrder };

View File

@@ -0,0 +1,308 @@
export interface TaxRate {
prt_type: string;
prt_discp: number;
prt_mktyp: boolean;
prt_mkupp: number;
prt_tax_in: boolean;
prt_tax_rt: number;
}
export interface BillTaxRates {
local_tax_rate: number;
state_tax_rate: number;
federal_tax_rate: number;
}
export interface PaintCodes {
paint_cd1: string | null;
paint_cd2: string | null;
paint_cd3: string | null;
}
export interface AreaOfDamage {
impact1: string;
impact2: string | null;
}
// Jobline export interface
export interface Jobline {
tran_code: string;
act_price: number;
db_ref: string;
db_price: number;
db_hrs: number;
glass_flag: boolean;
id: string;
lbr_amt: number;
lbr_hrs_j: boolean;
lbr_inc: boolean;
lbr_op: string;
lbr_op_j: boolean;
lbr_tax: boolean;
lbr_typ_j: boolean;
line_desc: string;
line_ind: string;
line_no: number;
line_ref: number;
location: string | null;
misc_amt: number;
misc_sublt: boolean;
misc_tax: boolean;
mod_lb_hrs: number;
mod_lbr_ty: string;
oem_partno: string;
op_code_desc: string;
paint_stg: number;
paint_tone: number;
part_qty: number;
part_type: string;
price_inc: boolean;
price_j: boolean;
prt_dsmk_m: number;
prt_dsmk_p: number;
tax_part: boolean;
unq_seq: number;
alt_co_id: string | null;
alt_overrd: boolean;
alt_part_i: boolean;
alt_partm: string | null;
alt_partno: string | null;
bett_amt: number;
bett_pctg: number;
bett_tax: boolean;
bett_type: string | null;
cert_part: boolean;
est_seq: string | null;
}
// Parts Order Line export interface
export interface PartsOrderLine {
jobline: Jobline;
act_price: number;
id: string;
db_price: number;
line_desc: string;
quantity: number;
part_type: string;
}
// Vehicle export interface
export interface Vehicle {
v_bstyle: string;
v_type: string;
v_trimcode: string | null;
v_tone: string;
v_stage: string;
v_prod_dt: string | null;
v_options: string | null;
v_paint_codes: PaintCodes;
v_model_yr: string;
v_model_desc: string;
v_mldgcode: string | null;
v_makecode: string;
v_make_desc: string;
v_engine: string;
v_cond: string;
v_color: string | null;
trim_color: string | null;
shopid: string;
plate_no: string;
plate_st: string;
db_v_code: string;
v_vin: string;
}
// Bodyshop export interface
export interface Bodyshop {
shopname: string;
bill_tax_rates: BillTaxRates;
}
// Job export interface
export interface Job {
bodyshop: Bodyshop;
ro_number: string;
clm_no: string;
asgn_no: string;
asgn_date: string;
state_tax_rate: number | null;
area_of_damage: AreaOfDamage;
asgn_type: string | null;
ciecaid: string;
clm_addr1: string | null;
clm_city: string | null;
clm_addr2: string | null;
clm_ct_fn: string | null;
clm_ct_ln: string | null;
clm_ct_ph: string | null;
clm_ct_phx: string | null;
clm_ctry: string | null;
clm_ea: string | null;
clm_fax: string | null;
clm_faxx: string | null;
clm_ofc_id: string | null;
clm_ofc_nm: string | null;
clm_ph1: string | null;
clm_ph1x: string | null;
clm_ph2: string | null;
clm_ph2x: string | null;
clm_st: string | null;
clm_title: string | null;
clm_total: number;
clm_zip: string | null;
ded_amt: number;
est_addr1: string | null;
est_addr2: string | null;
est_city: string | null;
est_co_nm: string | null;
est_ct_fn: string;
est_ctry: string | null;
est_ct_ln: string;
est_ea: string;
est_ph1: string | null;
est_st: string | null;
est_zip: string | null;
g_bett_amt: number;
id: string;
ins_addr1: string | null;
ins_city: string | null;
ins_addr2: string | null;
ins_co_id: string | null;
ins_co_nm: string;
ins_ct_fn: string | null;
ins_ct_ln: string | null;
ins_ct_ph: string | null;
ins_ct_phx: string | null;
ins_ctry: string | null;
ins_ea: string | null;
ins_fax: string | null;
ins_faxx: string | null;
ins_memo: string | null;
ins_ph1: string | null;
ins_ph1x: string | null;
ins_ph2: string | null;
ins_ph2x: string | null;
ins_st: string | null;
ins_title: string | null;
ins_zip: string | null;
insd_addr1: string;
insd_addr2: string | null;
insd_city: string;
insd_co_nm: string | null;
insd_ctry: string | null;
insd_ea: string | null;
insd_fax: string | null;
insd_faxx: string | null;
insd_fn: string;
insd_ln: string;
insd_ph1: string;
insd_ph1x: string | null;
insd_ph2: string;
insd_ph2x: string | null;
insd_st: string;
insd_title: string | null;
insd_zip: string;
loss_cat: string;
loss_date: string;
loss_desc: string;
loss_of_use: string | null;
loss_type: string;
ownr_addr1: string;
ownr_addr2: string | null;
ownr_city: string;
ownr_co_nm: string | null;
ownr_ctry: string | null;
ownr_ea: string | null;
ownr_fax: string | null;
ownr_faxx: string | null;
ownr_ph1: string;
ownr_fn: string;
ownr_ln: string;
ownr_ph1x: string | null;
ownr_ph2: string;
ownr_ph2x: string | null;
ownr_st: string;
ownr_title: string | null;
ownr_zip: string;
parts_tax_rates: Record<string, TaxRate>;
pay_amt: number;
pay_date: string | null;
pay_type: string | null;
pay_chknm: string;
payee_nms: string | null;
plate_no: string;
plate_st: string;
po_number: string | null;
policy_no: string;
tax_lbr_rt: number;
tax_levies_rt: number;
tax_paint_mat_rt: number;
tax_predis: number;
tax_prethr: number;
tax_pstthr: number;
tax_registration_number: string | null;
tax_str_rt: number;
tax_shop_mat_rt: number;
tax_sub_rt: number;
tax_thramt: number;
tax_tow_rt: number;
theft_ind: boolean;
tlos_ind: boolean;
towin: boolean;
v_color: string | null;
v_make_desc: string;
v_model_desc: string;
v_model_yr: string;
v_vin: string;
vehicle: Vehicle;
agt_zip: string | null;
agt_st: string | null;
agt_ph2x: string | null;
agt_ph2: string | null;
agt_ph1x: string | null;
agt_ph1: string | null;
agt_lic_no: string | null;
agt_faxx: string | null;
agt_fax: string | null;
agt_ea: string | null;
agt_ctry: string | null;
agt_ct_phx: string | null;
agt_ct_ph: string | null;
agt_ct_ln: string | null;
agt_ct_fn: string | null;
agt_co_nm: string | null;
agt_co_id: string | null;
agt_city: string | null;
agt_addr1: string | null;
agt_addr2: string | null;
adj_g_disc: number;
rate_matd: number | null;
rate_mash: number;
rate_mapa: number;
rate_mahw: number;
rate_macs: number;
rate_mabl: number | null;
rate_ma3s: number;
rate_ma2t: number;
rate_ma2s: number;
rate_lau: number;
rate_las: number;
rate_lar: number;
rate_lam: number;
rate_lag: number;
rate_laf: number;
rate_lae: number | null;
rate_lad: number | null;
rate_lab: number;
rate_laa: number;
rate_la4: number;
rate_la3: number;
rate_la2: number;
rate_la1: number;
}
// Main Parts Order export interface
export interface EmsPartsOrder {
parts_order_lines: PartsOrderLine[];
job: Job;
}

View File

@@ -8,6 +8,7 @@ import ImportJob from "../decoder/decoder";
import folderScan from "../decoder/folder-scan";
import { handlePartsPariceChangeRequest } from "../ppc/ppc-handler";
import { handleQuickBookRequest } from "../quickbooks-desktop/quickbooks-desktop";
import { handleEMSPartsOrder } from "../ems-parts-order/ems-parts-order-handler";
export default class LocalServer {
private app: express.Application;
@@ -119,6 +120,7 @@ export default class LocalServer {
return;
});
this.app.post("/ppc", handlePartsPariceChangeRequest);
this.app.post("/oec", handleEMSPartsOrder);
this.app.post(
"/import",
async (req: express.Request, res: express.Response) => {

View File

@@ -14,6 +14,8 @@ import {
SettingsWatchedFilePathsRemove,
SettingsWatcherPollingGet,
SettingsWatcherPollingSet,
SettingEmsOutFilPathSet,
SettingEmsOutFilPathGet,
} from "./ipcMainHandler.settings";
import {
ipcMainHandleAuthStateChanged,
@@ -98,6 +100,14 @@ ipcMain.handle(
ipcMain.handle(ipcTypes.toMain.settings.getPpcFilePath, SettingsPpcFilPathGet);
ipcMain.handle(ipcTypes.toMain.settings.setPpcFilePath, SettingsPpcFilPathSet);
ipcMain.handle(
ipcTypes.toMain.settings.getEmsOutFilePath,
SettingEmsOutFilPathGet,
);
ipcMain.handle(
ipcTypes.toMain.settings.setEmsOutFilePath,
SettingEmsOutFilPathSet,
);
ipcMain.handle(ipcTypes.toMain.user.getActiveShop, () => {
return store.get("app.bodyshop.shopname");

View File

@@ -96,6 +96,27 @@ const SettingsPpcFilPathSet = async (): Promise<string> => {
return (Store.get("settings.ppcFilePath") as string) || "";
};
const SettingEmsOutFilPathGet = async (): Promise<string> => {
const emsOutFilePath: string = Store.get("settings.emsOutFilePath");
return emsOutFilePath;
};
const SettingEmsOutFilPathSet = async (): Promise<string> => {
const mainWindow = getMainWindow();
if (!mainWindow) {
log.error("No main window found when trying to open dialog");
return "";
}
const result = await dialog.showOpenDialog(mainWindow, {
properties: ["openDirectory"],
});
if (!result.canceled) {
Store.set("settings.emsOutFilePath", result.filePaths[0]); //There should only ever be on directory that was selected.
}
return (Store.get("settings.emsOutFilePath") as string) || "";
};
export {
SettingsPpcFilPathGet,
SettingsPpcFilPathSet,
@@ -104,4 +125,6 @@ export {
SettingsWatchedFilePathsRemove,
SettingsWatcherPollingGet,
SettingsWatcherPollingSet,
SettingEmsOutFilPathGet,
SettingEmsOutFilPathSet,
};

View File

@@ -1,8 +1,6 @@
import { DBFFile, FieldDescriptor } from "dbffile";
import {
deleteEmsFileIfExists,
generatePpcFilePath,
} from "./ppc-generate-file";
import { DBFFile } from "dbffile";
import { envFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/env-field-descriptor";
import { deleteEmsFileIfExists, generatePpcFilePath } from "../util/ems-util";
import { PpcJob } from "./ppc-handler";
const GenerateEnvFile = async (job: PpcJob): Promise<boolean> => {
@@ -20,7 +18,6 @@ const GenerateEnvFile = async (job: PpcJob): Promise<boolean> => {
INCL_VENDR: false,
},
];
//Check if it already exists, delete it if so.
await deleteEmsFileIfExists(generatePpcFilePath(`${job.ciecaid}.ENV`));
@@ -35,157 +32,3 @@ const GenerateEnvFile = async (job: PpcJob): Promise<boolean> => {
};
export default GenerateEnvFile;
//Taken from a set of CCC ems files.
const envFieldLineDescriptors: FieldDescriptor[] = [
{
name: "EST_SYSTEM",
type: "C",
size: 1,
decimalPlaces: 0,
},
{
name: "SW_VERSION",
type: "C",
size: 10,
decimalPlaces: 0,
},
{
name: "DB_VERSION",
type: "C",
size: 12,
decimalPlaces: 0,
},
{
name: "DB_DATE",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "UNQFILE_ID",
type: "C",
size: 8,
decimalPlaces: 0,
},
{
name: "RO_ID",
type: "C",
size: 8,
decimalPlaces: 0,
},
{
name: "ESTFILE_ID",
type: "C",
size: 38,
decimalPlaces: 0,
},
{
name: "SUPP_NO",
type: "C",
size: 3,
decimalPlaces: 0,
},
{
name: "EST_CTRY",
type: "C",
size: 3,
decimalPlaces: 0,
},
{
name: "TOP_SECRET",
type: "C",
size: 80,
decimalPlaces: 0,
},
{
name: "H_TRANS_ID",
type: "C",
size: 9,
decimalPlaces: 0,
},
{
name: "H_CTRL_NO",
type: "C",
size: 9,
decimalPlaces: 0,
},
{
name: "TRANS_TYPE",
type: "C",
size: 1,
decimalPlaces: 0,
},
{
name: "STATUS",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "CREATE_DT",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "CREATE_TM",
type: "C",
size: 6,
decimalPlaces: 0,
},
{
name: "TRANSMT_DT",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "TRANSMT_TM",
type: "C",
size: 6,
decimalPlaces: 0,
},
{
name: "INCL_ADMIN",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_VEH",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_EST",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_PROFL",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_TOTAL",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_VENDR",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "EMS_VER",
type: "C",
size: 5,
decimalPlaces: 0,
},
];

View File

@@ -1,8 +1,6 @@
import { DBFFile, FieldDescriptor } from "dbffile";
import {
deleteEmsFileIfExists,
generatePpcFilePath,
} from "./ppc-generate-file";
import { DBFFile } from "dbffile";
import { linFieldDescriptors } from "../util/ems-interface/fielddescriptors/lin-field-descriptor";
import { deleteEmsFileIfExists, generatePpcFilePath } from "../util/ems-util";
import { PpcJob } from "./ppc-handler";
const GenerateLinFile = async (job: PpcJob): Promise<boolean> => {
@@ -14,7 +12,6 @@ const GenerateLinFile = async (job: PpcJob): Promise<boolean> => {
ACT_PRICE: line.act_price,
};
});
//Check if it already exists, delete it if so.
await deleteEmsFileIfExists(generatePpcFilePath(`${job.ciecaid}.LIN`));
@@ -29,277 +26,3 @@ const GenerateLinFile = async (job: PpcJob): Promise<boolean> => {
};
export default GenerateLinFile;
//Taken from a set of CCC ems files.
const linFieldDescriptors: FieldDescriptor[] = [
{
name: "LINE_NO",
type: "N",
size: 3,
decimalPlaces: 0,
},
{
name: "LINE_IND",
type: "C",
size: 3,
decimalPlaces: 0,
},
{
name: "LINE_REF",
type: "N",
size: 3,
decimalPlaces: 0,
},
{
name: "TRAN_CODE",
type: "C",
size: 1,
decimalPlaces: 0,
},
{
name: "DB_REF",
type: "C",
size: 7,
decimalPlaces: 0,
},
{
name: "UNQ_SEQ",
type: "N",
size: 4,
decimalPlaces: 0,
},
{
name: "WHO_PAYS",
type: "C",
size: 2,
decimalPlaces: 0,
},
{
name: "LINE_DESC",
type: "C",
size: 40,
decimalPlaces: 0,
},
{
name: "PART_TYPE",
type: "C",
size: 4,
decimalPlaces: 0,
},
{
name: "PART_DES_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "GLASS_FLAG",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "OEM_PARTNO",
type: "C",
size: 25,
decimalPlaces: 0,
},
{
name: "PRICE_INC",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "ALT_PART_I",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "TAX_PART",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "DB_PRICE",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "ACT_PRICE",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "PRICE_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "CERT_PART",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "PART_QTY",
type: "N",
size: 2,
decimalPlaces: 0,
},
{
name: "ALT_CO_ID",
type: "C",
size: 20,
decimalPlaces: 0,
},
{
name: "ALT_PARTNO",
type: "C",
size: 25,
decimalPlaces: 0,
},
{
name: "ALT_OVERRD",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "ALT_PARTM",
type: "C",
size: 45,
decimalPlaces: 0,
},
{
name: "PRT_DSMK_P",
type: "N",
size: 7,
decimalPlaces: 2,
},
{
name: "PRT_DSMK_M",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "MOD_LBR_TY",
type: "C",
size: 4,
decimalPlaces: 0,
},
{
name: "DB_HRS",
type: "N",
size: 5,
decimalPlaces: 1,
},
{
name: "MOD_LB_HRS",
type: "N",
size: 5,
decimalPlaces: 1,
},
{
name: "LBR_INC",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_OP",
type: "C",
size: 4,
decimalPlaces: 0,
},
{
name: "LBR_HRS_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_TYP_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_OP_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "PAINT_STG",
type: "N",
size: 1,
decimalPlaces: 0,
},
{
name: "PAINT_TONE",
type: "N",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_TAX",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_AMT",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "MISC_AMT",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "MISC_SUBLT",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "MISC_TAX",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "BETT_TYPE",
type: "C",
size: 4,
decimalPlaces: 0,
},
{
name: "BETT_PCTG",
type: "N",
size: 8,
decimalPlaces: 4,
},
{
name: "BETT_AMT",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "BETT_TAX",
type: "L",
size: 1,
decimalPlaces: 0,
},
];

View File

@@ -1,13 +1,12 @@
import { UUID } from "crypto";
import log from "electron-log/main";
import express from "express";
import fs from "fs";
import _ from "lodash";
import path from "path";
import errorTypeCheck from "../../util/errorTypeCheck";
import store from "../store/store";
import GenerateLinFile from "./ppc-generate-lin";
import createdDirectoryIfNotExist from "../util/createDirectoryIfNotExist";
import GenerateEnvFile from "./ppc-generate-env";
import GenerateLinFile from "./ppc-generate-lin";
const handlePartsPariceChangeRequest = async (
req: express.Request,
@@ -40,12 +39,8 @@ const generatePartsPriceChange = async (job: PpcJob): Promise<void> => {
throw new Error("PPC file path is not set");
}
try {
//If the directory doesn't exist, create it.
const directoryPath = path.dirname(ppcOutFilePath);
if (!fs.existsSync(directoryPath)) {
log.info(`Directory does not exist. Creating: ${directoryPath}`);
fs.mkdirSync(directoryPath, { recursive: true });
}
createdDirectoryIfNotExist(ppcOutFilePath);
await GenerateLinFile(job);
await GenerateEnvFile(job);
} catch (error) {

View File

@@ -6,6 +6,7 @@ const store = new Store({
runOnStartup: true,
filepaths: [],
ppcFilePath: null,
emsOutFilePath: null,
qbFilePath: "",
runWatcherOnStartup: true,
polling: {

View File

@@ -0,0 +1,21 @@
import log from "electron-log/main";
import fs from "fs";
import path from "path";
import errorTypeCheck from "../../util/errorTypeCheck";
const createdDirectoryIfNotExist = async (dirpath: string) => {
try {
const directoryPath = path.dirname(dirpath);
if (!fs.existsSync(directoryPath)) {
log.info(`Directory does not exist. Creating: ${directoryPath}`);
fs.mkdirSync(directoryPath, { recursive: true });
}
} catch (error) {
log.error("Error creating directory as needed", errorTypeCheck(error));
throw new Error(
"Error creating directory: " + errorTypeCheck(error).message,
);
}
};
export default createdDirectoryIfNotExist;

View File

@@ -0,0 +1,154 @@
import { FieldDescriptor } from "dbffile";
export const envFieldLineDescriptors: FieldDescriptor[] = [
{
name: "EST_SYSTEM",
type: "C",
size: 1,
decimalPlaces: 0,
},
{
name: "SW_VERSION",
type: "C",
size: 10,
decimalPlaces: 0,
},
{
name: "DB_VERSION",
type: "C",
size: 12,
decimalPlaces: 0,
},
{
name: "DB_DATE",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "UNQFILE_ID",
type: "C",
size: 8,
decimalPlaces: 0,
},
{
name: "RO_ID",
type: "C",
size: 8,
decimalPlaces: 0,
},
{
name: "ESTFILE_ID",
type: "C",
size: 38,
decimalPlaces: 0,
},
{
name: "SUPP_NO",
type: "C",
size: 3,
decimalPlaces: 0,
},
{
name: "EST_CTRY",
type: "C",
size: 3,
decimalPlaces: 0,
},
{
name: "TOP_SECRET",
type: "C",
size: 80,
decimalPlaces: 0,
},
{
name: "H_TRANS_ID",
type: "C",
size: 9,
decimalPlaces: 0,
},
{
name: "H_CTRL_NO",
type: "C",
size: 9,
decimalPlaces: 0,
},
{
name: "TRANS_TYPE",
type: "C",
size: 1,
decimalPlaces: 0,
},
{
name: "STATUS",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "CREATE_DT",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "CREATE_TM",
type: "C",
size: 6,
decimalPlaces: 0,
},
{
name: "TRANSMT_DT",
type: "D",
size: 8,
decimalPlaces: 0,
},
{
name: "TRANSMT_TM",
type: "C",
size: 6,
decimalPlaces: 0,
},
{
name: "INCL_ADMIN",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_VEH",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_EST",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_PROFL",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_TOTAL",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "INCL_VENDR",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "EMS_VER",
type: "C",
size: 5,
decimalPlaces: 0,
},
];

View File

@@ -0,0 +1,274 @@
import { FieldDescriptor } from "dbffile";
export const linFieldDescriptors: FieldDescriptor[] = [
{
name: "LINE_NO",
type: "N",
size: 3,
decimalPlaces: 0,
},
{
name: "LINE_IND",
type: "C",
size: 3,
decimalPlaces: 0,
},
{
name: "LINE_REF",
type: "N",
size: 3,
decimalPlaces: 0,
},
{
name: "TRAN_CODE",
type: "C",
size: 1,
decimalPlaces: 0,
},
{
name: "DB_REF",
type: "C",
size: 7,
decimalPlaces: 0,
},
{
name: "UNQ_SEQ",
type: "N",
size: 4,
decimalPlaces: 0,
},
{
name: "WHO_PAYS",
type: "C",
size: 2,
decimalPlaces: 0,
},
{
name: "LINE_DESC",
type: "C",
size: 40,
decimalPlaces: 0,
},
{
name: "PART_TYPE",
type: "C",
size: 4,
decimalPlaces: 0,
},
{
name: "PART_DES_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "GLASS_FLAG",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "OEM_PARTNO",
type: "C",
size: 25,
decimalPlaces: 0,
},
{
name: "PRICE_INC",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "ALT_PART_I",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "TAX_PART",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "DB_PRICE",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "ACT_PRICE",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "PRICE_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "CERT_PART",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "PART_QTY",
type: "N",
size: 2,
decimalPlaces: 0,
},
{
name: "ALT_CO_ID",
type: "C",
size: 20,
decimalPlaces: 0,
},
{
name: "ALT_PARTNO",
type: "C",
size: 25,
decimalPlaces: 0,
},
{
name: "ALT_OVERRD",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "ALT_PARTM",
type: "C",
size: 45,
decimalPlaces: 0,
},
{
name: "PRT_DSMK_P",
type: "N",
size: 7,
decimalPlaces: 2,
},
{
name: "PRT_DSMK_M",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "MOD_LBR_TY",
type: "C",
size: 4,
decimalPlaces: 0,
},
{
name: "DB_HRS",
type: "N",
size: 5,
decimalPlaces: 1,
},
{
name: "MOD_LB_HRS",
type: "N",
size: 5,
decimalPlaces: 1,
},
{
name: "LBR_INC",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_OP",
type: "C",
size: 4,
decimalPlaces: 0,
},
{
name: "LBR_HRS_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_TYP_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_OP_J",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "PAINT_STG",
type: "N",
size: 1,
decimalPlaces: 0,
},
{
name: "PAINT_TONE",
type: "N",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_TAX",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "LBR_AMT",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "MISC_AMT",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "MISC_SUBLT",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "MISC_TAX",
type: "L",
size: 1,
decimalPlaces: 0,
},
{
name: "BETT_TYPE",
type: "C",
size: 4,
decimalPlaces: 0,
},
{
name: "BETT_PCTG",
type: "N",
size: 8,
decimalPlaces: 4,
},
{
name: "BETT_AMT",
type: "N",
size: 9,
decimalPlaces: 2,
},
{
name: "BETT_TAX",
type: "L",
size: 1,
decimalPlaces: 0,
},
];

View File

@@ -1,6 +1,7 @@
import path from "path";
import store from "../store/store";
import fs from "fs";
const generatePpcFilePath = (filename: string): string => {
const ppcOutFilePath: string | null = store.get("settings.ppcFilePath");
if (!ppcOutFilePath) {
@@ -9,6 +10,14 @@ const generatePpcFilePath = (filename: string): string => {
return path.resolve(ppcOutFilePath, filename);
};
const generateEmsOutFilePath = (filename: string): string => {
const emsOutFilePath: string | null = store.get("settings.emsOutFilePath");
if (!emsOutFilePath) {
throw new Error("EMS Out file path is not set");
}
return path.resolve(emsOutFilePath, filename);
};
const deleteEmsFileIfExists = async (filename: string): Promise<void> => {
// Check if the file exists and delete it if it does
try {
@@ -16,7 +25,7 @@ const deleteEmsFileIfExists = async (filename: string): Promise<void> => {
await fs.promises.unlink(filename); // Delete the file
console.log(`Existing file at ${filename} deleted.`);
} catch (err) {
if (err.code !== "ENOENT") {
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
// If the error is not "file not found", rethrow it
throw err;
}
@@ -24,4 +33,4 @@ const deleteEmsFileIfExists = async (filename: string): Promise<void> => {
}
};
export { generatePpcFilePath, deleteEmsFileIfExists };
export { generatePpcFilePath, generateEmsOutFilePath, deleteEmsFileIfExists };

View File

@@ -0,0 +1,46 @@
import { FolderOpenFilled } from "@ant-design/icons";
import { Button, Card, Input, Space } from "antd";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import ipcTypes from "../../../../util/ipcTypes.json";
const SettingsEmsOutFilePath: React.FC = () => {
const { t } = useTranslation();
const [emsFilePath, setEmsFilePath] = useState<string | null>(null);
const getPollingStateFromStore = (): void => {
window.electron.ipcRenderer
.invoke(ipcTypes.toMain.settings.getEmsOutFilePath)
.then((filePath: string | null) => {
setEmsFilePath(filePath);
});
};
//Get state first time it renders.
useEffect(() => {
getPollingStateFromStore();
}, []);
const handlePathChange = (): void => {
window.electron.ipcRenderer
.invoke(ipcTypes.toMain.settings.setEmsOutFilePath)
.then((filePath: string | null) => {
setEmsFilePath(filePath);
});
};
return (
<Card title={t("settings.labels.emsOutFilePath")}>
<Space wrap>
<Input
value={emsFilePath || ""}
placeholder={t("settings.labels.emsOutFilePath")}
disabled
/>
<Button onClick={handlePathChange} icon={<FolderOpenFilled />} />
</Space>
</Card>
);
};
export default SettingsEmsOutFilePath;

View File

@@ -3,6 +3,7 @@ import SettingsWatchedPaths from "./Settings.WatchedPaths";
import SettingsWatcher from "./Settings.Watcher";
import Welcome from "../Welcome/Welcome";
import SettingsPpcFilepath from "./Settings.PpcFilePath";
import SettingsEmsOutFilePath from "./Settings.EmsOutFilePath";
const Settings: React.FC = () => {
console.log("is test?", window.api.isTest());
@@ -20,6 +21,9 @@ const Settings: React.FC = () => {
<Col span={12}>
<SettingsPpcFilepath />
</Col>
<Col span={12}>
<SettingsEmsOutFilePath />
</Col>
</Row>
);
};

View File

@@ -20,6 +20,8 @@
"add": "toMain_settings_filepaths_add",
"remove": "toMain_settings_filepaths_remove"
},
"getEmsOutFilePath": "toMain_settings_filepaths_getEmsOutFilePath",
"setEmsOutFilePath": "toMain_settings_filepaths_setEmsOutFilePath",
"getPpcFilePath": "toMain_settings_filepaths_getPpcFilePath",
"setPpcFilePath": "toMain_settings_filepaths_setPpcFilePath",
"watcher": {