From 282eab01e15f81bcc407f45f1f3ffff056e0f27a Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Thu, 16 Oct 2025 14:37:51 -0500 Subject: [PATCH] feat(preprint): added in preprint function to help with operations planning constraints --- .../logistics/controller/labeling/preprint.ts | 133 ++++++++++++++++++ app/src/internal/logistics/routes.ts | 21 +-- .../routes/labeling/labelingRoutes.ts | 8 ++ .../logistics/routes/labeling/perprint.ts | 27 ++++ app/src/pkg/utils/axiosInstance.ts | 8 ++ app/src/pkg/utils/prodEndpoint.ts | 90 ++++++++++++ 6 files changed, 277 insertions(+), 10 deletions(-) create mode 100644 app/src/internal/logistics/controller/labeling/preprint.ts create mode 100644 app/src/internal/logistics/routes/labeling/labelingRoutes.ts create mode 100644 app/src/internal/logistics/routes/labeling/perprint.ts create mode 100644 app/src/pkg/utils/axiosInstance.ts create mode 100644 app/src/pkg/utils/prodEndpoint.ts diff --git a/app/src/internal/logistics/controller/labeling/preprint.ts b/app/src/internal/logistics/controller/labeling/preprint.ts new file mode 100644 index 0000000..a1ec20d --- /dev/null +++ b/app/src/internal/logistics/controller/labeling/preprint.ts @@ -0,0 +1,133 @@ +/** + * we want to be able to preprint labels from finished lots. + * we will need a lot number + * machine + * printer + * qty will come over as one by default + * copies will come over as 0 by default + * layout + */ + +import { createLogger } from "../../../../pkg/logger/logger.js"; +import { delay } from "../../../../pkg/utils/delay.js"; +import { prodEndpoint } from "../../../../pkg/utils/prodEndpoint.js"; +import type { returnFunc } from "../../../../pkg/utils/return.js"; + +export type Preprint = { + scannerId: number; + lotNr: number; + machineId: number; + printerId: number; + layoutId: number; + numberOfCopies: number; + qtyToPrint: number; +}; + +export const preprintLabels = async (preprint: Preprint) => { + const log = createLogger({ + module: "logistics", + subModule: "preprint", + }); + let x = 0; + + const labelsPrinted: number[] = []; + if (preprint.qtyToPrint > 1) { + do { + const labels = await prodEndpoint( + "POST", + "/public/v1.0/Warehousing/GenerateAndPrintLabel", + { + scannerId: preprint.scannerId, + lotNr: preprint.lotNr, + machineId: preprint.machineId, // 457=22, 458=23 + printerId: preprint.printerId, // 457=22, 458=23 + layoutId: preprint.layoutId, + numberOfCopies: preprint.numberOfCopies, + }, + ); + if (labels?.data.Result === 1) { + log.error( + {}, + `There was an error printing the label: ${labels.data.Message}`, + ); + return { + success: false, + message: `${labels.data.Message}`, + }; + } else { + if (!labels?.success) { + log.error( + { error: labels?.data }, + `There was an error printing the label`, + ); + return { + success: false, + message: `${labels?.message}`, + data: labels?.data, + }; + } + labelsPrinted.push(parseInt(labels?.data.SSCC.slice(10, -1))); + log.info( + {}, + `Label just created ${parseInt(labels?.data.SSCC.slice(10, -1))} and printed, remaining to print ${preprint.qtyToPrint - x}`, + ); + } + await delay(250); + x++; + } while (x < preprint.qtyToPrint); + + return { + success: true, + message: `${preprint.qtyToPrint} were just printed`, + data: labelsPrinted, + }; + } else { + const labels = await prodEndpoint( + "POST", + "/public/v1.0/Warehousing/GenerateAndPrintLabel", + { + scannerId: preprint.scannerId, + lotNr: preprint.lotNr, + machineId: preprint.machineId, // 457=22, 458=23 + printerId: preprint.printerId, // 457=22, 458=23 + layoutId: preprint.layoutId, + numberOfCopies: preprint.numberOfCopies, + }, + ); + + if (labels?.data.Result === 1) { + log.error( + {}, + `There was an error printing the label: ${labels.data.Message}`, + ); + return { + success: false, + message: `${labels.data.Message}`, + }; + } else { + if (!labels?.success) { + log.error( + { error: labels?.data }, + `There was an error printing the label`, + ); + return { + success: false, + message: `${labels?.message}`, + data: labels?.data, + }; + } + + labelsPrinted.push(parseInt(labels.data.SSCC.slice(10, -1))); + log.info( + {}, + `Label just created ${parseInt(labels.data.SSCC.slice(10, -1))} and printed`, + ); + + return { + success: true, + message: `${preprint.qtyToPrint} were just printed.`, + data: labelsPrinted, + }; + } + } +}; diff --git a/app/src/internal/logistics/routes.ts b/app/src/internal/logistics/routes.ts index ce82092..5018446 100644 --- a/app/src/internal/logistics/routes.ts +++ b/app/src/internal/logistics/routes.ts @@ -1,16 +1,17 @@ import type { Express, Request, Response } from "express"; -import { requireAuth } from "../../pkg/middleware/authMiddleware.js"; +import labeling from "./routes/labeling/labelingRoutes.js"; import schedule from "./routes/scheduler/scheduleRoutes.js"; export const setupLogisticsRoutes = (app: Express, basePath: string) => { - app.use(basePath + "/api/logistics/schedule", schedule); + app.use(basePath + "/api/logistics/schedule", schedule); + app.use(basePath + "/api/logistics/labeling", labeling); - app.use( - basePath + "/api/admin/users", - requireAuth("user", ["systemAdmin"]) // will pass bc system admin but this is just telling us we need this - ); - app.use( - basePath + "/api/admin", - requireAuth("user", ["systemAdmin", "admin"]) // will pass bc system admin but this is just telling us we need this - ); + // app.use( + // basePath + "/api/admin/users", + // requireAuth("user", ["systemAdmin"]), // will pass bc system admin but this is just telling us we need this + // ); + // app.use( + // basePath + "/api/admin", + // requireAuth("user", ["systemAdmin", "admin"]), // will pass bc system admin but this is just telling us we need this + // ); }; diff --git a/app/src/internal/logistics/routes/labeling/labelingRoutes.ts b/app/src/internal/logistics/routes/labeling/labelingRoutes.ts new file mode 100644 index 0000000..1b3c685 --- /dev/null +++ b/app/src/internal/logistics/routes/labeling/labelingRoutes.ts @@ -0,0 +1,8 @@ +import { Router } from "express"; +import preprint from "./perprint.js"; + +const router = Router(); + +router.use("/", preprint); + +export default router; diff --git a/app/src/internal/logistics/routes/labeling/perprint.ts b/app/src/internal/logistics/routes/labeling/perprint.ts new file mode 100644 index 0000000..b728502 --- /dev/null +++ b/app/src/internal/logistics/routes/labeling/perprint.ts @@ -0,0 +1,27 @@ +import type { Request, Response } from "express"; +import { Router } from "express"; +import z from "zod"; +import { preprintLabels } from "../../controller/labeling/preprint.js"; + +export const Preprint = z.object({ + scannerId: z.number(), + lotNr: z.number(), + machineId: z.number(), // 457=22, 458=23 + printerId: z.number(), // 457=22, 458=23 + layoutId: z.number(), + numberOfCopies: z.number(), + qtyToPrint: z.number().default(1), +}); + +const router = Router(); + +router.post("/preprint", async (req: Request, res: Response) => { + const parsed = Preprint.safeParse(req.body); + const print = await preprintLabels(req.body); + + res + .status(200) + .json({ success: print.success, message: print.message, data: print.data }); +}); + +export default router; diff --git a/app/src/pkg/utils/axiosInstance.ts b/app/src/pkg/utils/axiosInstance.ts new file mode 100644 index 0000000..58b00bf --- /dev/null +++ b/app/src/pkg/utils/axiosInstance.ts @@ -0,0 +1,8 @@ +import axios from "axios"; +import https from "https"; + +export const axiosInstance = axios.create({ + httpsAgent: new https.Agent({ rejectUnauthorized: false }), + baseURL: process.env.MAIN_SERVER, + withCredentials: true, +}); diff --git a/app/src/pkg/utils/prodEndpoint.ts b/app/src/pkg/utils/prodEndpoint.ts new file mode 100644 index 0000000..7c8934b --- /dev/null +++ b/app/src/pkg/utils/prodEndpoint.ts @@ -0,0 +1,90 @@ +/** + * This will fire the endpoints + * we only need the endpoint url grabbed from swagger + * and the data to be passed over + */ + +import axios, { type Method } from "axios"; +import { eq } from "drizzle-orm"; +import https from "https"; +import { db } from "../db/db.js"; +import { settings } from "../db/schema/settings.js"; +import { createLogger } from "../logger/logger.js"; +import { tryCatch } from "./tryCatch.js"; + +// create the test server stuff +const testServers = [ + { token: "test1", port: 8940 }, + { token: "test2", port: 8941 }, + { token: "test3", port: 8942 }, +]; + +export const prodEndpoint = async ( + method: Method, + endpoint: string, + data?: T, +) => { + const log = createLogger({ module: "pkg", subModule: "prodEndpoints" }); + // example url "https://usmcd1vms036.alpla.net:8942/application/public/v1.0/DemandManagement/ORDERS" + let url = ""; + + // as a reminder when we look for specific like below it will come over as an array this is due to more than one item could be found + const plantToken = await db + .select() + .from(settings) + .where(eq(settings.name, "plantToken")); + + const testServer = testServers.some( + (server) => server.token === plantToken[0]?.value, + ); + const server = await db + .select() + .from(settings) + .where(eq(settings.name, "dbServer")); + + if (testServer) { + //filter out what testserver we are + const test = testServers.filter((t) => t.token === plantToken[0].value); + url = `https://${server[0]?.value}.alpla.net:${test[0]?.port}/application${endpoint}`; + } else { + url = `https://${plantToken[0]?.value}prod.alpla.net/application${endpoint}`; + } + + // create the axio instance + const axiosInstance = axios.create({ + httpsAgent: new https.Agent({ rejectUnauthorized: false }), + withCredentials: true, + headers: { + "X-API-Key": process.env.TEC_API_KEY || "", + "Content-Type": "application/json", + }, + }); + + const { data: api, error: apiError } = (await tryCatch( + axiosInstance({ + method, + url: url, + ...(data && { data }), + }), + )) as any; + + if (apiError) { + log.error( + { error: apiError?.response?.data }, + "There was an error running the endpoint", + ); + return { + success: false, + message: "There was an error processing the endpoint", + data: apiError.response.data, + }; + } + + if (api) { + return { + success: true, + message: "Prod endpoint processed", + data: api.data, + }; + } +};