Updates for dynamic ruleset choices.
This commit is contained in:
45
electron/decoder/constants.js
Normal file
45
electron/decoder/constants.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
const moment = require("moment");
|
||||||
|
|
||||||
|
const DateFormat = "MM/DD/yyyy";
|
||||||
|
const RuleSets = [
|
||||||
|
{
|
||||||
|
title: "V1",
|
||||||
|
range: [moment("2010-01-01"), moment("2023-04-01")],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "V2",
|
||||||
|
range: [moment("2023-04-01"), moment("2040-01-01")],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function ChangeOfRuleSet({
|
||||||
|
prevDateMoment = moment(),
|
||||||
|
newDateMoment = moment(),
|
||||||
|
}) {
|
||||||
|
const prevRuleSet = RuleSets.find(
|
||||||
|
(r) =>
|
||||||
|
prevDateMoment.isSameOrAfter(r.range[0]) &&
|
||||||
|
prevDateMoment.isSameOrBefore(r.range[1])
|
||||||
|
);
|
||||||
|
|
||||||
|
const newRuleSet = RuleSets.find(
|
||||||
|
(r) =>
|
||||||
|
newDateMoment.isSameOrAfter(r.range[0]) &&
|
||||||
|
newDateMoment.isSameOrBefore(r.range[1])
|
||||||
|
);
|
||||||
|
|
||||||
|
return prevRuleSet?.title !== newRuleSet?.title;
|
||||||
|
}
|
||||||
|
|
||||||
|
function WhichRulesetToApply(close_date) {
|
||||||
|
const DateMoment = moment(close_date);
|
||||||
|
const newRuleSet = RuleSets.find(
|
||||||
|
(r) =>
|
||||||
|
DateMoment.isSameOrAfter(r.range[0]) &&
|
||||||
|
DateMoment.isSameOrBefore(r.range[1])
|
||||||
|
);
|
||||||
|
console.log("Using ruleset:", newRuleSet);
|
||||||
|
|
||||||
|
return newRuleSet?.title;
|
||||||
|
}
|
||||||
|
exports.WhichRulesetToApply = WhichRulesetToApply;
|
||||||
@@ -8,13 +8,27 @@ const ipcTypes = require("../../src/ipc.types");
|
|||||||
const {
|
const {
|
||||||
NewNotification,
|
NewNotification,
|
||||||
} = require("../notification-wrapper/notification-wrapper");
|
} = require("../notification-wrapper/notification-wrapper");
|
||||||
|
const { WhichRulesetToApply } = require("./constants");
|
||||||
//const Nucleus = require("nucleus-nodejs");
|
//const Nucleus = require("nucleus-nodejs");
|
||||||
|
|
||||||
async function ImportJob(path) {
|
async function ImportJob(filepath) {
|
||||||
const b = BrowserWindow.getAllWindows()[0];
|
const parsedFilePath = path.parse(filepath);
|
||||||
b.webContents.send(ipcTypes.default.estimate.toRenderer.estimateDecodeStart);
|
let extensionlessFilePath = path.join(
|
||||||
const newJob = await DecodeEstimate(path);
|
parsedFilePath.dir,
|
||||||
|
parsedFilePath.name
|
||||||
|
);
|
||||||
|
|
||||||
|
const decodedJob = await DecodeAd1File(extensionlessFilePath);
|
||||||
|
const b = BrowserWindow.getAllWindows()[0];
|
||||||
|
b.webContents.send(ipcTypes.default.estimate.toRenderer.getCloseDate, {
|
||||||
|
filepath,
|
||||||
|
clm_no: decodedJob.CLM_NO,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function ImportJobWithCloseDate(filepath, close_date) {
|
||||||
|
const newJob = await DecodeEstimate(filepath, false, close_date);
|
||||||
|
const b = BrowserWindow.getAllWindows()[0];
|
||||||
if (newJob && !newJob.ERROR) {
|
if (newJob && !newJob.ERROR) {
|
||||||
b.webContents.send(
|
b.webContents.send(
|
||||||
ipcTypes.default.estimate.toRenderer.estimateDecodeSuccess,
|
ipcTypes.default.estimate.toRenderer.estimateDecodeSuccess,
|
||||||
@@ -35,7 +49,13 @@ async function ImportJob(path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function DecodeEstimate(filePath, includeFilePathInReturnJob = false) {
|
exports.ImportJobWithCloseDate = ImportJobWithCloseDate;
|
||||||
|
|
||||||
|
async function DecodeEstimate(
|
||||||
|
filePath,
|
||||||
|
includeFilePathInReturnJob = false,
|
||||||
|
close_date = null
|
||||||
|
) {
|
||||||
const parsedFilePath = path.parse(filePath);
|
const parsedFilePath = path.parse(filePath);
|
||||||
let extensionlessFilePath = path.join(
|
let extensionlessFilePath = path.join(
|
||||||
parsedFilePath.dir,
|
parsedFilePath.dir,
|
||||||
@@ -45,7 +65,7 @@ async function DecodeEstimate(filePath, includeFilePathInReturnJob = false) {
|
|||||||
...(await DecodeAd1File(extensionlessFilePath)),
|
...(await DecodeAd1File(extensionlessFilePath)),
|
||||||
...(await DecodeVehFile(extensionlessFilePath)),
|
...(await DecodeVehFile(extensionlessFilePath)),
|
||||||
...(await DecodeTtlFile(extensionlessFilePath)),
|
...(await DecodeTtlFile(extensionlessFilePath)),
|
||||||
...(await DecodeLinFile(extensionlessFilePath)),
|
...(await DecodeLinFile(extensionlessFilePath, close_date)),
|
||||||
...(includeFilePathInReturnJob ? { filePath } : {}),
|
...(includeFilePathInReturnJob ? { filePath } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -286,7 +306,7 @@ async function DecodeTtlFile(extensionlessFilePath) {
|
|||||||
return { clm_total: records[0]["G_TTL_AMT"] };
|
return { clm_total: records[0]["G_TTL_AMT"] };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function DecodeLinFile(extensionlessFilePath) {
|
async function DecodeLinFile(extensionlessFilePath, close_date) {
|
||||||
let dbf = await DBFFile.open(`${extensionlessFilePath}.LIN`);
|
let dbf = await DBFFile.open(`${extensionlessFilePath}.LIN`);
|
||||||
let records = await dbf.readRecords();
|
let records = await dbf.readRecords();
|
||||||
let joblines = records.map((record) => {
|
let joblines = records.map((record) => {
|
||||||
@@ -356,12 +376,20 @@ async function DecodeLinFile(extensionlessFilePath) {
|
|||||||
|
|
||||||
joblines.map((jobline) => {
|
joblines.map((jobline) => {
|
||||||
jobline.ignore = false;
|
jobline.ignore = false;
|
||||||
|
const rulesetToApply = WhichRulesetToApply(close_date);
|
||||||
|
|
||||||
if (false) {
|
switch (rulesetToApply) {
|
||||||
jobline = V2Ruleset(jobline);
|
case "V1":
|
||||||
} else {
|
jobline = V1Ruleset(jobline, joblines);
|
||||||
jobline = V1Ruleset(jobline);
|
break;
|
||||||
|
case "V2":
|
||||||
|
jobline = V2Ruleset(jobline, joblines);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jobline = V1Ruleset(jobline, joblines);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return jobline;
|
return jobline;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -373,9 +401,8 @@ async function DecodeLinFile(extensionlessFilePath) {
|
|||||||
exports.DecodeEstimate = DecodeEstimate;
|
exports.DecodeEstimate = DecodeEstimate;
|
||||||
exports.ImportJob = ImportJob;
|
exports.ImportJob = ImportJob;
|
||||||
|
|
||||||
function V1Ruleset(jobline) {
|
function V1Ruleset(jobline, joblines) {
|
||||||
//These set of MPI rules are valid until April 1, 2023.
|
//These set of MPI rules are valid until April 1, 2023.
|
||||||
log.info(`Using V1 ruleset for line scanning.`);
|
|
||||||
|
|
||||||
//Wheel Repair Pricing PRS-82
|
//Wheel Repair Pricing PRS-82
|
||||||
//Verified on 08/24/21
|
//Verified on 08/24/21
|
||||||
@@ -484,11 +511,11 @@ function V1Ruleset(jobline) {
|
|||||||
return jobline;
|
return jobline;
|
||||||
}
|
}
|
||||||
|
|
||||||
function V2Ruleset(jobline) {
|
function V2Ruleset(jobline, joblines) {
|
||||||
//This is the rules psot 04/01/2023. They are a further restrictive set, and therefore
|
//This is the rules psot 04/01/2023. They are a further restrictive set, and therefore
|
||||||
//V1 rules are called first, and then run through this filter as well.
|
//V1 rules are called first, and then run through this filter as well.
|
||||||
|
|
||||||
V1Ruleset(jobline);
|
V1Ruleset(jobline, joblines);
|
||||||
|
|
||||||
//Remove any glass related items.
|
//Remove any glass related items.
|
||||||
if (jobline.part_type.toUpperCase() === "PAG") {
|
if (jobline.part_type.toUpperCase() === "PAG") {
|
||||||
@@ -497,7 +524,10 @@ function V2Ruleset(jobline) {
|
|||||||
|
|
||||||
//ADAS Part Line
|
//ADAS Part Line
|
||||||
if (
|
if (
|
||||||
AdasDescriptions.some((d) => jobline.line_desc.toLowerCase().includes(d))
|
AdasDescriptions.some((d) => {
|
||||||
|
const ret = jobline.line_desc.toLowerCase().includes(d);
|
||||||
|
return ret;
|
||||||
|
})
|
||||||
) {
|
) {
|
||||||
jobline.ignore = true;
|
jobline.ignore = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const { ipcMain, app: electronApp } = require("electron");
|
|||||||
const { default: ipcTypes } = require("../src/ipc.types");
|
const { default: ipcTypes } = require("../src/ipc.types");
|
||||||
const { store } = require("./electron-store");
|
const { store } = require("./electron-store");
|
||||||
const log = require("electron-log");
|
const log = require("electron-log");
|
||||||
|
const { ImportJobWithCloseDate } = require("./decoder/decoder");
|
||||||
|
|
||||||
//Import Ipc Handlers
|
//Import Ipc Handlers
|
||||||
require("./file-watcher/file-watcher-ipc");
|
require("./file-watcher/file-watcher-ipc");
|
||||||
@@ -46,6 +47,10 @@ ipcMain.on(ipcTypes.app.toMain.getReleaseNotes, (event, obj) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on(ipcTypes.app.toMain.importJob, (event, { filepath, close_date }) => {
|
||||||
|
ImportJobWithCloseDate(filepath, close_date);
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.on(ipcTypes.app.toMain.log.debug, (event, ...obj) => {
|
ipcMain.on(ipcTypes.app.toMain.log.debug, (event, ...obj) => {
|
||||||
log.debug(obj);
|
log.debug(obj);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -140,6 +140,16 @@ export const QUERY_JOB_BY_CLM_NO = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
||||||
|
export const QUERY_CLOSE_DATE_BY_CLM_NO = gql`
|
||||||
|
query QUERY_CLOSE_DATE_BY_CLM_NO($clm_no: String!) {
|
||||||
|
jobs(where: { clm_no: { _eq: $clm_no } }) {
|
||||||
|
id
|
||||||
|
close_date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const UPDATE_JOB = gql`
|
export const UPDATE_JOB = gql`
|
||||||
mutation UPDATE_JOB($jobId: uuid!, $job: jobs_set_input!) {
|
mutation UPDATE_JOB($jobId: uuid!, $job: jobs_set_input!) {
|
||||||
update_jobs(where: { id: { _eq: $jobId } }, _set: $job) {
|
update_jobs(where: { id: { _eq: $jobId } }, _set: $job) {
|
||||||
|
|||||||
@@ -13,13 +13,14 @@ exports.default = {
|
|||||||
downloadUpdates: "app_downloadUpdates",
|
downloadUpdates: "app_downloadUpdates",
|
||||||
installUpdates: "app_installupdates",
|
installUpdates: "app_installupdates",
|
||||||
getReleaseNotes: "app_getReleaseNotes",
|
getReleaseNotes: "app_getReleaseNotes",
|
||||||
|
importJob:"app_importJob",
|
||||||
log: {
|
log: {
|
||||||
info: "app_logInfo",
|
info: "app_logInfo",
|
||||||
debug: "app_logDebug",
|
debug: "app_logDebug",
|
||||||
warn: "app_logWarn",
|
warn: "app_logWarn",
|
||||||
error: "app_logError",
|
error: "app_logError",
|
||||||
silly: "app_logSilly"
|
silly: "app_logSilly",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
toRenderer: {
|
toRenderer: {
|
||||||
updateAvailable: "app_updateAvailable",
|
updateAvailable: "app_updateAvailable",
|
||||||
@@ -67,6 +68,7 @@ exports.default = {
|
|||||||
estimateDecodeStart: "estimatedecode__start",
|
estimateDecodeStart: "estimatedecode__start",
|
||||||
estimateDecodeSuccess: "estimatedecode__success",
|
estimateDecodeSuccess: "estimatedecode__success",
|
||||||
estimateDecodeFailure: "estimatedecode__failure",
|
estimateDecodeFailure: "estimatedecode__failure",
|
||||||
|
getCloseDate: "getclosedate",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import moment from "moment";
|
|||||||
import client from "../graphql/GraphQLClient";
|
import client from "../graphql/GraphQLClient";
|
||||||
import {
|
import {
|
||||||
INSERT_NEW_JOB,
|
INSERT_NEW_JOB,
|
||||||
|
QUERY_CLOSE_DATE_BY_CLM_NO,
|
||||||
QUERY_JOB_BY_CLM_NO,
|
QUERY_JOB_BY_CLM_NO,
|
||||||
UPDATE_JOB,
|
UPDATE_JOB,
|
||||||
} from "../graphql/jobs.queries";
|
} from "../graphql/jobs.queries";
|
||||||
@@ -48,6 +49,14 @@ export function CalculateVehicleAge(job) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function GetR4PDateWithClaim(clm_no) {
|
||||||
|
const existingJobs = await client.query({
|
||||||
|
query: QUERY_CLOSE_DATE_BY_CLM_NO,
|
||||||
|
variables: { clm_no: clm_no },
|
||||||
|
});
|
||||||
|
return existingJobs.data.jobs[0] && existingJobs.data.jobs[0].close_date;
|
||||||
|
}
|
||||||
|
|
||||||
export async function UpsertEstimate(job) {
|
export async function UpsertEstimate(job) {
|
||||||
const shopId = store.getState().user.bodyshop.id;
|
const shopId = store.getState().user.bodyshop.id;
|
||||||
//logger.info("Beginning Upserting job from Renderer.");
|
//logger.info("Beginning Upserting job from Renderer.");
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
setWatcherStatus,
|
setWatcherStatus,
|
||||||
} from "../redux/application/application.actions";
|
} from "../redux/application/application.actions";
|
||||||
import { store } from "../redux/store";
|
import { store } from "../redux/store";
|
||||||
import { UpsertEstimate } from "./ipc-estimate-utils";
|
import { GetR4PDateWithClaim, UpsertEstimate } from "./ipc-estimate-utils";
|
||||||
import { setScanEstimateList } from "../redux/scan/scan.actions";
|
import { setScanEstimateList } from "../redux/scan/scan.actions";
|
||||||
import { signOutStart } from "../redux/user/user.actions";
|
import { signOutStart } from "../redux/user/user.actions";
|
||||||
const { ipcRenderer } = window;
|
const { ipcRenderer } = window;
|
||||||
@@ -44,16 +44,19 @@ ipcRenderer.on(ipcTypes.default.fileWatcher.toRenderer.error, (event, obj) => {
|
|||||||
|
|
||||||
//Estimate Section
|
//Estimate Section
|
||||||
ipcRenderer.on(
|
ipcRenderer.on(
|
||||||
ipcTypes.default.estimate.toRenderer.estimateDecodeStart,
|
ipcTypes.default.estimate.toRenderer.getCloseDate,
|
||||||
(event, obj) => {
|
async (event, { filepath, clm_no }) => {
|
||||||
console.log("Decoding started!");
|
const close_date = await GetR4PDateWithClaim(clm_no);
|
||||||
|
ipcRenderer.send(ipcTypes.default.app.toMain.importJob, {
|
||||||
|
filepath,
|
||||||
|
close_date,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
ipcRenderer.on(
|
ipcRenderer.on(
|
||||||
ipcTypes.default.estimate.toRenderer.estimateDecodeSuccess,
|
ipcTypes.default.estimate.toRenderer.estimateDecodeSuccess,
|
||||||
async (event, obj) => {
|
async (event, obj) => {
|
||||||
|
|
||||||
await UpsertEstimate(obj);
|
await UpsertEstimate(obj);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,27 +1,21 @@
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
|
||||||
export const DateFormat = "MM/DD/yyyy";
|
export const DateFormat = "MM/DD/yyyy";
|
||||||
|
const RuleSets = [
|
||||||
|
{
|
||||||
|
title: "V1",
|
||||||
|
range: [moment("2010-01-01"), moment("2023-04-01")],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "V2",
|
||||||
|
range: [moment("2023-04-01"), moment("2040-01-01")],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export function ChangeOfRuleSet({
|
export function ChangeOfRuleSet({
|
||||||
prevDateMoment = moment(),
|
prevDateMoment = moment(),
|
||||||
newDateMoment = moment(),
|
newDateMoment = moment(),
|
||||||
}) {
|
}) {
|
||||||
console.log("🚀 ~ file: constants.js ~ line 9 ~ newDateMoment", newDateMoment)
|
|
||||||
console.log("🚀 ~ file: constants.js ~ line 9 ~ prevDateMoment", prevDateMoment)
|
|
||||||
|
|
||||||
|
|
||||||
//Define the rule periods.
|
|
||||||
const V1 = {
|
|
||||||
title: "V1",
|
|
||||||
range: [moment("2010-01-01"), moment("2023-04-01")],
|
|
||||||
};
|
|
||||||
const V2 = {
|
|
||||||
title: "V2",
|
|
||||||
range: [moment("2023-04-01"), moment("2040-01-01")],
|
|
||||||
}; //Arbitrarily long away date.
|
|
||||||
|
|
||||||
const RuleSets = [V1, V2];
|
|
||||||
|
|
||||||
const prevRuleSet = RuleSets.find(
|
const prevRuleSet = RuleSets.find(
|
||||||
(r) =>
|
(r) =>
|
||||||
prevDateMoment.isSameOrAfter(r.range[0]) &&
|
prevDateMoment.isSameOrAfter(r.range[0]) &&
|
||||||
@@ -36,3 +30,13 @@ export function ChangeOfRuleSet({
|
|||||||
|
|
||||||
return prevRuleSet?.title !== newRuleSet?.title;
|
return prevRuleSet?.title !== newRuleSet?.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function WhichRulesetToApply({ DateMoment = moment() }) {
|
||||||
|
const newRuleSet = RuleSets.find(
|
||||||
|
(r) =>
|
||||||
|
DateMoment.isSameOrAfter(r.range[0]) &&
|
||||||
|
DateMoment.isSameOrBefore(r.range[1])
|
||||||
|
);
|
||||||
|
|
||||||
|
return newRuleSet?.title;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user