Compare commits

..

69 Commits

Author SHA1 Message Date
90e9bb0ff6 refactor(rfid): refactored the way the wrapper works to indlude backup dyco plan 2025-03-26 22:10:39 -05:00
bd11feb136 refactor(rfid): refactored station 3 (lines) and complete logic 2025-03-26 22:10:05 -05:00
96e7f742fe refactor(ocme): removed some info logs as ocme calls alot 2025-03-26 22:09:23 -05:00
eb051d51f2 feat(notify): intial nofity system added to monitor crashes and rfid wrapper 2025-03-26 22:08:53 -05:00
7a1a4773e7 feat(ocp): create and book in plus dyco controller implemented 2025-03-26 22:07:19 -05:00
878e650e62 chore(release): bump build number to 92 2025-03-26 22:05:21 -05:00
a31e7ea163 chore(release): bump build number to 91 2025-03-26 16:17:53 -05:00
04aa943920 chore(release): bump build number to 90 2025-03-26 16:00:56 -05:00
af076b8e27 chore(release): bump build number to 89 2025-03-26 15:39:57 -05:00
c0a0589b3c chore(release): bump build number to 88 2025-03-26 15:19:55 -05:00
509ef84726 chore(release): bump build number to 87 2025-03-26 15:18:53 -05:00
5ab813f378 chore(release): bump build number to 86 2025-03-26 12:44:17 -05:00
5d61eb879e chore(release): bump build number to 85 2025-03-26 12:42:58 -05:00
2d4b1db5f4 fix(logistics): correction to the lane grab 2025-03-26 09:16:16 -05:00
58f7b4322d feat(logistics): added in return material by lane name and gets lane id 2025-03-26 08:36:47 -05:00
3b5e82fdc1 feat(ocp): added wrappercard into the mix 2025-03-25 18:57:00 -05:00
f9cd3fb881 feat(ocp): prodlink check added 2025-03-25 18:56:36 -05:00
51267f5202 fix(ocme): fixed the camera routes 2025-03-25 18:55:57 -05:00
ceaa25f31e feat(ocp): added labeling logs in 2025-03-25 18:55:23 -05:00
416254353c chore(release): bump build number to 84 2025-03-25 18:21:47 -05:00
7f946c095b chore(release): bump build number to 83 2025-03-25 18:03:32 -05:00
c2aa69ab0a chore(release): bump build number to 82 2025-03-25 18:02:14 -05:00
250988800e chore(release): bump build number to 81 2025-03-25 17:57:13 -05:00
cacfd6d2e0 chore(release): bump build number to 80 2025-03-25 17:49:07 -05:00
8d2721b0c2 chore(release): bump build number to 79 2025-03-25 17:44:41 -05:00
36cdc7b4bf chore(release): bump build number to 78 2025-03-25 17:39:26 -05:00
4d4d6fc7a4 chore(release): bump build number to 77 2025-03-25 15:48:28 -05:00
030f9f9aac refactor(ocp): moved printers to there own folder to keep everything clean 2025-03-25 13:39:39 -05:00
9e9a56cbb1 feat(ocp): add lots with scroll view was added 2025-03-25 13:39:18 -05:00
b01980e1c5 fix(ocme): fixed some import errors 2025-03-25 12:48:18 -05:00
fe0c500dcf feat(server): clearn up code 2025-03-25 12:47:52 -05:00
8a040d15db fix(servers): fixed the weird conflict import that happened 2025-03-25 12:47:36 -05:00
f90066c090 feat(ocp): added in printers get and add 2025-03-25 12:47:15 -05:00
04eb2e3e14 refactor(tcpserver): just the tcp server doing something 2025-03-25 07:58:37 -05:00
90fb0d364d Merge branch 'main' of https://git.tuffraid.net/cowch/lstV2 2025-03-25 07:57:55 -05:00
e6e1cecce3 refactor(ocme): corrections to endpoints to work with ocnme as intneeded 2025-03-25 07:54:58 -05:00
73aa95a693 refactor(ocme): cleaup on pickedup 2025-03-25 07:54:22 -05:00
b9f19095cb refactor(ocme): clean up on the getInfo endpoint 2025-03-25 07:54:00 -05:00
dcb56d4274 fix(ocme): corrections to posting data for the response was added 2025-03-25 07:53:30 -05:00
bc1821132e feat(ocme): manual camera trigger for the wrapper added 2025-03-25 07:52:40 -05:00
2551d6c907 refactor(updateserver): removed ocme from starting back up as it was migrated 2025-03-25 07:41:10 -05:00
adf0880659 refactor(server): changed to log only when in dev, and removed the redirect of the url 2025-03-25 07:40:15 -05:00
5149de3199 ci(lst): changes made to the settings file to work across all pvs 2025-03-25 07:39:32 -05:00
c71b514d9a refactor(frontend): prettier change to formatting 2025-03-25 07:27:45 -05:00
9254e52808 chore(release): bump build number to 76 2025-03-25 06:17:31 -05:00
b8c028a6c1 chore(release): bump build number to 75 2025-03-24 20:20:55 -05:00
529e922485 chore(release): bump build number to 74 2025-03-24 20:13:07 -05:00
5201012235 chore(release): bump build number to 73 2025-03-24 20:08:59 -05:00
abe53b8f5d chore(release): bump build number to 72 2025-03-24 20:06:15 -05:00
836f3e294b chore(release): bump build number to 71 2025-03-24 19:56:03 -05:00
96abef762b chore(release): bump build number to 70 2025-03-24 19:40:39 -05:00
2c227f9428 chore(release): bump build number to 69 2025-03-24 18:33:12 -05:00
46647687dc chore(release): bump build number to 68 2025-03-24 18:23:24 -05:00
cb01ef1af1 chore(release): bump build number to 67 2025-03-24 17:16:23 -05:00
b3b5fcec65 chore(release): bump build number to 66 2025-03-24 17:14:25 -05:00
3a4dc47a36 chore(release): bump build number to 65 2025-03-24 17:06:23 -05:00
63177b523e chore(release): bump build number to 64 2025-03-24 17:00:20 -05:00
e1cad027d2 chore(release): bump build number to 63 2025-03-24 16:42:53 -05:00
c1cc355f4f chore(release): bump build number to 62 2025-03-24 16:40:50 -05:00
5ed67f3fc0 chore(release): bump build number to 61 2025-03-24 16:28:32 -05:00
57e82d2360 chore(release): bump build number to 60 2025-03-24 16:26:04 -05:00
9395ec6cd4 chore(release): bump build number to 59 2025-03-24 15:50:29 -05:00
0475bb30f9 chore(release): bump build number to 58 2025-03-24 15:49:37 -05:00
6843368c36 chore(release): bump build number to 57 2025-03-24 15:47:16 -05:00
335ea2deca chore(release): bump build number to 56 2025-03-24 15:39:33 -05:00
96814c1115 Merge branch 'main' of https://git.tuffraid.net/cowch/lstV2 2025-03-24 15:31:35 -05:00
6dd9ed848b test(ocme): lots of changes to get it working in production 2025-03-24 15:31:31 -05:00
0c5fc1dfb0 chore(release): bump build number to 55 2025-03-24 15:28:10 -05:00
5886bea85d chore(release): bump build number to 52 2025-03-24 11:43:52 -05:00
94 changed files with 11583 additions and 1101 deletions

50
.vscode/settings.json vendored
View File

@@ -1,26 +1,28 @@
{
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"[javascript]": {
"editor.formatOnSave": true
},
"[javascriptreact]": {
"editor.formatOnSave": true
},
"[typescript]": {
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.formatOnSave": true
},
"[json]": {
"editor.formatOnSave": true
},
"[graphql]": {
"editor.formatOnSave": true
},
"[handlebars]": {
"editor.formatOnSave": true
}
"editor.defaultFormatter": "esbenp.prettier-vscode",
"workbench.colorTheme": "Default Dark+",
"prettier.tabWidth": 4,
"terminal.integrated.env.windows": {},
"editor.formatOnSave": true,
"[javascript]": {
"editor.formatOnSave": true
},
"[javascriptreact]": {
"editor.formatOnSave": true
},
"[typescript]": {
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.formatOnSave": true
},
"[json]": {
"editor.formatOnSave": true
},
"[graphql]": {
"editor.formatOnSave": true
},
"[handlebars]": {
"editor.formatOnSave": true
}
}

View File

@@ -0,0 +1,17 @@
CREATE TABLE "printers" (
"printer_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"humanReadableId" text,
"name" text NOT NULL,
"ipAddress" text,
"port" numeric NOT NULL,
"status" text,
"statusText" text NOT NULL,
"lastTimePrinted" text,
"assigned" boolean DEFAULT false NOT NULL,
"remark" text,
"monitorState" boolean DEFAULT false NOT NULL,
"add_Date" timestamp DEFAULT now(),
"upd_date" timestamp DEFAULT now()
);
--> statement-breakpoint
CREATE UNIQUE INDEX "humanReadableId" ON "printers" USING btree ("name");

View File

@@ -0,0 +1,3 @@
ALTER TABLE "printers" ALTER COLUMN "statusText" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "printers" ALTER COLUMN "assigned" DROP NOT NULL;--> statement-breakpoint
ALTER TABLE "printers" ALTER COLUMN "monitorState" DROP NOT NULL;

View File

@@ -0,0 +1 @@
ALTER TABLE "printers" ALTER COLUMN "port" DROP NOT NULL;

View File

@@ -0,0 +1,2 @@
DROP INDEX "humanReadableId";--> statement-breakpoint
CREATE UNIQUE INDEX "humanReadableId" ON "printers" USING btree ("humanReadableId");

View File

@@ -0,0 +1,4 @@
CREATE TABLE "prodlabels" (
"label_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"runningNr" integer NOT NULL
);

View File

@@ -0,0 +1,7 @@
ALTER TABLE "prodlabels" ADD COLUMN "printerID" integer;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "printerName" text;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "line" integer;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "status" text;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "add_date" timestamp;--> statement-breakpoint
ALTER TABLE "prodlabels" ADD COLUMN "upd_date" timestamp;--> statement-breakpoint
CREATE UNIQUE INDEX "runningNr" ON "prodlabels" USING btree ("runningNr");

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -183,6 +183,48 @@
"when": 1742655504936,
"tag": "0025_amusing_sugar_man",
"breakpoints": true
},
{
"idx": 26,
"version": "7",
"when": 1742914066219,
"tag": "0026_daily_the_twelve",
"breakpoints": true
},
{
"idx": 27,
"version": "7",
"when": 1742917145140,
"tag": "0027_needy_sleepwalker",
"breakpoints": true
},
{
"idx": 28,
"version": "7",
"when": 1742917676211,
"tag": "0028_fast_wong",
"breakpoints": true
},
{
"idx": 29,
"version": "7",
"when": 1742917978318,
"tag": "0029_giant_blue_blade",
"breakpoints": true
},
{
"idx": 30,
"version": "7",
"when": 1742938986653,
"tag": "0030_conscious_cable",
"breakpoints": true
},
{
"idx": 31,
"version": "7",
"when": 1742939306614,
"tag": "0031_loud_alex_power",
"breakpoints": true
}
]
}

View File

@@ -0,0 +1,42 @@
import {
text,
pgTable,
numeric,
index,
timestamp,
boolean,
uuid,
uniqueIndex,
} from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import { z } from "zod";
export const printers = pgTable(
"printers",
{
printer_id: uuid("printer_id").defaultRandom().primaryKey(),
humanReadableId: text("humanReadableId"),
name: text("name").notNull(),
ipAddress: text("ipAddress"),
port: numeric("port"),
status: text("status"),
statusText: text("statusText"),
lastTimePrinted: text("lastTimePrinted"),
assigned: boolean("assigned").default(false),
remark: text("remark"),
monitorState: boolean("monitorState").default(false),
add_Date: timestamp("add_Date").defaultNow(),
upd_date: timestamp("upd_date").defaultNow(),
},
(table) => [
//uniqueIndex("emailUniqueIndex").on(sql`lower(${table.email})`),
uniqueIndex("humanReadableId").on(table.humanReadableId),
]
);
// 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(printers);

View File

@@ -0,0 +1,30 @@
import {
integer,
pgTable,
uuid,
uniqueIndex,
text,
timestamp,
} from "drizzle-orm/pg-core";
import { createSelectSchema } from "drizzle-zod";
export const prodlabels = pgTable(
"prodlabels",
{
label_id: uuid("label_id").defaultRandom().primaryKey(),
printerID: integer("printerID"),
printerName: text("printerName"),
line: integer("line"),
runningNr: integer("runningNr").notNull(),
status: text("status"),
add_user: text("add_user").default("lst"),
add_date: timestamp("add_date").defaultNow(),
upd_date: timestamp("upd_date").defaultNow(),
},
(table) => [
//uniqueIndex("emailUniqueIndex").on(sql`lower(${table.email})`),
uniqueIndex("runningNr").on(table.runningNr),
]
);
export const prodlabelsSchema = createSelectSchema(prodlabels);

View File

