From 41308788fdc5e918450db0721199bd4ac7da17e7 Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Mon, 14 Jul 2025 10:18:23 -0500 Subject: [PATCH] feat(labelratio): new feature to monitor label ratio from auto and manual this was designed more for dayton but could be used for all plants --- database/schema/ratios.ts | 32 +++++++++++ .../ocp/controller/labeling/getLabelRatio.ts | 23 ++++++++ .../ocp/controller/labeling/labelRatio.ts | 53 +++++++++++++++++++ .../ocp/controller/printers/printerStatus.ts | 3 ++ .../dyco/plcTags/labelerTag.ts | 2 + .../ocp/routes/labeling/getLabelRatio.ts | 39 ++++++++++++++ .../ocp/routes/labeling/manualPrint.ts | 3 +- .../rfid/controller/stations/wrappers.ts | 3 +- 8 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 database/schema/ratios.ts create mode 100644 server/services/ocp/controller/labeling/getLabelRatio.ts create mode 100644 server/services/ocp/controller/labeling/labelRatio.ts create mode 100644 server/services/ocp/routes/labeling/getLabelRatio.ts diff --git a/database/schema/ratios.ts b/database/schema/ratios.ts new file mode 100644 index 0000000..f9dab99 --- /dev/null +++ b/database/schema/ratios.ts @@ -0,0 +1,32 @@ +import { + integer, + jsonb, + pgTable, + text, + timestamp, + uniqueIndex, + uuid, +} from "drizzle-orm/pg-core"; +import { createSelectSchema } from "drizzle-zod"; + +export const labelRatio = pgTable( + "labelRatio", + { + ratio_id: uuid(" ratio_id").defaultRandom().primaryKey(), + name: text("name").default("labels"), + autoLabel: integer("autoLabel").default(1), + manualLabel: integer("manualLabel").default(1), + lastReset: timestamp().defaultNow(), + }, + (table) => [ + // uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`), + uniqueIndex("labelname").on(table.name), + ] +); + +// Schema for inserting a user - can be used to validate API requests +// export const insertRolesSchema = createInsertSchema(roles, { +// name: z.string().min(3, {message: "Role name must be more than 3 letters"}), +// }); +// Schema for selecting a Expenses - can be used to validate API responses +export const selectRolesSchema = createSelectSchema(labelRatio); diff --git a/server/services/ocp/controller/labeling/getLabelRatio.ts b/server/services/ocp/controller/labeling/getLabelRatio.ts new file mode 100644 index 0000000..1bd368e --- /dev/null +++ b/server/services/ocp/controller/labeling/getLabelRatio.ts @@ -0,0 +1,23 @@ +import { db } from "../../../../../database/dbclient.js"; +import { labelRatio } from "../../../../../database/schema/ratios.js"; +import { tryCatch } from "../../../../globalUtils/tryCatch.js"; +export const getLabelRatio = async () => { + const { data: labelInfo, error: labelError } = await tryCatch( + db.select().from(labelRatio) + ); + + if (labelError) { + return { + success: false, + message: "There was an error getting the labels", + data: [labelError], + }; + } + + return { + success: true, + message: "Current labels order by upd_Date.", + count: labelInfo.length, + data: labelInfo, + }; +}; diff --git a/server/services/ocp/controller/labeling/labelRatio.ts b/server/services/ocp/controller/labeling/labelRatio.ts new file mode 100644 index 0000000..b15587b --- /dev/null +++ b/server/services/ocp/controller/labeling/labelRatio.ts @@ -0,0 +1,53 @@ +import { sql } from "drizzle-orm"; +import { db } from "../../../../../database/dbclient.js"; +import { labelRatio } from "../../../../../database/schema/ratios.js"; +import { tryCatch } from "../../../../globalUtils/tryCatch.js"; +import { createLog } from "../../../logger/logger.js"; + +export const autoLabelCreated = async () => { + const { error } = await tryCatch( + db + .insert(labelRatio) + .values({ + name: "label", + autoLabel: 1, + }) + .onConflictDoUpdate({ + target: labelRatio.name, + set: { autoLabel: sql`${labelRatio.autoLabel} + 1` }, + }) + ); + + if (error) { + createLog( + "error", + "labeling", + "ocp", + "There was an error updating auto label ratio" + ); + } +}; + +export const manualLabelCreated = async () => { + const { error } = await tryCatch( + db + .insert(labelRatio) + .values({ + name: "label", + manualLabel: 1, + }) + .onConflictDoUpdate({ + target: labelRatio.name, + set: { manualLabel: sql`${labelRatio.manualLabel} + 1` }, + }) + ); + + if (error) { + createLog( + "error", + "labeling", + "ocp", + "There was an error updating manual Label Ratio" + ); + } +}; diff --git a/server/services/ocp/controller/printers/printerStatus.ts b/server/services/ocp/controller/printers/printerStatus.ts index 8d69cc9..c632261 100644 --- a/server/services/ocp/controller/printers/printerStatus.ts +++ b/server/services/ocp/controller/printers/printerStatus.ts @@ -7,6 +7,7 @@ import { unPausePrinter } from "../../utils/unpausePrinter.js"; import { labelingProcess } from "../labeling/labelProcess.js"; import { timeZoneFix } from "../../../../globalUtils/timeZoneFix.js"; +import { autoLabelCreated } from "../labeling/labelRatio.js"; let logLevel: string = process.env.LOG_LEVEL || "info"; let errorCheck = false; @@ -132,6 +133,7 @@ export const printerStatus = async (p: any) => { // sending over for labeling. labelingProcess({ printer: p }); + autoLabelCreated(); } else if (tmp[2] === "0") { // printer was unpaused for the first time or made it here createLog( @@ -146,6 +148,7 @@ export const printerStatus = async (p: any) => { // sending over for labeling. labelingProcess({ printer: p }); + autoLabelCreated(); } else if (tmp[2] === "1") { // printer is paused and waiting createLog( diff --git a/server/services/ocp/controller/specialProcesses/dyco/plcTags/labelerTag.ts b/server/services/ocp/controller/specialProcesses/dyco/plcTags/labelerTag.ts index 5efeded..a12e20a 100644 --- a/server/services/ocp/controller/specialProcesses/dyco/plcTags/labelerTag.ts +++ b/server/services/ocp/controller/specialProcesses/dyco/plcTags/labelerTag.ts @@ -4,6 +4,7 @@ import { tryCatch } from "../../../../../../globalUtils/tryCatch.js"; import { createLog } from "../../../../../logger/logger.js"; import { readTags } from "../../../../../rfid/controller/readTags.js"; import { labelingProcess } from "../../../labeling/labelProcess.js"; +import { autoLabelCreated } from "../../../labeling/labelRatio.js"; import { stapperFaulted, strapperFaults } from "./strapperFault.js"; export let cameraPalletCheck = 20; @@ -85,6 +86,7 @@ export const labelerTagRead = async (tagData: any) => { cameraPalletCheck - currentPalletCheck }.` ); + autoLabelCreated(); } else { currentPalletCheck = 0; createLog( diff --git a/server/services/ocp/routes/labeling/getLabelRatio.ts b/server/services/ocp/routes/labeling/getLabelRatio.ts new file mode 100644 index 0000000..19b2ef4 --- /dev/null +++ b/server/services/ocp/routes/labeling/getLabelRatio.ts @@ -0,0 +1,39 @@ +// an external way to creating logs +import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; +import { responses } from "../../../../globalUtils/routeDefs/responses.js"; +import { tryCatch } from "../../../../globalUtils/tryCatch.js"; +import { apiHit } from "../../../../globalUtils/apiHits.js"; +import { getLabelRatio } from "../../controller/labeling/getLabelRatio.js"; + +const app = new OpenAPIHono({ strict: false }); + +app.openapi( + createRoute({ + tags: ["ocp"], + summary: "Returns current active lots that are tech released", + method: "get", + path: "/labelratio", + responses: responses(), + }), + async (c) => { + const { data: labelData, error: labelError } = await tryCatch( + getLabelRatio() + ); + apiHit(c, { endpoint: "/labelratio" }); + + if (labelError) { + return c.json({ + success: false, + message: "There was an error getting the printers", + }); + } + + return c.json({ + success: labelData.success, + message: labelData.message, + count: labelData.count, + data: labelData.data, + }); + } +); +export default app; diff --git a/server/services/ocp/routes/labeling/manualPrint.ts b/server/services/ocp/routes/labeling/manualPrint.ts index b69f158..4d51107 100644 --- a/server/services/ocp/routes/labeling/manualPrint.ts +++ b/server/services/ocp/routes/labeling/manualPrint.ts @@ -4,6 +4,7 @@ import { responses } from "../../../../globalUtils/routeDefs/responses.js"; import { tryCatch } from "../../../../globalUtils/tryCatch.js"; import { labelingProcess } from "../../controller/labeling/labelProcess.js"; import { apiHit } from "../../../../globalUtils/apiHits.js"; +import { manualLabelCreated } from "../../controller/labeling/labelRatio.js"; const app = new OpenAPIHono({ strict: false }); @@ -32,7 +33,7 @@ app.openapi( const { data: createLabel, error: labelError } = await tryCatch( labelingProcess({ line: bodyData.line }) ); - + manualLabelCreated(); if (labelError) { return c.json({ success: false, diff --git a/server/services/rfid/controller/stations/wrappers.ts b/server/services/rfid/controller/stations/wrappers.ts index 756e362..01ac5a5 100644 --- a/server/services/rfid/controller/stations/wrappers.ts +++ b/server/services/rfid/controller/stations/wrappers.ts @@ -14,6 +14,7 @@ import { rfidTags } from "../../../../../database/schema/rfidTags.js"; import { and, eq, gte, ne, sql } from "drizzle-orm"; import { rfidReaders } from "../../../../../database/schema/rfidReaders.js"; import { shouldSkipByCooldown } from "../../utils/rateLimit.js"; +import { autoLabelCreated } from "../../../ocp/controller/labeling/labelRatio.js"; export const wrapperStuff = async (tagData: any) => { console.log("WrapperTag", tagData[0].tag); @@ -152,7 +153,7 @@ export const wrapperStuff = async (tagData: any) => { const genlabel = await labelingProcess({ line: lineNum.toString(), }); - + autoLabelCreated(); console.log(genlabel); if (genlabel?.success) { const createPrintData = {