From 9df316599836d7b67f4f77c95fd17df86d5e4ce1 Mon Sep 17 00:00:00 2001 From: Patrick FIc Date: Thu, 11 Sep 2025 13:02:59 -0700 Subject: [PATCH] Add improved error handling for 4xx errors from ES. --- .../estimate-scrubber/estimate-scrubber.js | 139 ++++++++++-------- package.json | 2 +- .../estimate-scrubber-button.molecule.jsx | 31 ++-- src/ipc.types.json | 3 +- src/ipc/ipc-renderer-handler.js | 7 +- 5 files changed, 102 insertions(+), 80 deletions(-) diff --git a/electron/estimate-scrubber/estimate-scrubber.js b/electron/estimate-scrubber/estimate-scrubber.js index 0eb42fb..637240f 100644 --- a/electron/estimate-scrubber/estimate-scrubber.js +++ b/electron/estimate-scrubber/estimate-scrubber.js @@ -7,41 +7,41 @@ const { promises: fsPromises } = require("fs"); // Function to write job object to logs subfolder async function writeJobToLogsFolder(job, fileName) { - try { - // Get the directory where electron-log stores its files - const logFilePath = log.transports.file.getFile().path; - const logsDir = path.dirname(logFilePath); + try { + // Get the directory where electron-log stores its files + const logFilePath = log.transports.file.getFile().path; + const logsDir = path.dirname(logFilePath); - // Create a subfolder for job objects - const jobLogsDir = path.join(logsDir, 'esjson'); + // Create a subfolder for job objects + const jobLogsDir = path.join(logsDir, "esjson"); - // Ensure the directory exists - await fsPromises.mkdir(jobLogsDir, { recursive: true }); + // Ensure the directory exists + await fsPromises.mkdir(jobLogsDir, { recursive: true }); - // Write the job object as JSON - const jobFilePath = path.join(jobLogsDir, `${fileName}.json`); - await fsPromises.writeFile(jobFilePath, JSON.stringify(job, null, 2), 'utf8'); + // Write the job object as JSON + const jobFilePath = path.join(jobLogsDir, `${fileName}.json`); + await fsPromises.writeFile(jobFilePath, JSON.stringify(job, null, 2), "utf8"); - log.debug(`Job object written to: ${jobFilePath}`); - console.log(`Job object written to: ${jobFilePath}`); - return jobFilePath; - } catch (error) { - log.error('Error writing job object to logs folder:', error); - throw error; - } + log.debug(`Job object written to: ${jobFilePath}`); + console.log(`Job object written to: ${jobFilePath}`); + return jobFilePath; + } catch (error) { + log.error("Error writing job object to logs folder:", error); + throw error; + } } async function ScrubEstimate({ job }) { - //These are hard coded as they are not secure values and checking happens based on other values. - //No secret or private information is exposed. - const basicAuthUser = "Imex2"; - const basicAuthpassword = "Patrick"; - const estimateScrubberUrl = "https://insurtechtoolkit.com/api/sendems"; - const sendingEntityId = '87330f61-412b-4251-baaa-d026565b23c5' - + //These are hard coded as they are not secure values and checking happens based on other values. + //No secret or private information is exposed. + const basicAuthUser = "Imex2"; + const basicAuthpassword = "Patrick"; + const estimateScrubberUrl = "https://insurtechtoolkit.com/api/sendems"; + const sendingEntityId = "87330f61-412b-4251-baaa-d026565b23c5"; + try { //Perform data manipulation on the job object if (!job) { - console.error("No job provided to ScrubEstimate"); - return; + console.error("No job provided to ScrubEstimate"); + return; } //Set shop metrics @@ -53,47 +53,47 @@ async function ScrubEstimate({ job }) { job.g_ttl_amt = job.clm_total; job.source_system = "M"; //Requested by Steven. delete job.clm_total; - delete job.bodyshop //Bodyshop has to be passed through the object as we don't have access to the store here. + delete job.bodyshop; //Bodyshop has to be passed through the object as we don't have access to the store here. //Adjust the rates field to be MAT_TYPE instead of MATL_TYPE if (job.rates && Array.isArray(job.rates)) { - job.rates.forEach(rate => { - if (rate.MATL_TYPE) { - rate.MAT_TYPE = rate.MATL_TYPE; - delete rate.MATL_TYPE; - } - }); + job.rates.forEach((rate) => { + if (rate.MATL_TYPE) { + rate.MAT_TYPE = rate.MATL_TYPE; + delete rate.MATL_TYPE; + } + }); } //Lower case the rates & totals if (job.rates && Array.isArray(job.rates)) { - job.rates = job.rates.map(rate => { - const lowercasedRate = {}; - for (const [key, value] of Object.entries(rate)) { - lowercasedRate[key.toLowerCase()] = value; - } - return lowercasedRate; - }); + job.rates = job.rates.map((rate) => { + const lowercasedRate = {}; + for (const [key, value] of Object.entries(rate)) { + lowercasedRate[key.toLowerCase()] = value; + } + return lowercasedRate; + }); } if (job.totals && Array.isArray(job.totals)) { - job.totals = job.totals.map(total => { - const lowercasedTotal = {}; - for (const [key, value] of Object.entries(total)) { - lowercasedTotal[key.toLowerCase()] = value; - } - return lowercasedTotal; - }); + job.totals = job.totals.map((total) => { + const lowercasedTotal = {}; + for (const [key, value] of Object.entries(total)) { + lowercasedTotal[key.toLowerCase()] = value; + } + return lowercasedTotal; + }); } const fileName = `RPS-Scrub-${job.id}-${job.clm_no}-${Date.now()}`; // Write job object to logs subfolder try { - await writeJobToLogsFolder(job, fileName); + await writeJobToLogsFolder(job, fileName); } catch (error) { - log.error('Failed to write job to logs folder:', error); - // Continue with the rest of the function even if this fails + log.error("Failed to write job to logs folder:", error); + // Continue with the rest of the function even if this fails } const formData = new FormData(); @@ -101,21 +101,21 @@ async function ScrubEstimate({ job }) { formData.append("file", new Blob([jsonString], { type: "application/json" }), `${fileName}.json`); const result = await axios.post(estimateScrubberUrl, formData, { - auth: { - username: basicAuthUser, - password: basicAuthpassword - }, - headers: formData.getHeaders ? formData.getHeaders() : {} + auth: { + username: basicAuthUser, + password: basicAuthpassword + }, + headers: formData.getHeaders ? formData.getHeaders() : {} }); - const resultPDFUrl = result?.data?.report_link + const resultPDFUrl = result?.data?.report_link; // log.log("Estimate Scrubber Result:", result.data, resultPDFUrl); const b = BrowserWindow.getAllWindows()[0]; b.webContents.send(ipcTypes.app.toRenderer.scrubResults, { - jobid: job.id, - items: result.data?.identified_item, - pdfUrl: resultPDFUrl + jobid: job.id, + items: result.data?.identified_item, + pdfUrl: resultPDFUrl }); // const pdfWindow = new BrowserWindow({ @@ -127,6 +127,21 @@ async function ScrubEstimate({ job }) { // pdfWindow.loadURL(resultPDFUrl); // pdfWindow.focus(); - return resultPDFUrl + return resultPDFUrl; + } catch (error) { + log.error("Error while scrubbing estimate:", error); + log.error("Error Response Data:", error.response?.data); + const mainWindow = BrowserWindow.getAllWindows()[0]; + + if (error.status === 400) { + mainWindow.webContents.send(ipcTypes.app.toRenderer.scrubError, { + message: error.response?.data || "Error encountered sending estimate to Estimate Scrubber." + }); + } else if (error.status === 401) { + mainWindow.webContents.send(ipcTypes.app.toRenderer.scrubError, { + message: "Authentication with Estimate Scrubber failed." || error.response?.data + }); + } + } } -exports.ScrubEstimate = ScrubEstimate \ No newline at end of file +exports.ScrubEstimate = ScrubEstimate; diff --git a/package.json b/package.json index 5ef2243..0f8d5bc 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "productName": "ImEX RPS", "author": "ImEX Systems Inc. ", "description": "ImEX RPS", - "version": "1.4.2-beta.1", + "version": "1.4.2-beta.2", "main": "electron/main.js", "homepage": "./", "dependencies": { diff --git a/src/components/molecules/estimate-scrubber-button/estimate-scrubber-button.molecule.jsx b/src/components/molecules/estimate-scrubber-button/estimate-scrubber-button.molecule.jsx index 7c7dec7..a3f76b4 100644 --- a/src/components/molecules/estimate-scrubber-button/estimate-scrubber-button.molecule.jsx +++ b/src/components/molecules/estimate-scrubber-button/estimate-scrubber-button.molecule.jsx @@ -37,22 +37,23 @@ export function EstimateScrubberButton({ bodyshop, jobid, job }) { const result = await ipcRenderer.invoke(ipcTypes.app.toMain.scrubEstimate, { job: jobData.data.jobs_by_pk }); + if (result) { + message.success("Estimate scrubbed successfully! "); + // Scroll to the estimate scrubber results section + const scrollToResults = () => { + const element = document.getElementById("es-results-card"); + if (element) { + element.scrollIntoView({ + behavior: "smooth", + block: "start", + inline: "nearest" + }); + } + }; - message.success("Estimate scrubbed successfully! "); - // Scroll to the estimate scrubber results section - const scrollToResults = () => { - const element = document.getElementById("es-results-card"); - if (element) { - element.scrollIntoView({ - behavior: "smooth", - block: "start", - inline: "nearest" - }); - } - }; - - // Small delay to ensure DOM is updated before scrolling - setTimeout(scrollToResults, 100); + // Small delay to ensure DOM is updated before scrolling + setTimeout(scrollToResults, 100); + } } catch (error) { message.error("Error scrubbing estimate: " + error.message); console.error("Error scrubbing estimate:", error); diff --git a/src/ipc.types.json b/src/ipc.types.json index f3be029..02bd6b5 100644 --- a/src/ipc.types.json +++ b/src/ipc.types.json @@ -31,7 +31,8 @@ "signOut": "app_signOut", "setReleaseNotes": "app_setReleaseNotes", "appVersion": "app_appVersion", - "scrubResults": "app_scrubResults" + "scrubResults": "app_scrubResults", + "scrubError": "app_scrubError" } }, "store": { diff --git a/src/ipc/ipc-renderer-handler.js b/src/ipc/ipc-renderer-handler.js index be8a605..2343954 100644 --- a/src/ipc/ipc-renderer-handler.js +++ b/src/ipc/ipc-renderer-handler.js @@ -1,3 +1,4 @@ +import { notification } from "antd"; import ipcTypes from "../ipc.types"; import { setReleaseNotes, @@ -77,7 +78,7 @@ ipcRenderer.on(ipcTypes.app.toRenderer.appVersion, async (event, appversion) => window.$crisp.push(["set", "session:data", [[["rps-version", appversion]]]]); }); -//HAndle Autdit +//Handle Autdit ipcRenderer.on(ipcTypes.audit.toRenderer.auditClaimsArray, async (event, claimsArray) => { store.dispatch(calculateAudit(claimsArray)); @@ -88,3 +89,7 @@ ipcRenderer.on(ipcTypes.audit.toRenderer.auditError, async (event, error) => { ipcRenderer.on(ipcTypes.app.toRenderer.scrubResults, async (event, results) => { store.dispatch(setScrubResults(results)); }); + +ipcRenderer.on(ipcTypes.app.toRenderer.scrubError, async (event, { message }) => { + notification.open({ type: "error", message: "Estimate Scrubber Error", description: message }); +});