test(fifo index): running fifo index data on 2 servers as a trial to validate data
This commit is contained in:
11
database/migrations/0061_mature_the_stranger.sql
Normal file
11
database/migrations/0061_mature_the_stranger.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE "fifoIndex" (
|
||||||
|
"fifoIndex_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"lot" text NOT NULL,
|
||||||
|
"av" numeric NOT NULL,
|
||||||
|
"runningNr" numeric NOT NULL,
|
||||||
|
"prodDate" timestamp NOT NULL,
|
||||||
|
"fifoFollowed" boolean NOT NULL,
|
||||||
|
"add_Date" timestamp DEFAULT now()
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "fifo_runningNr" ON "fifoIndex" USING btree ("runningNr");
|
||||||
1925
database/migrations/meta/0061_snapshot.json
Normal file
1925
database/migrations/meta/0061_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -428,6 +428,13 @@
|
|||||||
"when": 1747357513268,
|
"when": 1747357513268,
|
||||||
"tag": "0060_daffy_overlord",
|
"tag": "0060_daffy_overlord",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 61,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1748370693078,
|
||||||
|
"tag": "0061_mature_the_stranger",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
40
database/schema/fifoIndex.ts
Normal file
40
database/schema/fifoIndex.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import {
|
||||||
|
text,
|
||||||
|
pgTable,
|
||||||
|
numeric,
|
||||||
|
index,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
jsonb,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const fifoIndex = pgTable(
|
||||||
|
"fifoIndex",
|
||||||
|
{
|
||||||
|
fifoIndex_id: uuid("fifoIndex_id").defaultRandom().primaryKey(),
|
||||||
|
lot: text("lot").notNull(),
|
||||||
|
av: numeric("av").notNull(),
|
||||||
|
runningNr: numeric("runningNr").notNull(),
|
||||||
|
prodDate: timestamp("prodDate").notNull(),
|
||||||
|
|
||||||
|
// currentInv: jsonb("currentInv").default([]),
|
||||||
|
fifoFollowed: boolean("fifoFollowed").notNull(),
|
||||||
|
add_Date: timestamp("add_Date").defaultNow(),
|
||||||
|
},
|
||||||
|
(table) => [
|
||||||
|
// uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
// uniqueIndex("role_name").on(table.name),
|
||||||
|
uniqueIndex("fifo_runningNr").on(table.runningNr),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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(fifoIndex);
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
import { isBefore } from "date-fns";
|
||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
|
import { currentInv } from "../../../sqlServer/querys/notifications/fifoIndex/currentInv.js";
|
||||||
|
import { shippedPallets } from "../../../sqlServer/querys/notifications/fifoIndex/shippedPallets.js";
|
||||||
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
|
import { fifoIndex } from "../../../../../database/schema/fifoIndex.js";
|
||||||
|
|
||||||
|
export default async function fifoIndexCheck() {
|
||||||
|
/**
|
||||||
|
* getting the shipped pallets
|
||||||
|
*/
|
||||||
|
const { data: shipped, error: eShipped } = await tryCatch(
|
||||||
|
query(shippedPallets, "notify shipped pallets")
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data: currentStuff, error: eCurrentInv } = await tryCatch(
|
||||||
|
query(currentInv, "notify shipped pallets")
|
||||||
|
);
|
||||||
|
|
||||||
|
// console.log(shipped?.data[2]);
|
||||||
|
// console.log(currentStuff?.data[2]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We want to check if the each shippened pallet is out of fifo
|
||||||
|
*/
|
||||||
|
const check = shipped?.data.map((n: any) => {
|
||||||
|
/**
|
||||||
|
* Returns all data so we know if we are in or out.
|
||||||
|
*/
|
||||||
|
//check if there are pallets older than the current one we are mapped on.
|
||||||
|
const fifoCheck = currentStuff?.data.filter(
|
||||||
|
(i: any) => isBefore(i.prodDate, n.prodDate) && i.av === n.av
|
||||||
|
);
|
||||||
|
//console.log(fifoCheck.length);
|
||||||
|
if (fifoCheck.length > 0) {
|
||||||
|
// console.log("Out of fifo", {
|
||||||
|
// av: n.av,
|
||||||
|
// rn: n.runningNr,
|
||||||
|
// fRn: fifoCheck[0].runningNr,
|
||||||
|
// dates: [fifoCheck[0].prodDate, n.prodDate],
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...n,
|
||||||
|
// currentInv: fifoCheck[0],
|
||||||
|
fifoFollowed: fifoCheck.length === 0 ? true : false,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lets see just the av that is our or in
|
||||||
|
*/
|
||||||
|
|
||||||
|
const avCheck = (check: any) => {
|
||||||
|
/**
|
||||||
|
* This will only return the data based on out of fifo.
|
||||||
|
*/
|
||||||
|
// check how many times each av showed up
|
||||||
|
const avCounts = check.reduce((a: any, c: any) => {
|
||||||
|
if (c.fifoFollowed === false) {
|
||||||
|
const avValue = c.av;
|
||||||
|
a[avValue] = (a[avValue] || 0) + 1;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// transform them back to an avCount Object
|
||||||
|
const result = Object.keys(avCounts).map((av) => ({
|
||||||
|
av: parseInt(av, 10),
|
||||||
|
count: avCounts[av],
|
||||||
|
}));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const outOfFifo: any = avCheck(check);
|
||||||
|
const totalOut = outOfFifo.reduce((sum: any, c: any) => {
|
||||||
|
return sum + c.count;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add the data to the db
|
||||||
|
*/
|
||||||
|
for (let i = 0; i < check.length; i++) {
|
||||||
|
const { data: dbInsert, error: dbE } = await tryCatch(
|
||||||
|
db
|
||||||
|
.insert(fifoIndex)
|
||||||
|
.values({
|
||||||
|
lot: check[i].lot,
|
||||||
|
av: check[i].av,
|
||||||
|
runningNr: check[i].runningNr,
|
||||||
|
prodDate: check[i].prodDate,
|
||||||
|
fifoFollowed: check[i].fifoFollowed,
|
||||||
|
add_Date: check[i].add_Date,
|
||||||
|
})
|
||||||
|
.onConflictDoNothing()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Fifo index data",
|
||||||
|
data: {
|
||||||
|
palletsOut: check,
|
||||||
|
totalShipped: shipped?.data.length,
|
||||||
|
inFifo: shipped?.data.length - totalOut,
|
||||||
|
outOfFifoData: outOfFifo,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -12,10 +12,18 @@ import notifyStats from "./routes/getActiveNotifications.js";
|
|||||||
import tiTrigger from "./routes/manualTiggerTi.js";
|
import tiTrigger from "./routes/manualTiggerTi.js";
|
||||||
import blocking from "./routes/qualityBlocking.js";
|
import blocking from "./routes/qualityBlocking.js";
|
||||||
import notify from "./routes/getNotifications.js";
|
import notify from "./routes/getNotifications.js";
|
||||||
|
import fifoIndex from "./routes/fifoIndex.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const routes = [sendemail, notifyStats, tiTrigger, blocking, notify] as const;
|
const routes = [
|
||||||
|
sendemail,
|
||||||
|
notifyStats,
|
||||||
|
tiTrigger,
|
||||||
|
blocking,
|
||||||
|
notify,
|
||||||
|
fifoIndex,
|
||||||
|
] as const;
|
||||||
|
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
app.route("/notify", route);
|
app.route("/notify", route);
|
||||||
|
|||||||
41
server/services/notifications/routes/fifoIndex.ts
Normal file
41
server/services/notifications/routes/fifoIndex.ts
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
// an external way to creating logs
|
||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
|
import fifoIndexCheck from "../controller/notifications/fifoIndex.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["notify"],
|
||||||
|
summary: "Manually trigger TI intergrations.",
|
||||||
|
method: "get",
|
||||||
|
path: "/fifoindex",
|
||||||
|
//middleware: authMiddleware,
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
/**
|
||||||
|
* get the blocking notification stuff
|
||||||
|
*/
|
||||||
|
apiHit(c, { endpoint: "/fifoindex" });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getting the shipped pallets
|
||||||
|
*/
|
||||||
|
const checkedData = await fifoIndexCheck();
|
||||||
|
|
||||||
|
return c.json({
|
||||||
|
success: true,
|
||||||
|
message: "Fifo index results",
|
||||||
|
data: checkedData.data.palletsOut,
|
||||||
|
fifoCheck: {
|
||||||
|
totalShipped: checkedData.data.totalShipped,
|
||||||
|
inFifo: checkedData.data.inFifo,
|
||||||
|
outOfFifoData: checkedData.data.outOfFifoData,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -93,6 +93,20 @@ export const note: any = [
|
|||||||
releases: [1, 2, 3],
|
releases: [1, 2, 3],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "fifoIndex",
|
||||||
|
description: "Checks for pallets that were shipped out of fifo",
|
||||||
|
checkInterval: 1,
|
||||||
|
timeType: "hour",
|
||||||
|
emails: "blake.matthes@alpla.com",
|
||||||
|
active: false,
|
||||||
|
notifiySettings: {
|
||||||
|
prodID: 1,
|
||||||
|
start: 36,
|
||||||
|
end: 36,
|
||||||
|
releases: [1, 2, 3],
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const notificationCreate = async () => {
|
export const notificationCreate = async () => {
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
export const currentInv = `
|
||||||
|
SELECT Produktionslos as lot
|
||||||
|
,Lfdnr as runningNr
|
||||||
|
,IdArtikelVarianten as av
|
||||||
|
,Barcode
|
||||||
|
,ProduktionsDatumMin as prodDate
|
||||||
|
FROM [AlplaPROD_test1].[dbo].V_LagerPositionenBarcodes t
|
||||||
|
where GesperrtAktivSum = 0 and t.IdArtikelTyp in (1)
|
||||||
|
order by ProduktionsDatumMin
|
||||||
|
`;
|
||||||
@@ -7,7 +7,7 @@ SELECT
|
|||||||
,[LfdNrJeArtikelKunde] as runningNr
|
,[LfdNrJeArtikelKunde] as runningNr
|
||||||
,l.IdArtikelvarianten as av
|
,l.IdArtikelvarianten as av
|
||||||
,x.[Barcode]
|
,x.[Barcode]
|
||||||
,[ProduktionsDatum]
|
,[ProduktionsDatum] as prodDate
|
||||||
--,x.[Add_User]
|
--,x.[Add_User]
|
||||||
--,x.[Add_Date]
|
--,x.[Add_Date]
|
||||||
--,x.[Upd_User]
|
--,x.[Upd_User]
|
||||||
@@ -27,6 +27,6 @@ SELECT
|
|||||||
[AlplaPROD_test1].[dbo].[T_EtikettenGedruckt] l on
|
[AlplaPROD_test1].[dbo].[T_EtikettenGedruckt] l on
|
||||||
x.LfdNrJeArtikelKunde = l.LfdNr
|
x.LfdNrJeArtikelKunde = l.LfdNr
|
||||||
|
|
||||||
where x.Add_Date between getDate()-2 and getDate()
|
where x.Add_Date between dateadd(hour, -1, getDate()) and getDate()
|
||||||
|
order by [ProduktionsDatum]
|
||||||
`;
|
`;
|
||||||
Reference in New Issue
Block a user