feature/IO-3205-Paint-Scale-Integrations: Pre Change Checkpoint

This commit is contained in:
Dave Richer
2025-04-29 13:10:18 -04:00
parent 9a33993dea
commit 2c2652d07e
4 changed files with 143 additions and 191 deletions

View File

@@ -5,3 +5,5 @@ VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.bodyshop.app/v1/graphql
VITE_COMPANY=IMEX VITE_COMPANY=IMEX
VITE_FE_URL=https://imex.online VITE_FE_URL=https://imex.online
VITE_FE_URL_TEST=https://test.imex.online VITE_FE_URL_TEST=https://test.imex.online
VITE_API_URL="http://localhost:4000"
VITE_API_TEST_URL="http://api.test.imex.online"

View File

@@ -5,3 +5,5 @@ VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.bodyshop.app/v1/graphql
VITE_COMPANY=IMEX VITE_COMPANY=IMEX
VITE_FE_URL=https://imex.online VITE_FE_URL=https://imex.online
VITE_FE_URL_TEST=https://test.imex.online VITE_FE_URL_TEST=https://test.imex.online
VITE_API_URL="http://localhost:4000"
VITE_API_TEST_URL="http://api.test.imex.online"

View File

@@ -5,3 +5,5 @@ VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.romeonline.io/v1/graphql
VITE_COMPANY=ROME VITE_COMPANY=ROME
VITE_FE_URL=https://romeonline.io VITE_FE_URL=https://romeonline.io
VITE_FE_URL_TEST=https://test.romeonline.io VITE_FE_URL_TEST=https://test.romeonline.io
VITE_API_URL="http://localhost:4000"
VITE_API_TEST_URL="http://api.test.romeonline.io"

View File

