Add PFL and PFH files.
This commit is contained in:
@@ -18,10 +18,6 @@ nsis:
|
||||
shortcutName: ${productName}
|
||||
uninstallDisplayName: ${productName}
|
||||
createDesktopShortcut: always
|
||||
azureSignOptions:
|
||||
endpoint: https://eus.codesigning.azure.net
|
||||
certificateProfileName: ImEXRPS
|
||||
codeSigningAccountName: ImEX
|
||||
mac:
|
||||
entitlementsInherit: build/entitlements.mac.plist
|
||||
category: public.app-category.business
|
||||
|
||||
@@ -2,8 +2,8 @@ import { DBFFile } from "dbffile";
|
||||
import log from "electron-log/main";
|
||||
import _ from "lodash";
|
||||
import deepLowerCaseKeys from "../../util/deepLowercaseKeys";
|
||||
import { OwnerRecordInterface, DecodedAd1 } from "./decode-ad1.interface";
|
||||
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||
import { DecodedAd1, OwnerRecordInterface } from "./decode-ad1.interface";
|
||||
|
||||
const DecodeAD1 = async (
|
||||
extensionlessFilePath: string
|
||||
@@ -14,7 +14,7 @@ const DecodeAD1 = async (
|
||||
} catch (error) {
|
||||
log.error("Error opening AD1 File.", errorTypeCheck(error));
|
||||
dbf = await DBFFile.open(`${extensionlessFilePath}.AD1`);
|
||||
log.log("Found AD1 file using regular CIECA Id.");
|
||||
log.log("Trying to find AD1 file using regular CIECA Id.");
|
||||
}
|
||||
|
||||
if (!dbf) {
|
||||
|
||||
@@ -25,5 +25,5 @@ export interface DecodedAD2 {
|
||||
est_ct_fn?: string;
|
||||
est_ea?: string;
|
||||
date_estimated?: Date; // This is transformed from insp_date
|
||||
//insp_date?: string; // This exists initially but gets deleted
|
||||
insp_date?: Date; // This exists initially but gets deleted
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ const DecodeAD2 = async (
|
||||
} catch (error) {
|
||||
log.error("Error opening AD2 File.", errorTypeCheck(error));
|
||||
dbf = await DBFFile.open(`${extensionlessFilePath}.AD2`);
|
||||
log.log("Found AD2 file using regular CIECA Id.");
|
||||
log.log("Trying to find AD2 file using regular CIECA Id.");
|
||||
}
|
||||
|
||||
if (!dbf) {
|
||||
@@ -27,7 +27,7 @@ const DecodeAD2 = async (
|
||||
//AD2 will always have only 1 row.
|
||||
//Commented lines have been cross referenced with existing partner fields.
|
||||
|
||||
const rawAd2Data = deepLowerCaseKeys(
|
||||
const rawAd2Data: DecodedAD2 = deepLowerCaseKeys(
|
||||
_.pick(rawDBFRecord[0], [
|
||||
//TODO: Add typings for EMS File Formats.
|
||||
"CLMT_LN",
|
||||
|
||||
15
src/main/decoder/decode-pfh.interface.ts
Normal file
15
src/main/decoder/decode-pfh.interface.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
export interface DecodedPfh {
|
||||
tax_prethr: number;
|
||||
tax_thr_amt?: number;
|
||||
tax_pstthr?: number;
|
||||
tax_tow_rt: number;
|
||||
tax_str_rt: number;
|
||||
tax_sub_rt: number;
|
||||
tax_lbr_rt: number;
|
||||
federal_tax_rate: number;
|
||||
adj_g_disc?: number;
|
||||
adj_towdis?: number;
|
||||
adj_strdis?: number;
|
||||
tax_predis?: number;
|
||||
tax_gst_rt?: number;
|
||||
}
|
||||
71
src/main/decoder/decode-pfh.ts
Normal file
71
src/main/decoder/decode-pfh.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { DBFFile } from "dbffile";
|
||||
import log from "electron-log/main";
|
||||
import _ from "lodash";
|
||||
import deepLowerCaseKeys from "../../util/deepLowercaseKeys";
|
||||
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||
import { DecodedPfh } from "./decode-pfh.interface";
|
||||
|
||||
const DecodePfh = async (
|
||||
extensionlessFilePath: string
|
||||
): Promise<DecodedPfh> => {
|
||||
let dbf: DBFFile;
|
||||
try {
|
||||
dbf = await DBFFile.open(`${extensionlessFilePath}.PFH`);
|
||||
} catch (error) {
|
||||
log.error("Error opening PFH File.", errorTypeCheck(error));
|
||||
dbf = await DBFFile.open(`${extensionlessFilePath}.PFH`);
|
||||
log.log("Trying to find PFH file using regular CIECA Id.");
|
||||
}
|
||||
|
||||
if (!dbf) {
|
||||
log.error(`Could not find any PFH files at ${extensionlessFilePath}`);
|
||||
throw new Error(`Could not find any PFH files at ${extensionlessFilePath}`);
|
||||
}
|
||||
|
||||
const rawDBFRecord = await dbf.readRecords(1);
|
||||
|
||||
//AD2 will always have only 1 row.
|
||||
//Commented lines have been cross referenced with existing partner fields.
|
||||
|
||||
const rawPfhData: DecodedPfh = deepLowerCaseKeys(
|
||||
_.pick(rawDBFRecord[0], [
|
||||
//TODO: Add typings for EMS File Formats.
|
||||
//TODO: Several of these fields will fail. Should extend schema to capture them.
|
||||
"ID_PRO_NAM", //Remove
|
||||
"TAX_PRETHR",
|
||||
"TAX_THRAMT", //Remove
|
||||
"TAX_PSTTHR",
|
||||
"TAX_TOW_IN", //Remove
|
||||
"TAX_TOW_RT",
|
||||
"TAX_STR_IN", //Remove
|
||||
"TAX_STR_RT",
|
||||
"TAX_SUB_IN", //Remove
|
||||
"TAX_SUB_RT",
|
||||
"TAX_BTR_IN", //Remove
|
||||
"TAX_LBR_RT",
|
||||
"TAX_GST_RT",
|
||||
"TAX_GST_IN", //Remove
|
||||
"ADJ_G_DISC",
|
||||
"ADJ_TOWDIS",
|
||||
"ADJ_STRDIS",
|
||||
"ADJ_BTR_IN", //Remove
|
||||
"TAX_PREDIS",
|
||||
])
|
||||
);
|
||||
|
||||
//Apply business logic transfomrations.
|
||||
|
||||
//Standardize some of the numbers and divide by 100.
|
||||
|
||||
rawPfhData.tax_prethr = rawPfhData.tax_prethr ?? 0 / 100;
|
||||
rawPfhData.tax_pstthr = rawPfhData.tax_pstthr ?? 0 / 100;
|
||||
rawPfhData.tax_tow_rt = rawPfhData.tax_tow_rt ?? 0 / 100;
|
||||
rawPfhData.tax_str_rt = rawPfhData.tax_str_rt ?? 0 / 100;
|
||||
rawPfhData.tax_sub_rt = rawPfhData.tax_sub_rt ?? 0 / 100;
|
||||
rawPfhData.tax_lbr_rt = rawPfhData.tax_lbr_rt ?? 0 / 100;
|
||||
rawPfhData.federal_tax_rate = rawPfhData.tax_gst_rt ?? 0 / 100;
|
||||
delete rawPfhData.tax_gst_rt;
|
||||
|
||||
return rawPfhData;
|
||||
};
|
||||
export default DecodePfh;
|
||||
41
src/main/decoder/decode-pfl.interface.ts
Normal file
41
src/main/decoder/decode-pfl.interface.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
//TODO: Clean up this interface. A bit messy as we store the data in very different ways.
|
||||
|
||||
export interface DecodedPflLine {
|
||||
lbr_type: string;
|
||||
lbr_desc: string;
|
||||
lbr_rate: number;
|
||||
lbr_tax_in: boolean;
|
||||
lbr_taxp: number;
|
||||
lbr_adjP: number;
|
||||
lbr_tx_ty1: string;
|
||||
lbr_tx_in1: boolean;
|
||||
lbr_tx_ty2: string;
|
||||
lbr_tx_in2: boolean;
|
||||
lbr_tx_ty3: string;
|
||||
lbr_tx_in3: boolean;
|
||||
lbr_tx_ty4: string;
|
||||
lbr_tx_in4: boolean;
|
||||
lbr_tx_ty5: string;
|
||||
lbr_tx_in5: boolean;
|
||||
}
|
||||
|
||||
export interface JobLaborRateFields {
|
||||
rate_laa: number;
|
||||
rate_lab: number;
|
||||
rate_lad: number;
|
||||
rate_las: number;
|
||||
rate_lar: number;
|
||||
rate_lae: number;
|
||||
rate_lag: number;
|
||||
rate_laf: number;
|
||||
rate_lam: number;
|
||||
rate_lau: number;
|
||||
rate_la1: number;
|
||||
rate_la2: number;
|
||||
rate_la3: number;
|
||||
rate_la4: number;
|
||||
}
|
||||
|
||||
export interface DecodedPfl extends JobLaborRateFields {
|
||||
cieca_pfl: DecodedPflLine[];
|
||||
}
|
||||
89
src/main/decoder/decode-pfl.ts
Normal file
89
src/main/decoder/decode-pfl.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { DBFFile } from "dbffile";
|
||||
import log from "electron-log/main";
|
||||
import _ from "lodash";
|
||||
import deepLowerCaseKeys from "../../util/deepLowercaseKeys";
|
||||
import errorTypeCheck from "../../util/errorTypeCheck";
|
||||
import {
|
||||
DecodedPfl,
|
||||
JobLaborRateFields,
|
||||
DecodedPflLine,
|
||||
} from "./decode-pfl.interface";
|
||||
|
||||
const DecodePfl = async (
|
||||
extensionlessFilePath: string
|
||||
): Promise<DecodedPfl> => {
|
||||
let dbf: DBFFile;
|
||||
try {
|
||||
dbf = await DBFFile.open(`${extensionlessFilePath}.PFL`);
|
||||
} catch (error) {
|
||||
//PFL File only has 1 location.
|
||||
log.error("Error opening PFL File.", errorTypeCheck(error));
|
||||
}
|
||||
|
||||
if (!dbf) {
|
||||
log.error(`Could not find any PFL files at ${extensionlessFilePath}`);
|
||||
throw new Error(`Could not find any PFL files at ${extensionlessFilePath}`);
|
||||
}
|
||||
|
||||
const rawDBFRecord = await dbf.readRecords();
|
||||
|
||||
//AD2 will always have only 1 row.
|
||||
//Commented lines have been cross referenced with existing partner fields.
|
||||
|
||||
const jobLaborRates: JobLaborRateFields = {
|
||||
rate_laa: 0,
|
||||
rate_lab: 0,
|
||||
rate_lad: 0,
|
||||
rate_las: 0,
|
||||
rate_lar: 0,
|
||||
rate_lae: 0,
|
||||
rate_lag: 0,
|
||||
rate_laf: 0,
|
||||
rate_lam: 0,
|
||||
rate_lau: 0,
|
||||
rate_la1: 0,
|
||||
rate_la2: 0,
|
||||
rate_la3: 0,
|
||||
rate_la4: 0,
|
||||
};
|
||||
|
||||
const rawPflData: DecodedPflLine[] = rawDBFRecord.map((record) => {
|
||||
const singleLineData: DecodedPflLine = deepLowerCaseKeys(
|
||||
_.pick(record, [
|
||||
//TODO: Add typings for EMS File Formats.
|
||||
"LBR_TYPE",
|
||||
"LBR_DESC",
|
||||
"LBR_RATE",
|
||||
"LBR_TAX_IN",
|
||||
"LBR_TAXP",
|
||||
"LBR_ADJP",
|
||||
"LBR_TX_TY1",
|
||||
"LBR_TX_IN1",
|
||||
"LBR_TX_TY2",
|
||||
"LBR_TX_IN2",
|
||||
"LBR_TX_TY3",
|
||||
"LBR_TX_IN3",
|
||||
"LBR_TX_TY4",
|
||||
"LBR_TX_IN4",
|
||||
"LBR_TX_TY5",
|
||||
"LBR_TX_IN5",
|
||||
])
|
||||
);
|
||||
//Apply line by line adjustments.
|
||||
//Set the job.rate_<CIECA_TYPE> field based on the value.
|
||||
jobLaborRates[`rate_${singleLineData.lbr_type.toLowerCase()}`] =
|
||||
singleLineData.lbr_rate;
|
||||
//Also capture the whole object.
|
||||
//This is segmented because the whole object was not previously captured for ImEX as it wasn't needed.
|
||||
//Rome needs the whole object to accurately calculate the tax rates.
|
||||
|
||||
return singleLineData;
|
||||
});
|
||||
|
||||
//Apply business logic transfomrations.
|
||||
//We don't have an inspection date, we instead have `date_estimated`
|
||||
|
||||
return { ...jobLaborRates, cieca_pfl: rawPflData };
|
||||
};
|
||||
|
||||
export default DecodePfl;
|
||||
@@ -7,6 +7,10 @@ import DecodeAD2 from "./decode-ad2";
|
||||
import { DecodedAD2 } from "./decode-ad2.interface";
|
||||
import DecodeLin from "./decode-lin";
|
||||
import { DecodedLin } from "./decode-lin.interface";
|
||||
import DecodePfh from "./decode-pfh";
|
||||
import { DecodedPfh } from "./decode-pfh.interface";
|
||||
import DecodePfl from "./decode-pfl";
|
||||
import { DecodedPfl } from "./decode-pfl.interface";
|
||||
import DecodeVeh from "./decode-veh";
|
||||
import { DecodedVeh } from "./decode-veh.interface";
|
||||
|
||||
@@ -25,7 +29,9 @@ async function ImportJob(filepath: string): Promise<void> {
|
||||
const ad2: DecodedAD2 = await DecodeAD2(extensionlessFilePath);
|
||||
const veh: DecodedVeh = await DecodeVeh(extensionlessFilePath);
|
||||
const lin: DecodedLin[] = await DecodeLin(extensionlessFilePath);
|
||||
log.debug("EMS Object", { ad1, ad2, veh, lin });
|
||||
const pfh: DecodedPfh = await DecodePfh(extensionlessFilePath);
|
||||
const pfl: DecodedPfl = await DecodePfl(extensionlessFilePath);
|
||||
log.debug("EMS Object", { ad1, ad2, veh, lin, pfh, pfl });
|
||||
} catch (error) {
|
||||
log.error("Error encountered while decoding job. ", errorTypeCheck(error));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user