From a691dc276e8650c669409241f73d7b2d7a1f9176 Mon Sep 17 00:00:00 2001 From: Blake Matthes Date: Thu, 9 Apr 2026 21:12:43 -0500 Subject: [PATCH] feat(puchase hist): finished up purhcase historical / gp updates --- backend/configs/gpSql.config.ts | 23 + backend/db/schema/alplapurchase.schema.ts | 3 +- backend/gpSql/gpSql.routes.ts | 17 + backend/gpSql/gpSqlConnection.controller.ts | 155 ++ backend/gpSql/gpSqlQuery.controller.ts | 97 ++ backend/gpSql/gpSqlQuerySelector.utils.ts | 29 + backend/gpSql/gpSqlRestart.route.ts | 23 + backend/gpSql/gpSqlStart.route.ts | 20 + backend/gpSql/gpSqlStop.route.ts | 20 + backend/gpSql/queries/reqCheck.sql | 39 + backend/purchase/puchase.gpCheck.ts | 117 ++ backend/purchase/purchase.controller.ts | 143 +- backend/routeHandler.routes.ts | 2 + backend/types/purhcaseTypes.ts | 9 + backend/utils/returnHelper.utils.ts | 11 +- migrations/0025_talented_vector.sql | 1 + migrations/0026_vengeful_wiccan.sql | 1 + migrations/meta/0025_snapshot.json | 1474 +++++++++++++++++++ migrations/meta/0026_snapshot.json | 1474 +++++++++++++++++++ migrations/meta/_journal.json | 14 + package-lock.json | 19 + package.json | 7 +- 22 files changed, 3686 insertions(+), 12 deletions(-) create mode 100644 backend/configs/gpSql.config.ts create mode 100644 backend/gpSql/gpSql.routes.ts create mode 100644 backend/gpSql/gpSqlConnection.controller.ts create mode 100644 backend/gpSql/gpSqlQuery.controller.ts create mode 100644 backend/gpSql/gpSqlQuerySelector.utils.ts create mode 100644 backend/gpSql/gpSqlRestart.route.ts create mode 100644 backend/gpSql/gpSqlStart.route.ts create mode 100644 backend/gpSql/gpSqlStop.route.ts create mode 100644 backend/gpSql/queries/reqCheck.sql create mode 100644 backend/purchase/puchase.gpCheck.ts create mode 100644 backend/types/purhcaseTypes.ts create mode 100644 migrations/0025_talented_vector.sql create mode 100644 migrations/0026_vengeful_wiccan.sql create mode 100644 migrations/meta/0025_snapshot.json create mode 100644 migrations/meta/0026_snapshot.json diff --git a/backend/configs/gpSql.config.ts b/backend/configs/gpSql.config.ts new file mode 100644 index 0000000..69deaf2 --- /dev/null +++ b/backend/configs/gpSql.config.ts @@ -0,0 +1,23 @@ +import type sql from "mssql"; + +const username = "gpviewer"; +const password = "gp$$ViewOnly!"; + +export const gpSqlConfig: sql.config = { + server: `USMCD1VMS011`, + database: `ALPLA`, + user: username, + password: password, + options: { + encrypt: true, + trustServerCertificate: true, + }, + requestTimeout: 90000, // how long until we kill the query and fail it + pool: { + max: 20, // Maximum number of connections in the pool + min: 0, // Minimum number of connections in the pool + idleTimeoutMillis: 10000, // How long a connection is allowed to be idle before being released + reapIntervalMillis: 1000, // how often to check for idle resources to destroy + acquireTimeoutMillis: 100000, // How long until a complete timeout happens + }, +}; diff --git a/backend/db/schema/alplapurchase.schema.ts b/backend/db/schema/alplapurchase.schema.ts index 287a3c0..40ca9b8 100644 --- a/backend/db/schema/alplapurchase.schema.ts +++ b/backend/db/schema/alplapurchase.schema.ts @@ -22,9 +22,10 @@ export const alplaPurchaseHistory = pgTable("alpla_purchase_history", { upd_user: text("upd_user"), upd_date: timestamp("upd_date").defaultNow(), remark: text("remark"), - approvedStatus: text("approved_status").default("pending"), + approvedStatus: text("approved_status").default("new"), position: jsonb("position").default([]), createdAt: timestamp("created_at").defaultNow(), + updatedAt: timestamp("updated_at").defaultNow(), }); export const alplaPurchaseHistorySchema = diff --git a/backend/gpSql/gpSql.routes.ts b/backend/gpSql/gpSql.routes.ts new file mode 100644 index 0000000..923bcec --- /dev/null +++ b/backend/gpSql/gpSql.routes.ts @@ -0,0 +1,17 @@ +import { type Express, Router } from "express"; +import { requireAuth } from "../middleware/auth.middleware.js"; +import restart from "./gpSqlRestart.route.js"; +import start from "./gpSqlStart.route.js"; +import stop from "./gpSqlStop.route.js"; +export const setupGPSqlRoutes = (baseUrl: string, app: Express) => { + //setup all the routes + // Apply auth to entire router + const router = Router(); + router.use(requireAuth); + + router.use(start); + router.use(stop); + router.use(restart); + + app.use(`${baseUrl}/api/system/gpSql`, router); +}; diff --git a/backend/gpSql/gpSqlConnection.controller.ts b/backend/gpSql/gpSqlConnection.controller.ts new file mode 100644 index 0000000..3ee01be --- /dev/null +++ b/backend/gpSql/gpSqlConnection.controller.ts @@ -0,0 +1,155 @@ +import sql from "mssql"; +import { gpSqlConfig } from "../configs/gpSql.config.js"; +import { createLogger } from "../logger/logger.controller.js"; +import { checkHostnamePort } from "../utils/checkHost.utils.js"; +import { returnFunc } from "../utils/returnHelper.utils.js"; + +export let pool2: sql.ConnectionPool; +export let connected: boolean = false; +export let reconnecting = false; + +export const connectGPSql = async () => { + const serverUp = await checkHostnamePort(`USMCD1VMS011:1433`); + if (!serverUp) { + // we will try to reconnect + connected = false; + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "db", + message: "GP server is offline or unreachable.", + }); + } + + // if we are trying to click restart from the api for some reason we want to kick back and say no + if (connected) { + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "db", + message: "The Sql server is already connected.", + }); + } + + // try to connect to the sql server + try { + pool2 = new sql.ConnectionPool(gpSqlConfig); + await pool2.connect(); + connected = true; + return returnFunc({ + success: true, + level: "info", + module: "system", + subModule: "db", + message: `${gpSqlConfig.server} is connected to ${gpSqlConfig.database}`, + data: [], + notify: false, + }); + } catch (error) { + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "db", + message: "Failed to connect to the prod sql server.", + data: [error], + notify: false, + }); + } +}; + +export const closePool = async () => { + if (!connected) { + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "db", + message: "There is no connection to the prod server currently.", + }); + } + + try { + await pool2.close(); + connected = false; + return returnFunc({ + success: true, + level: "info", + module: "system", + subModule: "db", + message: "The sql connection has been closed.", + }); + } catch (error) { + connected = false; + + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "db", + message: "There was an error closing the sql connection", + data: [error], + }); + } +}; +export const reconnectToSql = async () => { + const log = createLogger({ + module: "system", + subModule: "db", + }); + if (reconnecting) return; + + //set reconnecting to true while we try to reconnect + reconnecting = true; + + // start the delay out as 2 seconds + let delayStart = 2000; + let attempt = 0; + const maxAttempts = 10; + + while (!connected && attempt < maxAttempts) { + attempt++; + log.info( + `Reconnect attempt ${attempt}/${maxAttempts} in ${delayStart / 1000}s ...`, + ); + + await new Promise((res) => setTimeout(res, delayStart)); + + const serverUp = await checkHostnamePort(`${process.env.PROD_SERVER}:1433`); + + if (!serverUp) { + delayStart = Math.min(delayStart * 2, 30000); // exponential backoff until up to 30000 + return; + } + + try { + pool2 = await sql.connect(gpSqlConfig); + reconnecting = false; + connected = true; + log.info(`${gpSqlConfig.server} is connected to ${gpSqlConfig.database}`); + } catch (error) { + delayStart = Math.min(delayStart * 2, 30000); + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "db", + message: "Failed to reconnect to the prod sql server.", + data: [error], + notify: false, + }); + } + } + + if (!connected) { + log.error( + { notify: true }, + "Max reconnect attempts reached on the prodSql server. Stopping retries.", + ); + + reconnecting = false; + // TODO: exit alert someone here + } +}; diff --git a/backend/gpSql/gpSqlQuery.controller.ts b/backend/gpSql/gpSqlQuery.controller.ts new file mode 100644 index 0000000..f8509db --- /dev/null +++ b/backend/gpSql/gpSqlQuery.controller.ts @@ -0,0 +1,97 @@ +import { returnFunc } from "../utils/returnHelper.utils.js"; +import { + connected, + pool2, + reconnecting, + reconnectToSql, +} from "./gpSqlConnection.controller.js"; + +interface SqlError extends Error { + code?: string; + originalError?: { + info?: { message?: string }; + }; +} + +/** + * Run a prod query + * just pass over the query as a string and the name of the query. + * Query should be like below. + * * select * from AlplaPROD_test1.dbo.table + * You must use test1 always as it will be changed via query + */ +export const gpQuery = async (queryToRun: string, name: string) => { + if (!connected) { + reconnectToSql(); + + if (reconnecting) { + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "gpSql", + message: `The sql ${process.env.PROD_PLANT_TOKEN} is trying to reconnect already`, + data: [], + notify: false, + }); + } else { + return returnFunc({ + success: false, + level: "error", + module: "system", + subModule: "gpSql", + message: `${process.env.PROD_PLANT_TOKEN} is not connected, and failed to connect.`, + data: [], + notify: true, + }); + } + } + + //change to the correct server + const query = queryToRun.replaceAll( + "test1", + `${process.env.PROD_PLANT_TOKEN}`, + ); + + try { + const result = await pool2.request().query(query); + return { + success: true, + message: `Query results for: ${name}`, + data: result.recordset ?? [], + }; + } catch (error: unknown) { + const err = error as SqlError; + if (err.code === "ETIMEOUT") { + return returnFunc({ + success: false, + module: "system", + subModule: "gpSql", + level: "error", + message: `${name} did not run due to a timeout.`, + notify: false, + data: [], + }); + } + + if (err.code === "EREQUEST") { + return returnFunc({ + success: false, + module: "system", + subModule: "gpSql", + level: "error", + message: `${name} encountered an error ${err.originalError?.info?.message || "undefined error"}`, + data: [], + }); + } + + return returnFunc({ + success: false, + module: "system", + subModule: "gpSql", + level: "error", + message: `${name} encountered an unknown error.`, + data: [], + }); + } +}; diff --git a/backend/gpSql/gpSqlQuerySelector.utils.ts b/backend/gpSql/gpSqlQuerySelector.utils.ts new file mode 100644 index 0000000..64da8df --- /dev/null +++ b/backend/gpSql/gpSqlQuerySelector.utils.ts @@ -0,0 +1,29 @@ +import { readFileSync } from "node:fs"; + +export type SqlGPQuery = { + query: string; + success: boolean; + message: string; +}; + +export const sqlGpQuerySelector = (name: string) => { + try { + const queryFile = readFileSync( + new URL(`../gpSql/queries/${name}.sql`, import.meta.url), + "utf8", + ); + + return { + success: true, + message: `Query for: ${name}`, + query: queryFile, + }; + } catch (e) { + console.error(e); + return { + success: false, + message: + "Error getting the query file, please make sure you have the correct name.", + }; + } +}; diff --git a/backend/gpSql/gpSqlRestart.route.ts b/backend/gpSql/gpSqlRestart.route.ts new file mode 100644 index 0000000..3b73cda --- /dev/null +++ b/backend/gpSql/gpSqlRestart.route.ts @@ -0,0 +1,23 @@ +import { Router } from "express"; +import { apiReturn } from "../utils/returnHelper.utils.js"; +import { closePool, connectGPSql } from "./gpSqlConnection.controller.js"; + +const r = Router(); + +r.post("/restart", async (_, res) => { + await closePool(); + + await new Promise((r) => setTimeout(r, 2000)); + + const connect = await connectGPSql(); + apiReturn(res, { + success: connect.success, + level: connect.success ? "info" : "error", + module: "routes", + subModule: "prodSql", + message: "Sql Server has been restarted", + data: connect.data, + status: connect.success ? 200 : 400, + }); +}); +export default r; diff --git a/backend/gpSql/gpSqlStart.route.ts b/backend/gpSql/gpSqlStart.route.ts new file mode 100644 index 0000000..a479dbe --- /dev/null +++ b/backend/gpSql/gpSqlStart.route.ts @@ -0,0 +1,20 @@ +import { Router } from "express"; +import { apiReturn } from "../utils/returnHelper.utils.js"; +import { connectGPSql } from "./gpSqlConnection.controller.js"; + +const r = Router(); + +r.post("/start", async (_, res) => { + const connect = await connectGPSql(); + apiReturn(res, { + success: connect.success, + level: connect.success ? "info" : "error", + module: "routes", + subModule: "prodSql", + message: connect.message, + data: connect.data, + status: connect.success ? 200 : 400, + }); +}); + +export default r; diff --git a/backend/gpSql/gpSqlStop.route.ts b/backend/gpSql/gpSqlStop.route.ts new file mode 100644 index 0000000..5e3fc86 --- /dev/null +++ b/backend/gpSql/gpSqlStop.route.ts @@ -0,0 +1,20 @@ +import { Router } from "express"; +import { apiReturn } from "../utils/returnHelper.utils.js"; +import { closePool } from "./gpSqlConnection.controller.js"; + +const r = Router(); + +r.post("/stop", async (_, res) => { + const connect = await closePool(); + apiReturn(res, { + success: connect.success, + level: connect.success ? "info" : "error", + module: "routes", + subModule: "prodSql", + message: connect.message, + data: connect.data, + status: connect.success ? 200 : 400, + }); +}); + +export default r; diff --git a/backend/gpSql/queries/reqCheck.sql b/backend/gpSql/queries/reqCheck.sql new file mode 100644 index 0000000..2647eb6 --- /dev/null +++ b/backend/gpSql/queries/reqCheck.sql @@ -0,0 +1,39 @@ +USE [ALPLA] + +SELECT Distinct r.[POPRequisitionNumber] as req, +r.[ApprovalStatus] as approvalStatus, +r.[Requested By] requestedBy, +format(t.[Created Date], 'yyyy-MM-dd') as createdAt, +format(r.[Requisition Date], 'MM/dd/yyyy') as expectedDate, +r.[Requisition Amount] as glAccount, +case when r.[Account Segment 2] is null or r.[Account Segment 2] = '' then '999' else cast(r.[Account Segment 2] as varchar) end as plant +,t.Status as status +,t.[Document Status] as docStatus +,t.[Workflow Status] as reqState +,CASE + WHEN [Workflow Status] = 'Completed' + THEN 'Pending APO convertion' + WHEN [Workflow Status] = 'Pending User Action' + AND r.[ApprovalStatus] = 'Pending Approval' + THEN 'Pending plant approver' + WHEN [Workflow Status] = '' + AND r.[ApprovalStatus] = 'Not Submitted' + THEN 'Req not submited' + ELSE 'Unknown reason' +END AS approvedStatus + +FROM [dbo].[PORequisitions] r (nolock) + + + +left join +[dbo].[PurchaseRequisitions] as t (nolock) on +t.[Requisition Number] = r.[POPRequisitionNumber] + + +--where ApprovalStatus = 'Pending Approval' +--and [Account Segment 2] = 80 + +where r.POPRequisitionNumber in ([reqsToCheck]) + +Order By r.POPRequisitionNumber \ No newline at end of file diff --git a/backend/purchase/puchase.gpCheck.ts b/backend/purchase/puchase.gpCheck.ts new file mode 100644 index 0000000..e01559a --- /dev/null +++ b/backend/purchase/puchase.gpCheck.ts @@ -0,0 +1,117 @@ +import { gpQuery } from "../gpSql/gpSqlQuery.controller.js"; +import { + type SqlGPQuery, + sqlGpQuerySelector, +} from "../gpSql/gpSqlQuerySelector.utils.js"; +import { createLogger } from "../logger/logger.controller.js"; +import type { GpStatus } from "../types/purhcaseTypes.js"; +import { returnFunc } from "../utils/returnHelper.utils.js"; + +const log = createLogger({ module: "purchase", subModule: "gp" }); + +export const gpReqCheck = async (data: GpStatus[]) => { + const gpReqCheck = sqlGpQuerySelector("reqCheck") as SqlGPQuery; + const reqs = data.map((r) => r.req.trim()); + + if (!gpReqCheck.success) { + return returnFunc({ + success: false, + level: "error", + module: "purchase", + subModule: "query", + message: `Error getting alpla purchase info`, + data: [gpReqCheck.message], + notify: false, + }); + } + + try { + // check the initial req table + const result = await gpQuery( + gpReqCheck.query.replace( + "[reqsToCheck]", + data.map((r) => `'${r.req}'`).join(", ") ?? "", + ), + "Get req info", + ); + + log.debug( + {}, + `There are ${result.data.length} reqs that need to be updated with there current status`, + ); + + const firstFound = result.data.map((r) => ({ + req: r.req.trim(), + approvedStatus: r.approvedStatus, + })); + + const firstFoundSet = new Set(result.data.map((r) => r.req.trim())); + + const missing1Reqs = reqs.filter((req) => !firstFoundSet.has(req)); + + //check if we have a recall on our req + const reqCheck = await gpQuery( + `select + [Requisition Number] as req + ,case when [Workflow Status] = 'recall' then 'returned' else [Workflow Status] end as approvedStatus + --,* + from [dbo].[PurchaseRequisitions] where [Requisition Number] in (${missing1Reqs.map((r) => `'${r}'`).join(", ")})`, + "validate req is not in recall", + ); + + const secondFound = reqCheck.data.map((r) => ({ + req: r.req.trim(), + approvedStatus: r.approvedStatus, + })); + + const secondFoundSet = + new Set(reqCheck.data.map((r) => r.req.trim())) ?? []; + + const missing2Reqs = missing1Reqs.filter((req) => !secondFoundSet.has(req)); + + // check if we have a po already + const apoCheck = await gpQuery( + `select + SOPNUMBE + ,PONUMBER + ,reqStatus='converted' + ,* + from alpla.dbo.sop60100 (nolock) where sopnumbe in (${missing2Reqs.map((r) => `'${r}'`).join(", ")})`, + "Get release info", + ); + + const thirdRound = apoCheck.data.map((r) => ({ + req: r.req.trim(), + approvedStatus: r.approvedStatus, + })); + + const missing3Reqs = missing2Reqs.filter((req) => !secondFoundSet.has(req)); + + // remaining just got canceled or no longer exist + const remaining = missing3Reqs.map((m) => ({ + req: m, + approvedStatus: "canceled", + })); + + const allFound = [ + ...firstFound, + ...secondFound, + ...thirdRound, + ...remaining, + ]; + + const statusMap = new Map( + allFound.map((r: any) => [r.req, r.approvedStatus]), + ); + + const updateData = data.map((row) => ({ + id: row.id, + //req: row.req, + approvedStatus: statusMap.get(row.req.trim()) ?? null, + })); + + return updateData; + } catch (error) { + log.error({ stack: error }); + } +}; diff --git a/backend/purchase/purchase.controller.ts b/backend/purchase/purchase.controller.ts index 665383f..8018381 100644 --- a/backend/purchase/purchase.controller.ts +++ b/backend/purchase/purchase.controller.ts @@ -2,7 +2,7 @@ * This will monitor alpla purchase */ -import { eq } from "drizzle-orm"; +import { eq, sql } from "drizzle-orm"; import { db } from "../db/db.controller.js"; import { alplaPurchaseHistory, @@ -15,10 +15,12 @@ import { type SqlQuery, sqlQuerySelector, } from "../prodSql/prodSqlQuerySelector.utils.js"; +import type { GpStatus, StatusUpdate } from "../types/purhcaseTypes.js"; import { createCronJob } from "../utils/croner.utils.js"; import { delay } from "../utils/delay.utils.js"; import { returnFunc } from "../utils/returnHelper.utils.js"; import { tryCatch } from "../utils/trycatch.utils.js"; +import { gpReqCheck } from "./puchase.gpCheck.js"; const log = createLogger({ module: "purchase", subModule: "purchaseMonitor" }); @@ -84,14 +86,145 @@ export const monitorAlplaPurchase = async () => { await delay(500); } } catch (e) { - console.error( - { error: e }, - "Error occurred while running the monitor job", - ); + log.error({ error: e }, "Error occurred while running the monitor job"); log.error({ error: e }, "Error occurred while running the monitor job"); return; } + + // re-pull re-pull everything that has approvedStatus is pending + + const { data: allReq, error: errorReq } = await tryCatch( + db + .select() + .from(alplaPurchaseHistory) + .where(eq(alplaPurchaseHistory.approvedStatus, "new")), + ); + + // if theres no reqs just end meow + if (errorReq) { + log.error( + { stack: errorReq }, + "There was an error getting history data", + ); + return; + } + + log.debug({}, `There are ${allReq.length} pending reqs to be updated`); + + if (!allReq.length) { + log.debug({}, "There are not reqs to be processed"); + return; + } + /** + * approvedStatus + * remark = '' then pending req/manual po + * pending = pending + * approved = approved + * + */ + + // the flow for all the fun stuff + + const needsGpLookup: GpStatus[] = []; + const updates: StatusUpdate[] = []; + + for (const row of allReq ?? []) { + const remark = row.remark?.toLowerCase() ?? ""; + + if (remark === "") { + updates.push({ id: row.id, approvedStatus: "initial" }); + continue; + } + + if (remark.includes("rct")) { + updates.push({ id: row.id, approvedStatus: "received" }); + continue; + } + + if (remark.includes("apo")) { + updates.push({ id: row.id, approvedStatus: "approved" }); + continue; + } + + // not handled locally, defer to GP lookup + needsGpLookup.push({ id: row.id, req: row.remark?.trim() ?? "" }); + } + + const gpSmash = (await gpReqCheck(needsGpLookup)) as StatusUpdate[]; + + const merge = [...updates, ...gpSmash]; + + if (merge.length > 0) { + await db.execute(sql` + UPDATE ${alplaPurchaseHistory} + SET approved_status = CASE + ${sql.join( + merge.map( + (row) => + sql`WHEN ${alplaPurchaseHistory.id} = ${row.id} THEN ${row.approvedStatus}`, + ), + sql` `, + )} + ELSE approved_status + END, + updated_at = NOW() + WHERE ${alplaPurchaseHistory.id} IN ( + ${sql.join( + merge.map((row) => sql`${row.id}`), + sql`, `, + )} + ) + `); + log.info( + {}, + "All alpla purchase orders have been processed and updated", + ); + } + + // for reqs, create a string of reqs then run them through the gp req table to see there status. then update in lst ass see fit. + + // then double check if we have all reqs covered, for the reqs missing from above restring them and check the po table + + // these ones will be called to as converted to po + + // for the remaining reqs from above check the actual req table to see the status of it if the workflow is set at Recall this means a change was requested from purchasing team and needs to be re approved + + // for all remaining reqs we change them to replace/canceled }); } }; + +// const updates = (allReq ?? []) +// .map((row) => { +// const remark = row.remark?.toLowerCase() ?? ""; + +// let approvedStatus: string | null = null; + +// // priority order matters here +// if (remark === "") { +// approvedStatus = "initial"; +// } else if (remark.includes("rct")) { +// approvedStatus = "received"; +// } else if (remark.includes("apo")) { +// approvedStatus = "approved"; +// } + +// // add your next 4 checks here +// // else if (...) approvedStatus = "somethingElse"; + +// if (!approvedStatus) return null; + +// return { +// id: row.id, +// approvedStatus, +// }; +// }) +// .filter( +// ( +// row, +// ): row is { +// id: string; +// approvedStatus: string; +// } => row !== null, +// ); diff --git a/backend/routeHandler.routes.ts b/backend/routeHandler.routes.ts index ba8fae2..1e85ffd 100644 --- a/backend/routeHandler.routes.ts +++ b/backend/routeHandler.routes.ts @@ -4,6 +4,7 @@ import { setupAuthRoutes } from "./auth/auth.routes.js"; // import the routes and route setups import { setupApiDocsRoutes } from "./configs/scaler.config.js"; import { setupDatamartRoutes } from "./datamart/datamart.routes.js"; +import { setupGPSqlRoutes } from "./gpSql/gpSql.routes.js"; import { setupNotificationRoutes } from "./notification/notification.routes.js"; import { setupOCPRoutes } from "./ocp/ocp.routes.js"; import { setupOpendockRoutes } from "./opendock/opendock.routes.js"; @@ -16,6 +17,7 @@ export const setupRoutes = (baseUrl: string, app: Express) => { setupSystemRoutes(baseUrl, app); setupApiDocsRoutes(baseUrl, app); setupProdSqlRoutes(baseUrl, app); + setupGPSqlRoutes(baseUrl, app); setupDatamartRoutes(baseUrl, app); setupAuthRoutes(baseUrl, app); setupUtilsRoutes(baseUrl, app); diff --git a/backend/types/purhcaseTypes.ts b/backend/types/purhcaseTypes.ts new file mode 100644 index 0000000..805a0b5 --- /dev/null +++ b/backend/types/purhcaseTypes.ts @@ -0,0 +1,9 @@ +export type GpStatus = { + id: string; + req: string; +}; + +export type StatusUpdate = { + id: string; + approvedStatus: string; +}; diff --git a/backend/utils/returnHelper.utils.ts b/backend/utils/returnHelper.utils.ts index 57ced08..cf2eaae 100644 --- a/backend/utils/returnHelper.utils.ts +++ b/backend/utils/returnHelper.utils.ts @@ -31,7 +31,9 @@ interface Data { | "post" | "notification" | "delete" - | "printing"; + | "printing" + | "gpSql" + | "email"; level: "info" | "error" | "debug" | "fatal"; message: string; room?: string; @@ -63,13 +65,14 @@ export const returnFunc = (data: Data) => { log.info({ notify: notify, room }, data.message); break; case "error": - log.error({ notify: notify, error: data.data, room }, data.message); + log.error({ notify: notify, stack: data.data ?? [], room }, data.message); + break; case "debug": - log.debug({ notify: notify, room }, data.message); + log.debug({ notify: notify, stack: data.data ?? [], room }, data.message); break; case "fatal": - log.fatal({ notify: notify, room }, data.message); + log.fatal({ notify: notify, stack: data.data ?? [], room }, data.message); } // api section to return diff --git a/migrations/0025_talented_vector.sql b/migrations/0025_talented_vector.sql new file mode 100644 index 0000000..6be471a --- /dev/null +++ b/migrations/0025_talented_vector.sql @@ -0,0 +1 @@ +ALTER TABLE "alpla_purchase_history" ADD COLUMN "updated_at" timestamp DEFAULT now(); \ No newline at end of file diff --git a/migrations/0026_vengeful_wiccan.sql b/migrations/0026_vengeful_wiccan.sql new file mode 100644 index 0000000..d1791b9 --- /dev/null +++ b/migrations/0026_vengeful_wiccan.sql @@ -0,0 +1 @@ +ALTER TABLE "alpla_purchase_history" ALTER COLUMN "approved_status" SET DEFAULT 'new'; \ No newline at end of file diff --git a/migrations/meta/0025_snapshot.json b/migrations/meta/0025_snapshot.json new file mode 100644 index 0000000..fe978e1 --- /dev/null +++ b/migrations/meta/0025_snapshot.json @@ -0,0 +1,1474 @@ +{ + "id": "20a3ad7c-3b2c-4c28-aec0-6c72018ca542", + "prevId": "26034639-85f0-4038-bf23-2adaef00a364", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.alpla_purchase_history": { + "name": "alpla_purchase_history", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "apo": { + "name": "apo", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "confirmed": { + "name": "confirmed", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status_text": { + "name": "status_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "journal_num": { + "name": "journal_num", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "add_date": { + "name": "add_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "add_user": { + "name": "add_user", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "upd_user": { + "name": "upd_user", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "remark": { + "name": "remark", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "approved_status": { + "name": "approved_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'pending'" + }, + "position": { + "name": "position", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_audit_log": { + "name": "job_audit_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_name": { + "name": "job_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start_at": { + "name": "start_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "finished_at": { + "name": "finished_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_stack": { + "name": "error_stack", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "meta_data": { + "name": "meta_data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "idx_job_audit_logs_cleanup": { + "name": "idx_job_audit_logs_cleanup", + "columns": [ + { + "expression": "start_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.apikey": { + "name": "apikey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start": { + "name": "start", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refill_interval": { + "name": "refill_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "refill_amount": { + "name": "refill_amount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_enabled": { + "name": "rate_limit_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_time_window": { + "name": "rate_limit_time_window", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 86400000 + }, + "rate_limit_max": { + "name": "rate_limit_max", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 10 + }, + "request_count": { + "name": "request_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "remaining": { + "name": "remaining", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_request": { + "name": "last_request", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "apikey_key_idx": { + "name": "apikey_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "apikey_userId_idx": { + "name": "apikey_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "apikey_user_id_user_id_fk": { + "name": "apikey_user_id_user_id_fk", + "tableFrom": "apikey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_username": { + "name": "display_username", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_username_unique": { + "name": "user_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.datamart": { + "name": "datamart", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "query": { + "name": "query", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "public_access": { + "name": "public_access", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "add_date": { + "name": "add_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "add_user": { + "name": "add_user", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'lst-system'" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "upd_user": { + "name": "upd_user", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'lst-system'" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "datamart_name_unique": { + "name": "datamart_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.logs": { + "name": "logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "module": { + "name": "module", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subModule": { + "name": "subModule", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stack": { + "name": "stack", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "checked": { + "name": "checked", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "hostname": { + "name": "hostname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.notifications": { + "name": "notifications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "interval": { + "name": "interval", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'5'" + }, + "options": { + "name": "options", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + } + }, + "indexes": { + "notify_name": { + "name": "notify_name", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.notification_sub": { + "name": "notification_sub", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notification_id": { + "name": "notification_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "emails": { + "name": "emails", + "type": "text[]", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "notification_sub_user_id_user_id_fk": { + "name": "notification_sub_user_id_user_id_fk", + "tableFrom": "notification_sub", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_sub_notification_id_notifications_id_fk": { + "name": "notification_sub_notification_id_notifications_id_fk", + "tableFrom": "notification_sub", + "tableTo": "notifications", + "columnsFrom": [ + "notification_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "notification_sub_user_notification_unique": { + "name": "notification_sub_user_notification_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id", + "notification_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.opendock_apt": { + "name": "opendock_apt", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release": { + "name": "release", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "open_dock_apt_id": { + "name": "open_dock_apt_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appointment": { + "name": "appointment", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "opendock_apt_release_idx": { + "name": "opendock_apt_release_idx", + "columns": [ + { + "expression": "release", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "opendock_apt_opendock_id_idx": { + "name": "opendock_apt_opendock_id_idx", + "columns": [ + { + "expression": "open_dock_apt_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "opendock_apt_release_unique": { + "name": "opendock_apt_release_unique", + "nullsNotDistinct": false, + "columns": [ + "release" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.printer_log": { + "name": "printer_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "printer_log_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "settings_id": { + "name": "settings_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "moduleName": { + "name": "moduleName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "roles": { + "name": "roles", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[\"systemAdmin\"]'::jsonb" + }, + "settingType": { + "name": "settingType", + "type": "setting_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "seed_version": { + "name": "seed_version", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 1 + }, + "add_User": { + "name": "add_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "add_Date": { + "name": "add_Date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "upd_User": { + "name": "upd_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "name": { + "name": "name", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.stats": { + "name": "stats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'serverStats'" + }, + "build": { + "name": "build", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "last_update": { + "name": "last_update", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.setting_type": { + "name": "setting_type", + "schema": "public", + "values": [ + "feature", + "system", + "standard" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/migrations/meta/0026_snapshot.json b/migrations/meta/0026_snapshot.json new file mode 100644 index 0000000..e881be4 --- /dev/null +++ b/migrations/meta/0026_snapshot.json @@ -0,0 +1,1474 @@ +{ + "id": "cc72b3f1-a9be-4583-86e5-5cdee93fd825", + "prevId": "20a3ad7c-3b2c-4c28-aec0-6c72018ca542", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.alpla_purchase_history": { + "name": "alpla_purchase_history", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "apo": { + "name": "apo", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "revision": { + "name": "revision", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "confirmed": { + "name": "confirmed", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status_text": { + "name": "status_text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "journal_num": { + "name": "journal_num", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "add_date": { + "name": "add_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "add_user": { + "name": "add_user", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "upd_user": { + "name": "upd_user", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "remark": { + "name": "remark", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "approved_status": { + "name": "approved_status", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'new'" + }, + "position": { + "name": "position", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.job_audit_log": { + "name": "job_audit_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "job_name": { + "name": "job_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start_at": { + "name": "start_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "finished_at": { + "name": "finished_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "duration_ms": { + "name": "duration_ms", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_message": { + "name": "error_message", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error_stack": { + "name": "error_stack", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "meta_data": { + "name": "meta_data", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "idx_job_audit_logs_cleanup": { + "name": "idx_job_audit_logs_cleanup", + "columns": [ + { + "expression": "start_at", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.account": { + "name": "account", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "account_id": { + "name": "account_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "provider_id": { + "name": "provider_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "access_token_expires_at": { + "name": "access_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "refresh_token_expires_at": { + "name": "refresh_token_expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "password": { + "name": "password", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + } + }, + "indexes": { + "account_userId_idx": { + "name": "account_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "account_user_id_user_id_fk": { + "name": "account_user_id_user_id_fk", + "tableFrom": "account", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.apikey": { + "name": "apikey", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "start": { + "name": "start", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "prefix": { + "name": "prefix", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key": { + "name": "key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refill_interval": { + "name": "refill_interval", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "refill_amount": { + "name": "refill_amount", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_refill_at": { + "name": "last_refill_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_enabled": { + "name": "rate_limit_enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "rate_limit_time_window": { + "name": "rate_limit_time_window", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 86400000 + }, + "rate_limit_max": { + "name": "rate_limit_max", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 10 + }, + "request_count": { + "name": "request_count", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 0 + }, + "remaining": { + "name": "remaining", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "last_request": { + "name": "last_request", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "permissions": { + "name": "permissions", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "apikey_key_idx": { + "name": "apikey_key_idx", + "columns": [ + { + "expression": "key", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "apikey_userId_idx": { + "name": "apikey_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "apikey_user_id_user_id_fk": { + "name": "apikey_user_id_user_id_fk", + "tableFrom": "apikey", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.jwks": { + "name": "jwks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "public_key": { + "name": "public_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "private_key": { + "name": "private_key", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session": { + "name": "session", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "ip_address": { + "name": "ip_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_agent": { + "name": "user_agent", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "impersonated_by": { + "name": "impersonated_by", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "session_userId_idx": { + "name": "session_userId_idx", + "columns": [ + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "session_user_id_user_id_fk": { + "name": "session_user_id_user_id_fk", + "tableFrom": "session", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_token_unique": { + "name": "session_token_unique", + "nullsNotDistinct": false, + "columns": [ + "token" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user": { + "name": "user", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "email_verified": { + "name": "email_verified", + "type": "boolean", + "primaryKey": false, + "notNull": true, + "default": false + }, + "image": { + "name": "image", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "banned": { + "name": "banned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "ban_reason": { + "name": "ban_reason", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "ban_expires": { + "name": "ban_expires", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "display_username": { + "name": "display_username", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "user_email_unique": { + "name": "user_email_unique", + "nullsNotDistinct": false, + "columns": [ + "email" + ] + }, + "user_username_unique": { + "name": "user_username_unique", + "nullsNotDistinct": false, + "columns": [ + "username" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.verification": { + "name": "verification", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "expires_at": { + "name": "expires_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "verification_identifier_idx": { + "name": "verification_identifier_idx", + "columns": [ + { + "expression": "identifier", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.datamart": { + "name": "datamart", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "query": { + "name": "query", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "version": { + "name": "version", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "options": { + "name": "options", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "''" + }, + "public_access": { + "name": "public_access", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "add_date": { + "name": "add_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "add_user": { + "name": "add_user", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'lst-system'" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "upd_user": { + "name": "upd_user", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'lst-system'" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "datamart_name_unique": { + "name": "datamart_name_unique", + "nullsNotDistinct": false, + "columns": [ + "name" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.logs": { + "name": "logs", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "level": { + "name": "level", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "module": { + "name": "module", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "subModule": { + "name": "subModule", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "message": { + "name": "message", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "stack": { + "name": "stack", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "checked": { + "name": "checked", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "hostname": { + "name": "hostname", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.notifications": { + "name": "notifications", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "interval": { + "name": "interval", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'5'" + }, + "options": { + "name": "options", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + } + }, + "indexes": { + "notify_name": { + "name": "notify_name", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.notification_sub": { + "name": "notification_sub", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "notification_id": { + "name": "notification_id", + "type": "uuid", + "primaryKey": false, + "notNull": true + }, + "emails": { + "name": "emails", + "type": "text[]", + "primaryKey": false, + "notNull": false, + "default": "'{}'" + } + }, + "indexes": {}, + "foreignKeys": { + "notification_sub_user_id_user_id_fk": { + "name": "notification_sub_user_id_user_id_fk", + "tableFrom": "notification_sub", + "tableTo": "user", + "columnsFrom": [ + "user_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "notification_sub_notification_id_notifications_id_fk": { + "name": "notification_sub_notification_id_notifications_id_fk", + "tableFrom": "notification_sub", + "tableTo": "notifications", + "columnsFrom": [ + "notification_id" + ], + "columnsTo": [ + "id" + ], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "notification_sub_user_notification_unique": { + "name": "notification_sub_user_notification_unique", + "nullsNotDistinct": false, + "columns": [ + "user_id", + "notification_id" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.opendock_apt": { + "name": "opendock_apt", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "release": { + "name": "release", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "open_dock_apt_id": { + "name": "open_dock_apt_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "appointment": { + "name": "appointment", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[]'::jsonb" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "opendock_apt_release_idx": { + "name": "opendock_apt_release_idx", + "columns": [ + { + "expression": "release", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "opendock_apt_opendock_id_idx": { + "name": "opendock_apt_opendock_id_idx", + "columns": [ + { + "expression": "open_dock_apt_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "opendock_apt_release_unique": { + "name": "opendock_apt_release_unique", + "nullsNotDistinct": false, + "columns": [ + "release" + ] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.printer_log": { + "name": "printer_log", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "printer_log_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.settings": { + "name": "settings", + "schema": "", + "columns": { + "settings_id": { + "name": "settings_id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "value": { + "name": "value", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "moduleName": { + "name": "moduleName", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "active": { + "name": "active", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "roles": { + "name": "roles", + "type": "jsonb", + "primaryKey": false, + "notNull": true, + "default": "'[\"systemAdmin\"]'::jsonb" + }, + "settingType": { + "name": "settingType", + "type": "setting_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "seed_version": { + "name": "seed_version", + "type": "integer", + "primaryKey": false, + "notNull": false, + "default": 1 + }, + "add_User": { + "name": "add_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "add_Date": { + "name": "add_Date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "upd_User": { + "name": "upd_User", + "type": "text", + "primaryKey": false, + "notNull": true, + "default": "'LST_System'" + }, + "upd_date": { + "name": "upd_date", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": { + "name": { + "name": "name", + "columns": [ + { + "expression": "name", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.stats": { + "name": "stats", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true, + "default": "'serverStats'" + }, + "build": { + "name": "build", + "type": "integer", + "primaryKey": false, + "notNull": true, + "default": 1 + }, + "last_update": { + "name": "last_update", + "type": "timestamp", + "primaryKey": false, + "notNull": false, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "enums": { + "public.setting_type": { + "name": "setting_type", + "schema": "public", + "values": [ + "feature", + "system", + "standard" + ] + } + }, + "schemas": {}, + "sequences": {}, + "roles": {}, + "policies": {}, + "views": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/migrations/meta/_journal.json b/migrations/meta/_journal.json index b5b8554..a3dc856 100644 --- a/migrations/meta/_journal.json +++ b/migrations/meta/_journal.json @@ -176,6 +176,20 @@ "when": 1775661516749, "tag": "0024_absent_barracuda", "breakpoints": true + }, + { + "idx": 25, + "version": "7", + "when": 1775755338816, + "tag": "0025_talented_vector", + "breakpoints": true + }, + { + "idx": 26, + "version": "7", + "when": 1775786221817, + "tag": "0026_vengeful_wiccan", + "breakpoints": true } ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 22c3d5f..117a53b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "drizzle-zod": "^0.8.3", "express": "^5.2.1", "husky": "^9.1.7", + "ldapts": "^8.1.7", "morgan": "^1.10.1", "mssql": "^12.2.1", "multer": "^2.1.1", @@ -8063,6 +8064,18 @@ "node": ">=20.0.0" } }, + "node_modules/ldapts": { + "version": "8.1.7", + "resolved": "https://registry.npmjs.org/ldapts/-/ldapts-8.1.7.tgz", + "integrity": "sha512-TJl6T92eIwMf/OJ0hDfKVa6ISwzo+lqCWCI5Mf//ARlKa3LKQZaSrme/H2rCRBhW0DZCQlrsV+fgoW5YHRNLUw==", + "license": "MIT", + "dependencies": { + "strict-event-emitter-types": "2.0.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -10422,6 +10435,12 @@ "node": ">=10.0.0" } }, + "node_modules/strict-event-emitter-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz", + "integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA==", + "license": "ISC" + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", diff --git a/package.json b/package.json index 3d6958a..aeb8cb7 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,12 @@ "dev:frontend": "cd frontend && npm run dev", "dev:db:migrate": "npx drizzle-kit push", "dev:db:generate": "tsc && npx drizzle-kit generate --config=drizzle.config.ts", - "build": "rimraf dist && npm run dev:db:generate && npm run dev:db:migrate && npm run build:app && npm run build:copySql && cd frontend && npm run build", + "build": "rimraf dist && npm run dev:db:generate && npm run dev:db:migrate && npm run build:app && npm run build:copySql && npm run build:copyGpSql && npm run build:emailTemplate && cd frontend && npm run build", "build:app": "tsc", "agent": "powershell -ExecutionPolicy Bypass -File scripts/agentController.ps1", - "build:docker": "rimraf dist && npm run build:app && npm run build:copySql", + "build:docker": "rimraf dist && npm run build:app && npm run build:copySql && npm run build:copyGpSql && npm run build:emailTemplate", + "build:emailTemplate": "cpy \"backend/utils/mailViews/**/*\" dist/utils/mailViews --parents", + "build:copyGpSql": "cpy \"backend/gpSql/queries/**/*\" dist/gpSql/queries --parents", "build:copySql": "cpy \"backend/prodSql/queries/**/*\" dist/prodSql/queries --parents", "lint": "tsc && biome lint", "start": "npm run start:server", @@ -75,6 +77,7 @@ "drizzle-zod": "^0.8.3", "express": "^5.2.1", "husky": "^9.1.7", + "ldapts": "^8.1.7", "morgan": "^1.10.1", "mssql": "^12.2.1", "multer": "^2.1.1",