@@ -119,7 +119,6 @@ const initializeCronTasks = async () => {
} }
}; };
// Log all IPC messages and their payloads // Log all IPC messages and their payloads
const logIpcMessages = (): void => { const logIpcMessages = (): void => {
Object.keys(ipcTypes.toMain).forEach((key) => { Object.keys(ipcTypes.toMain).forEach((key) => {
@@ -180,6 +179,7 @@ const inputTypeHandlers: Record<
// Upload file to API // Upload file to API
const formData = new FormData(); const formData = new FormData();
formData.append( formData.append(
"file", "file",
new Blob([await fs.readFile(filePath)]), new Blob([await fs.readFile(filePath)]),
@@ -190,17 +190,20 @@ const inputTypeHandlers: Record<
(store.get("app.bodyshop") as BodyShop)?.shopname || "", (store.get("app.bodyshop") as BodyShop)?.shopname || "",
); );
// TODO Clear up how to fetch API URL const baseURL = store.get("app.isTest")
const response = await axios.post( ? import.meta.env.VITE_API_TEST_URL
"https://your-api-base-url/mixdata/upload", : import.meta.env.VITE_API_URL;
formData,
{ const finalUrl = `${baseURL}/mixdata/upload`;
log.debug(`Uploading file to ${finalUrl}`);
const response = await axios.post(finalUrl, formData, {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
"Content-Type": "multipart/form-data", "Content-Type": "multipart/form-data",
}, },
}, });
);
if (response.status === 200) { if (response.status === 200) {
log.info(`Successful upload of ${filePath}`); log.info(`Successful upload of ${filePath}`);
@@ -311,137 +314,80 @@ const outputTypeHandlers: Record<
variables, variables,
)) as GraphQLResponse; )) as GraphQLResponse;
// Generate XML // Build JSON structure
const doc = create({ version: "1.0" }) const jsonData = {
.ele("PPG") PPG: {
.ele("Header") Header: {
.ele("Protocol") Protocol: {
.ele("Message") Message: "PaintShopInterface",
.txt("PaintShopInterface") Name: "PPG",
.up() Version: "1.5.0",
.ele("Name") },
.txt("PPG") Transaction: {
.up() TransactionID: "",
.ele("Version") TransactionDate: new Date()
.txt("1.5.0") .toISOString()
.up() .replace("T", " ")
.up() .substring(0, 19),
.ele("Transaction") },
.ele("TransactionID") Product: {
.txt("") Name: "ImEX Online",
.up() Version: "",
.ele("TransactionDate") },
.txt(new Date().toISOString().replace("T", " ").substring(0, 19)) },
.up() DataInterface: {
.up() ROData: {
.ele("Product") ShopInfo: {
.ele("Name") ShopID: response.bodyshops_by_pk?.imexshopid || "",
.txt("ImEX Online") ShopName: response.bodyshops_by_pk?.shopname || "",
.up() },
.ele("Version") RepairOrders: {
.txt("") ROCount: (response.jobs?.length || 0).toString(),
.up() RO:
.up() response.jobs?.map((job) => ({
.up() RONumber: job.ro_number || "",
.ele("DataInterface") ROStatus: "Open",
.ele("ROData") Customer: `${job.ownr_ln || ""}, ${job.ownr_fn || ""}`,
.ele("ShopInfo") ROPainterNotes: "",
.ele("ShopID") LicensePlateNum: job.plate_no || "",
.txt(response.bodyshops_by_pk?.imexshopid || "") VIN: job.v_vin || "",
.up() ModelYear: job.v_model_yr || "",
.ele("ShopName") MakeDesc: job.v_make_desc || "",
.txt(response.bodyshops_by_pk?.shopname || "") ModelName: job.v_model_desc || "",
.up() OEMColorCode: job.vehicle?.v_paint_codes?.paint_cd1 || "",
.up() RefinishLaborHours:
.ele("RepairOrders") job.larhrs_aggregate?.aggregate?.sum?.mod_lb_hrs || 0,
.ele("ROCount") InsuranceCompanyName: job.ins_co_nm || "",
.txt((response.jobs?.length || 0).toString()) EstimatorName: `${job.est_ct_ln || ""}, ${job.est_ct_fn || ""}`,
.up() PaintMaterialsRevenue: (
.up() (job.job_totals?.rates?.mapa?.total?.amount || 0) / 100
.up() ).toFixed(2),
.up(); PaintMaterialsRate: job.rate_mapa || 0,
BodyHours:
job.labhrs_aggregate?.aggregate?.sum?.mod_lb_hrs || 0,
BodyLaborRate: job.rate_lab || 0,
TotalCostOfRepairs: (
(job.job_totals?.totals?.subtotal?.amount || 0) / 100
).toFixed(2),
})) || [],
},
},
},
},
};
const repairOrders = (doc.root() as any).findOne("RepairOrders"); // Convert JSON to XML
(response as GraphQLResponse).jobs?.forEach((job: any) => { const doc = create({ version: "1.0" }, jsonData);
repairOrders const xmlString = doc.end({ prettyPrint: true });
.ele("RO")
.ele("RONumber")
.txt(job.ro_number || "")
.up()
.ele("ROStatus")
.txt("Open")
.up()
.ele("Customer")
.txt(`${job.ownr_ln || ""}, ${job.ownr_fn || ""}`)
.up()
.ele("ROPainterNotes")
.txt("")
.up()
.ele("LicensePlateNum")
.txt(job.plate_no || "")
.up()
.ele("VIN")
.txt(job.v_vin || "")
.up()
.ele("ModelYear")
.txt(job.v_model_yr || "")
.up()
.ele("MakeDesc")
.txt(job.v_make_desc || "")
.up()
.ele("ModelName")
.txt(job.v_model_desc || "")
.up()
.ele("OEMColorCode")
.txt(job.vehicle?.v_paint_codes?.paint_cd1 || "")
.up()
.ele("RefinishLaborHours")
.txt(job.larhrs_aggregate?.aggregate?.sum?.mod_lb_hrs || 0)
.up()
.ele("InsuranceCompanyName")
.txt(job.ins_co_nm || "")
.up()
.ele("EstimatorName")
.txt(`${job.est_ct_ln || ""}, ${job.est_ct_fn || ""}`)
.up()
.ele("PaintMaterialsRevenue")
.txt(
((job.job_totals?.rates?.mapa?.total?.amount || 0) / 100).toFixed(
2,
),
)
.up()
.ele("PaintMaterialsRate")
.txt(job.rate_mapa || 0)
.up()
.ele("BodyHours")
.txt(job.labhrs_aggregate?.aggregate?.sum?.mod_lb_hrs || 0)
.up()
.ele("BodyLaborRate")
.txt(job.rate_lab || 0)
.up()
.ele("TotalCostOfRepairs")
.txt(
((job.job_totals?.totals?.subtotal?.amount || 0) / 100).toFixed(2),
)
.up();
});
// Save XML to file // Save XML to file
const xmlString = doc.end({ prettyPrint: true }); const outputPath = path.join(config.path!, `PPGPaint.xml`);
const timestamp = new Date()
.toISOString()
.replace(/[-:]/g, "")
.replace("T", "")
.substring(0, 14);
const outputPath = path.join(config.path!, `PPGPaint_${timestamp}.xml`);
await fs.writeFile(outputPath, xmlString); await fs.writeFile(outputPath, xmlString);
log.info(`Saved PPG output XML to ${outputPath}`); log.info(`Saved PPG output XML to ${outputPath}`);
} catch (error) { } catch (error) {
log.error(`Error generating PPG output for config ${config.id}:`, error); log.error(`Error generating PPG output for config ${config.id}:`, error);
} }
}, }, // Add other output type handlers as needed
// Add other output type handlers as needed
}; };
// Default handler for unsupported types // Default handler for unsupported types
@@ -469,7 +415,7 @@ const handlePaintScaleInputCron = async (configs: PaintScaleConfig[]) => {
await handler(config); await handler(config);
}); });
log.info( log.info(
`Started input cron task for config ${config.id} (type: ${config.type}) with interval ${config.pollingInterval}s`, `Started input cron task for config ${config.id} (type: ${config.type}) with interval ${config.pollingInterval}m`,
); );
}); });
}; };
@@ -492,7 +438,7 @@ const handlePaintScaleOutputCron = async (configs: PaintScaleConfig[]) => {
await handler(config); await handler(config);
}); });
log.info( log.info(
`Started output cron task for config ${config.id} (type: ${config.type}) with interval ${config.pollingInterval}s`, `Started output cron task for config ${config.id} (type: ${config.type}) with interval ${config.pollingInterval}m`,
); );
}); });
}; };