@@ -16,6 +16,7 @@
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-scroll-area": "^1.2.3",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.1.2",
@@ -1740,6 +1741,37 @@
}
}
},
"node_modules/@radix-ui/react-scroll-area": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.3.tgz",
"integrity": "sha512-l7+NNBfBYYJa9tNqVcP2AGvxdE3lmE6kFTBXdvHgUaZuy+4wGCL1Cl2AfaR7RKyimj7lZURGLwFO59k4eBnDJQ==",
"license": "MIT",
"dependencies": {
"@radix-ui/number": "1.1.0",
"@radix-ui/primitive": "1.1.1",
"@radix-ui/react-compose-refs": "1.1.1",
"@radix-ui/react-context": "1.1.1",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-presence": "1.1.2",
"@radix-ui/react-primitive": "2.0.2",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-select": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz",

View File

@@ -20,6 +20,7 @@
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-popover": "^1.1.6",
"@radix-ui/react-scroll-area": "^1.2.3",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slot": "^1.1.2",

View File

@@ -0,0 +1,131 @@
import axios from "axios";
import { LstCard } from "../extendedUI/LstCard";
import { Button } from "../ui/button";
import { ScrollArea } from "../ui/scroll-area";
import { Skeleton } from "../ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "../ui/table";
import { toast } from "sonner";
const currentPallets = [
{ key: "line", label: "Line" },
{ key: "runningNr", label: "Running #" },
{ key: "upd_date", label: "Date Scanned" },
{ key: "waitingfor", label: "Waiting For" },
{ key: "clear", label: "Clear" },
];
const currentTags = [
{ key: "line", label: "Line" },
{ key: "printerName", label: "Printer" },
{ key: "runningNr", label: "Running #" },
{ key: "upd_date", label: "Label date" },
{ key: "status", label: "Label Status" },
];
export default function WrapperManualTrigger() {
const cameraTrigger = async () => {
try {
const res = await axios.get("/ocme/api/v1/manualCameraTrigger");
if (res.data.success) {
toast.success(res.data.message);
return;
}
if (!res.data.success) {
toast.error(res.data.message);
}
} catch (error) {
console.log(error);
//stoast.success(error.data.message);
}
};
return (
<LstCard className="m-2 p-2">
<ScrollArea className="max-h-[200px]">
<span>Wrapper Pallet Info</span>
<Table>
<TableHeader>
<TableRow>
{currentPallets.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{Array(3)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</ScrollArea>
<ScrollArea className="max-h-[200px]">
<Table>
<TableHeader>
<TableRow>
{currentTags.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{Array(3)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</ScrollArea>
<div>
<hr />
<p className="text-center mb-3">Manual Triggers</p>
<div className="flex flex-row justify-between">
<Button onClick={cameraTrigger}>Camera</Button>
<Button>Rfid</Button>
</div>
</div>
</LstCard>
);
}

View File

@@ -1,14 +1,27 @@
import {toast} from "sonner";
import {LstCard} from "../extendedUI/LstCard";
import {Button} from "../ui/button";
import {Input} from "../ui/input";
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "../ui/table";
import {Skeleton} from "../ui/skeleton";
import { toast } from "sonner";
import { LstCard } from "../extendedUI/LstCard";
import { Button } from "../ui/button";
import { Input } from "../ui/input";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "../ui/table";
import { Skeleton } from "../ui/skeleton";
//import CycleCountLog from "./CycleCountLog";
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "../ui/select";
import {Controller, useForm} from "react-hook-form";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "../ui/select";
import { Controller, useForm } from "react-hook-form";
import axios from "axios";
import {useState} from "react";
import { useState } from "react";
export default function OcmeCycleCount() {
const token = localStorage.getItem("auth_token");
@@ -18,7 +31,7 @@ export default function OcmeCycleCount() {
register,
handleSubmit,
//watch,
formState: {errors},
formState: { errors },
reset,
control,
} = useForm();
@@ -29,7 +42,7 @@ export default function OcmeCycleCount() {
toast.success(`Cycle count started`);
try {
const res = await axios.post("/ocme/api/v1/cyclecount", data, {
headers: {Authorization: `Bearer ${token}`},
headers: { Authorization: `Bearer ${token}` },
});
toast.success(res.data.message);
setData(res.data.data);
@@ -45,20 +58,25 @@ export default function OcmeCycleCount() {
<div className="flex flex-row w-screen">
<div className="m-2 w-5/6">
<LstCard>
<p className="ml-2">Please enter the name or laneID you want to cycle count.</p>
<p className="ml-2">
Please enter the name or laneID you want to cycle count.
</p>
<div>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex justify-between">
<div className="m-2 flex flex-row">
<Input
placeholder="enter lane: L064"
className={errors.lane ? "border-red-500" : ""}
className={
errors.lane ? "border-red-500" : ""
}
aria-invalid={!!errors.lane}
{...register("lane", {
required: true,
minLength: {
value: 3,
message: "The lane is too short!",
message:
"The lane is too short!",
},
})}
/>
@@ -68,25 +86,39 @@ export default function OcmeCycleCount() {
name="laneType"
defaultValue={""}
render={({
field: {onChange},
field: { onChange },
fieldState: {},
//formState,
}) => (
<Select onValueChange={onChange}>
<Select
onValueChange={onChange}
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select name or id" />
</SelectTrigger>
<SelectContent>
<SelectItem value="name">Name</SelectItem>
<SelectItem value="laneId">Lane ID</SelectItem>
<SelectItem value="name">
Name
</SelectItem>
<SelectItem value="laneId">
Lane ID
</SelectItem>
</SelectContent>
</Select>
)}
/>
</div>
</div>
<Button className="m-2" type="submit" disabled={counting}>
{counting ? <span>Counting...</span> : <span>CycleCount</span>}
<Button
className="m-2"
type="submit"
disabled={counting}
>
{counting ? (
<span>Counting...</span>
) : (
<span>CycleCount</span>
)}
</Button>
</div>
</form>
@@ -108,41 +140,43 @@ export default function OcmeCycleCount() {
{data.length === 0 ? (
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
) : (
<>
{data.map((i: any) => {
let classname = ``;
if (i.info === "Quality Check Required") {
if (
i.info === "Quality Check Required"
) {
classname = `bg-red-500`;
}
if (i.info === "Sent to Inv") {
@@ -150,24 +184,46 @@ export default function OcmeCycleCount() {
}
return (
<TableRow key={i.runningNumber}>
<TableCell className={`font-medium ${classname}`}>
<TableCell
className={`font-medium ${classname}`}
>
{i.alpla_laneID}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
<TableCell
className={`font-medium ${classname}`}
>
{i.alpla_laneDescription}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
<TableCell
className={`font-medium ${classname}`}
>
{i.Article}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
<TableCell
className={`font-medium ${classname}`}
>
{i.alpla_laneDescription}
</TableCell>
<TableCell className={`font-medium ${classname}`}>
<TableCell
className={`font-medium ${classname}`}
>
{i.runningNumber}
</TableCell>
<TableCell className={`font-medium ${classname}`}>{i.ocme}</TableCell>
<TableCell className={`font-medium ${classname}`}>{i.stock}</TableCell>
<TableCell className={`font-medium ${classname}`}>{i.info}</TableCell>
<TableCell
className={`font-medium ${classname}`}
>
{i.ocme}
</TableCell>
<TableCell
className={`font-medium ${classname}`}
>
{i.stock}
</TableCell>
<TableCell
className={`font-medium ${classname}`}
>
{i.info}
</TableCell>
</TableRow>
);
})}

View File

@@ -1,23 +1,30 @@
import {LstCard} from "@/components/extendedUI/LstCard";
import { LstCard } from "@/components/extendedUI/LstCard";
import {Skeleton} from "@/components/ui/skeleton";
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
import { Skeleton } from "@/components/ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
// import {useSessionStore} from "@/lib/store/sessionStore";
// import {useSettingStore} from "@/lib/store/useSettings";
import {useQuery} from "@tanstack/react-query";
import {getlabels} from "@/utils/querys/production/labels";
import {format} from "date-fns";
import { useQuery } from "@tanstack/react-query";
import { getlabels } from "@/utils/querys/production/labels";
import { format } from "date-fns";
const labelLogs = [
{key: "line", label: "Line"},
{key: "printerName", label: "Printer"},
{key: "runningNr", label: "Running #"},
{key: "upd_date", label: "Label date"},
{key: "status", label: "Label Status"},
{ key: "line", label: "Line" },
{ key: "printerName", label: "Printer" },
{ key: "runningNr", label: "Running #" },
{ key: "upd_date", label: "Label date" },
{ key: "status", label: "Label Status" },
//{key: "reprint", label: "Reprint"}, // removing the reprint button for now until repritning is working as intended
];
export default function LabelLog() {
const {data, isError, isLoading} = useQuery(getlabels("4"));
const { data, isError, isLoading } = useQuery(getlabels("4"));
//const {user} = useSessionStore();
//const {settings} = useSettingStore();
//const server = settings.filter((n) => n.name === "server")[0]?.value || "";
@@ -40,33 +47,33 @@ export default function LabelLog() {
<TableBody>
{Array(7)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</LstCard>
</div>
);
}
const labelData = data ? data : [];
return (
<LstCard className="m-2 p-2 min-h-2/5">
<p className="text-center">Labels for the last 2 hours</p>
@@ -82,39 +89,47 @@ export default function LabelLog() {
<>
<TableBody>
{Array(7)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</>
) : (
<TableBody>
{data?.map((label: any) => (
{labelData.map((label: any) => (
<TableRow key={label.runningNr}>
<TableCell className="font-medium">{label.line}</TableCell>
<TableCell className="font-medium">{label.printerName}</TableCell>
<TableCell className="font-medium">{label.runningNr}</TableCell>
<TableCell className="font-medium">
{label.line}
</TableCell>
<TableCell className="font-medium">
{label.printerName}
</TableCell>
<TableCell className="font-medium">
{label.runningNr}
</TableCell>
<TableCell className="font-medium">
{format(label.upd_date, "M/d/yyyy hh:mm")}
</TableCell>
<TableCell className="font-medium">{label.status}</TableCell>
<TableCell className="font-medium">
{label.status}
</TableCell>
</TableRow>
))}
</TableBody>

View File

@@ -1,14 +1,22 @@
import {LstCard} from "@/components/extendedUI/LstCard";
import { LstCard } from "@/components/extendedUI/LstCard";
import {Skeleton} from "@/components/ui/skeleton";
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
import {useSessionStore} from "@/lib/store/sessionStore";
import {useSettingStore} from "@/lib/store/useSettings";
import {LotType} from "@/types/lots";
import {getlots} from "@/utils/querys/production/lots";
import {useQuery} from "@tanstack/react-query";
import { Skeleton } from "@/components/ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { useSessionStore } from "@/lib/store/sessionStore";
import { useSettingStore } from "@/lib/store/useSettings";
import { LotType } from "@/types/lots";
import { getlots } from "@/utils/querys/production/lots";
import { useQuery } from "@tanstack/react-query";
import ManualPrint from "./ManualPrinting/ManualPrint";
import ManualPrintForm from "./ManualPrinting/ManualPrintForm";
import { ScrollArea } from "@/components/ui/scroll-area";
let lotColumns = [
{
@@ -57,12 +65,12 @@ let lotColumns = [
// },
];
export default function Lots() {
const {data, isError, isLoading} = useQuery(getlots());
const {user} = useSessionStore();
const {settings} = useSettingStore();
const { data, isError, isLoading } = useQuery(getlots());
const { user } = useSessionStore();
const { settings } = useSettingStore();
const server = settings.filter((n) => n.name === "server")[0]?.value || "";
console.log(server);
console.log(data);
const roles = ["admin", "manager", "operator"];
@@ -83,140 +91,167 @@ export default function Lots() {
if (isError) {
return (
<div className="m-2 p-2 min-h-2/5">
<LstCard>
<p className="text-center">Current Assigned lots</p>
<Table>
<TableHeader>
<TableRow>
{lotColumns.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<ScrollArea className="max-h-1/2 rounded-md border p-4">
<LstCard>
<p className="text-center">Current Assigned lots</p>
<Table>
<TableHeader>
<TableRow>
{lotColumns.map((l) => (
<TableHead key={l.key}>
{l.label}
</TableHead>
))}
</TableRow>
))}
</TableBody>
</Table>
</LstCard>
</TableHeader>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</LstCard>
</ScrollArea>
</div>
);
}
return (
<LstCard className="m-2 p-2 min-h-2/5">
<p className="text-center">Current Assigned lots</p>
<Table>
<TableHeader>
<TableRow>
{lotColumns.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
{isLoading ? (
<>
<ScrollArea className="h-[400px]">
<p className="text-center">Current Assigned lots</p>
<Table>
<TableHeader>
<TableRow>
{lotColumns.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
{isLoading ? (
<>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</>
) : (
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
{data?.map((lot: LotType) => (
<TableRow key={lot.LabelOnlineID}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
{lot.MachineLocation}
</TableCell>
<TableCell>
<Skeleton className="h-4" />
<TableCell className="font-medium">
{lot.AV}
</TableCell>
<TableCell>
<Skeleton className="h-4" />
<TableCell className="font-medium">
{lot.Alias}
</TableCell>
<TableCell>
<Skeleton className="h-4" />
<TableCell className="font-medium">
{lot.LOT}
</TableCell>
<TableCell>
<Skeleton className="h-4" />
<TableCell className="font-medium">
{lot.ProlinkLot}
</TableCell>
<TableCell>
<Skeleton className="h-4" />
<TableCell className="font-medium">
{lot.PlannedQTY}
</TableCell>
<TableCell>
<Skeleton className="h-4" />
<TableCell className="font-medium">
{lot.Produced}
</TableCell>
<TableCell>
<Skeleton className="h-4" />
<TableCell className="font-medium">
{lot.Remaining}
</TableCell>
<TableCell>
<Skeleton className="h-4" />
<TableCell className="font-medium">
{lot.overPrinting}
</TableCell>
{user && roles.includes(user.role) && (
<>
{server === "usday1vms006" ||
server === "localhost" ? (
<>
<TableCell className="flex justify-center">
<ManualPrintForm
lot={lot}
/>
</TableCell>
</>
) : (
<TableCell className="flex justify-center">
<ManualPrint lot={lot} />
</TableCell>
)}
</>
)}
</TableRow>
))}
</TableBody>
</>
) : (
<TableBody>
{data?.map((lot: LotType) => (
<TableRow key={lot.LabelOnlineID}>
<TableCell className="font-medium">{lot.MachineLocation}</TableCell>
<TableCell className="font-medium">{lot.AV}</TableCell>
<TableCell className="font-medium">{lot.Alias}</TableCell>
<TableCell className="font-medium">{lot.LOT}</TableCell>
<TableCell className="font-medium">{lot.ProlinkLot}</TableCell>
<TableCell className="font-medium">{lot.PlannedQTY}</TableCell>
<TableCell className="font-medium">{lot.Produced}</TableCell>
<TableCell className="font-medium">{lot.Remaining}</TableCell>
<TableCell className="font-medium">{lot.overPrinting}</TableCell>
{user && roles.includes(user.role) && (
<>
{server === "usday1vms006" || server === "localhost" ? (
<>
<TableCell className="flex justify-center">
<ManualPrintForm lot={lot} />
</TableCell>
</>
) : (
<TableCell className="flex justify-center">
<ManualPrint lot={lot} />
</TableCell>
)}
</>
)}
</TableRow>
))}
</TableBody>
)}
</Table>
)}
</Table>
</ScrollArea>
</LstCard>
);
}

View File

@@ -1,9 +1,14 @@
import WrapperManualTrigger from "@/components/ocme/WrapperCard";
import LabelLog from "./LabelLog";
import Lots from "./Lots";
import OcpLogs from "./OcpLogs";
import PrinterStatus from "./PrinterStatus";
import { useSettingStore } from "@/lib/store/useSettings";
export default function OCPPage() {
const { settings } = useSettingStore();
const server = settings.filter((n) => n.plantToken === "usday1");
return (
<div className="h-dvh w-full overflow-hidden">
<div className="flex flex-wrap gap-2">
@@ -21,8 +26,15 @@ export default function OCPPage() {
</div>
</div>
</div>
<div className="w-1/6">
<PrinterStatus />
<div className="w-1/6 flex flex-col">
{server && (
<div>
<WrapperManualTrigger />
</div>
)}
<div>
<PrinterStatus />
</div>
</div>
</div>
</div>

View File

@@ -1,6 +1,14 @@
import {LstCard} from "@/components/extendedUI/LstCard";
import {Skeleton} from "@/components/ui/skeleton";
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
import { LstCard } from "@/components/extendedUI/LstCard";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Skeleton } from "@/components/ui/skeleton";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
let printerCols = [
{
@@ -19,34 +27,37 @@ let printerCols = [
export default function PrinterStatus() {
return (
<LstCard className="m-2 p-2">
<p className="text-center">Printer Status</p>
<Table>
<TableHeader>
<TableRow>
{printerCols.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
</TableHeader>
<ScrollArea className="max-h-[300px]">
<p className="text-center">Printer Status</p>
<TableBody>
{Array(10)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<Table>
<TableHeader>
<TableRow>
{printerCols.map((l) => (
<TableHead key={l.key}>{l.label}</TableHead>
))}
</TableRow>
))}
</TableBody>
</Table>
</TableHeader>
<TableBody>
{Array(5)
.fill(0)
.map((_, i) => (
<TableRow key={i}>
<TableCell className="font-medium">
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
<TableCell>
<Skeleton className="h-4" />
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</ScrollArea>
</LstCard>
);
}

View File

@@ -0,0 +1,56 @@
import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
import { cn } from "@/lib/utils"
function ScrollArea({
className,
children,
...props
}: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
return (
<ScrollAreaPrimitive.Root
data-slot="scroll-area"
className={cn("relative", className)}
{...props}
>
<ScrollAreaPrimitive.Viewport
data-slot="scroll-area-viewport"
className="ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] focus-visible:ring-4 focus-visible:outline-1"
>
{children}
</ScrollAreaPrimitive.Viewport>
<ScrollBar />
<ScrollAreaPrimitive.Corner />
</ScrollAreaPrimitive.Root>
)
}
function ScrollBar({
className,
orientation = "vertical",
...props
}: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
return (
<ScrollAreaPrimitive.ScrollAreaScrollbar
data-slot="scroll-area-scrollbar"
orientation={orientation}
className={cn(
"flex touch-none p-px transition-colors select-none",
orientation === "vertical" &&
"h-full w-2.5 border-l border-l-transparent",
orientation === "horizontal" &&
"h-2.5 flex-col border-t border-t-transparent",
className
)}
{...props}
>
<ScrollAreaPrimitive.ScrollAreaThumb
data-slot="scroll-area-thumb"
className="bg-border relative flex-1 rounded-full"
/>
</ScrollAreaPrimitive.ScrollAreaScrollbar>
)
}
export { ScrollArea, ScrollBar }

View File

@@ -1,4 +1,4 @@
import {queryOptions} from "@tanstack/react-query";
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlabels(hours: string) {
@@ -13,7 +13,7 @@ export function getlabels(hours: string) {
}
const fetchSettings = async (hours: string) => {
const {data} = await axios.get(`/api/v1/ocp/labels?hours=${hours}`);
const { data } = await axios.get(`/api/ocp/getlabels?hours=${hours}`);
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
return data.data ?? [];

View File

@@ -1,4 +1,4 @@
import {queryOptions} from "@tanstack/react-query";
import { queryOptions } from "@tanstack/react-query";
import axios from "axios";
export function getlots() {
@@ -13,7 +13,7 @@ export function getlots() {
}
const fetchSettings = async () => {
const {data} = await axios.get("/api/v1/ocp/lots");
const { data } = await axios.get("/api/ocp/getlots");
// if we are not localhost ignore the devDir setting.
//const url: string = window.location.host.split(":")[0];
let lotData = data.data;

361
package-lock.json generated
View File

@@ -13,13 +13,16 @@
"@hono/zod-openapi": "^0.19.2",
"@scalar/hono-api-reference": "^0.7.2",
"@types/jsonwebtoken": "^9.0.9",
"@types/nodemailer-express-handlebars": "^4.0.5",
"adm-zip": "^0.5.16",
"axios": "^1.8.4",
"bcryptjs": "^3.0.2",
"date-fns": "^4.1.0",
"drizzle-kit": "^0.30.5",
"drizzle-orm": "^0.41.0",
"drizzle-zod": "^0.7.0",
"fast-xml-parser": "^5.0.9",
"fs-extra": "^11.3.0",
"jsonwebtoken": "^9.0.2",
"mssql": "^11.0.1",
"nodemailer": "^6.10.0",
@@ -30,6 +33,7 @@
"pino-pretty": "^13.0.0",
"postgres": "^3.4.5",
"rimraf": "^6.0.1",
"st-ethernet-ip": "^2.7.3",
"ws": "^8.18.1",
"zod": "^3.24.2"
},
@@ -40,12 +44,11 @@
"@types/js-cookie": "^3.0.6",
"@types/mssql": "^9.1.7",
"@types/node": "^22.13.11",
"@types/nodemailer": "^6.4.17",
"@types/pg": "^8.11.11",
"@types/ws": "^8.18.0",
"concurrently": "^9.1.2",
"cz-conventional-changelog": "^3.3.0",
"drizzle-kit": "^0.30.5",
"fs-extra": "^11.3.0",
"standard-version": "^9.5.0",
"tsx": "^4.19.3",
"typescript": "^5.8.2"
@@ -520,7 +523,6 @@
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/@drizzle-team/brocli/-/brocli-0.10.2.tgz",
"integrity": "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==",
"dev": true,
"license": "Apache-2.0"
},
"node_modules/@ecies/ciphers": {
@@ -542,7 +544,6 @@
"resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.3.2.tgz",
"integrity": "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==",
"deprecated": "Merged into tsx: https://tsx.is",
"dev": true,
"license": "MIT",
"dependencies": {
"esbuild": "~0.18.20",
@@ -556,7 +557,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -573,7 +573,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -590,7 +589,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -607,7 +605,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -624,7 +621,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -641,7 +637,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -658,7 +653,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -675,7 +669,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -692,7 +685,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -709,7 +701,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -726,7 +717,6 @@
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -743,7 +733,6 @@
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -760,7 +749,6 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -777,7 +765,6 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -794,7 +781,6 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -811,7 +797,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -828,7 +813,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -845,7 +829,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -862,7 +845,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -879,7 +861,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -896,7 +877,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -913,7 +893,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -927,7 +906,6 @@
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz",
"integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@@ -966,7 +944,6 @@
"resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.6.5.tgz",
"integrity": "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==",
"deprecated": "Merged into tsx: https://tsx.is",
"dev": true,
"license": "MIT",
"dependencies": {
"@esbuild-kit/core-utils": "^3.3.2",
@@ -980,7 +957,6 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -997,7 +973,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1014,7 +989,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1031,7 +1005,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1048,7 +1021,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1065,7 +1037,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1082,7 +1053,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1099,7 +1069,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1116,7 +1085,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1133,7 +1101,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1150,7 +1117,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1167,7 +1133,6 @@
"cpu": [
"loong64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1184,7 +1149,6 @@
"cpu": [
"mips64el"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1201,7 +1165,6 @@
"cpu": [
"ppc64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1218,7 +1181,6 @@
"cpu": [
"riscv64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1235,7 +1197,6 @@
"cpu": [
"s390x"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1252,7 +1213,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1286,7 +1246,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1320,7 +1279,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1337,7 +1295,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1354,7 +1311,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1371,7 +1327,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1388,7 +1343,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -1592,7 +1546,6 @@
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.9.2.tgz",
"integrity": "sha512-VgffxawQde93xKxT3qap3OH+meZf7VaSB5Sqd4Rqc+FP5alWbpOyan/7tRbOAvynjpG3GpdtAuGU/NdhQpmrog==",
"devOptional": true,
"license": "MIT"
},
"node_modules/@scalar/core": {
@@ -1682,6 +1635,12 @@
"@types/node": "*"
}
},
"node_modules/@types/express-handlebars": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@types/express-handlebars/-/express-handlebars-5.3.1.tgz",
"integrity": "sha512-DSzaERLO4gHb8AqnrL58jzSDyT0yDdl6HqDc+bGz1Hf0nrG1FK30nHGzv8NBEGR8QV9eUGB/YaE0Qj3NjF7siw==",
"license": "MIT"
},
"node_modules/@types/fs-extra": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz",
@@ -1754,6 +1713,25 @@
"undici-types": "~6.20.0"
}
},
"node_modules/@types/nodemailer": {
"version": "6.4.17",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.17.tgz",
"integrity": "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/nodemailer-express-handlebars": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/nodemailer-express-handlebars/-/nodemailer-express-handlebars-4.0.5.tgz",
"integrity": "sha512-SuSYGNQPGtgMkDlQTO7zacXDENqQR3QXW1Ip5PvvookodvUKCbNVRF1tisY3Bgew1h8Wjfsf6dPQ5E45pJ1bJA==",
"license": "MIT",
"dependencies": {
"@types/express-handlebars": "^5",
"@types/nodemailer": "*"
}
},
"node_modules/@types/normalize-package-data": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
@@ -2085,7 +2063,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true,
"license": "MIT"
},
"node_modules/bundle-name": {
@@ -2113,6 +2090,24 @@
"node": ">=6"
}
},
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.0",
"es-define-property": "^1.0.0",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
@@ -2126,6 +2121,22 @@
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
@@ -2993,7 +3004,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
"integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": "*"
@@ -3060,6 +3070,26 @@
"dev": true,
"license": "MIT"
},
"node_modules/deep-equal": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
"integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
"license": "MIT",
"dependencies": {
"is-arguments": "^1.1.1",
"is-date-object": "^1.0.5",
"is-regex": "^1.1.4",
"object-is": "^1.1.5",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.5.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/default-browser": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz",
@@ -3101,6 +3131,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-lazy-prop": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
@@ -3113,6 +3160,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/define-properties": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0",
"object-keys": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -3261,7 +3325,6 @@
"version": "0.30.5",
"resolved": "https://registry.npmjs.org/drizzle-kit/-/drizzle-kit-0.30.5.tgz",
"integrity": "sha512-l6dMSE100u7sDaTbLczibrQZjA35jLsHNqIV+jmhNVO3O8jzM6kywMOmV9uOz9ZVSCMPQhAZEFjL/qDPVrqpUA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@drizzle-team/brocli": "^0.10.2",
@@ -3536,7 +3599,6 @@
"version": "0.19.12",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz",
"integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"bin": {
@@ -3575,7 +3637,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz",
"integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==",
"dev": true,
"license": "MIT",
"dependencies": {
"debug": "^4.3.4"
@@ -3894,7 +3955,6 @@
"version": "11.3.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz",
"integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==",
"dev": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
@@ -3936,11 +3996,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/functions-have-names": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gel": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/gel/-/gel-2.0.1.tgz",
"integrity": "sha512-gfem3IGvqKqXwEq7XseBogyaRwGsQGuE7Cw/yQsjLGdgiyqX92G1xENPCE0ltunPGcsJIa6XBOTx/PK169mOqw==",
"devOptional": true,
"license": "Apache-2.0",
"dependencies": {
"@petamoriken/float16": "^3.8.7",
@@ -3961,7 +4029,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz",
"integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
@@ -3974,7 +4041,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz",
"integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==",
"devOptional": true,
"license": "ISC",
"engines": {
"node": ">=16"
@@ -3984,7 +4050,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
"integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
"devOptional": true,
"license": "ISC",
"dependencies": {
"isexe": "^3.1.1"
@@ -4122,7 +4187,6 @@
"version": "4.10.0",
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz",
"integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==",
"dev": true,
"license": "MIT",
"dependencies": {
"resolve-pkg-maps": "^1.0.0"
@@ -4381,6 +4445,18 @@
"node": ">=4"
}
},
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -4724,6 +4800,31 @@
"node": ">=8"
}
},
"node_modules/int64-buffer": {
"version": "0.99.1007",
"resolved": "https://registry.npmjs.org/int64-buffer/-/int64-buffer-0.99.1007.tgz",
"integrity": "sha512-XDBEu44oSTqlvCSiOZ/0FoUkpWu/vwjJLGSKDabNISPQNZ5wub1FodGHBljRsrR0IXRPq7SslshZYMuA55CgTQ==",
"license": "MIT",
"engines": {
"node": ">= 4.5.0"
}
},
"node_modules/is-arguments": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
@@ -4747,6 +4848,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-date-object": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-docker": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
@@ -4852,6 +4969,24 @@
"node": ">=0.10.0"
}
},
"node_modules/is-regex": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
@@ -5030,7 +5165,6 @@
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
@@ -5817,6 +5951,31 @@
"node": ">=8"
}
},
"node_modules/object-is": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/object-treeify": {
"version": "1.1.33",
"resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-1.1.33.tgz",
@@ -6757,6 +6916,26 @@
"node": ">=8"
}
},
"node_modules/regexp.prototype.flags": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
"integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
"define-properties": "^1.2.1",
"es-errors": "^1.3.0",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"set-function-name": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -6828,7 +7007,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
@@ -6965,6 +7143,38 @@
"node": ">=10"
}
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/set-function-name": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"functions-have-names": "^1.2.3",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -6990,7 +7200,6 @@
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz",
"integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==",
"devOptional": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -7033,7 +7242,6 @@
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
@@ -7105,6 +7313,18 @@
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
"license": "BSD-3-Clause"
},
"node_modules/st-ethernet-ip": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/st-ethernet-ip/-/st-ethernet-ip-2.7.3.tgz",
"integrity": "sha512-pc7cjrLwlZGzezuqEThensjk8o9lvI73xlNf4Ufzsfl51Akfe8Td9RdQJPWaAjaCCYV3h0pgRp5NrudgKCMBww==",
"license": "MIT",
"dependencies": {
"dateformat": "^3.0.3",
"deep-equal": "^1.1.1",
"int64-buffer": "^0.99.1007",
"task-easy": "^0.2.0"
}
},
"node_modules/standard-version": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.5.0.tgz",
@@ -7306,6 +7526,12 @@
"node": ">=8.0.0"
}
},
"node_modules/task-easy": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/task-easy/-/task-easy-0.2.1.tgz",
"integrity": "sha512-VMYezcVhfyaTkc3cWf4sSQG6YgYBdiNCAg4iXuUWRGB7tp7A/rZA9Nter0ZIG5chSoidLS0VWf87koFD9XHwDg==",
"license": "MIT"
},
"node_modules/tedious": {
"version": "18.6.1",
"resolved": "https://registry.npmjs.org/tedious/-/tedious-18.6.1.tgz",
@@ -7988,7 +8214,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"

View File

@@ -9,7 +9,7 @@
"dev:dbgen": " drizzle-kit generate --config=drizzle-dev.config.ts",
"dev:dbmigrate": " drizzle-kit migrate --config=drizzle-dev.config.ts",
"build": "npm run build:server && npm run build:frontend",
"build:server": "rimraf dist && tsc --build && npm run copy:scripts",
"build:server": "rimraf dist && tsc --build && npm run copy:scripts && xcopy server\\services\\notifications\\utils\\views\\ dist\\server\\services\\notifications\\utils\\views\\ /E /I /Y",
"build:frontend": "cd frontend && npm run build",
"copy:scripts": "tsx server/scripts/copyScripts.ts",
"copy:servers": "xcopy server\\services\\server\\utils\\serverData.json dist\\server\\services\\server\\utils /E /I /Y",
@@ -21,7 +21,8 @@
"deploy": "standard-version --conventional-commits && npm run prodBuild",
"zipServer": "dotenvx run -f .env -- tsx server/scripts/zipUpBuild.ts \"C:\\Users\\matthes01\\Documents\\lstv2\"",
"v1Build": "cd C:\\Users\\matthes01\\Documents\\logisticsSupportTool && npm run oldBuilder",
"prodBuild": "npm run v1Build && powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\" && npm run zipServer",
"scriptBuild": "powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2-dev\"",
"prodBuild": "npm run v1Build && npm run zipServer",
"commit": "cz",
"prodinstall": "npm i --omit=dev && npm run db:migrate",
"checkupdates": "npx npm-check-updates"
@@ -32,7 +33,7 @@
}
},
"admConfig": {
"build": 50,
"build": 92,
"oldBuild": "backend-0.1.3.zip"
},
"devDependencies": {
@@ -42,12 +43,11 @@
"@types/js-cookie": "^3.0.6",
"@types/mssql": "^9.1.7",
"@types/node": "^22.13.11",
"@types/nodemailer": "^6.4.17",
"@types/pg": "^8.11.11",
"@types/ws": "^8.18.0",
"concurrently": "^9.1.2",
"cz-conventional-changelog": "^3.3.0",
"drizzle-kit": "^0.30.5",
"fs-extra": "^11.3.0",
"standard-version": "^9.5.0",
"tsx": "^4.19.3",
"typescript": "^5.8.2"
@@ -58,13 +58,16 @@
"@hono/zod-openapi": "^0.19.2",
"@scalar/hono-api-reference": "^0.7.2",
"@types/jsonwebtoken": "^9.0.9",
"@types/nodemailer-express-handlebars": "^4.0.5",
"adm-zip": "^0.5.16",
"axios": "^1.8.4",
"bcryptjs": "^3.0.2",
"date-fns": "^4.1.0",
"drizzle-kit": "^0.30.5",
"drizzle-orm": "^0.41.0",
"drizzle-zod": "^0.7.0",
"fast-xml-parser": "^5.0.9",
"fs-extra": "^11.3.0",
"jsonwebtoken": "^9.0.2",
"mssql": "^11.0.1",
"nodemailer": "^6.10.0",
@@ -75,6 +78,7 @@
"pino-pretty": "^13.0.0",
"postgres": "^3.4.5",
"rimraf": "^6.0.1",
"st-ethernet-ip": "^2.7.3",
"ws": "^8.18.1",
"zod": "^3.24.2"
}

View File

@@ -1,12 +1,12 @@
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
import { serve } from "@hono/node-server";
import { OpenAPIHono } from "@hono/zod-openapi";
import { proxy } from "hono/proxy";
import { serveStatic } from "@hono/node-server/serve-static";
import { logger } from "hono/logger";
import { cors } from "hono/cors";
import { createLog } from "./services/logger/logger.js";
import { WebSocketServer } from "ws";
// custom routes
import scalar from "./services/general/route/scalar.js";
import system from "./services/server/systemServer.js";
@@ -21,7 +21,10 @@ import loggerService from "./services/logger/loggerService.js";
import ocpService from "./services/ocp/ocpService.js";
import { db } from "../database/dbclient.js";
import { settings } from "../database/schema/settings.js";
import { count } from "drizzle-orm";
import os from "os";
import { tryCatch } from "./globalUtils/tryCatch.js";
import { sendEmail } from "./services/notifications/controller/sendMail.js";
import notify from "./services/notifications/notifyService.js";
// create the main prodlogin here
const username = "lst_user";
@@ -29,66 +32,78 @@ const password = "Alpla$$Prod";
export const lstAuth = btoa(`${username}:${password}`);
// checking to make sure we have the settings intialized
const serverIntialized = await db.select({ count: count() }).from(settings);
const { data: settingsData, error: settingError } = await tryCatch(
db.select().from(settings)
);
if (settingError) {
throw Error("Error getting settings from the db. critical error.");
}
const serverIntialized: any = settingsData;
export const installed =
serverIntialized[0].count === 0 && process.env.NODE_ENV !== "development"
? false
: true;
serverIntialized.length === 0 && process.env.NODE_ENV !== "development"
? false
: true;
createLog("info", "LST", "server", `Server is installed: ${installed}`);
const app = new OpenAPIHono({ strict: false });
// middle ware
app.use("*", logger());
if (process.env.NODE_ENV === "development") {
app.use("*", logger());
}
app.use(
"*",
cors({
origin: "*", // Allow all origins
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
//exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
credentials: true, // Allow credentials if needed
maxAge: 600,
})
"*",
cors({
origin: "*", // Allow all origins
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
//exposeHeaders: ["Content-Length", "X-Kuma-Revision"],
credentials: true, // Allow credentials if needed
maxAge: 600,
})
);
// Middleware to normalize route case
app.use("*", async (c, next) => {
const lowercasedUrl = c.req.url.toLowerCase();
//console.log("Incoming Request:", c.req.url, c.req.method);
// If the URL is already lowercase, continue as usual
if (c.req.url === lowercasedUrl) {
return next();
}
// app.use("*", async (c, next) => {
// // const lowercasedUrl = c.req.url.toLowerCase();
// console.log("Incoming Request:", c.req.url, c.req.method);
// // // If the URL is already lowercase, continue as usual
// // if (c.req.url === lowercasedUrl) {
// await next();
// // }
// Otherwise, re-route internally
return c.redirect(lowercasedUrl, 308); // 308 preserves the HTTP method
});
// // // Otherwise, re-route internally
// // return c.redirect(lowercasedUrl, 308); // 308 preserves the HTTP method
// });
app.doc("/api/ref", {
openapi: "3.0.0",
info: {
version: "2.0.0",
title: "LST API",
},
openapi: "3.0.0",
info: {
version: "2.0.0",
title: "LST API",
},
});
const routes = [
scalar,
auth,
// apiHits,
system,
tcpServer,
sqlService,
logistics,
rfid,
printers,
loggerService,
ocpService,
scalar,
auth,
// apiHits,
system,
tcpServer,
sqlService,
logistics,
rfid,
printers,
loggerService,
ocpService,
notify,
] as const;
const appRoutes = routes.forEach((route) => {
app.route("/api/", route);
app.route("/api/", route);
});
app.route("/ocme/", ocme);
@@ -129,48 +144,59 @@ app.use("*", serveStatic({ path: "./frontend/dist/index.html" }));
// Handle app exit signals
process.on("SIGINT", async () => {
console.log("\nGracefully shutting down...");
//await closePool();
process.exit(0);
console.log("\nGracefully shutting down...");
//await closePool();
process.exit(0);
});
process.on("SIGTERM", async () => {
console.log("Received termination signal, closing database...");
//await closePool();
process.exit(0);
console.log("Received termination signal, closing database...");
//await closePool();
process.exit(0);
});
process.on("uncaughtException", async (err) => {
console.log("Uncaught Exception:", err);
//await closePool();
process.exit(1);
console.log("Uncaught Exception:", err);
//await closePool();
const emailData = {
email: "blake.matthes@alpla.com", // should be moved to the db so it can be reused.
subject: `${os.hostname()} has just encountered a crash.`,
template: "serverCrash",
context: {
error: err,
plant: `${os.hostname()}`,
},
};
await sendEmail(emailData);
//process.exit(1);
});
process.on("beforeExit", async () => {
console.log("Process is about to exit...");
//await closePool();
process.exit(0);
console.log("Process is about to exit...");
//await closePool();
process.exit(0);
});
const port =
process.env.NODE_ENV === "development"
? process.env.VITE_SERVER_PORT
: process.env.PROD_PORT;
process.env.NODE_ENV === "development"
? process.env.VITE_SERVER_PORT
: process.env.PROD_PORT;
serve(
{
fetch: app.fetch,
port: Number(port),
hostname: "0.0.0.0",
},
(info) => {
createLog(
"info",
"LST",
"server",
`Server is running on http://${info.address}:${info.port}`
);
}
{
fetch: app.fetch,
port: Number(port),
hostname: "0.0.0.0",
},
(info) => {
createLog(
"info",
"LST",
"server",
`Server is running on http://${info.address}:${info.port}`
);
}
);
export type AppRoutes = typeof appRoutes;

View File

@@ -415,10 +415,10 @@ try {
Start-Service -DisplayName $serviceLstV2
Start-Sleep -Seconds 1
Write-Host "$($server) finished updating"
if($token -eq "usday1"){
Write-Host "Starting $($serviceOcme)"
Start-Service -DisplayName $serviceOcme
}
# if($token -eq "usday1"){
# Write-Host "Starting $($serviceOcme)"
# Start-Service -DisplayName $serviceOcme
# }
}
Invoke-Command -ComputerName $server -ScriptBlock $plantFunness -ArgumentList $server, $token, $location, $buildZip, $buildLoc, $obslst, $obsBuild -Credential $credentials

View File

@@ -1,21 +1,24 @@
import {spawn} from "child_process";
import {getAppInfo} from "../globalUtils/appInfo.js";
import {db} from "../../database/dbclient.js";
import {serverData} from "../../database/schema/serverData.js";
import {eq, sql} from "drizzle-orm";
import {createLog} from "../services/logger/logger.js";
import { spawn } from "child_process";
import { getAppInfo } from "../globalUtils/appInfo.js";
import { db } from "../../database/dbclient.js";
import { serverData } from "../../database/schema/serverData.js";
import { eq, sql } from "drizzle-orm";
import { createLog } from "../services/logger/logger.js";
type UpdateServerResponse = {
success: boolean;
message: string;
};
export const updateServer = async (devApp: string, server: string | null): Promise<UpdateServerResponse> => {
export const updateServer = async (
devApp: string,
server: string | null
): Promise<UpdateServerResponse> => {
const app = await getAppInfo(devApp);
const serverInfo = await db
.select()
.from(serverData)
.where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));
.select()
.from(serverData)
.where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));
if (serverInfo.length === 0) {
createLog(
@@ -26,7 +29,8 @@ export const updateServer = async (devApp: string, server: string | null): Promi
);
return {
success: false,
message: "Looks like you are missing the plant token or have entered an incorrect one please try again.",
message:
"Looks like you are missing the plant token or have entered an incorrect one please try again.",
};
}
@@ -77,9 +81,9 @@ export const updateServer = async (devApp: string, server: string | null): Promi
const process = spawn("powershell", args);
// change the server to upgradeing
await db
.update(serverData)
.set({isUpgrading: true})
.where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));
.update(serverData)
.set({ isUpgrading: true })
.where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));
//let stdout = "";
//let stderr = "";
@@ -108,9 +112,14 @@ export const updateServer = async (devApp: string, server: string | null): Promi
//update the last build.
try {
await db
.update(serverData)
.set({lastUpdated: sql`NOW()`, isUpgrading: false})
.where(eq(serverData.plantToken, server?.toLowerCase() ?? ""));
.update(serverData)
.set({ lastUpdated: sql`NOW()`, isUpgrading: false })
.where(
eq(
serverData.plantToken,
server?.toLowerCase() ?? ""
)
);
createLog(
"info",
"lst",
@@ -156,17 +165,35 @@ export const updateServer = async (devApp: string, server: string | null): Promi
export async function processAllServers(devApp: string) {
const servers = await db.select().from(serverData);
createLog("info", "lst", "serverUpdater", `Running the update on all servers`);
createLog(
"info",
"lst",
"serverUpdater",
`Running the update on all servers`
);
let count = 1;
for (const server of servers) {
try {
const updateToServer = await updateServer(devApp, server.plantToken);
createLog("info", "lst", "serverUpdater", `${server.sName} was updated.`);
const updateToServer = await updateServer(
devApp,
server.plantToken
);
createLog(
"info",
"lst",
"serverUpdater",
`${server.sName} was updated.`
);
count = count + 1;
//return {success: true, message: `${server.sName} was updated.`, data: updateToServer};
} catch (error: any) {
createLog("info", "lst", "serverUpdater", `Error updating ${server.sName}: ${error.message}`);
createLog(
"info",
"lst",
"serverUpdater",
`Error updating ${server.sName}: ${error.message}`
);
//return {success: false, message: `Error updating ${server.sName}: ${error.message}`};
}
}

View File

@@ -99,7 +99,7 @@ const updateBuildNumber = (appLock: string) => {
// Auto-commit changes
execSync("git add package.json");
execSync(
`git commit -m "build: bump build number to ${pkgJson.admConfig.build}"`
`git commit -m "chore(release): bump build number to ${pkgJson.admConfig.build}"`
);
} else {
createLog(

View File

@@ -1,7 +0,0 @@
import {createLog} from "../../logger/logger.js";
export const sendEmail = async () => {
createLog("info", "lst", "general", "Preparing to send an email");
// settings
};

View File

@@ -0,0 +1,102 @@
import { ConsoleLogWriter } from "drizzle-orm";
import { prodEndpointCreation } from "../../../globalUtils/createUrl.js";
import { createLog } from "../../logger/logger.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import { labelData } from "../../sqlServer/querys/materialHelpers/labelInfo.js";
import axios from "axios";
import { laneInfo } from "../../sqlServer/querys/materialHelpers/laneInfo.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
type Data = {
runningNr: string;
laneName: string;
};
export const returnMaterial = async (data: Data, prod: any) => {
const { runningNr, laneName } = data;
// replace the rn
const rnReplace = labelData.replaceAll("[rn]", runningNr);
// get the lane id by name
const laneQuery = laneInfo.replaceAll("[laneName]", laneName);
let barcode;
// get the barcode from the running number
try {
barcode = await query(rnReplace, "labelData");
} catch (error) {
console.log(error);
createLog(
"error",
prod.user.username,
"logistics",
`Error getting barcode: ${error}`
);
}
const { data: laneData, error: laneError } = await tryCatch(
query(laneQuery, "laneInfo")
);
if (laneError) {
return {
success: false,
message:
"The lane you entered is either deactivated or dose not exist.",
laneError,
};
}
if (!laneData) {
return {
success: false,
message:
"The lane you entered is either deactivated or dose not exist.",
};
}
if (laneData.length === 0) {
return {
success: false,
message:
"The lane you entered is either deactivated or dose not exist.",
};
}
if (barcode.length === 0) {
return {
success: false,
message: "The running number you've is not in stock.",
};
//throw Error("The provided runningNr is not in stock");
}
// create the url to post
const url = await prodEndpointCreation(
"/public/v1.0/IssueMaterial/ReturnPartiallyConsumedManualMaterial"
);
const returnSomething = {
laneId: laneData[0]?.laneID,
barcode: barcode[0]?.barcode,
};
try {
const results = await axios.post(url, returnSomething, {
headers: {
"Content-Type": "application/json",
Authorization: `Basic ${prod.user.prod}`,
},
});
//console.log(results);
return {
success: true,
message: "Material was returned",
status: results.status,
};
} catch (error: any) {
return {
success: false,
status: 200,
message: error.response?.data.errors[0].message,
};
}
};

View File

@@ -1,9 +1,10 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import { OpenAPIHono } from "@hono/zod-openapi";
import comsumeMaterial from "./route/consumeMaterial.js";
import returnMat from "./route/returnMaterial.js";
const app = new OpenAPIHono();
const routes = [comsumeMaterial] as const;
const routes = [comsumeMaterial, returnMat] as const;
// app.route("/server", modules);
const appRoutes = routes.forEach((route) => {

View File

@@ -0,0 +1,70 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { verify } from "hono/jwt";
import { returnMaterial } from "../controller/returnMaterial.js";
const app = new OpenAPIHono();
const responseSchema = z.object({
success: z.boolean().optional().openapi({ example: true }),
message: z.string().optional().openapi({ example: "user access" }),
});
app.openapi(
createRoute({
tags: ["logistics"],
summary: "Retrns material based on its running number and laneName",
method: "post",
path: "/return",
middleware: authMiddleware,
description:
"Provided a running number and Lane to return the material.",
responses: {
200: {
content: { "application/json": { schema: responseSchema } },
description: "stopped",
},
400: {
content: { "application/json": { schema: responseSchema } },
description: "Failed to stop",
},
401: {
content: { "application/json": { schema: responseSchema } },
description: "Failed to stop",
},
},
}),
async (c) => {
apiHit(c, { endpoint: "api/sqlProd/close" });
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
try {
const payload = await verify(token, process.env.JWT_SECRET!);
try {
//return apiReturn(c, true, access?.message, access?.data, 200);
const data = await c.req.json();
const consume = await returnMaterial(data, payload);
return c.json(
{ success: consume?.success, message: consume?.message },
200
);
} catch (error) {
//console.log(error);
//return apiReturn(c, false, "Error in setting the user access", error, 400);
return c.json(
{
success: false,
message: "Missing data please try again",
error,
},
400
);
}
} catch (error) {
return c.json({ success: false, message: "Unauthorized" }, 401);
}
}
);
export default app;

View File

@@ -0,0 +1,144 @@
import { tryCatch } from "../../../globalUtils/tryCatch.js";
import { db } from "../../../../database/dbclient.js";
import { settings } from "../../../../database/schema/settings.js";
import nodemailer from "nodemailer";
import type { Transporter } from "nodemailer";
import type SMTPTransport from "nodemailer/lib/smtp-transport/index.js";
import type Mail from "nodemailer/lib/mailer/index.js";
import type { Address } from "nodemailer/lib/mailer/index.js";
import path from "path";
import { fileURLToPath } from "url";
import hbs from "nodemailer-express-handlebars";
import { promisify } from "util";
import { createLog } from "../../logger/logger.js";
interface HandlebarsMailOptions extends Mail.Options {
template: string;
context: Record<string, unknown>; // Use a generic object for context
}
interface EmailData {
email: string;
subject: string;
template: string;
context: [];
}
export const sendEmail = async (data: any): Promise<any> => {
let transporter: Transporter;
let fromEmail: string | Address;
const { data: settingData, error: settingError } = await tryCatch(
db.select().from(settings)
);
if (settingError) {
return {
success: false,
message: "There was an error getting the settings.",
settingError,
};
}
// get the plantToken
const server = settingData.filter((n) => n.name === "server");
if (
server[0].value === "localhost" &&
process.env.EMAIL_USER &&
process.env.EMAIL_PASSWORD
) {
transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASSWORD,
},
//debug: true,
});
// update the from email
fromEmail = process.env.EMAIL_USER;
} else {
// convert to the correct plant token.
const plantToken = settingData.filter((s) => s.name === "plantToken");
let host = `${plantToken[0].value}-smtp.alpla.net`;
const testServers = ["test1", "test2", "test3"];
if (testServers.includes(plantToken[0].value)) {
host = "USMCD1-smtp.alpla.net";
}
if (plantToken[0].value === "usiow2") {
host = "USIOW1-smtp.alpla.net";
}
transporter = nodemailer.createTransport({
host: host,
port: 25,
rejectUnauthorized: false,
//secure: false,
// auth: {
// user: "alplaprod",
// pass: "obelix",
// },
debug: true,
} as SMTPTransport.Options);
// update the from email
fromEmail = `noreply@alpla.com`;
}
// creating the handlbar options
const viewPath = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"../utils/views/"
);
const handlebarOptions = {
viewEngine: {
extname: ".hbs",
//layoutsDir: path.resolve(viewPath, "layouts"), // Path to layouts directory
defaultLayout: "", // Specify the default layout
partialsDir: viewPath,
},
viewPath: viewPath,
extName: ".hbs", // File extension for Handlebars templates
};
transporter.use("compile", hbs(handlebarOptions));
const mailOptions: HandlebarsMailOptions = {
from: fromEmail,
to: data.email,
subject: data.subject,
//text: "You will have a reset token here and only have 30min to click the link before it expires.",
//html: emailTemplate("BlakesTest", "This is an example with css"),
template: data.template, // Name of the Handlebars template (e.g., 'welcome.hbs')
context: data.context,
};
// now verify and send the email
const sendMailPromise = promisify(transporter.sendMail).bind(transporter);
try {
// Send email and await the result
const info = await sendMailPromise(mailOptions);
createLog(
"info",
"notification",
"system",
`Email was sent to: ${data.email}`
);
return { success: true, message: "Email sent.", data: info };
} catch (err) {
console.log(err);
createLog(
"error",
"notification",
"system",
`Error sending Email: ${JSON.stringify(err)}`
);
return { success: false, message: "Error sending email.", error: err };
}
};

View File

@@ -0,0 +1,19 @@
import { OpenAPIHono } from "@hono/zod-openapi";
import sendemail from "./routes/sendMail.js";
const app = new OpenAPIHono();
const routes = [sendemail] as const;
const appRoutes = routes.forEach((route) => {
app.route("/notify", route);
});
app.all("/notify/*", (c) => {
return c.json({
success: false,
message: "you have encounted a notication route that dose not exist.",
});
});
export default app;

View File

@@ -0,0 +1,73 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
import { sendEmail } from "../controller/sendMail.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
const app = new OpenAPIHono({ strict: false });
const EmailSchema = z
.object({
email: z.string().email().openapi({ example: "smith@example.come" }),
subject: z.string().openapi({ example: "Welcome to LST" }),
template: z.string().openapi({ example: "exampleTemplate" }),
context: z
.object({
name: z.string().optional(),
score: z.string().optional(),
})
.optional()
.openapi({}),
})
.openapi("User");
app.openapi(
createRoute({
tags: ["server"],
summary: "Returns current active lots that are tech released",
method: "post",
path: "/sendmail",
middleware: authMiddleware,
request: {
body: {
content: {
"application/json": { schema: EmailSchema },
},
},
},
responses: responses(),
}),
async (c) => {
const { data: bodyData, error: bodyError } = await tryCatch(
c.req.json()
);
if (bodyError) {
return c.json(
{
success: false,
message: "There was an error sending the email",
data: bodyError,
},
400
);
}
const { data: emailData, error: emailError } = await tryCatch(
sendEmail(bodyData)
);
if (emailError) {
return c.json({
success: false,
message: "There was an error sending the email",
data: emailError,
});
}
return c.json({
success: emailData.success,
message: emailData.message,
data: emailData.data,
});
}
);
export default app;

View File

@@ -0,0 +1,33 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Order Summary</title>
{{> styles}}
{{!-- <link rel="stylesheet" href="styles/styles.css" /> --}}
</head>
<body>
<h1>{{name}}, your Order Summary</h1>
<p>All,
This is an example of the test email
</p>
<table>
<thead>
<tr>
<th>Item Name</th>
<th>Quantity</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{{#each items}}
<tr>
<td>{{name}}</td>
<td>{{quantity}}</td>
<td>{{price}}</td>
</tr>
{{/each}}
</tbody>
</table>
</body>
</html>

View File

@@ -0,0 +1,35 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
{{!--<title>Order Summary</title> --}}
{{> styles}}
<style>
pre {
background-color: #f8f9fa;
color: #d63384;
padding: 10px;
border-radius: 5px;
white-space: pre-wrap;
font-family: monospace;
}
</style>
{{!-- <link rel="stylesheet" href="styles/styles.css" /> --}}
</head>
<body>
<h3>{{plant}},<br/> Has encountered an unexpected error.</h1>
<p>
Please see below the stack error from the crash.
</p>
<hr/>
<div>
<h3>Error Message: </h3>
<p>{{error.message}}</p>
</div>
<hr/>
<div>
<h3>Stack trace</h3>
<pre>{{{error.stack}}}</pre>
</div>
</body>
</html>

View File

@@ -0,0 +1,6 @@
<style>
table { width: 100%; background-color: #ffffff; border-collapse: collapse;
border-width: 2px; border-color: #14BDEA; border-style: solid; color:
#000000; } th, td { border: 1px solid #ddd; padding: 8px; } th {
background-color: #f4f4f4; }
</style>

View File

@@ -0,0 +1,19 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
{{!--<title>Order Summary</title> --}}
{{> styles}}
{{!-- <link rel="stylesheet" href="styles/styles.css" /> --}}
</head>
<body>
<p>All,<br/>
There has been {{count}} manual prints in the last {{hours}}.<br/>
Please consider checking the reason for this.<br/>
Thank you,<br/>
LST
</p>
</body>
</html>

View File

@@ -3,9 +3,14 @@ import axios from "axios";
export const ocmeInv = async (data: any) => {
try {
const res = await axios.post(
"http://usday1vms010:3250/api/v1/getLaneData",
{lane: data.lane, laneType: data.laneType},
{headers: {"Content-Type": "application/json", Connection: "keep-alive"}}
"http://usday1vms010:3250/api/v1/getlanedata",
{ lane: data.lane, laneType: data.laneType },
{
headers: {
"Content-Type": "application/json",
Connection: "keep-alive",
},
}
);
// console.log(res.data.data);

View File

@@ -1,23 +1,37 @@
import {db} from "../../../../database/dbclient.js";
import {ocmeData} from "../../../../database/schema/ocme.js";
import {differenceInMinutes} from "date-fns";
import {createLog} from "../../logger/logger.js";
import {eq} from "drizzle-orm";
import { db } from "../../../../database/dbclient.js";
import { ocmeData } from "../../../../database/schema/ocme.js";
import { differenceInMinutes } from "date-fns";
import { createLog } from "../../logger/logger.js";
import { eq } from "drizzle-orm";
export const getInfo = async () => {
let ocmeInfo: any = [];
try {
ocmeInfo = await db.select().from(ocmeData).where(eq(ocmeData.pickedUp, false));
ocmeInfo = await db
.select()
.from(ocmeData)
.where(eq(ocmeData.pickedUp, false));
// add in the time difference
ocmeInfo = ocmeInfo.map((o: any) => {
const now = new Date(Date.now());
const diff = differenceInMinutes(now, o.add_Date!);
return {...o, waitingFor: diff};
//const strippedDate = o.add_Date.replace("Z", "");
const diff = differenceInMinutes(now, o.add_Date);
return { ...o, waitingFor: diff };
});
createLog("info", "ocme", "ocme", `There are ${ocmeInfo.length} pallet(s) to be picked up.`);
createLog(
"debug",
"ocme",
"ocme",
`There are ${ocmeInfo.length} pallet(s) to be picked up.`
);
} catch (error) {
createLog("error", "ocme", "ocme", "There was an error trying to retrive the ocmeInfo.");
createLog(
"error",
"ocme",
"ocme",
"There was an error trying to retrive the ocmeInfo."
);
throw Error("There was an error trying to retrive the.");
}

View File

@@ -1,43 +1,76 @@
import {db} from "../../../../database/dbclient.js";
import {ocmeData} from "../../../../database/schema/ocme.js";
import {createSSCC} from "../../../globalUtils/createSSCC.js";
import {createLog} from "../../logger/logger.js";
import {query} from "../../sqlServer/prodSqlServer.js";
import {labelData} from "../../sqlServer/querys/materialHelpers/labelInfo.js";
import { db } from "../../../../database/dbclient.js";
import { ocmeData } from "../../../../database/schema/ocme.js";
import { createSSCC } from "../../../globalUtils/createSSCC.js";
import { createLog } from "../../logger/logger.js";
import { query } from "../../sqlServer/prodSqlServer.js";
import { labelData } from "../../sqlServer/querys/materialHelpers/labelInfo.js";
export const postLabelData = async (data: any) => {
// if we have sscc we will do everything here and ignore the rn even it its sent over
if (data.sscc && !data.runningNr) {
data.runningNr = data.sscc.slice(10, -1);
console.log(data);
let newData = data;
if (Array.isArray(data)) {
newData = {
sscc: data[1],
areaFrom: data[0],
completed: true,
};
}
if (!data.sscc && !data.runningNr) {
// data.runningNr = data.sscc.slice(10, -1);
return {success: false, message: "Missing data please try again", data: []};
if (newData.sscc && !newData.runningNr) {
newData.runningNr = newData.sscc.slice(10, -1);
}
if (!newData.sscc && !newData.runningNr) {
return {
success: false,
message: "Missing data please try again",
data: [],
};
}
let label;
const filterQuery = labelData.replaceAll("[rn]", data.runningNr);
const filterQuery = labelData.replaceAll("[rn]", newData.runningNr);
try {
label = await query(filterQuery, "Label data");
} catch (error) {
createLog("error", "ocme", "ocme", "There was an error getting the labelData");
createLog(
"error",
"ocme",
"ocme",
"There was an error getting the labelData"
);
}
const newPost = {
sscc: data.sscc ? data.sscc : await createSSCC(data.runningNr),
runningNr: data.runningNr,
completed: data.completed,
lineNum: label[0].machineLocation,
areaFrom: data.areaFrom,
sscc: newData.sscc ? newData.sscc : await createSSCC(newData.runningNr),
runningNr: newData.runningNr,
completed: newData.completed ? newData.completed : true,
lineNum: label[0]?.machineLocation,
areaFrom: newData.areaFrom,
pickedUp: false,
};
try {
const enterNewData = await db.insert(ocmeData).values(newPost).returning({sscc: ocmeData.sscc});
return {success: true, message: "Data was posted to ocme info", data: enterNewData};
const enterNewData = await db
.insert(ocmeData)
.values(newPost)
.returning({
sscc: ocmeData.sscc,
runningNr: ocmeData.runningNr,
areaFrom: ocmeData.areaFrom,
lineNum: ocmeData.lineNum,
completed: ocmeData.completed,
pickedUp: ocmeData.pickedUp,
});
//console.log(enterNewData);
return {
success: true,
message: "Data was posted to ocme info",
data: enterNewData,
};
} catch (error) {
console.log(error);
return {success: false, message: "Data was posted to ocme info", data: newPost};
//console.log(error);
return {
success: false,
message: "Data was posted to ocme info",
data: [],
};
}
};

View File

@@ -0,0 +1,56 @@
import net from "net";
import { db } from "../../../../database/dbclient.js";
import { settings } from "../../../../database/schema/settings.js";
import { eq } from "drizzle-orm";
import { createLog } from "../../logger/logger.js";
export const triggerScanner = async () => {
const camera = new net.Socket();
let setting = await db
.select()
.from(settings)
.where(eq(settings.name, "zebraScanners"));
if (setting.length === 0) {
return {
success: false,
message: "Looks like the setting is missing.",
};
}
const scannerData = JSON.parse(setting[0]?.value);
let data = scannerData.filter((n: any) => n.name === "wrapper1");
if (data.length === 0) {
return {
success: false,
message: "Looks like the scanner is missing.",
};
}
let port = data[0]?.port;
createLog(
"info",
"wrapperScanner",
"ocme",
`End of line Camera was triggered`
);
return new Promise((resolve, reject) => {
camera.connect(port, data[0].ip, async () => {
createLog("info", "wrapperScanner", "ocme", `Triggered`);
camera.write("TRIGGER", "utf8");
camera.end();
resolve({ success: true, message: "Camera was triggered." });
});
camera.on("error", (error) => {
createLog("error", "wrapperScanner", "ocme", `${error}`);
resolve({
success: false,
message: `There was an error triggering the camera: ${JSON.stringify(
error
)}`,
});
});
resolve({ success: true, message: "Camera was triggered." });
});
};

View File

@@ -1,4 +1,4 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import { OpenAPIHono } from "@hono/zod-openapi";
// routes
import getInfo from "./route/getInfo.js";
@@ -7,35 +7,52 @@ import pickedup from "./route/pickedUp.js";
import postsscc from "./route/postSSCC.js";
import getShipments from "./route/getShipmentPallets.js";
import cycleCount from "./route/cycleCount.js";
import {serve} from "@hono/node-server";
import {createLog} from "../logger/logger.js";
import {db} from "../../../database/dbclient.js";
import {settings} from "../../../database/schema/settings.js";
import { serve } from "@hono/node-server";
import { createLog } from "../logger/logger.js";
import { db } from "../../../database/dbclient.js";
import { settings } from "../../../database/schema/settings.js";
import manualTrigger from "./route/triggerCamera.js";
const app = new OpenAPIHono();
const port = process.env.OCME_PORT;
const routes = [getInfo, postRunningNr, postsscc, pickedup, getShipments, cycleCount] as const;
const routes = [
getInfo,
postRunningNr,
postsscc,
pickedup,
getShipments,
cycleCount,
manualTrigger,
] as const;
const setting = await db.select().from(settings);
const isActive = setting.filter((n) => n.name === "ocmeService");
const appRoutes = routes.forEach((route) => {
app.route("/api/v1", route);
app.route("/api/v1", route);
});
app.all("/api/v1/*", (c) => {
return c.json({success: false, message: "you have encounted an ocme route that dose not exist."});
return c.json({
success: false,
message: "you have encounted an ocme route that dose not exist.",
});
});
if (port && isActive[0]?.value === "1") {
serve(
{
fetch: app.fetch,
port: Number(port),
hostname: "0.0.0.0",
},
(info) => {
createLog("info", "LST", "server", `Ocme section is listening on http://${info.address}:${info.port}`);
}
);
serve(
{
fetch: app.fetch,
port: Number(port),
hostname: "0.0.0.0",
},
(info) => {
createLog(
"info",
"LST",
"server",
`Ocme section is listening on http://${info.address}:${info.port}`
);
}
);
}
export default app;

View File

@@ -1,60 +1,71 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import {apiHit} from "../../../globalUtils/apiHits.js";
import {responses} from "../../../globalUtils/routeDefs/responses.js";
import {authMiddleware} from "../../auth/middleware/authMiddleware.js";
import {cycleCount} from "../controller/cycleCount.js";
import type {User} from "../../../types/users.js";
import {verify} from "hono/jwt";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
import { cycleCount } from "../controller/cycleCount.js";
import type { User } from "../../../types/users.js";
import { verify } from "hono/jwt";
const app = new OpenAPIHono({strict: false});
const app = new OpenAPIHono({ strict: false });
const AddSetting = z.object({
lane: z.string().openapi({example: "L064"}),
lane: z.string().openapi({ example: "L064" }),
});
app.openapi(
createRoute({
tags: ["ocme"],
summary: "Cycle counts a lane based on the lane Alias",
method: "post",
path: "/cyclecount",
middleware: authMiddleware,
request: {
body: {
content: {
"application/json": {schema: AddSetting},
},
},
createRoute({
tags: ["ocme"],
summary: "Cycle counts a lane based on the lane Alias",
method: "post",
path: "/cycleCount",
middleware: authMiddleware,
request: {
body: {
content: {
"application/json": { schema: AddSetting },
},
responses: responses(),
}),
async (c) => {
apiHit(c, {endpoint: "api/auth/register"});
// make sure we have a vaid user being accessed thats really logged in
const body = await c.req.json();
},
},
responses: responses(),
}),
async (c) => {
apiHit(c, { endpoint: "api/auth/register" });
// make sure we have a vaid user being accessed thats really logged in
const body = await c.req.json();
const authHeader = c.req.header("Authorization");
const authHeader = c.req.header("Authorization");
const token = authHeader?.split("Bearer ")[1] || "";
let user: User;
const token = authHeader?.split("Bearer ")[1] || "";
let user: User;
try {
const payload = await verify(token, process.env.JWT_SECRET!);
user = payload.user as User;
} catch (error) {
return c.json({message: "Unauthorized"}, 401);
}
try {
const cycleData = await cycleCount(body, user);
return c.json({success: true, message: `${body.lane} was just cycle counted.`, data: cycleData}, 200);
} catch (error) {
return c.json(
{success: false, message: `There was an error cycle counting ${body.lane}`, data: error},
400
);
}
try {
const payload = await verify(token, process.env.JWT_SECRET!);
user = payload.user as User;
} catch (error) {
return c.json({ message: "Unauthorized" }, 401);
}
try {
const cycleData = await cycleCount(body, user);
return c.json(
{
success: true,
message: `${body.lane} was just cycle counted.`,
data: cycleData,
},
200
);
} catch (error) {
return c.json(
{
success: false,
message: `There was an error cycle counting ${body.lane}`,
data: error,
},
400
);
}
}
);
export default app;

View File

@@ -1,80 +1,36 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {getInfo} from "../controller/getInfo.js";
import {apiHit} from "../../../globalUtils/apiHits.js";
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { getInfo } from "../controller/getInfo.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
const app = new OpenAPIHono({strict: false});
const AddSetting = z.object({
name: z.string().openapi({example: "server"}),
value: z.string().openapi({example: "localhost"}),
description: z.string().openapi({example: "The server we are going to connect to"}),
roles: z.string().openapi({example: "admin"}),
module: z.string().openapi({example: "production"}),
});
const app = new OpenAPIHono({ strict: false });
app.openapi(
createRoute({
tags: ["ocme"],
summary: "Get all current info",
method: "get",
path: "/getinfo",
request: {
body: {
content: {
"application/json": {schema: AddSetting},
},
},
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
data: z.array(z.object({})).optional().openapi({example: []}),
}),
},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: false}),
message: z.string().optional().openapi({example: "Internal Server error"}),
data: z.array(z.object({})).optional().openapi({example: []}),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
// 500: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
// },
// },
// description: "Internal Server Error",
// },
},
path: "/getInfo",
responses: responses(),
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
apiHit(c, {endpoint: "api/auth/register"});
apiHit(c, { endpoint: "api/auth/register" });
try {
return c.json({success: true, message: "Ocme Info", data: await getInfo()}, 200);
return c.json(
{ success: true, message: "Ocme Info", data: await getInfo() },
200
);
} catch (error) {
return c.json({success: false, message: "There was an error getting ocmeInfo data", data: error}, 400);
return c.json(
{
success: false,
message: "There was an error getting ocmeInfo data",
data: error,
},
400
);
}
}
);

View File

@@ -1,94 +1,114 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {apiHit} from "../../../globalUtils/apiHits.js";
import {getShipmentPallets} from "../controller/getShipmentPallets.js";
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { getShipmentPallets } from "../controller/getShipmentPallets.js";
const app = new OpenAPIHono();
const ShipmentID = z.object({
shipmentID: z.string().optional().openapi({example: "14558"}),
shipmentID: z.string().optional().openapi({ example: "14558" }),
});
app.openapi(
createRoute({
tags: ["ocme"],
summary: "Post New running number to be picked up.",
method: "post",
path: "/getshipmentpallets",
request: {
body: {
content: {
"application/json": {schema: ShipmentID},
},
},
createRoute({
tags: ["ocme"],
summary: "Post New running number to be picked up.",
method: "post",
path: "/GetShipmentPallets",
request: {
body: {
content: {
"application/json": { schema: ShipmentID },
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
// data: z
// .array(z.object({sscc: z.string().optional()}))
// .optional()
// .openapi({example: []}),
}),
},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: false}),
message: z.string().optional().openapi({example: "Internal Server error"}),
data: z.array(z.object({})).optional().openapi({example: []}),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
// 500: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
// },
// },
// description: "Internal Server Error",
// },
},
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({ example: true }),
message: z.string().openapi({ example: "Starter" }),
// data: z
// .array(z.object({sscc: z.string().optional()}))
// .optional()
// .openapi({example: []}),
}),
},
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
try {
const data = await c.req.json();
apiHit(c, {endpoint: "api/ocme/getshipmentpallets", lastBody: data});
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({ example: false }),
message: z
.string()
.optional()
.openapi({ example: "Internal Server error" }),
data: z.array(z.object({})).optional().openapi({ example: [] }),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
// 500: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
// },
// },
// description: "Internal Server Error",
// },
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
try {
const data = await c.req.json();
apiHit(c, { endpoint: "api/ocme/getshipmentpallets", lastBody: data });
if (!data.shipmentID) {
return c.json(
{success: false, message: "You are missing the shipment id please try again.", data: []},
400
);
}
console.log;
const shiptmentData = await getShipmentPallets(data.shipmentID);
if (!data.shipmentID) {
return c.json(
{
success: false,
message: "You are missing the shipment id please try again.",
data: [],
},
400
);
}
return c.json(
{success: shiptmentData.success, message: shiptmentData.message, data: shiptmentData.data ?? []},
200
);
} catch (error) {
return c.json({success: false, message: "There was an error getting the shipment data.", data: error}, 400);
}
const shiptmentData = await getShipmentPallets(data.shipmentID);
return c.json(
{
success: shiptmentData.success,
message: shiptmentData.message,
data: shiptmentData.data ?? [],
},
200
);
} catch (error) {
return c.json(
{
success: false,
message: "There was an error getting the shipment data.",
data: error,
},
400
);
}
}
);
export default app;

View File

@@ -1,89 +1,114 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {postLabelData} from "../controller/postRunningNr.js";
import {apiHit} from "../../../globalUtils/apiHits.js";
import {pickedup} from "../controller/pickedup.js";
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { postLabelData } from "../controller/postRunningNr.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { pickedup } from "../controller/pickedup.js";
const app = new OpenAPIHono();
const PostRunningNr = z.object({
sscc: z.string().optional().openapi({example: "00090103830005710997"}),
runningNr: z.string().optional().openapi({example: "localhost"}),
areaFrom: z.string().optional().openapi({example: "The server we are going to connect to"}),
completed: z.boolean().optional().openapi({example: true}),
all: z.boolean().optional().openapi({example: false}),
sscc: z.string().optional().openapi({ example: "00090103830005710997" }),
runningNr: z.string().optional().openapi({ example: "localhost" }),
areaFrom: z
.string()
.optional()
.openapi({ example: "The server we are going to connect to" }),
completed: z.boolean().optional().openapi({ example: true }),
all: z.boolean().optional().openapi({ example: false }),
});
app.openapi(
createRoute({
tags: ["ocme"],
summary: "Picks up a pallet in the system.",
method: "patch",
description:
"removes the pallet(s) from showing as needed to be picked up, we clear everything related to the pallet number to reduce the risk of a mix, passing `all` will just clear everything that is pending.",
path: "/pickedup",
request: {
body: {
content: {
"application/json": {schema: PostRunningNr},
},
},
createRoute({
tags: ["ocme"],
summary: "Picks up a pallet in the system.",
method: "patch",
description:
"removes the pallet(s) from showing as needed to be picked up, we clear everything related to the pallet number to reduce the risk of a mix, passing `all` will just clear everything that is pending.",
path: "/pickedUp",
request: {
body: {
content: {
"application/json": { schema: PostRunningNr },
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
// data: z
// .array(z.object({sscc: z.string().optional()}))
// .optional()
// .openapi({example: []}),
}),
},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: false}),
message: z.string().optional().openapi({example: "Internal Server error"}),
data: z.array(z.object({})).optional().openapi({example: []}),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
500: {
content: {
"application/json": {
schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
},
},
description: "Internal Server Error",
},
},
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({ example: true }),
message: z.string().openapi({ example: "Starter" }),
// data: z
// .array(z.object({sscc: z.string().optional()}))
// .optional()
// .openapi({example: []}),
}),
},
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
try {
const data = await c.req.json();
apiHit(c, {endpoint: "api/ocme/pickedup", lastBody: data});
const postPallet = await pickedup(data);
return c.json({success: postPallet.success, message: postPallet.message, data: postPallet.data}, 200);
} catch (error) {
return c.json({success: false, message: "There was an error getting ocmeInfo data", data: error}, 400);
}
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({ example: false }),
message: z
.string()
.optional()
.openapi({ example: "Internal Server error" }),
data: z.array(z.object({})).optional().openapi({ example: [] }),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
500: {
content: {
"application/json": {
schema: z.object({
message: z
.string()
.optional()
.openapi({ example: "Internal Server error" }),
}),
},
},
description: "Internal Server Error",
},
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
try {
const data = await c.req.json();
apiHit(c, { endpoint: "api/ocme/pickedup", lastBody: data });
const postPallet = await pickedup(data);
return c.json(
{
success: postPallet.success,
message: postPallet.message,
data: postPallet.data,
},
200
);
} catch (error) {
return c.json(
{
success: false,
message: "There was an error getting ocmeInfo data",
data: error,
},
400
);
}
}
);
export default app;

View File

@@ -1,86 +1,106 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {getInfo} from "../controller/getInfo.js";
import {postLabelData} from "../controller/postRunningNr.js";
import {apiHit} from "../../../globalUtils/apiHits.js";
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { getInfo } from "../controller/getInfo.js";
import { postLabelData } from "../controller/postRunningNr.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
const app = new OpenAPIHono();
const PostRunningNr = z.object({
sscc: z.string().optional().openapi({example: "00090103830005710997"}),
runningNr: z.string().optional().openapi({example: "localhost"}),
areaFrom: z.string().optional().openapi({example: "The server we are going to connect to"}),
completed: z.boolean().optional().openapi({example: true}),
sscc: z.string().optional().openapi({ example: "00090103830005710997" }),
runningNr: z.string().optional().openapi({ example: "localhost" }),
areaFrom: z
.string()
.optional()
.openapi({ example: "The server we are going to connect to" }),
completed: z.boolean().optional().openapi({ example: true }),
});
app.openapi(
createRoute({
tags: ["ocme"],
summary: "Post New running number to be picked up.",
method: "post",
path: "/postrunningnumber",
request: {
body: {
content: {
"application/json": {schema: PostRunningNr},
},
},
createRoute({
tags: ["ocme"],
summary: "Post New running number to be picked up.",
method: "post",
path: "/postRunningNumber",
request: {
body: {
content: {
"application/json": { schema: PostRunningNr },
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
// data: z
// .array(z.object({sscc: z.string().optional()}))
// .optional()
// .openapi({example: []}),
}),
},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: false}),
message: z.string().optional().openapi({example: "Internal Server error"}),
data: z.array(z.object({})).optional().openapi({example: []}),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
// 500: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
// },
// },
// description: "Internal Server Error",
// },
},
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({ example: true }),
message: z.string().openapi({ example: "Starter" }),
// data: z
// .array(z.object({sscc: z.string().optional()}))
// .optional()
// .openapi({example: []}),
}),
},
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
try {
const data = await c.req.json();
apiHit(c, {endpoint: "api/ocme/postRunningNumber", lastBody: data});
const postPallet = await postLabelData(data);
return c.json({success: postPallet.success, message: postPallet.message, data: postPallet.data ?? []}, 200);
} catch (error) {
return c.json({success: false, message: "There was an error getting ocmeInfo data", data: error}, 400);
}
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({ example: false }),
message: z
.string()
.optional()
.openapi({ example: "Internal Server error" }),
data: z.array(z.object({})).optional().openapi({ example: [] }),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
// 500: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
// },
// },
// description: "Internal Server Error",
// },
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
try {
const data = await c.req.json();
apiHit(c, { endpoint: "api/ocme/postRunningNumber", lastBody: data });
const postPallet = await postLabelData(data);
return c.json(
{
success: postPallet.success,
message: postPallet.message,
data: postPallet.data ?? [],
},
200
);
} catch (error) {
return c.json(
{
success: false,
message: "There was an error getting ocmeInfo data",
data: error,
},
400
);
}
}
);
export default app;

View File

@@ -1,86 +1,106 @@
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {getInfo} from "../controller/getInfo.js";
import {postLabelData} from "../controller/postRunningNr.js";
import {apiHit} from "../../../globalUtils/apiHits.js";
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { getInfo } from "../controller/getInfo.js";
import { postLabelData } from "../controller/postRunningNr.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
const app = new OpenAPIHono();
const PostRunningNr = z.object({
sscc: z.string().optional().openapi({example: "00090103830005710997"}),
runningNr: z.string().optional().openapi({example: "localhost"}),
areaFrom: z.string().optional().openapi({example: "The server we are going to connect to"}),
completed: z.boolean().optional().openapi({example: true}),
sscc: z.string().optional().openapi({ example: "00090103830005710997" }),
runningNr: z.string().optional().openapi({ example: "localhost" }),
areaFrom: z
.string()
.optional()
.openapi({ example: "The server we are going to connect to" }),
completed: z.boolean().optional().openapi({ example: true }),
});
app.openapi(
createRoute({
tags: ["ocme"],
summary: "Post New running number to be picked up.",
method: "post",
path: "/postsscc",
request: {
body: {
content: {
"application/json": {schema: PostRunningNr},
},
},
createRoute({
tags: ["ocme"],
summary: "Post New running number to be picked up.",
method: "post",
path: "/postSSCC",
request: {
body: {
content: {
"application/json": { schema: PostRunningNr },
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: true}),
message: z.string().openapi({example: "Starter"}),
// data: z
// .array(z.object({sscc: z.string().optional()}))
// .optional()
// .openapi({example: []}),
}),
},
},
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({example: false}),
message: z.string().optional().openapi({example: "Internal Server error"}),
data: z.array(z.object({})).optional().openapi({example: []}),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
// 500: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
// },
// },
// description: "Internal Server Error",
// },
},
},
responses: {
200: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({ example: true }),
message: z.string().openapi({ example: "Starter" }),
// data: z
// .array(z.object({sscc: z.string().optional()}))
// .optional()
// .openapi({example: []}),
}),
},
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
try {
const data = await c.req.json();
apiHit(c, {endpoint: "api/ocme/postRunningNumber", lastBody: data});
const postPallet = await postLabelData(data);
return c.json({success: postPallet.success, message: postPallet.message, data: postPallet.data ?? []}, 200);
} catch (error) {
return c.json({success: false, message: "There was an error getting ocmeInfo data", data: error}, 400);
}
description: "Response message",
},
400: {
content: {
"application/json": {
schema: z.object({
success: z.boolean().openapi({ example: false }),
message: z
.string()
.optional()
.openapi({ example: "Internal Server error" }),
data: z.array(z.object({})).optional().openapi({ example: [] }),
}),
},
},
description: "Internal Server Error",
},
// 401: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Unauthenticated"})}),
// },
// },
// description: "Unauthorized",
// },
// 500: {
// content: {
// "application/json": {
// schema: z.object({message: z.string().optional().openapi({example: "Internal Server error"})}),
// },
// },
// description: "Internal Server Error",
// },
},
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
try {
const data = await c.req.json();
apiHit(c, { endpoint: "api/ocme/postRunningNumber", lastBody: data });
const postPallet = await postLabelData(data);
return c.json(
{
success: postPallet.success,
message: postPallet.message,
data: postPallet.data ?? [],
},
200
);
} catch (error) {
return c.json(
{
success: false,
message: "There was an error getting ocmeInfo data",
data: error,
},
400
);
}
}
);
export default app;

View File

@@ -0,0 +1,28 @@
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { getInfo } from "../controller/getInfo.js";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import { triggerScanner } from "../controller/triggerCamera.js";
const app = new OpenAPIHono({ strict: false });
app.openapi(
createRoute({
tags: ["ocme"],
summary: "Triggers the camera at the end of the dyco.",
method: "get",
path: "/manualCameraTrigger",
responses: responses(),
}),
async (c) => {
// make sure we have a vaid user being accessed thats really logged in
apiHit(c, { endpoint: "api/auth/register" });
const manualTrigger: any = await triggerScanner();
console.log(manualTrigger);
return c.json({
success: manualTrigger.success,
message: manualTrigger.message,
});
}
);
export default app;

View File

@@ -0,0 +1,89 @@
import axios from "axios";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { lstAuth } from "../../../../index.js";
import { createLog } from "../../../logger/logger.js";
import { db } from "../../../../../database/dbclient.js";
import { prodlabels } from "../../../../../database/schema/prodLabels.js";
import { eq, sql } from "drizzle-orm";
export const bookInLabel = async (data: any) => {
// update sscc so we can book in
const SSCC = data.SSCC.slice(2);
// api url
const url = await prodEndpointCreation("public/v1.0/Warehousing/BookIn");
// create bookin
const newBookin = {
scannerId: 777,
sscc: SSCC,
};
try {
const res = await axios.post(url, newBookin, {
headers: {
Authorization: `Basic ${lstAuth}`,
accept: "text/plain",
},
});
if (res.data.Result !== 0) {
createLog(
"error",
"labeling",
"ocp",
`${data.printer.name}, Error:${res.data.Message}`
);
//printerUpdate(data.printer, 7, "Error while booking in.");
return {
success: false,
message: "There was an error booking in the label.",
data: res.data,
};
}
// update the label.
try {
await db
.update(prodlabels)
.set({
status: "Booked in",
upd_date: sql`NOW()`,
})
.where(
eq(prodlabels.runningNr, parseInt(data.SSCC.slice(10, -1)))
);
} catch (error) {
createLog(
"error",
"labeling",
"ocp",
`Error creating new runningNumber in the DB.`
);
}
// label was booked in
createLog(
"info",
"labeling",
"ocp",
`${parseInt(data.SSCC.slice(10, -1))}, was just booked in`
);
return {
success: true,
message: `${parseInt(data.SSCC.slice(10, -1))}, was just booked in`,
};
} catch (error) {
createLog(
"error",
"labeling",
"ocp",
`${data.printer.name}, "Error: ${error}`
);
return {
success: false,
message: "There was an error booking in the label.",
data: error,
};
}
};

View File

@@ -0,0 +1,158 @@
import { eq, gte, sql } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js";
import { printers } from "../../../../../database/schema/printers.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { settings } from "../../../../../database/schema/settings.js";
import { lstAuth } from "../../../../index.js";
import axios from "axios";
import { prodlabels } from "../../../../../database/schema/prodLabels.js";
export const createLabel = async (data: any, userPrinted: any) => {
createLog("info", "labeling", "ocp", `Label being created`);
const { data: printer, error: printerError } = await tryCatch(
db
.select()
.from(printers)
.where(eq(printers.humanReadableId, data.printerID))
);
const { data: settingsData, error: settingsError } = await tryCatch(
db.select().from(settings)
);
if (printerError) {
return {
success: false,
message: "There was an error getting the printer.",
printerError,
};
}
if (settingsError) {
return {
success: false,
message: "There was an error getting the printer.",
settingsError,
};
}
const url = await prodEndpointCreation(
"/public/v1.0/Warehousing/GenerateAndPrintLabelExtended"
);
const plantToken = settingsData.filter((n) => n.name === "plantToken");
const newLabel = {
scannerId: 99,
lotNr: data.LOT,
machineId: data.machineID,
printerId: data.printerID,
//layoutId: cartonCustomers.includes(data.CustomerId.toString()) ? data.cartonLabel : data.palletLabel,
layoutId:
plantToken[0].value === "usksc1"
? data.cartonLabel
: data.palletLabel,
//numberOfCopies: cartonCustomers.includes(data.CustomerId.toString()) ? data.cartonCopies : data.pallerCopies,
numberOfCopies:
plantToken[0].value === "usksc1"
? data.cartonCopies
: data.pallerCopies,
};
// create the label
// create the label with the data we have
try {
const res = await axios.post(url, newLabel, {
headers: {
Authorization: `Basic ${lstAuth}`,
"Content-Type": "application/json",
},
});
// error handling
if (res.data.Result != 0) {
createLog(
"error",
"labeling",
"ocp",
`${data.MachineDescription}, has an error while printing: Error: ${res.data.Message}.`
);
return {
success: false,
mesasge: `${data.MachineDescription}, has an error while printing`,
data: res.data,
};
}
// save the data to lst db (only saved for x time see the db clean up functions)
let newlabel = res.data;
try {
await db.insert(prodlabels).values({
printerID: parseInt(printer[0]?.humanReadableId!, 10),
runningNr: parseInt(newlabel.SSCC.slice(10, -1)),
printerName: printer[0].name.toLowerCase(),
line: data.MachineLocation,
status: "printed",
add_user: userPrinted || "LST_System",
});
} catch (error) {
createLog(
"error",
"labeling",
"ocp",
`Error creating new runningNumber in the DB.`
);
}
createLog(
"info",
"labeling",
"ocp",
`New label was created for: ${
data.MachineDescription
}, Running number: ${parseInt(newlabel.SSCC.slice(10, -1))}`
);
const returnData = {
...newlabel,
printer,
};
// check if we can remove labels or not
deleteLabels();
return { sucess: true, message: "Label created", data: returnData }; // returning label data to be able to book in if active
} catch (error) {
createLog(
"info",
"labeling",
"ocp",
`${printer[0].name}, "Error: ${error}`
);
return {
success: false,
message: "There was an error creating the label",
data: error,
};
}
};
// run the label delete process we want to delate them older than 90 days right now
const deleteLabels = async () => {
/**
* Deletes labels older than 90 days from lst... all label data can be found in alpla prod.
*/
try {
await db
.delete(prodlabels)
.where(
gte(prodlabels.upd_date, sql.raw(`NOW() - INTERVAL '90 days'`))
);
} catch (error) {
createLog(
"error",
"labeling",
"ocp",
`Error deleting labels older than 90 days`
);
}
};

View File

@@ -0,0 +1,32 @@
import { desc, lte, sql } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js";
import { prodlabels } from "../../../../../database/schema/prodLabels.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
export const getLabels = async (hours: string) => {
const { data: labelInfo, error: labelError } = await tryCatch(
db
.select()
.from(prodlabels)
.where(
lte(
prodlabels.upd_date,
sql.raw(`NOW() - INTERVAL '${hours} hours'`)
)
)
.orderBy(desc(prodlabels.upd_date))
);
if (labelError) {
return {
success: false,
message: "There was an error getting the labels",
data: [labelError],
};
}
return {
success: true,
message: "Current labels order by upd_Date.",
data: labelInfo,
};
};

View File

@@ -0,0 +1,236 @@
import { eq } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js";
import { printers } from "../../../../../database/schema/printers.js";
import { settings } from "../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { getLots } from "../lots/lots.js";
import { getMac } from "../specialProcesses/utils/getMachineId.js";
import { billingCheck } from "../specialProcesses/billingCheck/billingCheck.js";
import { isMainMatStaged } from "../materials/mainMaterial.js";
import { firstLotLabel } from "../specialProcesses/lotChangeLabel/lotCHangeLabel.js";
import { prolinkCheck } from "../lots/prolinkCheck.js";
import { createLabel } from "./createLabel.js";
import { bookInLabel } from "./bookIn.js";
import { delieryInhouse } from "../specialProcesses/inhouse/inhouseDelivery.js";
interface Printer {
name: string;
// Add any other expected properties
}
export const labelingProcess = async ({
line = null as string | null,
printer = null as Printer | null,
userPrinted = null,
rfidTag = null,
} = {}) => {
/**
* Creates a label once all logic is passed
*/
let filteredLot: any = [];
createLog("debug", "labeling", "ocp", `Starting labeling process`);
const { data: settingData, error: settingError } = await tryCatch(
db.select().from(settings)
);
if (settingError) {
return {
success: false,
message: "There was an error getting the settings.",
settingError,
};
}
// get the plantToken
const plantToken = settingData.filter((n) => n.name === "plantToken");
// get the current lots
const lots = await getLots();
// if we got a line passed over we need to get the machine id from this.
if (line) {
const macId = await getMac(line);
// filter out the lot for the line
filteredLot = lots.data.filter((l: any) => l.machineId === macId);
if (filteredLot.length === 0) {
createLog(
"error",
"labeling",
"ocp",
`There is not a lot assigned to ${macId[0].Name}.`
);
return {
success: false,
message: `There is not a lot assigned to ${macId[0].Name}.`,
};
}
}
// if we came from a printer
if (printer) {
// filter the lot based on the printerID
// console.log(printer);
filteredLot = lots.data.filter((l: any) => l.printerID === printer);
if (filteredLot.length === 0) {
// console.log(`There is not a lot assigned to ${printer.name}`);
createLog(
"error",
"labeling",
"ocp",
`There is not a lot assigned to ${printer.name}`
);
//printerUpdate(printer, 7, `There is no lot assigned to this printer.`);
return {
success: false,
message: `There is not a lot assigned to ${printer.name}.`,
};
}
}
/**
*
* The checks we do before we can actually print a label will take place meow.
*
*/
// if the plant does not want to have dual printing and we have >2 assigned well return and send error.
let dualPrinting = settingData.filter((d) => d.name === "dualPrinting")[0]
?.value;
if (filteredLot.length > 1 && dualPrinting === "0") {
createLog(
"error",
"labeling",
"ocp",
`${printer?.name}, has more than one lot assigned to it, and dual printing shut off.`
);
return {
success: false,
message: `${printer?.name}, has more than one lot assigned to it, and dual printing shut off.`,
};
}
if (filteredLot.length > 1 && dualPrinting === "1") {
// send over for dual printing processing
createLog(
"info",
"labeling",
"ocp",
`${printer?.name}, being sent over for dual printing processing.`
);
// process what line to print the label for and return the lot info and change filteredLot to returned one.
//filteredLot = await dualPrintingProcess(filteredLot);
}
// if there are more than 2 lots it might be an auto labeler, autolabeler will be defined by its id for now only dayton
if (filteredLot.length > 2 && plantToken[0].value !== "usday1") {
createLog(
"error",
"labeling",
"ocp",
`${printer?.name}, has more than 2 lot assigned to it, and not in ${plantToken[0].value}`
);
return {
success: false,
message: `${printer?.name}, has more than 2 lot assigned to it, and not in ${plantToken[0].value}`,
};
}
// special process for florence
const isBillingTime = await billingCheck();
if (isBillingTime) {
// billing is inside the window we dont want to bill now.
return {
success: false,
message: "Billing time cant print.",
};
}
// check mm is good
const mmStaged = await isMainMatStaged(filteredLot[0]);
if (!mmStaged) {
createLog(
"error",
"labeling",
"ocp",
`Main material is not prepaired for lot ${filteredLot[0].lot}`
);
return;
}
// comment only but will check for color
createLog(
"info",
"labeling",
"ocp",
`Remaining pallets for: ${filteredLot[0].MachineDescription} is ${filteredLot[0].Remaining}`
);
// do we want to over run
if (filteredLot[0].overPrinting === "no" && filteredLot[0].Remaining <= 0) {
createLog(
"error",
"labeling",
"ocp",
`Over Printing on ${filteredLot[0].MachineDescription} is not allowed please change the lot`
);
// for slc we want to run the first label for henkel
firstLotLabel(filteredLot[0]);
return {
success: false,
message: `Over Printing on ${filteredLot[0].MachineDescription} is not allowed please change the lot`,
};
}
// prolink check by lot
const prolink = await prolinkCheck(filteredLot[0].lot);
if (!prolink) {
//console.error(`Prolink does not match for ${filteredLot[0].MachineDescription}`);
createLog(
"error",
"labeling",
"ocp",
`Prolink does not match for ${filteredLot[0].MachineDescription}`
);
return;
}
createLog("info", "labeling", "ocp", `Is prolink good? ${prolink}`);
// create the label
const label = await createLabel(filteredLot[0], userPrinted);
if (!label.success) {
return { sucess: false, message: label.message, data: label.data };
}
// send over to be booked in if we can do it.
const bookin = settingData.filter((s) => s.name === "bookin");
if (bookin[0].value === "1") {
const book = await bookInLabel(label.data);
} else {
createLog("info", "labeling", "ocp", "Bookin is turned off.");
// will add later!!! :P
}
// inhouse - if the inhouse funtion is turned on we will deliver to inhouse as long as we did not hit an error state
const inhouseDelivery = settingData.filter(
(s) => s.name === "inhouseDelivery"
);
if (inhouseDelivery[0].value === "1") {
const deliverPallet = await delieryInhouse(label);
}
return {
success: true,
message: "Label fully processed.",
data: label.data,
};
};

View File

@@ -0,0 +1,23 @@
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { lotQuery } from "../../../sqlServer/querys/ocp/lots.js";
export const getLots = async () => {
const { data: lotInfo, error: lotError } = await tryCatch(
query(lotQuery, "Alplalabel online lots")
);
if (lotError) {
return {
success: false,
message: "There was an error getting the lots",
data: lotError,
};
}
return {
success: true,
message: "Current active lots that are technically released.",
data: lotInfo,
};
};

View File

@@ -0,0 +1,68 @@
import { db } from "../../../../../database/dbclient.js";
import { settings } from "../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { prolinkQuery } from "../../../sqlServer/querys/ocp/prolinkCheck.js";
// check the if the lot matches
export const prolinkCheck = async (lot: any) => {
const { data, error: settingError } = await tryCatch(
db.select().from(settings)
);
if (settingError) {
createLog(
"error",
"ocp",
"ocp",
`There was an error getting the settings.`
);
return;
}
const settingData: any = data;
const plantToken = settingData.filter(
(s: any) => s.name === "plantToken"
)[0].value;
const prolinkCheck = settingData.filter(
(s: any) => s.name === "prolinkCheck"
)[0].value;
// if we want to ignore prolink check it will be disabled and then just return a pass as true
if (prolinkCheck === "0") {
createLog(
"info",
"ocp",
"ocp",
`Prolink Check is disabled skipping check.`
);
return true;
}
// run the query
try {
const prolink = await query(prolinkQuery, "Prolink Checks");
//console.log(lot);
// filter out the lot
const filterdLot = prolink.filter(
(p: any) => p.AlplaLabelOnline === lot
);
//console.log(filterdLot);
if (filterdLot[0].LotCheck === "Good") {
return true;
} else {
return false;
}
} catch (err) {
createLog(
"error",
"ocp",
"ocp",
`Error from running the Prolink Check query: ${err}`
);
return false;
}
};

View File

@@ -1,20 +1,44 @@
import {db} from "../../../../database/dbclient.js";
import {manualPrinting} from "../../../../database/schema/ocpManualPrint.js";
import { db } from "../../../../database/dbclient.js";
import { manualPrinting } from "../../../../database/schema/ocpManualPrint.js";
import { tryCatch } from "../../../globalUtils/tryCatch.js";
export const manualPrint = async (data: any) => {
export const manualPrint = async (manualPrint: any) => {
/**
* add the reason we did a manual print.
*/
const manualPrintData = {
line: data.line,
printReason: data.printReason,
initials: data.initials,
additionalComments: data?.additionalComments,
line: manualPrint.line,
printReason: manualPrint.printReason,
initials: manualPrint.initials,
additionalComments: manualPrint?.additionalComments,
add_user: "lst",
};
try {
const manualPrint = await db.insert(manualPrinting).values(manualPrintData);
} catch (error) {}
const { data, error } = await tryCatch(
db
.insert(manualPrinting)
.values(manualPrintData)
.returning({
line: manualPrinting.line,
printReason: manualPrinting.printReason,
initials: manualPrinting.initials,
additionalComments: manualPrinting?.additionalComments,
add_user: manualPrinting.add_user,
})
);
if (error) {
return {
success: false,
message: "There was an error posting the manualPrintData",
data: error,
};
}
return {
success: true,
message: "There was an error posting the manualPrintData",
data,
};
};

View File

@@ -0,0 +1,38 @@
import { createLog } from "../../../logger/logger.js";
import { query } from "../../../sqlServer/prodSqlServer.js";
import { mmQuery } from "../../../sqlServer/querys/ocp/mainMaterial.js";
export const isMainMatStaged = async (lot: any) => {
// make staged false by deefault and error logged if theres an issue
let isStaged = false;
// strangly the lot is not always sending over in slc so adding this in for now to see what line is cauing this issue
if (!lot) {
return isStaged;
}
const updateQuery = mmQuery.replaceAll("[lotNumber]", lot.lot);
try {
const res = await query(updateQuery, "Main Material Check");
createLog(
"info",
"mainMaterial",
"ocp",
`MainMaterial results: ${JSON.stringify(res)}`
);
if (res[0].Staged >= 1) {
isStaged = true;
}
} catch (err) {
createLog(
"error",
"mainMaterial",
"ocp",
`Error from running the Main Material query: ${err}`
);
}
return isStaged;
};

View File

@@ -0,0 +1,21 @@
import { db } from "../../../../../database/dbclient.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { printers } from "../../../../../database/schema/printers.js";
export const getPrinters = async () => {
const currentTime = new Date(Date.now());
const { data: printerData, error: printerError } = await tryCatch(
db.select().from(printers)
);
if (printerError) {
return {
success: false,
message: "there was an error getting the printers",
data: printerError,
};
}
return { success: true, message: "Printers", data: printerData };
};

View File

@@ -0,0 +1,84 @@
import { printers } from "../../../../../database/schema/printers.js";
import axios from "axios";
import { sql } from "drizzle-orm";
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { lstAuth } from "../../../../index.js";
import { db } from "../../../../../database/dbclient.js";
import { createLog } from "../../../logger/logger.js";
export const updatePrinters = async () => {
const currentTime = new Date(Date.now());
// get the printers from prod
let url = await prodEndpointCreation(
"/public/v1.0/Administration/Printers"
);
const { data: prodPrinters, error: prodError } = await tryCatch(
axios.get(url, {
headers: {
Authorization: `Basic ${lstAuth}`,
"Content-Type": "application/json",
},
})
);
if (prodError) {
console.log(prodError);
return {
success: false,
message: "there was an error getting the printers.",
data: prodError,
};
}
// do the printer update into our db
const prodPrinterInfo = prodPrinters.data;
for (let i = 0; i < prodPrinterInfo.length; i++) {
const printerStuff: any = {
humanReadableId: prodPrinterInfo[i].humanReadableId,
name: prodPrinterInfo[i].name,
ipAddress: prodPrinterInfo[i].ipAddress,
port: prodPrinterInfo[i].port,
remark: prodPrinterInfo[i].remark,
};
const { data, error } = await tryCatch(
db
.insert(printers)
.values(printerStuff)
.onConflictDoUpdate({
target: printers.humanReadableId,
set: {
//humanReadableId: prodPrinterInfo[i].humanReadableId,
name: prodPrinterInfo[i].name,
ipAddress: prodPrinterInfo[i].ipAddress,
port: prodPrinterInfo[i].port,
remark: prodPrinterInfo[i].remark,
upd_date: sql`NOW()`,
},
})
);
if (error) {
createLog(
"error",
"lst",
"ocp",
`${
prodPrinterInfo[i].name
} encoutered and error adding/updating ${JSON.stringify(error)}`
);
}
createLog(
"debug",
"lst",
"ocp",
`${prodPrinterInfo[i].name} were just added/updated.`
);
}
return { success: true, message: "Printers were just added or updated." };
};

View File

@@ -0,0 +1,54 @@
import { eq } from "drizzle-orm";
import { db } from "../../../../../../database/dbclient.js";
import { settings } from "../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../../logger/logger.js";
const st = 5;
const sm = 55;
const et = 6;
const em = 5;
export const billingCheck = async () => {
const now = new Date();
const startTime = new Date();
const endTime = new Date();
let isOutsideBilling = false;
const { data, error } = await tryCatch(db.select().from(settings));
if (error) {
return { success: false, message: "Error in getting settings." };
}
const plant = data.filter((n) => n.name === "plantToken");
// set everything up
startTime.setHours(st, sm, 0, 0);
endTime.setHours(et, em, 0, 0);
if (plant[0].value === "usflo1") {
if (now >= startTime && now <= endTime) {
createLog(
"warn",
"specialProcess",
"ocp",
`You are inside the billing window no labels will print! please wait`
);
isOutsideBilling = true;
} else {
createLog(
"info",
"specialProcess",
"ocp",
"Out side billing window ok to print"
);
}
} else {
createLog(
"debug",
"specialProcess",
"ocp",
"This plant dose not check for billing"
);
}
return isOutsideBilling;
};

View File

@@ -0,0 +1,76 @@
import { Controller, Tag } from "st-ethernet-ip";
import { createLog } from "../../../../logger/logger.js";
import { labelerTagRead } from "./plcTags/labelerTag.js";
import { palletSendTag } from "./plcTags/palletSendTag.js";
let PLC = new Controller();
let isDycoRunning = false;
// PLC address
let plcAddress = "10.44.5.4";
// Initialize the interval variable outside the function
let plcCycle: any;
let plcInterval = 500;
// Create Tag Instances
const labelerTag: any = new Tag("labeler.line_info");
const palletSend = new Tag("Zone_6.Ready_to_Send");
const strapperError = new Tag("Zone_3.Strapper_Faulted");
export const dycoConnect = async () => {
// if we crash or start over reset the timers so we dont get duplicates
clearInterval(plcCycle);
if (isDycoRunning)
return { success: false, message: "Dyco is already connected." };
// Remove all listeners before adding a new one to prevent memory leaks
PLC.removeAllListeners("error");
try {
await PLC.connect(plcAddress, 0).then(async () => {
createLog("info", "dyco", "ocp", `We are connected to the dyco.`);
isDycoRunning = true;
let buffer = "";
plcCycle = setInterval(async () => {
await PLC.readTag(labelerTag);
await PLC.readTag(palletSend);
// send the labeler tag data over
labelerTagRead(labelerTag);
// send the end of line check over.
palletSendTag(palletSend);
}, 500);
});
} catch (error) {
createLog(
"error",
"dyco",
"ocp",
`There was an error in the dyco: ${error}`
);
isDycoRunning = false;
}
};
export const closeDyco = async () => {
if (!isDycoRunning)
return { success: false, message: "Dyco is not connected." };
console.log(`Closing the connection`);
try {
await PLC.disconnect();
isDycoRunning = false;
return {
success: true,
message: "Dyco Connection is now closed.",
};
} catch (error) {
console.log(error);
return {
success: false,
message: "There was an error closing the dyco connection.",
};
}
};

View File

@@ -0,0 +1,66 @@
import { db } from "../../../../../../../database/dbclient.js";
import { settings } from "../../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../../../logger/logger.js";
import { readTags } from "../../../../../rfid/controller/readTags.js";
import { labelingProcess } from "../../../labeling/labelProcess.js";
let lastProcessedTimestamp = 0;
export const labelerTagRead = async (tagData: any) => {
/**
* Reads the tag data from the Dyco PLC and processes it based on the feedback.
*/
// Convert tag data buffer to a string and extract numeric values
const buffer = Buffer.from(tagData.value);
const numericString = buffer.toString("utf8").replace(/[^0-9#]/g, "");
// Ignore empty or invalid tag data
if (numericString === "#") {
return;
}
const tagTime = new Date(tagData.state.timestamp).getTime();
// get the settings
const { data: settingData, error: settingError } = await tryCatch(
db.select().from(settings)
);
if (settingError) {
createLog(
"error",
"dyco",
"ocp",
"There was an error getting the settings"
);
return;
}
// check the dyco settings
const dycoPrint = settingData.filter((n) => n.name === "dycoPrint");
// Only process if this is a new timestamp within the last 5 seconds
if (tagTime !== lastProcessedTimestamp && Date.now() - tagTime <= 5000) {
lastProcessedTimestamp = tagTime;
//console.log(numericString, tagData.state.timestamp);
if (dycoPrint[0].value === "1") {
createLog("info", "dyco", "ocp", "Dyco will be printing the label");
// send over to print.
labelingProcess({ line: numericString });
}
if (dycoPrint[0].value === "0") {
createLog(
"info",
"dyco",
"ocp",
"Rfid system is contorlling the printing"
);
// trigger the reader so we can get the label from the tag readers.
await readTags("wrapper1");
}
}
};
/**
* setting to switch between rfid and dyco labeling
*/

View File

@@ -0,0 +1,54 @@
import { createLog } from "../../../../../logger/logger.js";
import { pickedup } from "../../../../../ocme/controller/pickedup.js";
import { triggerScanner } from "../../../../../ocme/controller/triggerCamera.js";
let lastProcessedTimestamp = 0;
export const palletSendTag = async (tagData: any) => {
/**
* Reads the tag data from the Dyco PLC and processes it based on the feedback.
* We will only trigger the camera and removal of pending tags
*/
const tagTime = new Date(tagData.state.timestamp).getTime();
// Only process if this is a new timestamp within the last 5 seconds
if (
tagTime !== lastProcessedTimestamp &&
Date.now() - tagTime <= 5000 &&
tagData.value
) {
lastProcessedTimestamp = tagTime;
//console.log(tagData.state.timestamp);
createLog(
"info",
"dyco",
"ocp",
`Station 6 is ${tagData.value ? "full" : "empty"}`
);
// take the picture
setTimeout(async () => {
const scan: any = await triggerScanner();
if (!scan.success) {
createLog(
"error",
"dyco",
"ocp",
`Scanner failed to take a picture trying one more time in 10 seconds`
);
setTimeout(async () => {
await triggerScanner();
}, 10 * 1000);
}
}, 15 * 1000);
}
if (
tagTime !== lastProcessedTimestamp &&
Date.now() - tagTime <= 5000 &&
!tagData.value
) {
await pickedup({ runningNr: 1234, all: true });
}
};

View File

@@ -0,0 +1,91 @@
import axios from "axios";
import { prodEndpointCreation } from "../../../../../globalUtils/createUrl.js";
import { lstAuth } from "../../../../../index.js";
import { createLog } from "../../../../logger/logger.js";
import { db } from "../../../../../../database/dbclient.js";
import { prodlabels } from "../../../../../../database/schema/prodLabels.js";
import { eq, sql } from "drizzle-orm";
export const delieryInhouse = async (data: any) => {
// update sscc so we can book in
const SSCC = data.SSCC.slice(2);
// api url
const url = await prodEndpointCreation(
"/public/v1.0/Warehousing/InhouseDelivery"
);
// create bookin
const newDelivery = {
scannerId: 99,
sscc: SSCC,
};
try {
const res = await axios.post(url, newDelivery, {
headers: {
Authorization: `Basic ${lstAuth}`,
accept: "text/plain",
},
});
if (res.data.Result !== 0) {
createLog(
"error",
"labeling",
"ocp",
`${data.printer.name}, Error:${res.data.Message}`
);
//printerUpdate(data.printer, 7, "Error while deliverying inhouse.");
return {
success: true,
message: `${data.printer.name} had an error while trying to deliver.`,
data: res.data,
};
} // label was just delivered
createLog(
"info",
"labeling",
"ocp",
`${parseInt(data.SSCC.slice(10, -1))}, was just delivered`
);
try {
await db
.update(prodlabels)
.set({
status: "Delivered",
upd_date: sql`NOW()`,
})
.where(
eq(prodlabels.runningNr, parseInt(data.SSCC.slice(10, -1)))
);
} catch (error) {
createLog(
"error",
"labeling",
"ocp",
`Error updating ${parseInt(data.SSCC.slice(10, -1))} in the DB.`
);
return {
success: true,
message: `Error updating ${parseInt(
data.SSCC.slice(10, -1)
)} in the DB.`,
data: error,
};
}
} catch (error) {
createLog(
"error",
"labeling",
"ocp",
`${data.printer.name}, "Error: ${error}`
);
return {
success: true,
message: `Error deliverying ${parseInt(data.SSCC.slice(10, -1))}.`,
data: error,
};
}
};

View File

@@ -0,0 +1,72 @@
import { db } from "../../../../../../database/dbclient.js";
import { settings } from "../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../../logger/logger.js";
import { query } from "../../../../sqlServer/prodSqlServer.js";
export const firstLotLabel = async (lot: any) => {
/*
currently this is only requested by slc
when a lot is finished and not set to over run we will trigger this function to insert data into the custom T_firstLotLabel table.
in nice label we look for unique id to run the process and then if the add date is older than 7 days we delete it for tracablility purpose.
we will also only do this for specific customers currently henkel is the requested.
*/
/* work on the server side
new table created in the _cus db
CREATE TABLE T_firstLotLabel
(
ID INT IDENTITY(1,1) PRIMARY KEY,
printerName varchar(max),
add_date datetime
-- Add other columns here as needed
);
the nicelabel trigger to be activated.
*/
const { data: settingData, error: settingError } = await tryCatch(
db.select().from(settings)
);
if (settingError) {
return {
success: false,
message: "There was an error getting the settings.",
settingError,
};
}
// get the plantToken
const plantToken = settingData.filter((n) => n.name === "plantToken");
createLog(
"info",
"ocp",
"ocp",
`Checking if we can create the first label lot.`
);
if (plantToken[0].value === "usslc1") {
const newLabel = `insert into T_firstLotLabel (printerName, add_date) VALUES('${lot.PrinterName}', getdate())`;
// if (lot.CustomerId === 40) {
createLog(
"info",
"ocp",
"ocp",
`Creating first lot label for ${lot.MachineDescription}`
);
await query(newLabel, "newLotLabel");
createLog(
"info",
"ocp",
"ocp",
`Was created for ${lot.MachineDescription}`
);
//}
} else {
return;
}
};

View File

@@ -0,0 +1,27 @@
import { db } from "../../../../../../database/dbclient.js";
import { settings } from "../../../../../../database/schema/settings.js";
import { tryCatch } from "../../../../../globalUtils/tryCatch.js";
import { createLog } from "../../../../logger/logger.js";
import { query } from "../../../../sqlServer/prodSqlServer.js";
import { machineCheck } from "../../../../sqlServer/querys/ocp/machineId.js";
export const getMac = async (machine: string) => {
let updateQuery = machineCheck.replaceAll("[loc]", machine);
// create blank lots in case there is an error and dose not work
let mac = [];
try {
mac = await query(updateQuery, "Machine id check");
// console.log("Machine data", mac); // removed due to swr being activated
} catch (err) {
createLog(
"error",
"lst",
"ocp",
`Error with Machine id Check query: ${err}`
);
}
return mac;
};

View File

@@ -1,14 +1,33 @@
import {OpenAPIHono} from "@hono/zod-openapi";
import { OpenAPIHono } from "@hono/zod-openapi";
// routes
import manualLabelLog from "./routes/manualPrintLog.js";
import {db} from "../../../database/dbclient.js";
import {settings} from "../../../database/schema/settings.js";
import getPrinters from "./routes/printers/getPritners.js";
import { db } from "../../../database/dbclient.js";
import { settings } from "../../../database/schema/settings.js";
import updateprinters from "./routes/printers/updatePrinters.js";
import { updatePrinters } from "./controller/printers/updatePrinters.js";
import getLots from "./routes/lots/getLots.js";
import getLabels from "./routes/labeling/getLabels.js";
import { dycoConnect } from "./controller/specialProcesses/dyco/plcConnection.js";
import dycoCon from "./routes/specialProcesses/dyco/connection.js";
import dycoClose from "./routes/specialProcesses/dyco/closeConnection.js";
const app = new OpenAPIHono();
const routes = [manualLabelLog] as const;
const routes = [
manualLabelLog,
//printer
getPrinters,
updateprinters,
// lots
getLots,
// labeling
getLabels,
//dyco
dycoCon,
dycoClose,
] as const;
const setting = await db.select().from(settings);
const appRoutes = routes.forEach((route) => {
@@ -16,7 +35,20 @@ const appRoutes = routes.forEach((route) => {
});
app.all("/ocp/*", (c) => {
return c.json({success: false, message: "You have encounters a ocp route that dose not exist."});
return c.json({
success: false,
message: "You have encounters a ocp route that dose not exist.",
});
});
// run the printer update on restart just to keep everything good
setTimeout(() => {
updatePrinters();
}, 3 * 1000);
// do the intnal connection to the dyco
setTimeout(() => {
dycoConnect();
}, 3 * 1000);
export default app;

View File

@@ -0,0 +1,37 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { getLabels } from "../../controller/labeling/getLabels.js";
const app = new OpenAPIHono({ strict: false });
app.openapi(
createRoute({
tags: ["ocp"],
summary: "Returns current active lots that are tech released",
method: "get",
path: "/getlabels",
responses: responses(),
}),
async (c) => {
const hours = c.req.query("hours");
const { data: labelData, error: labelError } = await tryCatch(
getLabels(hours ?? "2")
);
if (labelError) {
return c.json({
success: false,
message: "There was an error getting the printers",
});
}
return c.json({
success: labelData.success,
message: labelData.message,
data: labelData.data,
});
}
);
export default app;

View File

@@ -0,0 +1,35 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { getPrinters } from "../../controller/printers/getPrinters.js";
import { getLots } from "../../controller/lots/lots.js";
const app = new OpenAPIHono({ strict: false });
app.openapi(
createRoute({
tags: ["ocp"],
summary: "Returns current active lots that are tech released",
method: "get",
path: "/getlots",
responses: responses(),
}),
async (c) => {
const { data: lotData, error: lotError } = await tryCatch(getLots());
if (lotError) {
return c.json({
success: false,
message: "There was an error getting the printers",
});
}
return c.json({
success: lotData.success,
message: lotData.message,
data: lotData.data,
});
}
);
export default app;

View File

@@ -1,18 +1,21 @@
// an external way to creating logs
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
import {apiHit} from "../../../globalUtils/apiHits.js";
import {responses} from "../../../globalUtils/routeDefs/responses.js";
import type {User} from "../../../types/users.js";
import {verify} from "hono/jwt";
import {manualPrint} from "../controller/manualLabelLog.js";
import {authMiddleware} from "../../auth/middleware/authMiddleware.js";
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { apiHit } from "../../../globalUtils/apiHits.js";
import { responses } from "../../../globalUtils/routeDefs/responses.js";
import type { User } from "../../../types/users.js";
import { verify } from "hono/jwt";
import { manualPrint } from "../controller/manualLabelLog.js";
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
const app = new OpenAPIHono({strict: false});
const app = new OpenAPIHono({ strict: false });
const CreateLog = z.object({
line: z.string().openapi({example: "info"}),
initials: z.string().openapi({example: "server"}),
printReason: z.string().openapi({example: "This is a new log posted"}),
additionalComments: z.string().optional().openapi({example: "Some reason why we did this."}),
line: z.string().openapi({ example: "info" }),
initials: z.string().openapi({ example: "server" }),
printReason: z.string().openapi({ example: "This is a new log posted" }),
additionalComments: z
.string()
.optional()
.openapi({ example: "Some reason why we did this." }),
});
app.openapi(
@@ -24,32 +27,33 @@ app.openapi(
//middleware: authMiddleware,
//description: "This might be a temp soltuin during the transtion between versions",
request: {
body: {content: {"application/json": {schema: CreateLog}}},
body: { content: { "application/json": { schema: CreateLog } } },
},
responses: responses(),
}),
async (c) => {
const body = await c.req.json();
apiHit(c, {endpoint: `api/logger/logs/id`});
// const authHeader = c.req.header("Authorization");
// const token = authHeader?.split("Bearer ")[1] || "";
// let user: User;
// try {
// const payload = await verify(token, process.env.JWT_SECRET!);
// user = payload.user as User;
// } catch (error) {
// console.log(error);
// return c.json({message: "Unauthorized"}, 401);
// }
apiHit(c, { endpoint: `api/logger/logs/id` });
try {
//const data = {...body, add_user: user.username};
await manualPrint(body);
return c.json({success: true, message: "Manual Print was added.", data: []}, 200);
const printLog: any = await manualPrint(body);
return c.json(
{
success: printLog.success,
message: printLog.message,
data: printLog.data ?? [],
},
200
);
} catch (error) {
return c.json({success: false, message: "There was an error clearing the log.", data: error}, 400);
return c.json(
{
success: false,
message: "There was an error clearing the log.",
data: error,
},
400
);
}
}
);

View File

@@ -0,0 +1,50 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { getPrinters } from "../../controller/printers/getPrinters.js";
const app = new OpenAPIHono({ strict: false });
const CreateLog = z.object({
line: z.string().openapi({ example: "info" }),
initials: z.string().openapi({ example: "server" }),
printReason: z.string().openapi({ example: "This is a new log posted" }),
additionalComments: z
.string()
.optional()
.openapi({ example: "Some reason why we did this." }),
});
app.openapi(
createRoute({
tags: ["ocp"],
summary: "Prints a label.",
method: "get",
path: "/getprinters",
//middleware: authMiddleware,
//description: "This might be a temp soltuin during the transtion between versions",
request: {
body: { content: { "application/json": { schema: CreateLog } } },
},
responses: responses(),
}),
async (c) => {
const { data: printData, error: printError } = await tryCatch(
getPrinters()
);
if (printError) {
return c.json({
success: false,
message: "There was an error getting the printers",
});
}
return c.json({
success: printData.success,
message: printData.message,
data: printData.data,
});
}
);
export default app;

View File

@@ -0,0 +1,50 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
import { updatePrinters } from "../../controller/printers/updatePrinters.js";
const app = new OpenAPIHono({ strict: false });
const CreateLog = z.object({
line: z.string().openapi({ example: "info" }),
initials: z.string().openapi({ example: "server" }),
printReason: z.string().openapi({ example: "This is a new log posted" }),
additionalComments: z
.string()
.optional()
.openapi({ example: "Some reason why we did this." }),
});
app.openapi(
createRoute({
tags: ["ocp"],
summary: "Prints a label.",
method: "get",
path: "/updateprinters",
//middleware: authMiddleware,
//description: "This might be a temp soltuin during the transtion between versions",
request: {
body: { content: { "application/json": { schema: CreateLog } } },
},
responses: responses(),
}),
async (c) => {
const { data: printData, error: printError } = await tryCatch(
updatePrinters()
);
if (printError) {
return c.json({
success: false,
message: "There was an error getting the printers",
});
}
return c.json({
success: printData.success,
message: printData.message,
data: printData.data,
});
}
);
export default app;

View File

@@ -0,0 +1,56 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../../globalUtils/routeDefs/responses.js";
import { authMiddleware } from "../../../../auth/middleware/authMiddleware.js";
import { tryCatch } from "../../../../../globalUtils/tryCatch.js";
import { closeDyco } from "../../../controller/specialProcesses/dyco/plcConnection.js";
const app = new OpenAPIHono({ strict: false });
app.openapi(
createRoute({
tags: ["ocp:dyco"],
summary: "Disconnect to the dyco.",
method: "get",
path: "/dycodisconnect",
middleware: authMiddleware,
description:
"Use this when you just want to stop the entire thing due to an error or what not.",
// request: {
// body: {content: {"application/json": {schema: CreateLog}}},
// },
responses: responses(),
}),
async (c) => {
//const body = await c.req.json();
//apiHit(c, {endpoint: `api/logger/logs/id`});
// const authHeader = c.req.header("Authorization");
// const token = authHeader?.split("Bearer ")[1] || "";
// let user: User;
// try {
// const payload = await verify(token, process.env.JWT_SECRET!);
// user = payload.user as User;
// } catch (error) {
// console.log(error);
// return c.json({message: "Unauthorized"}, 401);
// }
const { data, error } = await tryCatch(closeDyco());
if (error) {
return c.json({
success: false,
message: "Error in connecting to dyco",
data: error,
});
}
const getData: any = data;
return c.json({
success: getData?.success,
message: getData?.message,
});
}
);
export default app;

View File

@@ -0,0 +1,56 @@
// an external way to creating logs
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
import { responses } from "../../../../../globalUtils/routeDefs/responses.js";
import { authMiddleware } from "../../../../auth/middleware/authMiddleware.js";
import { tryCatch } from "../../../../../globalUtils/tryCatch.js";
import { dycoConnect } from "../../../controller/specialProcesses/dyco/plcConnection.js";
const app = new OpenAPIHono({ strict: false });
app.openapi(
createRoute({
tags: ["ocp:dyco"],
summary: "Connects to the dyco.",
method: "get",
path: "/dycoconnect",
middleware: authMiddleware,
//description: "This might be a temp soltuin during the transtion between versions",
// request: {
// body: {content: {"application/json": {schema: CreateLog}}},
// },
responses: responses(),
}),
async (c) => {
//const body = await c.req.json();
//apiHit(c, {endpoint: `api/logger/logs/id`});
// const authHeader = c.req.header("Authorization");
// const token = authHeader?.split("Bearer ")[1] || "";
// let user: User;
// try {
// const payload = await verify(token, process.env.JWT_SECRET!);
// user = payload.user as User;
// } catch (error) {
// console.log(error);
// return c.json({message: "Unauthorized"}, 401);
// }
const { data, error } = await tryCatch(dycoConnect());
const dataError: any = error;
if (error) {
return c.json({
success: false,
message: "Error in connecting to dyco",
data: dataError?.data,
});
}
const getData: any = data;
return c.json({
success: getData?.success,
message: getData?.message,
data: getData.data ?? [],
});
}
);
export default app;

View File

@@ -1,8 +1,8 @@
import axios from "axios";
import {createLog} from "../../logger/logger.js";
import {db} from "../../../../database/dbclient.js";
import {rfidReaders} from "../../../../database/schema/rfidReaders.js";
import {eq} from "drizzle-orm";
import { createLog } from "../../logger/logger.js";
import { db } from "../../../../database/dbclient.js";
import { rfidReaders } from "../../../../database/schema/rfidReaders.js";
import { eq } from "drizzle-orm";
const authData = btoa("admin:Zebra123!");
let token: string;
@@ -12,10 +12,18 @@ export const readTags = async (reader: string) => {
/**
* Start the read for x seconds then auto stop it
*/
const readers = await db.select().from(rfidReaders).where(eq(rfidReaders.active, true));
createLog("info", "rfid", "rfid", `Read was just triggered from ${reader}`);
const readers = await db
.select()
.from(rfidReaders)
.where(eq(rfidReaders.active, true));
if (readers.length === 0) {
createLog("error", "rfid", "rfid", `There are no active readers right now maybe one forgot to be activated`);
createLog(
"error",
"rfid",
"rfid",
`There are no active readers right now maybe one forgot to be activated`
);
return;
}
// get the auth token
@@ -23,7 +31,7 @@ export const readTags = async (reader: string) => {
try {
const res = await axios.get(`https://${ip}/cloud/localRestLogin`, {
headers: {Authorization: `Basic ${authData}`},
headers: { Authorization: `Basic ${authData}` },
});
token = res.data.message;
// start the read
@@ -47,7 +55,7 @@ const startRead = async () => {
`https://${ip}/cloud/start`,
{},
{
headers: {Authorization: `Bearer ${token}`},
headers: { Authorization: `Bearer ${token}` },
}
);
@@ -67,7 +75,12 @@ const startRead = async () => {
startRead();
}, 1000);
}
createLog("error", "rfid", "rfid", `There was an error Starting the read: ${error.response.data.message}`);
createLog(
"error",
"rfid",
"rfid",
`There was an error Starting the read: ${error.response.data.message}`
);
}
};
const stopRead = async () => {
@@ -76,10 +89,15 @@ const stopRead = async () => {
`https://${ip}/cloud/stop`,
{},
{
headers: {Authorization: `Bearer ${token}`},
headers: { Authorization: `Bearer ${token}` },
}
);
} catch (error: any) {
createLog("error", "rfid", "rfid", `There was an error Stopping the read: ${error.response.data.message}`);
createLog(
"error",
"rfid",
"rfid",
`There was an error Stopping the read: ${error.response.data.message}`
);
}
};

View File

@@ -3,9 +3,9 @@
* Phase 2 we will generate a label to be reprinted at staion 4
*/
import {createLog} from "../../../logger/logger.js";
import type {TagData} from "../tagData.js";
import {tagStuff} from "../tags/crudTag.js";
import { createLog } from "../../../logger/logger.js";
import type { TagData } from "../tagData.js";
import { tagStuff } from "../tags/crudTag.js";
export const station3Tags = async (tagData: TagData[]) => {
// make sure we only have one tag or dont update
@@ -17,11 +17,25 @@ export const station3Tags = async (tagData: TagData[]) => {
`There are ${tagData.length} tags, and ${tagData[0].reader} only allows 1 tag to create a label.`
);
// get tag data
tagStuff(tagData);
for (let i = 0; i < tagData.length; i++) {
const tag = {
...tagData[i],
runningNr: 0,
lastareaIn: "NeedsChecked",
};
tagStuff([tag]);
}
} else {
//console.log("Generate the label and link it to the tag.");
const tagdata = await tagStuff(tagData);
const tag = { ...tagData[0], runningNr: 0 };
const tagdata = await tagStuff([tag]);
createLog("info", "rfid", "rfid", "Generate a label and link it to this tag.");
createLog(
"debug",
"rfid",
"rfid",
"Generate a label and link it to this tag."
);
}
};

View File

@@ -2,12 +2,34 @@
* Phase 1 we will just follow the logic of printing a label when we are told requested to based on this tag.
* Phase 2 we will just reprint the tag that was generated at the line
*/
import {createLog} from "../../../logger/logger.js";
import type {TagData} from "../tagData.js";
import {tagStuff} from "../tags/crudTag.js";
import os from "os";
import { createLog } from "../../../logger/logger.js";
import { labelingProcess } from "../../../ocp/controller/labeling/labelProcess.js";
import type { TagData } from "../tagData.js";
import { tagStuff } from "../tags/crudTag.js";
import { sendEmail } from "../../../notifications/controller/sendMail.js";
export const wrapperStuff = async (tagData: TagData[]) => {
if (tagData[0]?.lastareaIn === "NeedsChecked") {
createLog(
"error",
"rfid",
"rfid",
`The tags on this pallet need to be checked as it was flagged as more than 1 tag number. please validate and looks at both sides.`
);
// just making sure we clear out the running number if one really came over.
for (let i = 0; i < tagData.length; i++) {
const tag = { ...tagData[i], runningNr: 0 };
tagStuff([tag]);
}
monitorChecks();
return {
success: false,
message:
"The tags on this pallet need to be checked as it was flagged as more than 1 tag number. please validate and looks at both sides.",
};
}
if (tagData.length != 1) {
createLog(
"error",
@@ -15,32 +37,123 @@ export const wrapperStuff = async (tagData: TagData[]) => {
"rfid",
`There are ${tagData.length} tags and this ${tagData[0].reader} only allows 1 tag to create a label.`
);
tagStuff(tagData);
const tag = { ...tagData[0], runningNr: 0 };
tagStuff([tag]);
monitorChecks();
} else {
if (!tagData) {
createLog("error", "rfid", "rfid", `No tagData was grabbed.`);
monitorChecks();
}
const tagdata = await tagStuff(tagData);
/**
* we want to make sure this pallet came from a line as its last spot if not we need to have a manual check.
*/
const station3 = tagdata.some((n: any) => n.lastareaIn.includes("line3"));
if (!station3) {
const lines = tagdata[0]?.lastareaIn.includes("line3");
if (!lines) {
createLog(
"error",
"rfid",
"rfid",
`${tagdata.tag}, Did not come from a line please check the pallet and manually print the label.`
`${tagdata[0].tag}, Did not come from a line please check the pallet and manually print the label.`
);
monitorChecks();
return {
success: false,
message: `${tagdata[0].tag}, Did not come from a line please check the pallet and manually print the label.`,
};
// when we manually run again we want to make sure we read from the 3rd antenna this way we do not get the wrong info.
// more testing will need to be done on this.
}
// check if a running number exists
if (station3.runningNumber) {
createLog("info", "rfid", "rfid", `Reprint label ${station3.runningNumber}`);
if (lines[0].runningNumber) {
createLog(
"info",
"rfid",
"rfid",
`Reprint label ${lines[0].runningNumber}`
);
} else {
createLog("info", "rfid", "rfid", `A new labels will be created and linked to this ${tagdata.tag} tag`);
createLog(
"info",
"rfid",
"rfid",
`A new label will be created and linked to this ${tagdata[0].tag} tag`
);
// get the actaul line number from the last area in
const lineNum = parseInt(
tagdata[0]?.lastareaIn.repalceAll("line3", "")
);
createLog(
"info",
"rfid",
"rfid",
`Line to be checked for printing: ${lineNum}`
);
const genlabel = await labelingProcess({
line: lineNum.toString(),
});
if (genlabel?.success) {
// update the tag and add the label into it
const createPrintData = {
...tagData[0],
runnungNr: parseInt(genlabel.data?.SSCC.slice(10, -1)),
};
}
}
}
};
const monitorErrorTags: any = [];
const monitorChecks = () => {
/**
* If we have to check more than 10 tags in an hour send an email to alert everyone.
*/
const now = new Date(Date.now()).getTime();
monitorErrorTags.push({ timestamp: now });
// remove if creater than 1 hour
const removalTiming = now - 1 * 60 * 60 * 1000; // 1 hour
while (
monitorErrorTags > 0 &&
monitorErrorTags[0].timestamp < removalTiming
) {
monitorErrorTags.shift();
}
if (monitorErrorTags > 10) {
// send the email.
const emailData = {
email: "blake.matthes@alpla.com", // should be moved to the db so it can be reused.
subject: `${os.hostname()} has had ${monitorErrorTags}.`,
template: "toManyManualPrints",
context: {
count: monitorErrorTags,
hours: "1",
},
};
sendEmail(emailData);
}
};
// if (
// !Array.isArray(tagdata) &&
// tagdata?.some((n: any) => n.lastareaIn.includes("line3"))
// ) {
// createLog(
// "error",
// "rfid",
// "rfid",
// `Data passed over is not an array.`
// );
// return;
// }

View File

@@ -1,5 +1,5 @@
import {station3Tags} from "./stations/station3.js";
import {wrapperStuff} from "./stations/wrappers.js";
import { station3Tags } from "./stations/station3.js";
import { wrapperStuff } from "./stations/wrappers.js";
export type TagData = {
tagHex: string;
@@ -8,6 +8,7 @@ export type TagData = {
timeStamp: Date;
antenna: number;
tagStrength: number;
lastareaIn?: string;
};
export const tagData = async (data: TagData[]) => {
/**

View File

@@ -1,8 +1,8 @@
import {eq} from "drizzle-orm";
import {db} from "../../../../../database/dbclient.js";
import {rfidTags} from "../../../../../database/schema/rfidTags.js";
import type {TagData} from "../tagData.js";
import {createLog} from "../../../logger/logger.js";
import { eq } from "drizzle-orm";
import { db } from "../../../../../database/dbclient.js";
import { rfidTags } from "../../../../../database/schema/rfidTags.js";
import type { TagData } from "../tagData.js";
import { createLog } from "../../../logger/logger.js";
type ReturnTag = {
success: boolean;
@@ -22,7 +22,7 @@ export const tagStuff = async (tagData: TagData[]): Promise<any> => {
tagHex: tagData[i].tagHex,
tag: tagData[i].tag,
lastRead: new Date(tagData[i].timeStamp),
counts: [{area: tagData[i].reader, timesHere: 1}], //jsonb("counts").notNull(), //.default([{area: 1, timesHere: 5}]).notNull(),
counts: [{ area: tagData[i].reader, timesHere: 1 }], //jsonb("counts").notNull(), //.default([{area: 1, timesHere: 5}]).notNull(),
lastareaIn: tagData[i].reader,
antenna: tagData[i].antenna,
tagStrength: tagData[i].tagStrength,
@@ -36,30 +36,37 @@ export const tagStuff = async (tagData: TagData[]): Promise<any> => {
lastareaIn: rfidTags.lastareaIn,
});
createLog("info", "rfid", "rfid", `Tags were jusdt updated.`);
return {success: true, tag};
return { success: true, tag };
} catch (error) {
createLog("error", "rfid", "rfid", `${JSON.stringify(error)}`);
return {success: false, error};
return { success: false, error };
}
} else {
// update tag
//console.log("Updating existing tag");
// make sure we actually have an array here
const countsArray = (tag[0]?.counts as {area: string; timesHere: number}[]) ?? [];
const countsArray =
(tag[0]?.counts as { area: string; timesHere: number }[]) ?? [];
// check if the reader exists on the array
const areaExists = countsArray.some((t) => t.area === tagData[0].reader);
const areaExists = countsArray.some(
(t) => t.area === tagData[0].reader
);
// run the update on the array
const updateCount = areaExists
? countsArray.map((t) => {
if (t.area === tagData[0].reader) {
return {...t, timesHere: t.timesHere + 1};
return { ...t, timesHere: t.timesHere + 1 };
} else {
return {...t, area: tagData[i].reader, timesHere: 1};
return {
...t,
area: tagData[i].reader,
timesHere: 1,
};
}
})
: [...countsArray, {area: tagData[i].reader, timesHere: 1}];
: [...countsArray, { area: tagData[i].reader, timesHere: 1 }];
const updateTag = {
lastRead: new Date(tagData[i].timeStamp),
@@ -70,17 +77,21 @@ export const tagStuff = async (tagData: TagData[]): Promise<any> => {
};
try {
await db.update(rfidTags).set(updateTag).where(eq(rfidTags.tagHex, tagData[0].tagHex)).returning({
tag: rfidTags.tag,
runningNumber: rfidTags.runningNumber,
counts: rfidTags.counts,
lastareaIn: rfidTags.lastareaIn,
});
await db
.update(rfidTags)
.set(updateTag)
.where(eq(rfidTags.tagHex, tagData[0].tagHex))
.returning({
tag: rfidTags.tag,
runningNumber: rfidTags.runningNumber,
counts: rfidTags.counts,
lastareaIn: rfidTags.lastareaIn,
});
createLog("info", "rfid", "rfid", `Tags were jusdt updated.`);
return {success: true, tag};
return { success: true, tag };
} catch (error) {
createLog("error", "rfid", "rfid", `${JSON.stringify(error)}`);
return {success: false, error};
return { success: false, error };
}
}
}

View File

@@ -3,20 +3,41 @@
* this will only run on a server start up
*/
import {db} from "../../../../database/dbclient.js";
import {settings} from "../../../../database/schema/settings.js";
import { db } from "../../../../database/dbclient.js";
import { settings } from "../../../../database/schema/settings.js";
import {createLog} from "../../logger/logger.js";
import { createLog } from "../../logger/logger.js";
// "view", "technician", "supervisor","manager", "admin", "systemAdmin"
const newSettings = [
{name: "server", value: "localhost", description: "Where the app runs at", moduleName: "server"},
{name: "serverPort", value: "4400", description: "What are we listening on", moduleName: "server"},
{name: "dbUser", value: "alplaprod", description: "What is the db username", moduleName: "server"},
{name: "dbPass", value: "b2JlbGl4", description: "What is the db password", moduleName: "server"},
{
name: "server",
value: "localhost",
description: "Where the app runs at",
moduleName: "server",
},
{
name: "serverPort",
value: "4400",
description: "What are we listening on",
moduleName: "server",
},
{
name: "dbUser",
value: "alplaprod",
description: "What is the db username",
moduleName: "server",
},
{
name: "dbPass",
value: "b2JlbGl4",
description: "What is the db password",
moduleName: "server",
},
{
name: "tcpPort",
value: "2222",
description: "TCP port for printers to connect send data and the zedra cameras",
description:
"TCP port for printers to connect send data and the zedra cameras",
moduleName: "server",
},
{
@@ -59,13 +80,15 @@ const newSettings = [
{
name: "ocmeService",
value: "0",
description: "Is the ocme service enabled. this is gernerally only for Dayton.",
description:
"Is the ocme service enabled. this is gernerally only for Dayton.",
moduleName: "ocme",
},
{
name: "fifoCheck",
value: "45",
description: "How far back do we want to check for fifo default 45, putting 0 will ignore.",
description:
"How far back do we want to check for fifo default 45, putting 0 will ignore.",
moduleName: "ocme",
},
{
@@ -83,7 +106,8 @@ const newSettings = [
{
name: "monitorAddress",
value: "8",
description: "What address is monitored to be limited to the amount of lots that can be added to a truck.",
description:
"What address is monitored to be limited to the amount of lots that can be added to a truck.",
moduleName: "ocme",
},
{
@@ -96,7 +120,8 @@ const newSettings = [
{
name: "devDir",
value: "C:\\Users\\matthes01\\Documents\\lstv2",
description: "This is the dev dir and strictly only for updating the servers.",
description:
"This is the dev dir and strictly only for updating the servers.",
moduleName: "server",
},
{
@@ -116,7 +141,30 @@ const newSettings = [
{
name: "ocpLogsCheck",
value: "4",
description: "How long do we want to allow logs to show that have not been cleared?",
description:
"How long do we want to allow logs to show that have not been cleared?",
roles: "admin",
module: "ocp",
},
{
name: "inhouseDelivery",
value: "0",
description: "Are we doing auto inhouse delivery?",
roles: "admin",
module: "ocp",
},
// dyco settings
{
name: "dycoConnect",
value: "0",
description: "Are we running the dyco system?",
roles: "admin",
module: "ocp",
},
{
name: "dycoPrint",
value: "0",
description: "Are we using the dyco to get the labels or the rfid?",
roles: "admin",
module: "ocp",
},
@@ -129,16 +177,31 @@ export const areSettingsIn = async () => {
if (settingsCheck.length !== newSettings.length) {
try {
const newRole = await db
.insert(settings)
.values(newSettings)
.onConflictDoNothing() // this will only update the ones that are new :D
.returning({name: settings.name});
createLog("info", "lst", "server", "Settingss were just added due to missing them on server startup");
.insert(settings)
.values(newSettings)
.onConflictDoNothing() // this will only update the ones that are new :D
.returning({ name: settings.name });
createLog(
"info",
"lst",
"server",
"Settingss were just added due to missing them on server startup"
);
} catch (error) {
createLog("error", "lst", "server", "There was an error adding new roles to the db");
createLog(
"error",
"lst",
"server",
"There was an error adding new roles to the db"
);
}
}
} catch (error) {
createLog("error", "lst", "server", "There was an error getting or adding new Settingss");
createLog(
"error",
"lst",
"server",
"There was an error getting or adding new Settingss"
);
}
};

View File

@@ -0,0 +1,7 @@
export const laneInfo = `
select IdLagerAbteilung as laneID,
Bezeichnung as laneName
from AlplaPROD_test1.dbo.T_LagerAbteilungen
where Aktiv = 1
and Bezeichnung = '[laneName]'
`;

View File

@@ -0,0 +1,55 @@
export const lotQuery = `
select IdMaschinen_ProdPlanung as LabelOnlineID,
IdMaschine as machineID,
MaschinenStandort as MachineLocation,
MaschinenBez as MachineDescription,
IdProdPlanung as LOT,
prolink.lot as ProlinkLot,
IdArtikelvarianten as AV,
ArtikelVariantenBez as Alias,
convert(varchar, add_date, 20) as Add_Date,
Add_user,
idEtikettenDrucker as printerID,
b.name as PrinterName,
CAST(TotalPlannedLoadingUnits as float) as PlannedQTY,
CAST(TotalProducedLoadingUnits as float) as Produced,
ROUND(CAST(TotalPlannedLoadingUnits as float) - CAST(TotalProducedLoadingUnits as float),2) as Remaining,
case
-- checks if someone changed the criteria to something else to trigger the over run
when x.ProzentReserveAnzahlPaletten > 0 then 'yes'
-- if the lot has a decimal in it to allow over running with no intervention
when CAST(TotalPlannedLoadingUnits as float) - floor(CAST(TotalPlannedLoadingUnits as float)) > 0 then 'yes'
else 'no' end as overPrinting,
CustomerHumanReadableId as CustomerId,
CustomerName as CustomerName,
idMaschine as MachineID,
prolink.lastProlinkUpdate as lastProlinkUpdate,
IdEtikettenLayoutPalette as palletLabel,
AnzahlKopienPalette as pallerCopies,
IdEtikettenLayoutKarton as cartonLabel,
AnzahlKopienKarton as cartonCopies,
IsTechnicallyReleased
--*
from AlplaPROD_test1.dbo.V_Maschinen_ProdPlanungen x (nolock)
join
[test1_AlplaPROD2.0_Read].[productionControlling].[ProducedLot] on
x.IdProdPlanung =
[test1_AlplaPROD2.0_Read].[productionControlling].[ProducedLot].ProductionLotHumanReadableId
left join
[test1_AlplaPROD2.0_Read].masterData.Printer as b on
x.IdEtikettenDrucker = b.HumanReadableId
-- adding in prolink lot
left join
(SELECT * from (SELECT IdMaschine as prolinkMachineId,
Produktionslos as lot,
Upd_Date as lastProlinkUpdate,
ROW_NUMBER() OVER (PARTITION BY IdMaschine ORDER BY Upd_Date DESC) RN_Prolink
FROM AlplaPROD_test1.dbo.T_HistoryProduktionsdaten (nolock)
WHERE Upd_Date BETWEEN DATEADD(DD, - 300, getdate()) AND DATEADD(DD, 1, getdate())) p
WHERE RN_Prolink = 1
) as prolink on
x.idMaschine = prolink.prolinkMachineId
where IsTechnicallyReleased = 1
`;

View File

@@ -0,0 +1,9 @@
export const machineCheck = `
SELECT [HumanReadableId]
,[Name]
,[Location]
,[Active]
,[ImportSource]
,[StagingMainMaterialMandatory]
FROM [test1_AlplaPROD2.0_Read].[masterData].[Machine] (nolock)
where Active = 1 and [Location] = [loc]`;

View File

@@ -0,0 +1,17 @@
export const mmQuery = `
SELECT lot.ProductionLotHumanReadableId,
case when SourcingState in (1, 2) then 1
when x.ProvidedAmount > 0 then 1
when x.EffectiveConsumption > 0 then 1
else 0 end as Staged,
x.ProvidedAmount as Provided,
x.EffectiveConsumption as consumption,
x.IsManualProcess as isManual,
MaterialHumanReadableId
FROM [test1_AlplaPROD2.0_Read].[issueMaterial].[MaterialDemand] x (nolock)
left join
[test1_AlplaPROD2.0_Read].[issueMaterial].[ProductionLot] as lot on
x.ProductionLotId = lot.Id
where lot.ProductionLotHumanReadableId = [lotNumber]
and IsMainMaterial = 1
`;

View File

@@ -0,0 +1,25 @@
export const prolinkQuery = `
select * from (
select *
From(select
V_Maschinen_ProdPlanungen.MaschinenStandort as Machine,
V_Maschinen_ProdPlanungen.IdProdPlanung as AlplaLabelOnline,
prolink.lot Prolink,
case when AlplaPROD_test1.dbo.V_Maschinen_ProdPlanungen.IdProdPlanung <> prolink.lot
Then 'IncorrectLot'
Else 'Good' end as LotCheck
from AlplaPROD_test1.dbo.V_Maschinen_ProdPlanungen (nolock)
left join
(
SELECT *
FROM (SELECT IdMaschine,
Produktionslos as lot,
Startzeit as StartTime,
Upd_Date,
ROW_NUMBER() OVER (PARTITION BY IdMaschine ORDER BY Upd_Date DESC) RN_Prolink
FROM AlplaPROD_test1.dbo.T_HistoryProduktionsdaten (nolock)
WHERE Upd_Date BETWEEN DATEADD(DD, - 10, getdate()) AND DATEADD(DD, 1, getdate())) a
WHERE RN_Prolink = 1
) as prolink on AlplaPROD_test1.dbo.V_Maschinen_ProdPlanungen.IdMaschine=prolink.IdMaschine) a
) a
`;

View File

@@ -1,23 +1,28 @@
import net from "net";
import {OpenAPIHono} from "@hono/zod-openapi";
import {createLog} from "../logger/logger.js";
import { OpenAPIHono } from "@hono/zod-openapi";
import { createLog } from "../logger/logger.js";
import startTCP from "./route/startServer.js";
import stopTCP from "./route/stopServer.js";
import restartTCP from "./route/restartServer.js";
import {db} from "../../../database/dbclient.js";
import {settings} from "../../../database/schema/settings.js";
import {eq} from "drizzle-orm";
import { db } from "../../../database/dbclient.js";
import { settings } from "../../../database/schema/settings.js";
import { eq } from "drizzle-orm";
import { postLabelData } from "../ocme/controller/postRunningNr.js";
let tcpServer: net.Server;
let tcpSockets: Set<net.Socket> = new Set();
let isServerRunning = false;
const tcpPort = await db.select().from(settings).where(eq(settings.name, "tcpPort"));
const tcpPort = await db
.select()
.from(settings)
.where(eq(settings.name, "tcpPort"));
const app = new OpenAPIHono();
export const startTCPServer = () => {
if (isServerRunning) return {success: false, message: "Server is already running"};
if (isServerRunning)
return { success: false, message: "Server is already running" };
tcpServer = net.createServer((socket) => {
console.log("Client connected");
@@ -25,7 +30,19 @@ export const startTCPServer = () => {
tcpSockets.add(socket);
socket.on("data", (data: Buffer) => {
console.log("Received:", data.toString());
socket.write("Message received");
const parseData = data.toString("utf-8").trimEnd().split(" ");
// hb from the scanners
if (parseData[0] === "HB") {
return;
}
// alert from the printers
if (parseData[0] === "ALERT:" || parseData[0] === "ALERT") {
return;
}
// from the wrapper send the data
postLabelData(parseData);
});
socket.on("end", () => {
@@ -40,16 +57,22 @@ export const startTCPServer = () => {
});
tcpServer.listen(tcpPort[0]?.value ?? 2222, () => {
createLog("info", "lst", "tcp", `TCP Server listening on port ${tcpPort[0]?.value ?? 2222}`);
createLog(
"info",
"lst",
"tcp",
`TCP Server listening on port ${tcpPort[0]?.value ?? 2222}`
);
});
isServerRunning = true;
return {success: true, message: "TCP Server started"};
return { success: true, message: "TCP Server started" };
};
// Function to stop the TCP server
export const stopTCPServer = () => {
if (!isServerRunning) return {success: false, message: "Server is not running"};
if (!isServerRunning)
return { success: false, message: "Server is not running" };
for (const socket of tcpSockets) {
socket.destroy();
}
@@ -58,7 +81,7 @@ export const stopTCPServer = () => {
console.log("TCP Server stopped");
});
isServerRunning = false;
return {success: true, message: "TCP Server stopped"};
return { success: true, message: "TCP Server stopped" };
};
app.route("/tcpserver/start", startTCP);

View File

@@ -1,20 +1,20 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "nodenext",
"strict": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true,
"types": ["node"],
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx",
"outDir": "./dist",
"removeComments": true,
"allowJs": true,
"esModuleInterop": true,
"resolveJsonModule": true
},
"include": ["server", "scripts/**/*.ts"],
"exclude": ["node_modules", "frontend", "dist", "testFiles"]
"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "nodenext",
"strict": true,
"verbatimModuleSyntax": true,
"skipLibCheck": true,
"types": ["node"],
"jsx": "react-jsx",
"jsxImportSource": "hono/jsx",
"outDir": "./dist",
"removeComments": true,
"allowJs": true,
"esModuleInterop": true,
"resolveJsonModule": true
},
"include": ["server", "scripts/**/*.ts"],
"exclude": ["node_modules", "frontend", "dist", "testFiles"]
}