diff --git a/electron/decoder/decoder.js b/electron/decoder/decoder.js index 3bc4057..fff6c3a 100644 --- a/electron/decoder/decoder.js +++ b/electron/decoder/decoder.js @@ -384,25 +384,38 @@ async function DecodeLinFile(extensionlessFilePath, close_date) { }); //Apply ruleset. + const ins_rule_set = store.get("ins_rule_set"); joblines.map((jobline) => { jobline.ignore = false; - const rulesetToApply = WhichRulesetToApply(close_date); + switch (ins_rule_set) { + case "MPI": + const rulesetToApply = WhichRulesetToApply(close_date); - switch (rulesetToApply) { - case "V1": - jobline = V1Ruleset(jobline, joblines); + switch (rulesetToApply) { + case "V1": + jobline = V1Ruleset(jobline, joblines); + break; + case "V2": + jobline = V2Ruleset(jobline, joblines); + break; + case "V3": + jobline = V3Ruleset(jobline, joblines); + break; + default: + jobline = V3Ruleset(jobline, joblines); + break; + } break; - case "V2": - jobline = V2Ruleset(jobline, joblines); - break; - case "V3": - jobline = V3Ruleset(jobline, joblines); + case "SGI": + log.info("Using SGI ruleset. Line will be automatically counted until rules are added."); + break; default: - jobline = V3Ruleset(jobline, joblines); + log.info("Using default ruleset (MPI)."); break; } + //2025-05-27 Commenting out to prepare release without claims clerk. // jobline.alerts = claimsClerk({ jobline, joblines }); diff --git a/electron/electron-store.js b/electron/electron-store.js index f7e5f7f..7433f5c 100644 --- a/electron/electron-store.js +++ b/electron/electron-store.js @@ -13,6 +13,7 @@ const store = new Store({ enabled: false, pollingInterval: 30000, }, + ins_rule_set: null }, }); diff --git a/electron/estimate-scrubber/estimate-scrubber.js b/electron/estimate-scrubber/estimate-scrubber.js index bac819a..935be9d 100644 --- a/electron/estimate-scrubber/estimate-scrubber.js +++ b/electron/estimate-scrubber/estimate-scrubber.js @@ -5,6 +5,7 @@ const { BrowserWindow } = require("electron"); const { default: ipcTypes } = require("../../src/ipc.types.commonjs"); const { promises: fsPromises } = require("fs"); const { autoUpdater } = require("electron-updater"); +const { store } = require("../electron-store") // Function to write job object to logs subfolder async function writeJobToLogsFolder(job, fileName) { @@ -60,10 +61,23 @@ async function ScrubEstimate({ job }) { return; } + let association_switch + switch (store.get("ins_rule_set")) { + case "MPI": + association_switch = "ATAM"; + break; + case "SGI": + association_switch = "SAAR"; + break; + default: + association_switch = "ATAM"; + break; + } + //Set shop metrics job.sending_entity_id = sendingEntityId; job.sending_entity_accept_terms_of_use = true; - job.association_switch = "ATAM"; + job.association_switch = association_switch; job.rf_zip = job.bodyshop.zip_post; job.rf_ph1 = job.bodyshop.phone; job.g_ttl_amt = job.clm_total; diff --git a/electron/ipc-main-handler.js b/electron/ipc-main-handler.js index f0e024a..c2aeae1 100644 --- a/electron/ipc-main-handler.js +++ b/electron/ipc-main-handler.js @@ -93,3 +93,7 @@ ipcMain.on(ipcTypes.app.toMain.openExternalWindow, (event, url) => { }); }); + +ipcMain.on(ipcTypes.app.toMain.setInsRuleSet, (event, ins_rule_set) => { + store.set("ins_rule_set", ins_rule_set); +}); \ No newline at end of file diff --git a/hasura/metadata/databases/default/tables/public_bodyshops.yaml b/hasura/metadata/databases/default/tables/public_bodyshops.yaml index 9457c35..098bc69 100644 --- a/hasura/metadata/databases/default/tables/public_bodyshops.yaml +++ b/hasura/metadata/databases/default/tables/public_bodyshops.yaml @@ -34,6 +34,7 @@ select_permissions: - features - groups - id + - ins_rule_set - mpi_count_quantity - phone - ppd_diff_alert diff --git a/hasura/migrations/default/1774026570092_alter_table_public_bodyshops_add_column_ins_rule_set/down.sql b/hasura/migrations/default/1774026570092_alter_table_public_bodyshops_add_column_ins_rule_set/down.sql new file mode 100644 index 0000000..f71152b --- /dev/null +++ b/hasura/migrations/default/1774026570092_alter_table_public_bodyshops_add_column_ins_rule_set/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."bodyshops" add column "ins_rule_set" text +-- not null default 'MPI'; diff --git a/hasura/migrations/default/1774026570092_alter_table_public_bodyshops_add_column_ins_rule_set/up.sql b/hasura/migrations/default/1774026570092_alter_table_public_bodyshops_add_column_ins_rule_set/up.sql new file mode 100644 index 0000000..de1698f --- /dev/null +++ b/hasura/migrations/default/1774026570092_alter_table_public_bodyshops_add_column_ins_rule_set/up.sql @@ -0,0 +1,2 @@ +alter table "public"."bodyshops" add column "ins_rule_set" text + not null default 'MPI'; diff --git a/package.json b/package.json index 33eeee7..72e3bf6 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "productName": "ImEX RPS", "author": "ImEX Systems Inc. ", "description": "ImEX RPS", - "version": "1.5.2", + "version": "1.6.0-alpha.1", "main": "electron/main.js", "homepage": "./", "dependencies": { diff --git a/src/components/molecules/shop-settings-form/shop-settings-form.molecule.jsx b/src/components/molecules/shop-settings-form/shop-settings-form.molecule.jsx index d91fb18..d09464c 100644 --- a/src/components/molecules/shop-settings-form/shop-settings-form.molecule.jsx +++ b/src/components/molecules/shop-settings-form/shop-settings-form.molecule.jsx @@ -1,10 +1,10 @@ -import { Button, Form, Input, InputNumber, Popconfirm, Select, Switch, Typography } from "antd"; +import { Button, Form, Input, InputNumber, Popconfirm, Select, Space, Switch, Typography } from "antd"; import React from "react"; import LayoutFormRow from "../../atoms/layout-form-row/layout-form-row.atom"; export default function ShopSettingsFormMolecule({ form, saveLoading }) { return ( -
+ Shop Settings - + + - -
+ + ); } diff --git a/src/components/organisms/shop-settings/shop-settings.organism.jsx b/src/components/organisms/shop-settings/shop-settings.organism.jsx index 6ac32bb..1e6c069 100644 --- a/src/components/organisms/shop-settings/shop-settings.organism.jsx +++ b/src/components/organisms/shop-settings/shop-settings.organism.jsx @@ -28,7 +28,7 @@ export function ShopSettingsOrganism({ setBodyshop }) { if (data) form.resetFields(); }, [form, data]); - const handleFinish = async (values) => { + const handleFinish = async ({ ins_rule_set, ...values }) => { setSaveLoading(true); ipcRenderer.send(ipcTypes.app.toMain.track, { event: "UPDATE_SHOP_DETAILS" @@ -74,6 +74,7 @@ export function ShopSettingsOrganism({ setBodyshop }) { }) .catch(() => { // Form validation failed, don't save + setSaveLoading(false); }); } }, 250); diff --git a/src/components/pages/routes/routes.page.jsx b/src/components/pages/routes/routes.page.jsx index 73d7c19..b53889a 100644 --- a/src/components/pages/routes/routes.page.jsx +++ b/src/components/pages/routes/routes.page.jsx @@ -1,4 +1,4 @@ -import { Layout } from "antd"; +import { Alert, Layout, notification } from "antd"; import React from "react"; import { connect } from "react-redux"; import { Routes } from "react-router-dom"; @@ -29,6 +29,17 @@ export function RoutesPage({ bodyshop, darkMode }) { /> ); + if (bodyshop?.ins_rule_set === "SGI") { + notification.warning({ + message: "SGI Target Warning", + description: "SGI has not yet released savings targets. Targets will be displayed as $0.", + placement: "bottomLeft", + key: "sgi-target-warning", + duration: -1, + closable: false + }); + } + return ( diff --git a/src/graphql/bodyshop.queries.js b/src/graphql/bodyshop.queries.js index 2930df7..f1e5944 100644 --- a/src/graphql/bodyshop.queries.js +++ b/src/graphql/bodyshop.queries.js @@ -14,6 +14,7 @@ export const QUERY_BODYSHOP = gql` phone es_api_key mpi_count_quantity + ins_rule_set } targets { id diff --git a/src/ipc.types.json b/src/ipc.types.json index e399e03..064901b 100644 --- a/src/ipc.types.json +++ b/src/ipc.types.json @@ -18,6 +18,7 @@ "setReleaseChannel": "app_setReleaseChannel", "scrubEstimate": "app_scrubEstimate", "openExternalWindow": "app_openExternalWindow", + "setInsRuleSet": "app_setInsRuleSet", "log": { "info": "app_logInfo", "debug": "app_logDebug", diff --git a/src/redux/application/application.sagas.js b/src/redux/application/application.sagas.js index 69a1ccc..6ef3629 100644 --- a/src/redux/application/application.sagas.js +++ b/src/redux/application/application.sagas.js @@ -8,9 +8,10 @@ export function* onSetTargetPc() { } export function* CalculateTarget({ payload }) { const { group, v_age, close_date, v_mileage, job } = payload; - const targets = yield select((state) => state.user.bodyshop.targets); - yield put(setSelectedJobTargetPcSuccess(GetJobTarget({ group, v_age, targets, close_date, v_mileage, job }))); + const { targets, ins_rule_set } = yield select((state) => state.user.bodyshop); + + yield put(setSelectedJobTargetPcSuccess(GetJobTarget({ group, v_age, targets, close_date, v_mileage, job, ins_rule_set }))); // const targetsForGroup = targets.filter((t) => t.group === group); // if (!targetsForGroup) return 0; // const targetPc = targetsForGroup.filter( diff --git a/src/redux/user/user.sagas.js b/src/redux/user/user.sagas.js index 86720b7..66e57de 100644 --- a/src/redux/user/user.sagas.js +++ b/src/redux/user/user.sagas.js @@ -137,6 +137,8 @@ export function* signInSuccessSaga({ payload }) { if (shop.data.bodyshops.length > 0) { yield put(setBodyshop(shop.data.bodyshops[0])); ipcRenderer.send(ipcTypes.app.toMain.setAcceptableInsCoNm, shop.data.bodyshops[0].accepted_ins_co); + ipcRenderer.send(ipcTypes.app.toMain.setInsRuleSet, shop.data.bodyshops[0].ins_rule_set); + ipcRenderer.send(ipcTypes.app.toMain.setReleaseChannel, shop.data.bodyshops[0].channel); ipcRenderer.send(ipcTypes.fileWatcher.toMain.start, { startup: true diff --git a/src/util/GetJobTarget.js b/src/util/GetJobTarget.js index 95e76c3..416d2c0 100644 --- a/src/util/GetJobTarget.js +++ b/src/util/GetJobTarget.js @@ -3,45 +3,36 @@ import { store } from "../redux/store"; import { WhichRulesetToApply } from "./constants"; export default function GetJobTarget({ group, v_age, targets, close_date, v_mileage, job }) { - // //Old Validation - // const targetsForGroup = targets.filter((t) => t.group === group); - // console.log( - // "🚀 ~ file: GetJobTarget.js:7 ~ GetJobTarget ~ targetsForGroup", - // targetsForGroup - // ); - // if (!targetsForGroup) { - // console.log("Result:", 0); - // } - // const targetPc = targetsForGroup.filter( - // (t) => t.ageGte <= v_age && (t.ageLt ? t.ageLt > v_age : true) - // ); - // if (targetPc.length === 0) console.log("Result:", 1); - // else if (targetPc.length === 1) console.log("Result: ", targetPc[0].target); - // else { - // console.log("Result:", 1); - // } + const ins_rule_set = store.getState().user.bodyshop.ins_rule_set; - //V2 Check - const newTargets = store.getState().user.targets; - - const rulesToApply = WhichRulesetToApply(close_date); - if (rulesToApply === "V3") { - //V3 Check - If vehicle is less than 20,000KM, there is NO TARGET. - if (v_mileage && v_mileage <= 20000) { + switch (ins_rule_set) { + case "SGI": return 0; - } - const v3Target = V3TargetFinder(job); - return v3Target; - } else { - const newTargetsForGroup = newTargets.filter((t) => t.name === rulesToApply && t.group === group); - if (!newTargetsForGroup) return 0; - const newTargetPc = newTargetsForGroup.filter((t) => t.ageGte <= v_age && (t.ageLt ? t.ageLt > v_age : true)); + case "MPI": + default: + const newTargets = store.getState().user.targets; + + const rulesToApply = WhichRulesetToApply(close_date); + if (rulesToApply === "V3") { + //V3 Check - If vehicle is less than 20,000KM, there is NO TARGET. + if (v_mileage && v_mileage <= 20000) { + return 0; + } + const v3Target = V3TargetFinder(job); + return v3Target; + } else { + const newTargetsForGroup = newTargets.filter((t) => t.name === rulesToApply && t.group === group); + + if (!newTargetsForGroup) return 0; + const newTargetPc = newTargetsForGroup.filter((t) => t.ageGte <= v_age && (t.ageLt ? t.ageLt > v_age : true)); + + if (newTargetPc.length === 0) return 1; + else if (newTargetPc.length === 1) return newTargetPc[0].target; + else { + return 1; + } + } - if (newTargetPc.length === 0) return 1; - else if (newTargetPc.length === 1) return newTargetPc[0].target; - else { - return 1; - } } }