Compare commits
25 Commits
b9397c029f
...
9f26f2334f
| Author | SHA1 | Date | |
|---|---|---|---|
| 9f26f2334f | |||
| a7818b4ca3 | |||
| 99477bac19 | |||
| 5eacbb5ecf | |||
| 8b5698a839 | |||
| ad5e77028d | |||
| e1973e4da6 | |||
| 8194798a37 | |||
| 16e5413a90 | |||
| 6065cccbd7 | |||
| 9a5dc980f0 | |||
| 23fa9f09dc | |||
| f1c9877686 | |||
| 6ad49b704d | |||
| 60cd6e551a | |||
| 74445149b7 | |||
| 2e05f79c72 | |||
| 13df4af860 | |||
| 6bd1bebe33 | |||
| 99fd875dbb | |||
| 17d7e54b7a | |||
| 498c1626a1 | |||
| 6180f61d08 | |||
| 3e4d8b260c | |||
| fa9e5dd70f |
2
database/migrations/0034_massive_penance.sql
Normal file
2
database/migrations/0034_massive_penance.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DATA TYPE timestamp;--> statement-breakpoint
|
||||||
|
ALTER TABLE "printers" ADD COLUMN "printDelay" numeric;
|
||||||
2
database/migrations/0035_even_adam_warlock.sql
Normal file
2
database/migrations/0035_even_adam_warlock.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DEFAULT now();--> statement-breakpoint
|
||||||
|
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET NOT NULL;
|
||||||
1
database/migrations/0036_fixed_spacker_dave.sql
Normal file
1
database/migrations/0036_fixed_spacker_dave.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "printers" ALTER COLUMN "lastTimePrinted" SET DATA TYPE timestamp with time zone;
|
||||||
1
database/migrations/0037_cooing_orphan.sql
Normal file
1
database/migrations/0037_cooing_orphan.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "printers" DROP COLUMN "lastTimePrinted";
|
||||||
1
database/migrations/0038_lumpy_kitty_pryde.sql
Normal file
1
database/migrations/0038_lumpy_kitty_pryde.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "printers" DROP COLUMN "printDelay";
|
||||||
19
database/migrations/0039_greedy_steve_rogers.sql
Normal file
19
database/migrations/0039_greedy_steve_rogers.sql
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
CREATE TABLE "printerData" (
|
||||||
|
"printer_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"humanReadableId" text,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"ipAddress" text,
|
||||||
|
"port" numeric,
|
||||||
|
"status" text,
|
||||||
|
"statusText" text,
|
||||||
|
"lastTimePrinted" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"assigned" boolean DEFAULT false,
|
||||||
|
"remark" text,
|
||||||
|
"printDelay" numeric,
|
||||||
|
"monitorState" boolean DEFAULT false,
|
||||||
|
"add_Date" timestamp DEFAULT now(),
|
||||||
|
"upd_date" timestamp DEFAULT now()
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
DROP TABLE "printers" CASCADE;--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "humanReadableId" ON "printerData" USING btree ("humanReadableId");
|
||||||
17
database/migrations/0040_luxuriant_aqueduct.sql
Normal file
17
database/migrations/0040_luxuriant_aqueduct.sql
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
CREATE TABLE "subModules" (
|
||||||
|
"submodule_id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"moduleName" text NOT NULL,
|
||||||
|
"name" text NOT NULL,
|
||||||
|
"description" text,
|
||||||
|
"link" text NOT NULL,
|
||||||
|
"active" boolean DEFAULT false,
|
||||||
|
"roles" jsonb DEFAULT '["systemAdmin"]'::jsonb NOT NULL,
|
||||||
|
"subSubModule" jsonb DEFAULT '[]'::jsonb,
|
||||||
|
"add_User" text DEFAULT 'LST_System' NOT NULL,
|
||||||
|
"add_Date" timestamp DEFAULT now(),
|
||||||
|
"upd_User" text DEFAULT 'LST_System' NOT NULL,
|
||||||
|
"upd_date" timestamp DEFAULT now()
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "subModules" ADD CONSTRAINT "subModules_moduleName_modules_name_fk" FOREIGN KEY ("moduleName") REFERENCES "public"."modules"("name") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
||||||
|
CREATE UNIQUE INDEX "subModule_name" ON "subModules" USING btree ("name");
|
||||||
1
database/migrations/0041_wise_molten_man.sql
Normal file
1
database/migrations/0041_wise_molten_man.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX "subModule_name";
|
||||||
3
database/migrations/0042_big_power_pack.sql
Normal file
3
database/migrations/0042_big_power_pack.sql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE "subModules" DROP CONSTRAINT "subModules_moduleName_modules_name_fk";
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "subModules" ALTER COLUMN "moduleName" DROP NOT NULL;
|
||||||
1366
database/migrations/meta/0034_snapshot.json
Normal file
1366
database/migrations/meta/0034_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1367
database/migrations/meta/0035_snapshot.json
Normal file
1367
database/migrations/meta/0035_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1367
database/migrations/meta/0036_snapshot.json
Normal file
1367
database/migrations/meta/0036_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1360
database/migrations/meta/0037_snapshot.json
Normal file
1360
database/migrations/meta/0037_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1354
database/migrations/meta/0038_snapshot.json
Normal file
1354
database/migrations/meta/0038_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1367
database/migrations/meta/0039_snapshot.json
Normal file
1367
database/migrations/meta/0039_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1490
database/migrations/meta/0040_snapshot.json
Normal file
1490
database/migrations/meta/0040_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1474
database/migrations/meta/0041_snapshot.json
Normal file
1474
database/migrations/meta/0041_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1460
database/migrations/meta/0042_snapshot.json
Normal file
1460
database/migrations/meta/0042_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -239,6 +239,69 @@
|
|||||||
"when": 1743424730855,
|
"when": 1743424730855,
|
||||||
"tag": "0033_flimsy_salo",
|
"tag": "0033_flimsy_salo",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 34,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743720994399,
|
||||||
|
"tag": "0034_massive_penance",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 35,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743721140937,
|
||||||
|
"tag": "0035_even_adam_warlock",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 36,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743721251498,
|
||||||
|
"tag": "0036_fixed_spacker_dave",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 37,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743721424503,
|
||||||
|
"tag": "0037_cooing_orphan",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 38,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743729665453,
|
||||||
|
"tag": "0038_lumpy_kitty_pryde",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 39,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743771209867,
|
||||||
|
"tag": "0039_greedy_steve_rogers",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 40,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743776921664,
|
||||||
|
"tag": "0040_luxuriant_aqueduct",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 41,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743778410407,
|
||||||
|
"tag": "0041_wise_molten_man",
|
||||||
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 42,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1743778477759,
|
||||||
|
"tag": "0042_big_power_pack",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -11,8 +11,8 @@ import {
|
|||||||
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
export const printers = pgTable(
|
export const printerData = pgTable(
|
||||||
"printers",
|
"printerData",
|
||||||
{
|
{
|
||||||
printer_id: uuid("printer_id").defaultRandom().primaryKey(),
|
printer_id: uuid("printer_id").defaultRandom().primaryKey(),
|
||||||
humanReadableId: text("humanReadableId"),
|
humanReadableId: text("humanReadableId"),
|
||||||
@@ -21,9 +21,10 @@ export const printers = pgTable(
|
|||||||
port: numeric("port"),
|
port: numeric("port"),
|
||||||
status: text("status"),
|
status: text("status"),
|
||||||
statusText: text("statusText"),
|
statusText: text("statusText"),
|
||||||
lastTimePrinted: text("lastTimePrinted"),
|
lastTimePrinted: timestamp("lastTimePrinted").notNull().defaultNow(),
|
||||||
assigned: boolean("assigned").default(false),
|
assigned: boolean("assigned").default(false),
|
||||||
remark: text("remark"),
|
remark: text("remark"),
|
||||||
|
printDelay: numeric("printDelay"),
|
||||||
monitorState: boolean("monitorState").default(false),
|
monitorState: boolean("monitorState").default(false),
|
||||||
add_Date: timestamp("add_Date").defaultNow(),
|
add_Date: timestamp("add_Date").defaultNow(),
|
||||||
upd_date: timestamp("upd_date").defaultNow(),
|
upd_date: timestamp("upd_date").defaultNow(),
|
||||||
@@ -39,4 +40,4 @@ export const printers = pgTable(
|
|||||||
// name: z.string().min(3, {message: "Role name must be more than 3 letters"}),
|
// 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
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
export const selectRolesSchema = createSelectSchema(printers);
|
export const selectRolesSchema = createSelectSchema(printerData);
|
||||||
|
|||||||
45
database/schema/subModules.ts
Normal file
45
database/schema/subModules.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import {
|
||||||
|
text,
|
||||||
|
pgTable,
|
||||||
|
timestamp,
|
||||||
|
boolean,
|
||||||
|
uuid,
|
||||||
|
uniqueIndex,
|
||||||
|
jsonb,
|
||||||
|
} from "drizzle-orm/pg-core";
|
||||||
|
import { createSelectSchema } from "drizzle-zod";
|
||||||
|
import { modules } from "./modules.js";
|
||||||
|
//import {z} from "zod";
|
||||||
|
|
||||||
|
export const subModules = pgTable(
|
||||||
|
"subModules",
|
||||||
|
{
|
||||||
|
submodule_id: uuid("submodule_id").defaultRandom().primaryKey(),
|
||||||
|
moduleName: text("moduleName"),
|
||||||
|
// .notNull()
|
||||||
|
// .references(() => modules.name),
|
||||||
|
name: text("name").notNull(),
|
||||||
|
description: text("description"),
|
||||||
|
link: text("link").notNull(),
|
||||||
|
active: boolean("active").default(false),
|
||||||
|
roles: jsonb("roles").notNull().default(["systemAdmin"]), // ["view", "technician", "supervisor","manager", "admin","systemAdmin"]
|
||||||
|
subSubModule: jsonb("subSubModule").default([]),
|
||||||
|
add_User: text("add_User").default("LST_System").notNull(),
|
||||||
|
add_Date: timestamp("add_Date").defaultNow(),
|
||||||
|
upd_user: text("upd_User").default("LST_System").notNull(),
|
||||||
|
upd_date: timestamp("upd_date").defaultNow(),
|
||||||
|
}
|
||||||
|
// (table) => [
|
||||||
|
// // uniqueIndex('emailUniqueIndex').on(sql`lower(${table.email})`),
|
||||||
|
// uniqueIndex("subModule_name").on(table.name),
|
||||||
|
// ]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Schema for inserting a user - can be used to validate API requests
|
||||||
|
// export const insertModuleSchema = createInsertSchema(modules, {
|
||||||
|
// name: z.string().min(3, {message: "Module name should be longer than 3 letters"}),
|
||||||
|
// });
|
||||||
|
// Schema for selecting a Expenses - can be used to validate API responses
|
||||||
|
export const selectModuleSchema = createSelectSchema(subModules);
|
||||||
|
|
||||||
|
export type Modules = typeof subModules;
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function DataMartStats() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
The stats for all the data mart querys out there and whos and when
|
||||||
|
they are last used to understand if we want to keep them or not
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
export default function NotificationMGT() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
Manage all notifications from here instad of going to the db,
|
||||||
|
locking some items that are auto updated on server restarts
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -19,6 +19,11 @@ import { adminUrlCheck } from "@/utils/adminUrlCheck";
|
|||||||
import RestartServer from "./RestartServer";
|
import RestartServer from "./RestartServer";
|
||||||
import StopServer from "./StopServer";
|
import StopServer from "./StopServer";
|
||||||
import StartServer from "./StartServer";
|
import StartServer from "./StartServer";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { getSettings } from "@/utils/querys/settings";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
import axios from "axios";
|
||||||
|
//import { useState } from "react";
|
||||||
|
|
||||||
export type Servers = {
|
export type Servers = {
|
||||||
server_id?: string;
|
server_id?: string;
|
||||||
@@ -33,6 +38,7 @@ export type Servers = {
|
|||||||
export default function ServerPage() {
|
export default function ServerPage() {
|
||||||
const { user, token } = useSessionStore();
|
const { user, token } = useSessionStore();
|
||||||
const { modules } = useModuleStore();
|
const { modules } = useModuleStore();
|
||||||
|
//const [upgrading, setUpgrading] = useState(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { data, isError, error, isLoading } = useQuery(
|
const { data, isError, error, isLoading } = useQuery(
|
||||||
@@ -51,10 +57,45 @@ export default function ServerPage() {
|
|||||||
if (isError) {
|
if (isError) {
|
||||||
return <div>{JSON.stringify(error)}</div>;
|
return <div>{JSON.stringify(error)}</div>;
|
||||||
}
|
}
|
||||||
|
const { data: set } = useQuery(getSettings(token ?? ""));
|
||||||
|
const upgrade = async () => {
|
||||||
|
let devDir = set.filter((n: any) => n.name === "devDir");
|
||||||
|
toast.success("All Servers was just triggered.");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await axios.post(
|
||||||
|
`/api/server/update/localhost`,
|
||||||
|
{ devDir: devDir[0].value, all: true },
|
||||||
|
{
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.data.success) {
|
||||||
|
toast.success(result.data.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result.data.success) {
|
||||||
|
toast.success(result.data.message);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.error(
|
||||||
|
`There was an error updating the server: ${error.data.message}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//console.log(data);
|
//console.log(data);
|
||||||
return (
|
return (
|
||||||
<LstCard className="m-2 flex place-content-center w-dvh">
|
<LstCard className="m-2 flex place-content-center w-dvh">
|
||||||
|
<div className="flex justify-end m-2">
|
||||||
|
<Button
|
||||||
|
onClick={upgrade}
|
||||||
|
disabled={data?.some((d: any) => d.isUpgrading)}
|
||||||
|
>
|
||||||
|
Update All Servers
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
@@ -10,6 +11,7 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
|
|
||||||
import { DebugButton } from "@/utils/formStuff/debugButton";
|
import { DebugButton } from "@/utils/formStuff/debugButton";
|
||||||
import { userFormOptions } from "@/utils/formStuff/options/userformOptions";
|
import { userFormOptions } from "@/utils/formStuff/options/userformOptions";
|
||||||
import { generatePassword } from "@/utils/passwordGen";
|
import { generatePassword } from "@/utils/passwordGen";
|
||||||
@@ -18,10 +20,16 @@ import { useForm } from "@tanstack/react-form";
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
import UserRoles from "./UserRoles";
|
||||||
|
import { CardHeader } from "@/components/ui/card";
|
||||||
|
|
||||||
export default function UserCard(data: any) {
|
export default function UserCard(data: any) {
|
||||||
const token = localStorage.getItem("auth_token");
|
const token = localStorage.getItem("auth_token");
|
||||||
const { refetch } = useQuery(getUsers());
|
const { refetch } = useQuery(getUsers());
|
||||||
|
|
||||||
|
//console.log(modules);
|
||||||
|
//console.log(data.user);
|
||||||
|
//console.log(userRoles);
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
...userFormOptions(data.user),
|
...userFormOptions(data.user),
|
||||||
onSubmit: async ({ value }) => {
|
onSubmit: async ({ value }) => {
|
||||||
@@ -53,185 +61,224 @@ export default function UserCard(data: any) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="flex flex-row">
|
||||||
<form
|
<div className="m-2">
|
||||||
onSubmit={(e) => {
|
<LstCard>
|
||||||
e.preventDefault();
|
<CardHeader>User Profile</CardHeader>
|
||||||
e.stopPropagation();
|
<form
|
||||||
}}
|
onSubmit={(e) => {
|
||||||
>
|
e.preventDefault();
|
||||||
<form.Field
|
e.stopPropagation();
|
||||||
name="username"
|
}}
|
||||||
validators={{
|
>
|
||||||
// We can choose between form-wide and field-specific validators
|
<form.Field
|
||||||
onChange: ({ value }) =>
|
name="username"
|
||||||
value.length > 3
|
validators={{
|
||||||
? undefined
|
// We can choose between form-wide and field-specific validators
|
||||||
: "Username must be longer than 3 letters",
|
onChange: ({ value }) =>
|
||||||
}}
|
value.length > 3
|
||||||
children={(field) => {
|
? undefined
|
||||||
return (
|
: "Username must be longer than 3 letters",
|
||||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
}}
|
||||||
<Label htmlFor="username">Username</Label>
|
children={(field) => {
|
||||||
<Input
|
return (
|
||||||
name={field.name}
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
value={field.state.value}
|
<Label htmlFor="username">
|
||||||
onBlur={field.handleBlur}
|
Username
|
||||||
//type="number"
|
</Label>
|
||||||
onChange={(e) =>
|
<Input
|
||||||
field.handleChange(e.target.value)
|
name={field.name}
|
||||||
}
|
value={field.state.value}
|
||||||
/>
|
onBlur={field.handleBlur}
|
||||||
{field.state.meta.errors.length ? (
|
//type="number"
|
||||||
<em>{field.state.meta.errors.join(",")}</em>
|
onChange={(e) =>
|
||||||
) : null}
|
field.handleChange(
|
||||||
</div>
|
e.target.value
|
||||||
);
|
)
|
||||||
}}
|
}
|
||||||
/>
|
|
||||||
<form.Field
|
|
||||||
name="email"
|
|
||||||
validators={{
|
|
||||||
// We can choose between form-wide and field-specific validators
|
|
||||||
onChange: ({ value }) =>
|
|
||||||
value.length > 3
|
|
||||||
? undefined
|
|
||||||
: "You must enter a correct ",
|
|
||||||
}}
|
|
||||||
children={(field) => {
|
|
||||||
return (
|
|
||||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
|
||||||
<Label htmlFor="email">Email</Label>
|
|
||||||
<Input
|
|
||||||
name={field.name}
|
|
||||||
value={field.state.value}
|
|
||||||
onBlur={field.handleBlur}
|
|
||||||
//type="number"
|
|
||||||
onChange={(e) =>
|
|
||||||
field.handleChange(e.target.value)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{field.state.meta.errors.length ? (
|
|
||||||
<em>{field.state.meta.errors.join(",")}</em>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<form.Field
|
|
||||||
name="role"
|
|
||||||
//listeners={{onChange: ({value})=>{}}}
|
|
||||||
children={(field) => {
|
|
||||||
return (
|
|
||||||
<div className="m-2 min-w-48 max-w-96 p-2">
|
|
||||||
<Label htmlFor={field.name}>Select role</Label>
|
|
||||||
<Select
|
|
||||||
value={field.state.value}
|
|
||||||
onValueChange={field.handleChange}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-[180px]">
|
|
||||||
<SelectValue
|
|
||||||
id={field.name}
|
|
||||||
placeholder="Select Role"
|
|
||||||
/>
|
/>
|
||||||
</SelectTrigger>
|
{field.state.meta.errors.length ? (
|
||||||
<SelectContent>
|
<em>
|
||||||
<SelectGroup>
|
{field.state.meta.errors.join(
|
||||||
<SelectLabel>Roles</SelectLabel>
|
","
|
||||||
<SelectItem value="viewer">
|
)}
|
||||||
Viewer
|
</em>
|
||||||
</SelectItem>
|
) : null}
|
||||||
<SelectItem value="operator">
|
</div>
|
||||||
Operator
|
);
|
||||||
</SelectItem>
|
}}
|
||||||
<SelectItem value="manager">
|
/>
|
||||||
Manager
|
<form.Field
|
||||||
</SelectItem>
|
name="email"
|
||||||
<SelectItem value="admin">
|
validators={{
|
||||||
Admin
|
// We can choose between form-wide and field-specific validators
|
||||||
</SelectItem>
|
onChange: ({ value }) =>
|
||||||
</SelectGroup>
|
value.length > 3
|
||||||
</SelectContent>
|
? undefined
|
||||||
</Select>
|
: "You must enter a correct ",
|
||||||
</div>
|
}}
|
||||||
);
|
children={(field) => {
|
||||||
}}
|
return (
|
||||||
/>
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
<form.Field
|
<Label htmlFor="email">Email</Label>
|
||||||
name="password"
|
<Input
|
||||||
validators={{
|
name={field.name}
|
||||||
onChangeAsyncDebounceMs: 500,
|
value={field.state.value}
|
||||||
onChangeAsync: ({ value }) => {
|
onBlur={field.handleBlur}
|
||||||
if (
|
//type="number"
|
||||||
window.location.pathname.includes("/users") &&
|
onChange={(e) =>
|
||||||
value.length === 0
|
field.handleChange(
|
||||||
) {
|
e.target.value
|
||||||
return;
|
)
|
||||||
}
|
}
|
||||||
if (value.length < 4) {
|
/>
|
||||||
return "Password must be at least 4 characters long.";
|
{field.state.meta.errors.length ? (
|
||||||
}
|
<em>
|
||||||
|
{field.state.meta.errors.join(
|
||||||
|
","
|
||||||
|
)}
|
||||||
|
</em>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<form.Field
|
||||||
|
name="role"
|
||||||
|
//listeners={{onChange: ({value})=>{}}}
|
||||||
|
children={(field) => {
|
||||||
|
return (
|
||||||
|
<div className="m-2 min-w-48 max-w-96 p-2">
|
||||||
|
<Label htmlFor={field.name}>
|
||||||
|
Select role
|
||||||
|
</Label>
|
||||||
|
<Select
|
||||||
|
value={field.state.value}
|
||||||
|
onValueChange={field.handleChange}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="w-[180px]">
|
||||||
|
<SelectValue
|
||||||
|
id={field.name}
|
||||||
|
placeholder="Select Role"
|
||||||
|
/>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>
|
||||||
|
Roles
|
||||||
|
</SelectLabel>
|
||||||
|
<SelectItem value="viewer">
|
||||||
|
Viewer
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="operator">
|
||||||
|
Operator
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="manager">
|
||||||
|
Manager
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value="admin">
|
||||||
|
Admin
|
||||||
|
</SelectItem>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<form.Field
|
||||||
|
name="password"
|
||||||
|
validators={{
|
||||||
|
onChangeAsyncDebounceMs: 500,
|
||||||
|
onChangeAsync: ({ value }) => {
|
||||||
|
if (
|
||||||
|
window.location.pathname.includes(
|
||||||
|
"/users"
|
||||||
|
) &&
|
||||||
|
value.length === 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value.length < 4) {
|
||||||
|
return "Password must be at least 4 characters long.";
|
||||||
|
}
|
||||||
|
|
||||||
if (!/[A-Z]/.test(value)) {
|
if (!/[A-Z]/.test(value)) {
|
||||||
return "Password must contain at least one uppercase letter.";
|
return "Password must contain at least one uppercase letter.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!/[a-z]/.test(value)) {
|
if (!/[a-z]/.test(value)) {
|
||||||
return "Password must contain at least one lower case letter.";
|
return "Password must contain at least one lower case letter.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!/[0-9]/.test(value)) {
|
if (!/[0-9]/.test(value)) {
|
||||||
return "Password must contain at least one number.";
|
return "Password must contain at least one number.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(
|
!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(
|
||||||
value
|
value
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return "Password must contain at least one special character.";
|
return "Password must contain at least one special character.";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
children={(field) => {
|
children={(field) => {
|
||||||
return (
|
return (
|
||||||
<div className="m-2 p-2">
|
<div className="m-2 p-2">
|
||||||
<Label htmlFor="password">
|
<Label htmlFor="password">
|
||||||
Change Password
|
Change Password
|
||||||
</Label>
|
</Label>
|
||||||
<div className="mt-2 flex flex-row">
|
<div className="mt-2 flex flex-row">
|
||||||
<Input
|
<Input
|
||||||
className="min-w-48 max-w-96"
|
className="min-w-48 max-w-96"
|
||||||
name={field.name}
|
name={field.name}
|
||||||
value={field.state.value}
|
value={field.state.value}
|
||||||
onBlur={field.handleBlur}
|
onBlur={field.handleBlur}
|
||||||
//type="number"
|
//type="number"
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
field.handleChange(e.target.value)
|
field.handleChange(
|
||||||
}
|
e.target.value
|
||||||
/>
|
)
|
||||||
<Button
|
}
|
||||||
className="ml-2"
|
/>
|
||||||
onClick={() =>
|
<Button
|
||||||
field.handleChange(
|
className="ml-2"
|
||||||
generatePassword(8)
|
onClick={() =>
|
||||||
)
|
field.handleChange(
|
||||||
}
|
generatePassword(8)
|
||||||
>
|
)
|
||||||
Random password
|
}
|
||||||
</Button>
|
>
|
||||||
<DebugButton data={form.state.values} />
|
Random password
|
||||||
</div>
|
</Button>
|
||||||
{field.state.meta.errors.length ? (
|
<DebugButton
|
||||||
<em>{field.state.meta.errors.join(",")}</em>
|
data={form.state.values}
|
||||||
) : null}
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
{field.state.meta.errors.length ? (
|
||||||
}}
|
<em>
|
||||||
/>
|
{field.state.meta.errors.join(
|
||||||
</form>
|
","
|
||||||
<div>
|
)}
|
||||||
<Button onClick={form.handleSubmit}>Save</Button>
|
</em>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</LstCard>
|
||||||
|
<div>
|
||||||
|
<Button onClick={form.handleSubmit}>Save</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="m-2">
|
||||||
|
<LstCard>
|
||||||
|
<CardHeader>User Module / Role Access</CardHeader>
|
||||||
|
<UserRoles user={data.user} />
|
||||||
|
</LstCard>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
16
frontend/src/components/admin/user/components/UserRoles.tsx
Normal file
16
frontend/src/components/admin/user/components/UserRoles.tsx
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { useModuleStore } from "@/lib/store/useModuleStore";
|
||||||
|
//import { Checkbox } from "@radix-ui/react-checkbox";
|
||||||
|
|
||||||
|
export default function UserRoles(user: any) {
|
||||||
|
const { modules } = useModuleStore();
|
||||||
|
console.log(user);
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{modules?.map((m: any) => {
|
||||||
|
console.log(m);
|
||||||
|
return <Label>{m.name}</Label>;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import {Cylinder, Package, Truck} from "lucide-react";
|
import { Cylinder, Package, Truck } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
SidebarGroup,
|
SidebarGroup,
|
||||||
SidebarGroupContent,
|
SidebarGroupContent,
|
||||||
@@ -7,8 +7,8 @@ import {
|
|||||||
SidebarMenuButton,
|
SidebarMenuButton,
|
||||||
SidebarMenuItem,
|
SidebarMenuItem,
|
||||||
} from "../../ui/sidebar";
|
} from "../../ui/sidebar";
|
||||||
import {hasPageAccess} from "@/utils/userAccess";
|
import { hasPageAccess } from "@/utils/userAccess";
|
||||||
import {User} from "@/types/users";
|
import { User } from "@/types/users";
|
||||||
// this will need to be moved to a links section the db to make it more easy to remove and add
|
// this will need to be moved to a links section the db to make it more easy to remove and add
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
@@ -20,48 +20,64 @@ const items = [
|
|||||||
active: true,
|
active: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Bulk orders",
|
name: "Bulk orders",
|
||||||
url: "#",
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "#",
|
||||||
icon: Truck,
|
icon: Truck,
|
||||||
role: ["systemAdmin"],
|
role: ["systemAdmin"],
|
||||||
module: "logistics",
|
|
||||||
active: true,
|
active: true,
|
||||||
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Forecast",
|
name: "Forecast",
|
||||||
url: "#",
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "#",
|
||||||
icon: Truck,
|
icon: Truck,
|
||||||
role: ["systemAdmin"],
|
role: ["systemAdmin"],
|
||||||
module: "logistics",
|
|
||||||
active: true,
|
active: true,
|
||||||
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Ocme cycle counts",
|
name: "Ocme cycle counts",
|
||||||
url: "#",
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "#",
|
||||||
icon: Package,
|
icon: Package,
|
||||||
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
module: "logistics",
|
|
||||||
active: false,
|
active: false,
|
||||||
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Material Helper",
|
name: "Material Helper",
|
||||||
url: "/materialHelper/consumption",
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "/materialHelper/consumption",
|
||||||
icon: Package,
|
icon: Package,
|
||||||
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
module: "logistics",
|
|
||||||
active: true,
|
active: true,
|
||||||
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Ocme Cyclecount",
|
name: "Ocme Cyclecount",
|
||||||
url: "/cyclecount",
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "/cyclecount",
|
||||||
icon: Package,
|
icon: Package,
|
||||||
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
module: "logistics",
|
|
||||||
active: true,
|
active: true,
|
||||||
|
subSubModule: [],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function LogisticsSideBar({user, moduleID}: {user: User | null; moduleID: string}) {
|
export function LogisticsSideBar({
|
||||||
|
user,
|
||||||
|
moduleID,
|
||||||
|
}: {
|
||||||
|
user: User | null;
|
||||||
|
moduleID: string;
|
||||||
|
}) {
|
||||||
return (
|
return (
|
||||||
<SidebarGroup>
|
<SidebarGroup>
|
||||||
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
<SidebarGroupLabel>Logistics</SidebarGroupLabel>
|
||||||
@@ -70,14 +86,15 @@ export function LogisticsSideBar({user, moduleID}: {user: User | null; moduleID:
|
|||||||
{items.map((item) => (
|
{items.map((item) => (
|
||||||
<SidebarMenuItem key={item.title}>
|
<SidebarMenuItem key={item.title}>
|
||||||
<>
|
<>
|
||||||
{hasPageAccess(user, item.role, moduleID) && item.active && (
|
{hasPageAccess(user, item.role, moduleID) &&
|
||||||
<SidebarMenuButton asChild>
|
item.active && (
|
||||||
<a href={item.url}>
|
<SidebarMenuButton asChild>
|
||||||
<item.icon />
|
<a href={item.url}>
|
||||||
<span>{item.title}</span>
|
<item.icon />
|
||||||
</a>
|
<span>{item.title}</span>
|
||||||
</SidebarMenuButton>
|
</a>
|
||||||
)}
|
</SidebarMenuButton>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
</SidebarMenuItem>
|
</SidebarMenuItem>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ let lotColumns = [
|
|||||||
label: "AvDescription",
|
label: "AvDescription",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "LOT",
|
key: "lot",
|
||||||
label: "LotNumber",
|
label: "LotNumber",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -208,10 +208,14 @@ export default function Lots() {
|
|||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">
|
||||||
{lot.Alias}
|
{lot.Alias}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="font-medium">
|
<TableCell
|
||||||
{lot.LOT}
|
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
|
||||||
|
>
|
||||||
|
{lot.lot}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="font-medium">
|
<TableCell
|
||||||
|
className={`font-medium ${lot.ProlinkLot != lot.lot ? "text-red-500" : ""}`}
|
||||||
|
>
|
||||||
{lot.ProlinkLot}
|
{lot.ProlinkLot}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="font-medium">
|
<TableCell className="font-medium">
|
||||||
|
|||||||
@@ -1,20 +1,28 @@
|
|||||||
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import {useModuleStore} from "../../lib/store/useModuleStore";
|
import { useModuleStore } from "../../lib/store/useModuleStore";
|
||||||
import {useEffect} from "react";
|
import { useEffect } from "react";
|
||||||
import {useSettingStore} from "@/lib/store/useSettings";
|
import { useSettingStore } from "@/lib/store/useSettings";
|
||||||
//import {useGetUserRoles} from "@/lib/store/useGetRoles";
|
import { useGetUserRoles } from "@/lib/store/useGetRoles";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
export const SessionProvider = ({children}: {children: React.ReactNode}) => {
|
export const SessionProvider = ({
|
||||||
const {fetchModules} = useModuleStore();
|
children,
|
||||||
const {fetchSettings} = useSettingStore();
|
}: {
|
||||||
//const {fetchUserRoles} = useGetUserRoles();
|
children: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
const { fetchModules } = useModuleStore();
|
||||||
|
const { fetchSettings } = useSettingStore();
|
||||||
|
const { fetchUserRoles } = useGetUserRoles();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchModules();
|
fetchModules();
|
||||||
fetchSettings();
|
fetchSettings();
|
||||||
//fetchUserRoles();
|
fetchUserRoles();
|
||||||
}, []);
|
}, []);
|
||||||
return <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>;
|
return (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
{children}
|
||||||
|
</QueryClientProvider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ function Checkbox({
|
|||||||
<CheckboxPrimitive.Root
|
<CheckboxPrimitive.Root
|
||||||
data-slot="checkbox"
|
data-slot="checkbox"
|
||||||
className={cn(
|
className={cn(
|
||||||
"peer border-input data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {create} from "zustand";
|
import { create } from "zustand";
|
||||||
import {useSessionStore} from "./sessionStore";
|
import { Modules } from "@/types/modules";
|
||||||
import {Modules} from "@/types/modules";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
interface SettingState {
|
interface SettingState {
|
||||||
@@ -15,15 +14,17 @@ interface FetchModulesResponse {
|
|||||||
|
|
||||||
export const useGetUserRoles = create<SettingState>()((set) => ({
|
export const useGetUserRoles = create<SettingState>()((set) => ({
|
||||||
userRoles: [],
|
userRoles: [],
|
||||||
setUserRoles: (userRoles) => set({userRoles}),
|
setUserRoles: (userRoles) => set({ userRoles }),
|
||||||
fetchUserRoles: async () => {
|
fetchUserRoles: async () => {
|
||||||
try {
|
try {
|
||||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||||
const {token} = useSessionStore();
|
const token = localStorage.getItem("auth_token");
|
||||||
const response = await axios.get("/api/auth/getuseraccess", {headers: {Authorization: `Bearer ${token}`}});
|
const response = await axios.get("/api/auth/getuseraccess", {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
const data: FetchModulesResponse = response.data; //await response.json();
|
const data: FetchModulesResponse = response.data; //await response.json();
|
||||||
//console.log(data);
|
//console.log(data);
|
||||||
set({userRoles: data.data});
|
set({ userRoles: data.data });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch settings:", error);
|
console.error("Failed to fetch settings:", error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export type LotType = {
|
export type LotType = {
|
||||||
AV: number;
|
AV: number;
|
||||||
Alias: string;
|
Alias: string;
|
||||||
LOT: number;
|
lot: number;
|
||||||
LabelOnlineID: number;
|
LabelOnlineID: number;
|
||||||
MachineDescription: string;
|
MachineDescription: string;
|
||||||
MachineID: number;
|
MachineID: number;
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
"commit": "cz",
|
"commit": "cz",
|
||||||
"prodinstall": "npm i --omit=dev && npm run db:migrate",
|
"prodinstall": "npm i --omit=dev && npm run db:migrate",
|
||||||
"checkupdates": "npx npm-check-updates",
|
"checkupdates": "npx npm-check-updates",
|
||||||
"testingCode": "dotenvx run -f .env -- tsx watch database/testFiles/checkServerData.ts"
|
"testingCode": "dotenvx run -f .env -- tsx watch server/services/notifications/controller/notifications/tiIntergrationV1.ts"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"commitizen": {
|
"commitizen": {
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"admConfig": {
|
"admConfig": {
|
||||||
"build": 152,
|
"build": 169,
|
||||||
"oldBuild": "backend-0.1.3.zip"
|
"oldBuild": "backend-0.1.3.zip"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ type UpdateServerResponse = {
|
|||||||
|
|
||||||
export const updateServer = async (
|
export const updateServer = async (
|
||||||
devApp: string,
|
devApp: string,
|
||||||
server: string | null
|
server: string | null,
|
||||||
|
all?: boolean | null
|
||||||
): Promise<UpdateServerResponse> => {
|
): Promise<UpdateServerResponse> => {
|
||||||
const app = await getAppInfo(devApp);
|
const app = await getAppInfo(devApp);
|
||||||
const serverInfo = await db
|
const serverInfo = await db
|
||||||
@@ -34,7 +35,7 @@ export const updateServer = async (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serverInfo[0].isUpgrading) {
|
if (serverInfo[0].isUpgrading && !all) {
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
"lst",
|
"lst",
|
||||||
@@ -165,6 +166,9 @@ export const updateServer = async (
|
|||||||
export async function processAllServers(devApp: string) {
|
export async function processAllServers(devApp: string) {
|
||||||
const servers = await db.select().from(serverData);
|
const servers = await db.select().from(serverData);
|
||||||
|
|
||||||
|
//change all servers to be upgrading
|
||||||
|
await db.update(serverData).set({ isUpgrading: true });
|
||||||
|
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
"lst",
|
"lst",
|
||||||
@@ -176,7 +180,8 @@ export async function processAllServers(devApp: string) {
|
|||||||
try {
|
try {
|
||||||
const updateToServer = await updateServer(
|
const updateToServer = await updateServer(
|
||||||
devApp,
|
devApp,
|
||||||
server.plantToken
|
server.plantToken,
|
||||||
|
true
|
||||||
);
|
);
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
@@ -186,7 +191,11 @@ export async function processAllServers(devApp: string) {
|
|||||||
);
|
);
|
||||||
count = count + 1;
|
count = count + 1;
|
||||||
|
|
||||||
//return {success: true, message: `${server.sName} was updated.`, data: updateToServer};
|
// return {
|
||||||
|
// success: true,
|
||||||
|
// message: `${server.sName} was updated.`,
|
||||||
|
// data: updateToServer,
|
||||||
|
// };
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
createLog(
|
createLog(
|
||||||
"info",
|
"info",
|
||||||
@@ -194,7 +203,15 @@ export async function processAllServers(devApp: string) {
|
|||||||
"serverUpdater",
|
"serverUpdater",
|
||||||
`Error updating ${server.sName}: ${error.message}`
|
`Error updating ${server.sName}: ${error.message}`
|
||||||
);
|
);
|
||||||
//return {success: false, message: `Error updating ${server.sName}: ${error.message}`};
|
// return {
|
||||||
|
// success: false,
|
||||||
|
// message: `Error updating ${server.sName}: ${error.message}`,
|
||||||
|
// };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: `All Servers are being updated this will take some time.`,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
29
server/services/dataMart/controller/getCustomerInventory.ts
Normal file
29
server/services/dataMart/controller/getCustomerInventory.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { query } from "../../sqlServer/prodSqlServer.js";
|
||||||
|
import { customerInvNoHold } from "../../sqlServer/querys/dataMart/customerInventoryQuerys.js";
|
||||||
|
|
||||||
|
export const getCurrentCustomerInv = async (customer: any | null) => {
|
||||||
|
let updatedQuery = customerInvNoHold;
|
||||||
|
|
||||||
|
if (customer) {
|
||||||
|
//console.log(data.customer);
|
||||||
|
updatedQuery = customerInvNoHold.replaceAll(
|
||||||
|
"--and IdAdressen",
|
||||||
|
`and IdAdressen = ${customer}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const inventory = await query(updatedQuery, "Get active inventory");
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "All customer inventory minus holds",
|
||||||
|
data: inventory,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "There was an error getting the inventory",
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
66
server/services/dataMart/controller/getOpenOrders.ts
Normal file
66
server/services/dataMart/controller/getOpenOrders.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
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 { query } from "../../sqlServer/prodSqlServer.js";
|
||||||
|
import { openOrders } from "../../sqlServer/querys/dataMart/openOrders.js";
|
||||||
|
|
||||||
|
export const getOpenOrders = async (data: any | null) => {
|
||||||
|
const { data: plantToken, error: plantError } = await tryCatch(
|
||||||
|
db.select().from(settings).where(eq(settings.name, "plantToken"))
|
||||||
|
);
|
||||||
|
if (plantError) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting Settings",
|
||||||
|
data: plantError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
let orders = [];
|
||||||
|
|
||||||
|
let updatedQuery = openOrders;
|
||||||
|
|
||||||
|
// start days can be sent over
|
||||||
|
if (data?.sDay) {
|
||||||
|
updatedQuery = updatedQuery.replaceAll("[sDay]", data.sDay[0]);
|
||||||
|
} else {
|
||||||
|
updatedQuery = updatedQuery.replaceAll("[sDay]", "15");
|
||||||
|
}
|
||||||
|
|
||||||
|
// end days can be sent over
|
||||||
|
if (data?.eDay) {
|
||||||
|
updatedQuery = updatedQuery.replaceAll("[eDay]", data.eDay[0]);
|
||||||
|
} else {
|
||||||
|
updatedQuery = updatedQuery.replaceAll("[eDay]", "5");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
orders = await query(updatedQuery, "Get active openorders");
|
||||||
|
} catch (error) {
|
||||||
|
return { success: false, message: "Current open orders", data: orders };
|
||||||
|
}
|
||||||
|
|
||||||
|
// add plant token in
|
||||||
|
const pOrders = orders.map((item: any) => {
|
||||||
|
// const dateCon = new Date(item.loadingDate).toLocaleString("en-US", {
|
||||||
|
// month: "numeric",
|
||||||
|
// day: "numeric",
|
||||||
|
// year: "numeric",
|
||||||
|
// hour: "2-digit",
|
||||||
|
// minute: "2-digit",
|
||||||
|
// hour12: false,
|
||||||
|
// });
|
||||||
|
|
||||||
|
//const dateCon = new Date(item.loadingDate).toISOString().replace("T", " ").split(".")[0];
|
||||||
|
const dateCon = new Date(item.loadingDate).toISOString().split("T")[0];
|
||||||
|
//const delDate = new Date(item.deliveryDate).toISOString().replace("T", " ").split(".")[0];
|
||||||
|
const delDate = new Date(item.deliveryDate).toISOString().split("T")[0];
|
||||||
|
return {
|
||||||
|
plantToken: plantToken[0].value,
|
||||||
|
...item,
|
||||||
|
loadingDate: dateCon,
|
||||||
|
deliveryDate: delDate,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return { success: true, message: "Current open orders", data: pOrders };
|
||||||
|
};
|
||||||
@@ -1,14 +1,25 @@
|
|||||||
|
import { createLog } from "../../logger/logger.js";
|
||||||
import { query } from "../../sqlServer/prodSqlServer.js";
|
import { query } from "../../sqlServer/prodSqlServer.js";
|
||||||
import {
|
import {
|
||||||
totalInvNoRn,
|
totalInvNoRn,
|
||||||
totalInvRn,
|
totalInvRn,
|
||||||
} from "../../sqlServer/querys/dataMart/totalINV.js";
|
} from "../../sqlServer/querys/dataMart/totalINV.js";
|
||||||
|
|
||||||
export const getINV = async () => {
|
export const getINV = async (rn: boolean) => {
|
||||||
let inventory: any = [];
|
let inventory: any = [];
|
||||||
|
|
||||||
let updatedQuery = totalInvNoRn;
|
let updatedQuery = totalInvNoRn;
|
||||||
|
|
||||||
|
if (rn) {
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"datamart",
|
||||||
|
"datamart",
|
||||||
|
"The user requested the running numbers this could take a while."
|
||||||
|
);
|
||||||
|
updatedQuery = totalInvRn;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
inventory = await query(updatedQuery, "Gets Curruent inv");
|
inventory = await query(updatedQuery, "Gets Curruent inv");
|
||||||
return { success: true, message: "Current inv", data: inventory };
|
return { success: true, message: "Current inv", data: inventory };
|
||||||
|
|||||||
@@ -2,10 +2,20 @@ import { OpenAPIHono } from "@hono/zod-openapi";
|
|||||||
import activequerys from "./route/getCurrentQuerys.js";
|
import activequerys from "./route/getCurrentQuerys.js";
|
||||||
import getArticles from "./route/getActiveArticles.js";
|
import getArticles from "./route/getActiveArticles.js";
|
||||||
import currentInv from "./route/getInventory.js";
|
import currentInv from "./route/getInventory.js";
|
||||||
|
import getCustomerInv from "./route/getCustomerInv.js";
|
||||||
|
import getOpenOrders from "./route/getOpenOrders.js";
|
||||||
|
import siloAdjustments from "./route/getSiloAdjustments.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const routes = [activequerys, getArticles, currentInv] as const;
|
const routes = [
|
||||||
|
activequerys,
|
||||||
|
getArticles,
|
||||||
|
currentInv,
|
||||||
|
getCustomerInv,
|
||||||
|
getOpenOrders,
|
||||||
|
siloAdjustments,
|
||||||
|
] as const;
|
||||||
|
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
app.route("/datamart", route);
|
app.route("/datamart", route);
|
||||||
|
|||||||
@@ -23,25 +23,26 @@ const current: any = [
|
|||||||
// endpoint: "/api/v1/masterData/getMissingPKGData",
|
// endpoint: "/api/v1/masterData/getMissingPKGData",
|
||||||
// description: "Returns all packaging data that is missing either printer, layout, or carton layout",
|
// description: "Returns all packaging data that is missing either printer, layout, or carton layout",
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// name: "getCustomerInventory",
|
name: "getCustomerInventory",
|
||||||
// endpoint: "/api/v1/masterData/getCustomerInventory",
|
endpoint: "/api/datamart/getcustomerinventory",
|
||||||
// description: "Returns specific customer inventory based on there address ID.",
|
description:
|
||||||
// criteria: "customer",
|
"Returns specific customer inventory based on there address ID.",
|
||||||
// },
|
criteria: "customer",
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// name: "getPalletLabels",
|
// name: "getPalletLabels",
|
||||||
// endpoint: "/api/v1/masterData/getPalletLabels",
|
// endpoint: "/api/v1/masterData/getPalletLabels",
|
||||||
// description: "Returns specific amount of pallets RN, Needs label number and printer, Specfic to Dayton.",
|
// description: "Returns specific amount of pallets RN, Needs label number and printer, Specfic to Dayton.",
|
||||||
// criteria: "runningNumber,printerName,count",
|
// criteria: "runningNumber,printerName,count",
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// name: "getOpenOrders",
|
name: "getopenorders",
|
||||||
// endpoint: "/api/v1/masterData/getOpenOrders",
|
endpoint: "/api/datamart/getopenorders",
|
||||||
// description:
|
description:
|
||||||
// "Returns open orders based on day count sent over, sDay 15 days in the past eDay 5 days in the future, can be left empty for this default days",
|
"Returns open orders based on day count sent over, sDay 15 days in the past eDay 5 days in the future, can be left empty for this default days",
|
||||||
// criteria: "sDay,eDay",
|
criteria: "sDay,eDay",
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// name: "getOpenIncoming",
|
// name: "getOpenIncoming",
|
||||||
// endpoint: "/api/v1/masterData/getOpenIncoming",
|
// endpoint: "/api/v1/masterData/getOpenIncoming",
|
||||||
@@ -60,7 +61,7 @@ const current: any = [
|
|||||||
// description: "Returns all inventory, by default excludes running numebrs, also excludes inv locations.",
|
// description: "Returns all inventory, by default excludes running numebrs, also excludes inv locations.",
|
||||||
description:
|
description:
|
||||||
"Returns all inventory, excludes inv locations. no running numbers",
|
"Returns all inventory, excludes inv locations. no running numbers",
|
||||||
//criteria: "includeRunnningNumbers", // uncomment this out once the improt process can be faster
|
criteria: "includeRunnningNumbers", // uncomment this out once the improt process can be faster
|
||||||
},
|
},
|
||||||
// {
|
// {
|
||||||
// name: "getOpenOrderUpdates",
|
// name: "getOpenOrderUpdates",
|
||||||
@@ -69,13 +70,14 @@ const current: any = [
|
|||||||
// description: "Returns all orders based on customer id, leaving empty will pull everythinng in.",
|
// description: "Returns all orders based on customer id, leaving empty will pull everythinng in.",
|
||||||
// criteria: "customer", // uncomment this out once the improt process can be faster
|
// criteria: "customer", // uncomment this out once the improt process can be faster
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// name: "getSiloAdjustment",
|
name: "getSiloAdjustment",
|
||||||
// endpoint: "/api/v1/warehouse/getSiloAdjustment",
|
endpoint: "/api/v1/warehouse/getSiloAdjustment",
|
||||||
// // description: "Returns all inventory, by default excludes running numebrs, also excludes inv locations.",
|
// description: "Returns all inventory, by default excludes running numebrs, also excludes inv locations.",
|
||||||
// description: "Returns all siloadjustments in selected date range IE: 1/1/2025 to 1/31/2025",
|
description:
|
||||||
// criteria: "startDate,endDate", // uncomment this out once the improt process can be faster
|
"Returns all siloadjustments in selected date range IE: 1/1/2025 to 1/31/2025",
|
||||||
// },
|
criteria: "startDate,endDate", // uncomment this out once the improt process can be faster
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
@@ -95,6 +97,7 @@ app.openapi(
|
|||||||
return c.json({
|
return c.json({
|
||||||
success: true,
|
success: true,
|
||||||
message: "All Current Active Querys.",
|
message: "All Current Active Querys.",
|
||||||
|
sheetVersion: 2.5,
|
||||||
data: current,
|
data: current,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
53
server/services/dataMart/route/getCustomerInv.ts
Normal file
53
server/services/dataMart/route/getCustomerInv.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { getINV } from "../controller/getinventory.js";
|
||||||
|
import { getCurrentCustomerInv } from "../controller/getCustomerInventory.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
const Body = z.object({
|
||||||
|
includeRunnningNumbers: z.string().openapi({ example: "x" }),
|
||||||
|
});
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["dataMart"],
|
||||||
|
summary: "Returns All customer minus holds.",
|
||||||
|
method: "get",
|
||||||
|
path: "/getcustomerinventory",
|
||||||
|
request: {
|
||||||
|
body: {
|
||||||
|
content: {
|
||||||
|
"application/json": { schema: Body },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const customer: string = c.req.query("customer") ?? "";
|
||||||
|
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
//apiHit(c, { endpoint: `api/logger/logs/id` });
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
getCurrentCustomerInv(customer ? customer : null)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "There was an error getting the inv.",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.json({
|
||||||
|
success: data.success,
|
||||||
|
message: data.message,
|
||||||
|
data: data.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -4,34 +4,33 @@ import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
|||||||
import { getINV } from "../controller/getinventory.js";
|
import { getINV } from "../controller/getinventory.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono({ strict: false });
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
const Body = z.object({
|
||||||
|
includeRunnningNumbers: z.string().openapi({ example: "x" }),
|
||||||
|
});
|
||||||
app.openapi(
|
app.openapi(
|
||||||
createRoute({
|
createRoute({
|
||||||
tags: ["dataMart"],
|
tags: ["dataMart"],
|
||||||
summary: "Returns All current inventory.",
|
summary: "Returns All current inventory.",
|
||||||
method: "get",
|
method: "get",
|
||||||
path: "/getinventory",
|
path: "/getinventory",
|
||||||
// request: {
|
request: {
|
||||||
// body: {
|
body: {
|
||||||
// content: {
|
content: {
|
||||||
// "application/json": { schema: Body },
|
"application/json": { schema: Body },
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
// },
|
},
|
||||||
responses: responses(),
|
responses: responses(),
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
// const { data: body, error } = await c.req.json();
|
const includeRunnningNumbers: string =
|
||||||
|
c.req.query("includeRunnningNumbers") ?? "";
|
||||||
|
|
||||||
// if (error) {
|
|
||||||
// return c.json({
|
|
||||||
// success: false,
|
|
||||||
// message: "Missing data please try again.",
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// make sure we have a vaid user being accessed thats really logged in
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
//apiHit(c, { endpoint: `api/logger/logs/id` });
|
//apiHit(c, { endpoint: `api/logger/logs/id` });
|
||||||
const { data, error } = await tryCatch(getINV());
|
const { data, error } = await tryCatch(
|
||||||
|
getINV(includeRunnningNumbers?.length > 0 ? true : false)
|
||||||
|
);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return c.json(
|
return c.json(
|
||||||
|
|||||||
52
server/services/dataMart/route/getOpenOrders.ts
Normal file
52
server/services/dataMart/route/getOpenOrders.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { getOpenOrders } from "../controller/getOpenOrders.js";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
// const Body = z.object({
|
||||||
|
// includeRunnningNumbers: z.string().openapi({ example: "x" }),
|
||||||
|
// });
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["dataMart"],
|
||||||
|
summary: "Returns All open orders.",
|
||||||
|
method: "get",
|
||||||
|
path: "/getopenorders",
|
||||||
|
// request: {
|
||||||
|
// body: {
|
||||||
|
// content: {
|
||||||
|
// "application/json": { schema: Body },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const customer: any = c.req.queries();
|
||||||
|
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
//apiHit(c, { endpoint: `api/logger/logs/id` });
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
getOpenOrders(customer ? customer : null)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "There was an error getting the inv.",
|
||||||
|
data: error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.json({
|
||||||
|
success: data.success,
|
||||||
|
message: data.message,
|
||||||
|
data: data.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
69
server/services/dataMart/route/getSiloAdjustments.ts
Normal file
69
server/services/dataMart/route/getSiloAdjustments.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { getOpenOrders } from "../controller/getOpenOrders.js";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
// const Body = z.object({
|
||||||
|
// includeRunnningNumbers: z.string().openapi({ example: "x" }),
|
||||||
|
// });
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["dataMart"],
|
||||||
|
summary: "Returns All open orders.",
|
||||||
|
method: "get",
|
||||||
|
path: "/getsilosdjustment",
|
||||||
|
// request: {
|
||||||
|
// body: {
|
||||||
|
// content: {
|
||||||
|
// "application/json": { schema: Body },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const customer: any = c.req.queries();
|
||||||
|
|
||||||
|
// make sure we have a vaid user being accessed thats really logged in
|
||||||
|
//apiHit(c, { endpoint: `api/logger/logs/id` });
|
||||||
|
// const { data, error } = await tryCatch(
|
||||||
|
// getOpenOrders(customer ? customer : null)
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (error) {
|
||||||
|
// return c.json(
|
||||||
|
// {
|
||||||
|
// success: false,
|
||||||
|
// message: "There was an error getting the inv.",
|
||||||
|
// data: error,
|
||||||
|
// },
|
||||||
|
// 400
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
const dates: any = c.req.queries();
|
||||||
|
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
axios.get(
|
||||||
|
`http://localhost:4400/api/v1/warehouse/getSilosAdjustment?startDate=${dates.startDate[0]}&endDate=${dates.endDate[0]}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return c.json({
|
||||||
|
success: false,
|
||||||
|
message: "Error running query",
|
||||||
|
data: error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.json({
|
||||||
|
success: data?.data.success,
|
||||||
|
message: data?.data.message,
|
||||||
|
data: data?.data.data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
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 axios from "axios";
|
||||||
|
import { labelData } from "../../../sqlServer/querys/materialHelpers/labelInfo.js";
|
||||||
|
|
||||||
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
|
import { createLog } from "../../../logger/logger.js";
|
||||||
|
|
||||||
|
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
||||||
|
|
||||||
type Data = {
|
type Data = {
|
||||||
runningNr: string;
|
runningNr: string;
|
||||||
lotNum: number;
|
lotNum: number;
|
||||||
};
|
};
|
||||||
export const consumeMaterial = async (data: Data, prod: any) => {
|
export const consumeMaterial = async (data: Data, prod: any) => {
|
||||||
const {runningNr, lotNum} = data;
|
const { runningNr, lotNum } = data;
|
||||||
// replace the rn
|
// replace the rn
|
||||||
|
|
||||||
const rnReplace = labelData.replaceAll("[rn]", runningNr);
|
const rnReplace = labelData.replaceAll("[rn]", runningNr);
|
||||||
@@ -21,7 +22,12 @@ export const consumeMaterial = async (data: Data, prod: any) => {
|
|||||||
barcode = await query(rnReplace, "labelData");
|
barcode = await query(rnReplace, "labelData");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
createLog("error", prod.user.username, "logistics", `Error getting barcode: ${error}`);
|
createLog(
|
||||||
|
"error",
|
||||||
|
prod.user.username,
|
||||||
|
"logistics",
|
||||||
|
`Error getting barcode: ${error}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (barcode.length === 0) {
|
if (barcode.length === 0) {
|
||||||
@@ -32,7 +38,9 @@ export const consumeMaterial = async (data: Data, prod: any) => {
|
|||||||
//throw Error("The provided runningNr is not in stock");
|
//throw Error("The provided runningNr is not in stock");
|
||||||
}
|
}
|
||||||
// create the url to post
|
// create the url to post
|
||||||
const url = await prodEndpointCreation("/public/v1.0/IssueMaterial/ConsumeNonPreparedManualMaterial");
|
const url = await prodEndpointCreation(
|
||||||
|
"/public/v1.0/IssueMaterial/ConsumeNonPreparedManualMaterial"
|
||||||
|
);
|
||||||
|
|
||||||
const consumeSomething = {
|
const consumeSomething = {
|
||||||
productionLot: lotNum,
|
productionLot: lotNum,
|
||||||
@@ -47,8 +55,16 @@ export const consumeMaterial = async (data: Data, prod: any) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
//console.log(results);
|
//console.log(results);
|
||||||
return {success: true, message: "Material was consumed", status: results.status};
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Material was consumed",
|
||||||
|
status: results.status,
|
||||||
|
};
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
return {success: false, status: 200, message: error.response?.data.errors[0].message};
|
return {
|
||||||
|
success: false,
|
||||||
|
status: 200,
|
||||||
|
message: error.response?.data.errors[0].message,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
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 axios from "axios";
|
||||||
import { laneInfo } from "../../sqlServer/querys/materialHelpers/laneInfo.js";
|
import { labelData } from "../../../sqlServer/querys/materialHelpers/labelInfo.js";
|
||||||
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
import { laneInfo } from "../../../sqlServer/querys/materialHelpers/laneInfo.js";
|
||||||
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
|
import { createLog } from "../../../logger/logger.js";
|
||||||
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
|
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
||||||
type Data = {
|
type Data = {
|
||||||
runningNr: string;
|
runningNr: string;
|
||||||
laneName: string;
|
laneName: string;
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
import {createRoute, OpenAPIHono, z} from "@hono/zod-openapi";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
import {authMiddleware} from "../../auth/middleware/authMiddleware.js";
|
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
|
||||||
import {apiHit} from "../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
import {consumeMaterial} from "../controller/consumeMaterial.js";
|
|
||||||
import {verify} from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
|
import { consumeMaterial } from "../controller/materials/consumeMaterial.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const responseSchema = z.object({
|
const responseSchema = z.object({
|
||||||
success: z.boolean().optional().openapi({example: true}),
|
success: z.boolean().optional().openapi({ example: true }),
|
||||||
message: z.string().optional().openapi({example: "user access"}),
|
message: z.string().optional().openapi({ example: "user access" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
app.openapi(
|
app.openapi(
|
||||||
@@ -18,24 +19,25 @@ app.openapi(
|
|||||||
method: "post",
|
method: "post",
|
||||||
path: "/consume",
|
path: "/consume",
|
||||||
middleware: authMiddleware,
|
middleware: authMiddleware,
|
||||||
description: "Provided a running number and lot number you can consume material.",
|
description:
|
||||||
|
"Provided a running number and lot number you can consume material.",
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: {"application/json": {schema: responseSchema}},
|
content: { "application/json": { schema: responseSchema } },
|
||||||
description: "stopped",
|
description: "stopped",
|
||||||
},
|
},
|
||||||
400: {
|
400: {
|
||||||
content: {"application/json": {schema: responseSchema}},
|
content: { "application/json": { schema: responseSchema } },
|
||||||
description: "Failed to stop",
|
description: "Failed to stop",
|
||||||
},
|
},
|
||||||
401: {
|
401: {
|
||||||
content: {"application/json": {schema: responseSchema}},
|
content: { "application/json": { schema: responseSchema } },
|
||||||
description: "Failed to stop",
|
description: "Failed to stop",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
apiHit(c, {endpoint: "api/sqlProd/close"});
|
apiHit(c, { endpoint: "api/sqlProd/close" });
|
||||||
const authHeader = c.req.header("Authorization");
|
const authHeader = c.req.header("Authorization");
|
||||||
const token = authHeader?.split("Bearer ")[1] || "";
|
const token = authHeader?.split("Bearer ")[1] || "";
|
||||||
|
|
||||||
@@ -45,14 +47,24 @@ app.openapi(
|
|||||||
//return apiReturn(c, true, access?.message, access?.data, 200);
|
//return apiReturn(c, true, access?.message, access?.data, 200);
|
||||||
const data = await c.req.json();
|
const data = await c.req.json();
|
||||||
const consume = await consumeMaterial(data, payload);
|
const consume = await consumeMaterial(data, payload);
|
||||||
return c.json({success: consume?.success, message: consume?.message}, 200);
|
return c.json(
|
||||||
|
{ success: consume?.success, message: consume?.message },
|
||||||
|
200
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//console.log(error);
|
//console.log(error);
|
||||||
//return apiReturn(c, false, "Error in setting the user access", error, 400);
|
//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);
|
return c.json(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: "Missing data please try again",
|
||||||
|
error,
|
||||||
|
},
|
||||||
|
400
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return c.json({success: false, message: "Unauthorized"}, 401);
|
return c.json({ success: false, message: "Unauthorized" }, 401);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
|||||||
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
|
import { authMiddleware } from "../../auth/middleware/authMiddleware.js";
|
||||||
import { apiHit } from "../../../globalUtils/apiHits.js";
|
import { apiHit } from "../../../globalUtils/apiHits.js";
|
||||||
import { verify } from "hono/jwt";
|
import { verify } from "hono/jwt";
|
||||||
import { returnMaterial } from "../controller/returnMaterial.js";
|
import { returnMaterial } from "../controller/materials/returnMaterial.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export default async function reprintLabelMonitor(notifyData: any) {
|
|||||||
) {
|
) {
|
||||||
//send the email :D
|
//send the email :D
|
||||||
const emailSetup = {
|
const emailSetup = {
|
||||||
emailTo: notifyData.emails,
|
email: notifyData.emails,
|
||||||
subject: `Alert! Downtime recorded greater than ${
|
subject: `Alert! Downtime recorded greater than ${
|
||||||
notifyData.notifiySettings?.duration
|
notifyData.notifiySettings?.duration
|
||||||
}min ${
|
}min ${
|
||||||
|
|||||||
@@ -65,7 +65,10 @@ export default async function reprintLabelMonitor(notifyData: any) {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
//update the time check
|
//update the time check
|
||||||
notifyQuery = notifyQuery.replaceAll("[timeCheck]", notifyData.checkTime);
|
notifyQuery = notifyQuery.replaceAll(
|
||||||
|
"[timeCheck]",
|
||||||
|
notifyData.checkInterval
|
||||||
|
);
|
||||||
notifyQuery = notifyQuery.replaceAll(
|
notifyQuery = notifyQuery.replaceAll(
|
||||||
"[locations]",
|
"[locations]",
|
||||||
notifyData.notifiySettings.locations
|
notifyData.notifiySettings.locations
|
||||||
@@ -82,13 +85,13 @@ export default async function reprintLabelMonitor(notifyData: any) {
|
|||||||
// update the count with the result
|
// update the count with the result
|
||||||
|
|
||||||
const emailSetup = {
|
const emailSetup = {
|
||||||
emailTo: notifyData.emails,
|
email: notifyData.emails,
|
||||||
subject: `Alert! Pallets in production greater than ${notifyData.checkTime} ${notifyData.timeType}`,
|
subject: `Alert! Pallets in production greater than ${notifyData.checkTime} ${notifyData.timeType}`,
|
||||||
template: "productionCheck",
|
template: "productionCheck",
|
||||||
context: {
|
context: {
|
||||||
items: prod,
|
items: prod,
|
||||||
count: prod.length,
|
count: prod.length,
|
||||||
checkTime: notifyData.checkTime,
|
checkTime: notifyData.checkInterval,
|
||||||
timeCheck: notifyData.timeType,
|
timeCheck: notifyData.timeType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
// SELECT count(*) FROM V_EtikettenGedruckt where AnzahlGedruckterKopien > 2 and CONVERT(varchar(5), Add_Date,108) not like CONVERT(varchar(5), Upd_Date,108) and Upd_Date > DATEADD(SECOND, -30,getdate()) and VpkVorschriftBez not like '%$%'
|
|
||||||
|
|
||||||
import { eq, sql } from "drizzle-orm";
|
import { eq, sql } from "drizzle-orm";
|
||||||
import { db } from "../../../../../database/dbclient.js";
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
import { notifications } from "../../../../../database/schema/notifications.js";
|
import { notifications } from "../../../../../database/schema/notifications.js";
|
||||||
@@ -7,152 +5,121 @@ import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
|||||||
import { createLog } from "../../../logger/logger.js";
|
import { createLog } from "../../../logger/logger.js";
|
||||||
import { query } from "../../../sqlServer/prodSqlServer.js";
|
import { query } from "../../../sqlServer/prodSqlServer.js";
|
||||||
import { sendEmail } from "../sendMail.js";
|
import { sendEmail } from "../sendMail.js";
|
||||||
|
import { blockQuery } from "../../../sqlServer/querys/notifications/blocking.js";
|
||||||
export interface Blocking {
|
|
||||||
HumanReadableId?: number;
|
|
||||||
subject?: string;
|
|
||||||
}
|
|
||||||
export default async function qualityBlockingMonitor(notifyData: any) {
|
export default async function qualityBlockingMonitor(notifyData: any) {
|
||||||
createLog("info", "notify", "notify", `monitoring ${notifyData.name}`);
|
createLog("info", "blcoking", "notify", `monitoring ${notifyData.name}`);
|
||||||
if (notifyData.emails === "") {
|
if (notifyData.emails === "") {
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
"notify",
|
"blocking",
|
||||||
"notify",
|
"notify",
|
||||||
`There are no emails set for ${notifyData.name}`
|
`There are no emails set for ${notifyData.name}`
|
||||||
);
|
);
|
||||||
|
return {
|
||||||
return;
|
success: false,
|
||||||
|
message: `There are no emails set for ${notifyData.name}`,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let blockQuery = `
|
const { data: noti, error: notiError } = await tryCatch(
|
||||||
SELECT
|
db
|
||||||
'Alert! new blocking order: #' + cast(HumanReadableId as varchar) + ' - ' + ArticleVariantDescription as subject,
|
.select()
|
||||||
cast([HumanReadableId] as varchar) as blockingNumber,
|
.from(notifications)
|
||||||
[ArticleVariantDescription] as article,
|
.where(eq(notifications.name, notifyData.name))
|
||||||
cast([CustomerHumanReadableId] as varchar) + ' - ' + [CustomerDescription] as customer,
|
|
||||||
convert(varchar(10), [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].[BlockingDate], 101) + ' - ' + convert(varchar(5), [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].[BlockingDate], 108) as blockingDate,
|
|
||||||
cast(ArticleVariantHumanReadableId as varchar) + ' - ' + ArticleVariantDescription as av,
|
|
||||||
case when [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].Remark = '' or [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].Remark is NULL then 'Please reach out to quality for the reason this was placed on hold as a remark was not entered during the blocking processs' else [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].Remark end as remark,
|
|
||||||
cast(FORMAT(TotalAmountOfPieces, '###,###') as varchar) + ' / ' + cast(LoadingUnit as varchar) as peicesAndLoadingUnits,
|
|
||||||
[test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].ProductionLotHumanReadableId as lotNumber,
|
|
||||||
cast(IdGlobalBlockingDefectsGroup as varchar) + ' - ' + BD.Description as mainDefectGroup,
|
|
||||||
cast(IdGlobalBlockingDefect as varchar) + ' - ' + MD.Description as mainDefect,
|
|
||||||
sent=0,
|
|
||||||
lot.MachineLocation as line,
|
|
||||||
HumanReadableId
|
|
||||||
FROM [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder] (nolock)
|
|
||||||
|
|
||||||
/*** Join 1.0 table to get correct id info to link ***/
|
|
||||||
join
|
|
||||||
[AlplaPROD_test1].[dbo].[T_BlockingOrders] (nolock) AS BO
|
|
||||||
on [HumanReadableId] = BO.[IdBlockingOrder]
|
|
||||||
|
|
||||||
|
|
||||||
/*** Get the main defect info ***/
|
|
||||||
Inner join
|
|
||||||
[AlplaPROD_test1].[dbo].[T_BlockingDefectsGroups] (nolock) as BD
|
|
||||||
ON BO.IdMainDefectGroup = BD.IdBlockingDefectsGroup
|
|
||||||
|
|
||||||
INNER join
|
|
||||||
[AlplaPROD_test1].[dbo].[T_BlockingDefects] as MD
|
|
||||||
ON BO.IdMainDefect = MD.IdBlockingDefect
|
|
||||||
/*** get lot info ***/
|
|
||||||
|
|
||||||
left join
|
|
||||||
(SELECT [MachineLocation]
|
|
||||||
,[MachineDescription]
|
|
||||||
,[ProductionLotHumanReadableId]
|
|
||||||
FROM [test1_AlplaPROD2.0_Reporting].[reporting_productionControlling].[ProducedLot]) as lot
|
|
||||||
on [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].ProductionLotHumanReadableId = lot.ProductionLotHumanReadableId
|
|
||||||
|
|
||||||
where [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].[BlockingDate] between getdate() - 1 and getdate() + 1
|
|
||||||
and [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].BlockingTrigger = 1
|
|
||||||
and HumanReadableId NOT IN ([sentBlockingOrders])
|
|
||||||
`;
|
|
||||||
|
|
||||||
//add the blocking orders in.
|
|
||||||
blockQuery = blockQuery.replaceAll(
|
|
||||||
"[sentBlockingOrders]",
|
|
||||||
notifyData.sentBlocking[0].sentBlockingOrders
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let blocking: any;
|
const notiData: any = noti;
|
||||||
try {
|
const blockingOrders = notiData[0]?.notifiySettings.sentBlockingOrders.map(
|
||||||
blocking = await query(blockQuery, "Quality Blocking");
|
(l: any) => {
|
||||||
//console.log(labels.length);
|
return l.blockingOrder;
|
||||||
// const now = Date.now()
|
|
||||||
//console.log(blocking);
|
|
||||||
// console.log(blocking[0].blockingNumber > data.prodID);
|
|
||||||
if (
|
|
||||||
blocking.length > 0 &&
|
|
||||||
blocking[0].HumanReadableId > notifyData.notifiySettings.prodID
|
|
||||||
) {
|
|
||||||
//send the email :D
|
|
||||||
const emailSetup = {
|
|
||||||
emailTo: notifyData.emails,
|
|
||||||
subject:
|
|
||||||
blocking.length > 0
|
|
||||||
? `Alert! New blocking orders.`
|
|
||||||
: blocking[0].subject,
|
|
||||||
template: "qualityBlocking",
|
|
||||||
context: {
|
|
||||||
items: blocking,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const sentEmail = await sendEmail(emailSetup);
|
|
||||||
|
|
||||||
if (!sentEmail.success) {
|
|
||||||
createLog(
|
|
||||||
"error",
|
|
||||||
"nofity",
|
|
||||||
"notify",
|
|
||||||
"Failed to send email, will try again on next interval"
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the new blocking order to this
|
|
||||||
const newBlockingOrders = blocking.map(
|
|
||||||
(b: any) => b.HumanReadableId
|
|
||||||
);
|
|
||||||
|
|
||||||
//console.log(newBlockingOrders);
|
|
||||||
//console.log(sentBlocking[0].sentBlockingOrders);
|
|
||||||
// Ensure no duplicates
|
|
||||||
const uniqueOrders = Array.from(
|
|
||||||
new Set([
|
|
||||||
...notifyData.sentBlocking[0].sentBlockingOrders,
|
|
||||||
...newBlockingOrders,
|
|
||||||
])
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update sentBlockingOrders
|
|
||||||
notifyData.sentBlocking[0].sentBlockingOrders = uniqueOrders;
|
|
||||||
|
|
||||||
//console.log(notifUpdate);
|
|
||||||
|
|
||||||
const { data, error } = await tryCatch(
|
|
||||||
db
|
|
||||||
.update(notifications)
|
|
||||||
.set({
|
|
||||||
lastRan: sql`NOW()`,
|
|
||||||
notifiySettings: {
|
|
||||||
...notifyData.notifiySettings,
|
|
||||||
prodID: blocking[0].HumanReadableId,
|
|
||||||
sentBlockingOrders: uniqueOrders,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.where(eq(notifications.name, notifyData.name))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
);
|
||||||
createLog(
|
|
||||||
"error",
|
let blockingQuery = blockQuery.replaceAll(
|
||||||
"notify",
|
"[sentBlockingOrders]",
|
||||||
"notify",
|
blockingOrders
|
||||||
`Error from running the blocking query: ${err}`
|
);
|
||||||
);
|
|
||||||
|
const { data: blocking, error: blockingError } = await tryCatch(
|
||||||
|
query(blockingQuery, "Quality Blocking")
|
||||||
|
);
|
||||||
|
|
||||||
|
if (blockingError) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting blocking orders",
|
||||||
|
data: blockingError,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (blocking.length > 0) {
|
||||||
|
const emailSetup = {
|
||||||
|
email: notifyData.emails,
|
||||||
|
subject:
|
||||||
|
blocking.length > 0
|
||||||
|
? `Alert! New blocking orders.`
|
||||||
|
: blocking[0].subject,
|
||||||
|
template: "qualityBlocking",
|
||||||
|
context: {
|
||||||
|
items: blocking,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data: sentEmail, error: sendEmailError } = await tryCatch(
|
||||||
|
sendEmail(emailSetup)
|
||||||
|
);
|
||||||
|
if (sendEmailError) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"blocking",
|
||||||
|
"notify",
|
||||||
|
"Failed to send email, will try again on next interval"
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message:
|
||||||
|
"Failed to send email, will try again on next interval",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const newBlockingOrders = blocking.map((b: any) => {
|
||||||
|
return {
|
||||||
|
blockingOrder: b.HumanReadableId,
|
||||||
|
timeStamp: new Date(Date.now()),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const uniqueOrders = Array.from(
|
||||||
|
new Set([
|
||||||
|
...notifyData.notifiySettings.sentBlockingOrders,
|
||||||
|
...newBlockingOrders,
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
db
|
||||||
|
.update(notifications)
|
||||||
|
.set({
|
||||||
|
lastRan: sql`NOW()`,
|
||||||
|
notifiySettings: {
|
||||||
|
...notifyData.notifiySettings,
|
||||||
|
prodID: blocking[0].HumanReadableId,
|
||||||
|
sentBlockingOrders: uniqueOrders,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.where(eq(notifications.name, notifyData.name))
|
||||||
|
);
|
||||||
|
if (error) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error updating the blocking orders",
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Blocking query ran successfully",
|
||||||
|
blocking,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,13 @@ const notification = async (notifyData: any) => {
|
|||||||
/**
|
/**
|
||||||
* Pass the entire notification over
|
* Pass the entire notification over
|
||||||
*/
|
*/
|
||||||
createLog("info", "notify", "notify", `monitoring ${notifyData.name}`);
|
createLog("debug", "reprinting", "notify", `monitoring ${notifyData.name}`);
|
||||||
|
|
||||||
// validate if there are any emails.
|
// validate if there are any emails.
|
||||||
if (notifyData.emails === "") {
|
if (notifyData.emails === "") {
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
"notify",
|
"reprinting",
|
||||||
"notify",
|
"notify",
|
||||||
`There are no emails set for ${notifyData.name}`
|
`There are no emails set for ${notifyData.name}`
|
||||||
);
|
);
|
||||||
@@ -31,13 +31,14 @@ const notification = async (notifyData: any) => {
|
|||||||
|
|
||||||
// set the time of getting the label
|
// set the time of getting the label
|
||||||
if (notifyData.timeType === "sec") {
|
if (notifyData.timeType === "sec") {
|
||||||
timeCheck = `DATEADD(SECOND, -${notifyData.checkTime}, getdate()) `;
|
timeCheck = `DATEADD(SECOND, -${notifyData.checkInterval}, getdate()) `;
|
||||||
} else if (notifyData.timeType === "min") {
|
} else if (notifyData.timeType === "min") {
|
||||||
timeCheck = `DATEADD(MINUTE, -${notifyData.checkTime}, getdate()) `;
|
timeCheck = `DATEADD(MINUTE, -${notifyData.checkInterval}, getdate()) `;
|
||||||
}
|
}
|
||||||
|
|
||||||
let reprintQuery = `
|
let reprintQuery = `
|
||||||
SELECT
|
SELECT
|
||||||
|
IdEtikettenHistorie,
|
||||||
IdArtikelvarianten as av,
|
IdArtikelvarianten as av,
|
||||||
ArtikelVariantenBez as alias,
|
ArtikelVariantenBez as alias,
|
||||||
LfdNr as runningNumber,
|
LfdNr as runningNumber,
|
||||||
@@ -55,6 +56,7 @@ const notification = async (notifyData: any) => {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
//update the time check
|
//update the time check
|
||||||
|
|
||||||
reprintQuery = reprintQuery.replaceAll(
|
reprintQuery = reprintQuery.replaceAll(
|
||||||
"DATEADD(SECOND, -30, getdate()) ",
|
"DATEADD(SECOND, -30, getdate()) ",
|
||||||
timeCheck
|
timeCheck
|
||||||
@@ -66,10 +68,20 @@ const notification = async (notifyData: any) => {
|
|||||||
query(reprintQuery, "Label Reprints")
|
query(reprintQuery, "Label Reprints")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (labelError) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"reprinting",
|
||||||
|
"notify",
|
||||||
|
`Failed to get the labels: ${labelError}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (labels.length > 0) {
|
if (labels.length > 0) {
|
||||||
//send the email :D
|
//send the email :D
|
||||||
const emailSetup = {
|
const emailSetup = {
|
||||||
emailTo: notifyData.emails,
|
email: notifyData.emails,
|
||||||
subject: "Alert! Label Reprinted",
|
subject: "Alert! Label Reprinted",
|
||||||
template: "reprintLabels",
|
template: "reprintLabels",
|
||||||
context: {
|
context: {
|
||||||
@@ -82,7 +94,7 @@ const notification = async (notifyData: any) => {
|
|||||||
if (!sentEmail.success) {
|
if (!sentEmail.success) {
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
"notify",
|
"reprinting",
|
||||||
"notify",
|
"notify",
|
||||||
"Failed to send email, will try again on next interval"
|
"Failed to send email, will try again on next interval"
|
||||||
);
|
);
|
||||||
@@ -96,7 +108,6 @@ const notification = async (notifyData: any) => {
|
|||||||
// };
|
// };
|
||||||
|
|
||||||
// update the last time ran
|
// update the last time ran
|
||||||
const updateSettings = notifyData.notifiySettings;
|
|
||||||
|
|
||||||
const { data, error } = await tryCatch(
|
const { data, error } = await tryCatch(
|
||||||
db
|
db
|
||||||
@@ -104,7 +115,7 @@ const notification = async (notifyData: any) => {
|
|||||||
.set({
|
.set({
|
||||||
lastRan: sql`NOW()`,
|
lastRan: sql`NOW()`,
|
||||||
notifiySettings: {
|
notifiySettings: {
|
||||||
...updateSettings,
|
...notifyData.notifiySettings,
|
||||||
prodID: labels[0].IdEtikettenHistorie,
|
prodID: labels[0].IdEtikettenHistorie,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export default async function reprintLabelMonitor(notifyData: any) {
|
|||||||
|
|
||||||
//update the time check
|
//update the time check
|
||||||
noteQuery = noteQuery
|
noteQuery = noteQuery
|
||||||
.replaceAll("[timeCheck]", notifyData.checkTime)
|
.replaceAll("[timeCheck]", notifyData.checkInterval)
|
||||||
.replaceAll("[locations]", notifyData.notifiySettings.locations);
|
.replaceAll("[locations]", notifyData.notifiySettings.locations);
|
||||||
|
|
||||||
let stage: PPOO[];
|
let stage: PPOO[];
|
||||||
@@ -78,13 +78,13 @@ export default async function reprintLabelMonitor(notifyData: any) {
|
|||||||
// update the count with the result
|
// update the count with the result
|
||||||
|
|
||||||
const emailSetup = {
|
const emailSetup = {
|
||||||
emailTo: notifyData.emails,
|
email: notifyData.emails,
|
||||||
subject: `Alert! Pallets in staging greater than ${notifyData.checkTime} ${notifyData.timeType}`,
|
subject: `Alert! Pallets in staging greater than ${notifyData.checkInterval} ${notifyData.timeType}`,
|
||||||
template: "stagingCheck",
|
template: "stagingCheck",
|
||||||
context: {
|
context: {
|
||||||
items: stage,
|
items: stage,
|
||||||
count: stage.length,
|
count: stage.length,
|
||||||
checkTime: notifyData.checkTime,
|
checkTime: notifyData.checkInterval,
|
||||||
timeCheck: notifyData.timeType,
|
timeCheck: notifyData.timeType,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export const dateCorrection = async (newDate: Date) => {
|
||||||
|
/**
|
||||||
|
* corrects the date format to be what ti is expecting
|
||||||
|
*/
|
||||||
|
|
||||||
|
const newDateFormat = new Date(newDate)
|
||||||
|
.toLocaleString("en-US", {
|
||||||
|
timeZone: "UTC",
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit",
|
||||||
|
second: "2-digit",
|
||||||
|
hourCycle: "h23", // Ensures 24-hour format
|
||||||
|
})
|
||||||
|
.replace(",", "");
|
||||||
|
|
||||||
|
return newDateFormat;
|
||||||
|
};
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const requestUser = process.env.REQUESTUSER || "";
|
||||||
|
export const headerUpdate = async (data: any, plantToken: any) => {
|
||||||
|
// update the header
|
||||||
|
let webHeader = `
|
||||||
|
<request-id>[requestID]</request-id>
|
||||||
|
<data>
|
||||||
|
<WebImport>
|
||||||
|
<WebImportHeader>
|
||||||
|
<FileName>[requestID].XML</FileName>
|
||||||
|
<Type>SOTransportLoader</Type>
|
||||||
|
<UserName>[requestUser]</UserName>
|
||||||
|
</WebImportHeader>
|
||||||
|
`;
|
||||||
|
|
||||||
|
webHeader = webHeader
|
||||||
|
.replaceAll(
|
||||||
|
"[requestID]",
|
||||||
|
`${data[0].releaseNumber}-${plantToken[0].value}`
|
||||||
|
)
|
||||||
|
.replaceAll("[requestUser]", requestUser);
|
||||||
|
|
||||||
|
return webHeader;
|
||||||
|
};
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { freightClass } from "../../../../../globalUtils/freightClass.js";
|
||||||
|
|
||||||
|
export const loadItems = async (data: any) => {
|
||||||
|
let itemGroups = "";
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
let newItem = `
|
||||||
|
<ItemGroup id="" isShipUnit="false" isHandlingUnit="false" sequence="${
|
||||||
|
i + 1
|
||||||
|
}">
|
||||||
|
<ContainedBy id=""/>
|
||||||
|
<LineItem lineNumber="${i + 1}"/>
|
||||||
|
<Dimensions>
|
||||||
|
<Dimension type="Length" uom="IN">${(
|
||||||
|
data[i].pkgLengh / 25.4
|
||||||
|
).toFixed(2)}</Dimension>
|
||||||
|
<Dimension type="Width" uom="IN">${(
|
||||||
|
data[i].pkgWidth / 25.4
|
||||||
|
).toFixed(2)}</Dimension>
|
||||||
|
<Dimension type="Height" uom="IN">${Math.round(
|
||||||
|
data[i].pkgHeight / 25.4
|
||||||
|
).toFixed(2)}</Dimension>
|
||||||
|
</Dimensions>
|
||||||
|
<Description>${`av ${data[i].article} ${data[i].articleAlias}`}</Description>
|
||||||
|
<FreightClasses>
|
||||||
|
<FreightClass type="">${freightClass(
|
||||||
|
data[i].pkgWeight,
|
||||||
|
data[i].pkgLengh,
|
||||||
|
data[i].pkgWidth,
|
||||||
|
data[i].pkgHeight
|
||||||
|
)}</FreightClass>
|
||||||
|
</FreightClasses>
|
||||||
|
<Commodity/>
|
||||||
|
<NmfcCode/>
|
||||||
|
<HazardousMaterial>false</HazardousMaterial>
|
||||||
|
<HazMatDetail/>
|
||||||
|
<Weights>
|
||||||
|
<Weight type="actual" uom="KG">${
|
||||||
|
data[i].pkgWeight * data[i].Pallets
|
||||||
|
}</Weight>
|
||||||
|
</Weights>
|
||||||
|
<Quantities>
|
||||||
|
<Quantity type="actual" uom="pallet">${
|
||||||
|
data[i].Pallets
|
||||||
|
}</Quantity>
|
||||||
|
</Quantities>
|
||||||
|
</ItemGroup>
|
||||||
|
`;
|
||||||
|
|
||||||
|
itemGroups += newItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemGroups;
|
||||||
|
};
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import querystring from "querystring";
|
||||||
|
import { createLog } from "../../../../logger/logger.js";
|
||||||
|
//tiCreds
|
||||||
|
const userid = process.env.USERID || "";
|
||||||
|
const password = process.env.PASSWORD || "";
|
||||||
|
|
||||||
|
export const postToTi = async (data: string) => {
|
||||||
|
const formBody = querystring.stringify({
|
||||||
|
userid,
|
||||||
|
password,
|
||||||
|
request: data,
|
||||||
|
});
|
||||||
|
axios
|
||||||
|
.post(
|
||||||
|
"https://t-insightws.mercurygate.net/MercuryGate/common/remoteService.jsp",
|
||||||
|
formBody,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
//console.log(response.data)
|
||||||
|
createLog("info", "ti", "notify", "Data was sent over to TI");
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "Data was sent over to TI",
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
createLog("error", "ti", "notify", error);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error sending data to TI",
|
||||||
|
data: error,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import { createLog } from "../../../../logger/logger.js";
|
||||||
|
|
||||||
|
export const scacCheck = async (data: any) => {
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"ti",
|
||||||
|
"notify",
|
||||||
|
`Checking if ${data[0].addressAlias} has scac: ${
|
||||||
|
data[0].remark.split(",")[0] ? "there was one" : "no scac"
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const priceSheet = `
|
||||||
|
<PriceSheets>
|
||||||
|
<PriceSheet type="Carrier" isSelected="${
|
||||||
|
data[0].remark.split(",")[0] ? "true" : "false"
|
||||||
|
}">
|
||||||
|
<ContractId/>
|
||||||
|
${
|
||||||
|
data[0].remark.split(",")[0]
|
||||||
|
? `<SCAC>${data[0].remark
|
||||||
|
.split(",")[0]
|
||||||
|
.split(":")[1]
|
||||||
|
.toUpperCase()}</SCAC>`
|
||||||
|
: `<SCAC/>`
|
||||||
|
}
|
||||||
|
<Mode/>
|
||||||
|
</PriceSheet>
|
||||||
|
</PriceSheets>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return priceSheet;
|
||||||
|
};
|
||||||
@@ -0,0 +1,301 @@
|
|||||||
|
import { eq, sql } from "drizzle-orm";
|
||||||
|
import { db } from "../../../../../../database/dbclient.js";
|
||||||
|
import { serverData } from "../../../../../../database/schema/serverData.js";
|
||||||
|
import { settings } from "../../../../../../database/schema/settings.js";
|
||||||
|
import { tryCatch } from "../../../../../globalUtils/tryCatch.js";
|
||||||
|
import { notifications } from "../../../../../../database/schema/notifications.js";
|
||||||
|
import { getHeaders } from "../../../../sqlServer/querys/notifications/ti/getHeaders.js";
|
||||||
|
import { query } from "../../../../sqlServer/prodSqlServer.js";
|
||||||
|
import { createLog } from "../../../../logger/logger.js";
|
||||||
|
import { getOrderToSend } from "../../../../sqlServer/querys/notifications/ti/getOrderToSend.js";
|
||||||
|
import { xmlPayloadTI } from "./tiXmlPayload.js";
|
||||||
|
import { headerUpdate } from "./headerUpdate.js";
|
||||||
|
import { loadItems } from "./loadItems.js";
|
||||||
|
import { dateCorrection } from "./dateCorrection.js";
|
||||||
|
import { scacCheck } from "./scacCodeCheck.js";
|
||||||
|
import { postToTi } from "./postToTI.js";
|
||||||
|
|
||||||
|
export const tiImport = async () => {
|
||||||
|
// get the plant token
|
||||||
|
let payload = xmlPayloadTI;
|
||||||
|
const { data: plantData, error: plantError } = await tryCatch(
|
||||||
|
db.select().from(settings)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (plantError)
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error Getting Plant Data.",
|
||||||
|
data: plantError,
|
||||||
|
};
|
||||||
|
const plantToken = plantData?.filter((n) => n.name === "plantToken");
|
||||||
|
|
||||||
|
const { data: plantInfo, error: plantEr } = await tryCatch(
|
||||||
|
db
|
||||||
|
.select()
|
||||||
|
.from(serverData)
|
||||||
|
.where(eq(serverData.plantToken, plantToken[0].value))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (plantEr)
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error Getting Plant Data.",
|
||||||
|
data: plantEr,
|
||||||
|
};
|
||||||
|
|
||||||
|
// parsing posting window
|
||||||
|
const plantI = plantInfo!;
|
||||||
|
|
||||||
|
// order notifications
|
||||||
|
const { data: notificationSet, error: notificationSettingsErr } =
|
||||||
|
await tryCatch(
|
||||||
|
db
|
||||||
|
.select()
|
||||||
|
.from(notifications)
|
||||||
|
.where(eq(notifications.name, "tiIntergration"))
|
||||||
|
);
|
||||||
|
if (notificationSettingsErr)
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Notification missing.",
|
||||||
|
data: notificationSettingsErr,
|
||||||
|
};
|
||||||
|
|
||||||
|
const notiSet: any = notificationSet;
|
||||||
|
const customerAccountNum = plantI[0].customerTiAcc as string; // tiIntergration
|
||||||
|
// get current releaes not in the already sent oders
|
||||||
|
|
||||||
|
const releaseString = notiSet[0].notifiySettings.releases
|
||||||
|
|
||||||
|
.map((num: any) => `'${num.releaseNumber}'`)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
let orders = getHeaders
|
||||||
|
.replaceAll("[from]", notiSet[0]?.notifiySettings.start)
|
||||||
|
.replaceAll("[to]", notiSet[0]?.notifiySettings.end)
|
||||||
|
.replaceAll("[exclude]", releaseString);
|
||||||
|
|
||||||
|
// get the headers pending
|
||||||
|
const { data: header, error: headerError } = await tryCatch(
|
||||||
|
query(orders, "Ti get open headers")
|
||||||
|
);
|
||||||
|
if (headerError) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"ti",
|
||||||
|
"notify",
|
||||||
|
`Error getting headers: ${headerError}`
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting headers",
|
||||||
|
data: headerError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (header.length === 0) {
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"ti",
|
||||||
|
"notify",
|
||||||
|
"There are no pending orders to be sent over to ti."
|
||||||
|
);
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
message: "There are no pending orders to be sent over to ti.",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"tiIntergration",
|
||||||
|
"notify",
|
||||||
|
`There are a total of ${header.length} to send over`
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the query to get only the first header
|
||||||
|
*/
|
||||||
|
|
||||||
|
// update query to have the correct plant token
|
||||||
|
let orderToSend = getOrderToSend
|
||||||
|
|
||||||
|
.replaceAll("test1", plantToken[0].value)
|
||||||
|
.replaceAll("[releaseToProcess]", `'${header[0].releaseNumber}'`)
|
||||||
|
.replaceAll("[from]", notiSet[0].notifiySettings.start)
|
||||||
|
.replaceAll("[to]", notiSet[0].notifiySettings.end);
|
||||||
|
|
||||||
|
// get the headers pending
|
||||||
|
const { data: orderData, error: ordersError } = await tryCatch(
|
||||||
|
query(orderToSend, "Ti get open headers")
|
||||||
|
);
|
||||||
|
if (ordersError)
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting getting orders",
|
||||||
|
data: ordersError,
|
||||||
|
};
|
||||||
|
|
||||||
|
// update the special instructions section
|
||||||
|
const otherSettings = plantI[0]?.otherSettings as {
|
||||||
|
specialInstructions: string;
|
||||||
|
active: boolean;
|
||||||
|
}[];
|
||||||
|
|
||||||
|
const specialInfo = otherSettings[0].specialInstructions.replaceAll(
|
||||||
|
"[header]",
|
||||||
|
orderData[0].Header
|
||||||
|
);
|
||||||
|
|
||||||
|
// add the full amount of pallets sending over
|
||||||
|
let fullPalToSend = orderData.reduce(
|
||||||
|
(acc: any, o: any) => acc + o.Pallets,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
//console.log("payload", payload);
|
||||||
|
payload = payload
|
||||||
|
.replaceAll(
|
||||||
|
`[WebImportHeader]`,
|
||||||
|
await headerUpdate(orderData, plantToken)
|
||||||
|
)
|
||||||
|
.replaceAll(`[items]`, await loadItems(orderData))
|
||||||
|
.replaceAll(`[customerAccountNum]`, customerAccountNum)
|
||||||
|
.replaceAll("[fullTotalPal]", fullPalToSend)
|
||||||
|
// add in release info
|
||||||
|
.replaceAll(`[shipNumber]`, orderData[0].releaseNumber)
|
||||||
|
.replaceAll(`[loadNumber]`, orderData[0].releaseNumber);
|
||||||
|
|
||||||
|
// add in the multi release numbers
|
||||||
|
let multiRelease = ``;
|
||||||
|
if (orderData.length > 0) {
|
||||||
|
for (let i = 0; i < orderData.length; i++) {
|
||||||
|
const newRelease = `
|
||||||
|
<ReferenceNumber type="Release Number" isPrimary="false">${orderData[i].releaseNumber}</ReferenceNumber>`;
|
||||||
|
multiRelease += newRelease;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = payload.replaceAll("[multieReleaseNumber]", multiRelease);
|
||||||
|
} else {
|
||||||
|
payload = payload.replaceAll("[multieReleaseNumber]", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the correct date stuff
|
||||||
|
payload = payload
|
||||||
|
.replaceAll(
|
||||||
|
"[loadingDate]",
|
||||||
|
await dateCorrection(orderData[0].LoadingDate)
|
||||||
|
)
|
||||||
|
|
||||||
|
.replaceAll(
|
||||||
|
"[deliveryDate]",
|
||||||
|
await dateCorrection(orderData[0].DeliveryDate)
|
||||||
|
);
|
||||||
|
|
||||||
|
// shipping ours corrections
|
||||||
|
const formattedDate = orderData[0].LoadingDate.toLocaleDateString("en-US", {
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
const shippingHours = JSON.parse(plantI[0]?.shippingHours!);
|
||||||
|
|
||||||
|
payload = payload
|
||||||
|
.replaceAll(
|
||||||
|
"[shippingHoursEarly]",
|
||||||
|
`${formattedDate} ${shippingHours[0].early}`
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
"[shippingHoursLate]",
|
||||||
|
`${formattedDate} ${shippingHours[0].late}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// special instructions
|
||||||
|
if (otherSettings[0].specialInstructions.length != 0) {
|
||||||
|
payload = payload.replaceAll("[specialInstructions]", specialInfo);
|
||||||
|
} else {
|
||||||
|
payload = payload.replaceAll("[specialInstructions]", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// shipper info
|
||||||
|
payload = payload
|
||||||
|
.replaceAll("[plantName]", `Alpla ${plantI[0]?.sName!}`)
|
||||||
|
.replaceAll("[plantStreetAddress]", plantI[0]?.streetAddress!)
|
||||||
|
.replaceAll("[plantCity]", plantI[0]?.cityState!.split(",")[0])
|
||||||
|
.replaceAll("[plantState]", plantI[0]?.cityState!.split(",")[1])
|
||||||
|
.replaceAll("[plantZipCode]", plantI[0]?.zipcode!)
|
||||||
|
.replaceAll("[contactNum]", plantI[0]?.contactPhone!)
|
||||||
|
.replaceAll("[contactEmail]", plantI[0]?.contactEmail!)
|
||||||
|
|
||||||
|
// customer info
|
||||||
|
.replaceAll("[customerName]", orderData[0].addressAlias)
|
||||||
|
.replaceAll("[customerStreetAddress]", orderData[0].streetAddress)
|
||||||
|
.replaceAll("[customerCity]", orderData[0].city.split(",")[0])
|
||||||
|
.replaceAll("[customerState]", orderData[0].city.split(",")[1])
|
||||||
|
.replaceAll("[customerZip]", orderData[0].zipCode)
|
||||||
|
.replaceAll("[customerPO]", orderData[0].Header)
|
||||||
|
.replaceAll(
|
||||||
|
"[glCoding]",
|
||||||
|
`52410-${
|
||||||
|
orderData[0].artileType.toLowerCase() === "preform" ||
|
||||||
|
orderData[0].artileType.toLowerCase() === "metalCage"
|
||||||
|
? 31
|
||||||
|
: plantI[0].greatPlainsPlantCode
|
||||||
|
}`
|
||||||
|
) // {"52410 - " + (artileType.toLowerCase() === "preform" || artileType.toLowerCase() === "metalCage" ? 31: plantInfo[0].greatPlainsPlantCode)}
|
||||||
|
.replaceAll(
|
||||||
|
"[pfc]",
|
||||||
|
`${
|
||||||
|
orderData[0].artileType.toLowerCase() === "preform" ||
|
||||||
|
orderData[0].artileType.toLowerCase() === "metalCage"
|
||||||
|
? 40
|
||||||
|
: orderData[0].costCenter
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
.replaceAll("[priceSheet]", await scacCheck(orderData));
|
||||||
|
//send over to be processed
|
||||||
|
|
||||||
|
//console.log("payload", payload);
|
||||||
|
|
||||||
|
const { data: tiPost, error: tiError } = await tryCatch(postToTi(payload));
|
||||||
|
|
||||||
|
if (tiError) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error posting to TI",
|
||||||
|
error: tiError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the db so we dont try to pull the next one
|
||||||
|
*/
|
||||||
|
|
||||||
|
const uniqueOrders = Array.from(
|
||||||
|
new Set([
|
||||||
|
...notiSet[0].notifiySettings.releases,
|
||||||
|
{
|
||||||
|
releaseNumber: header[0].releaseNumber,
|
||||||
|
timeStamp: new Date(Date.now()),
|
||||||
|
},
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
db
|
||||||
|
.update(notifications)
|
||||||
|
.set({
|
||||||
|
lastRan: sql`NOW()`,
|
||||||
|
notifiySettings: {
|
||||||
|
...notiSet[0].notifiySettings,
|
||||||
|
releases: uniqueOrders,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.where(eq(notifications.name, "tiIntergration"))
|
||||||
|
);
|
||||||
|
|
||||||
|
createLog("info", "ti", "notify", "done with this order");
|
||||||
|
|
||||||
|
return { message: "done with this order" };
|
||||||
|
};
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
export let xmlPayloadTI = `
|
export let xmlPayloadTI = `
|
||||||
<service-request>
|
<service-request>
|
||||||
<service-id>ImportWeb</service-id>
|
<service-id>ImportWeb</service-id>
|
||||||
<request-id>[requestID]</request-id>
|
|
||||||
<data>
|
|
||||||
<WebImport>
|
|
||||||
[WebImportHeader]
|
[WebImportHeader]
|
||||||
<WebImportFile>
|
<WebImportFile>
|
||||||
<MercuryGate>
|
<MercuryGate>
|
||||||
@@ -35,19 +32,18 @@ export let xmlPayloadTI = `
|
|||||||
</Address>
|
</Address>
|
||||||
</BillTo>
|
</BillTo>
|
||||||
</Payment>
|
</Payment>
|
||||||
<PriceSheets>
|
[priceSheet]
|
||||||
<PriceSheet type="Carrier" isSelected="false"> // get this from the price sheet
|
<!-- Comments here -->
|
||||||
<ContractId/>
|
<Comments>
|
||||||
<SCAC/>
|
<Comment type="SpecialInstructions">[specialInstructions]</Comment>
|
||||||
<Mode/>
|
</Comments>
|
||||||
</PriceSheet>
|
|
||||||
</PriceSheets>
|
|
||||||
<Plan>
|
<Plan>
|
||||||
<Events count="2">
|
<Events count="2">
|
||||||
<Event type="Pickup" sequenceNum="1">
|
<Event type="Pickup" sequenceNum="1">
|
||||||
<Dates>
|
<Dates>
|
||||||
<Date type="earliest">[loadingDate]</Date>
|
<Date type="earliest">[shippingHoursEarly]</Date>
|
||||||
<Date type="latest">[deliveryDate]</Date>
|
<Date type="latest">[shippingHoursLate]</Date>
|
||||||
</Dates>
|
</Dates>
|
||||||
<Address type="" isResidential="" isPrimary="false">
|
<Address type="" isResidential="" isPrimary="false">
|
||||||
<LocationCode/>
|
<LocationCode/>
|
||||||
@@ -119,24 +115,20 @@ export let xmlPayloadTI = `
|
|||||||
</ReferenceNumbers>
|
</ReferenceNumbers>
|
||||||
<Services/>
|
<Services/>
|
||||||
<EquipmentList/>
|
<EquipmentList/>
|
||||||
6
|
<Dimensions>
|
||||||
|
<Dimension type="RatingCount">[fullTotalPal]</Dimension>
|
||||||
|
</Dimensions>
|
||||||
<Dates>
|
<Dates>
|
||||||
<Pickup>
|
<Pickup>
|
||||||
<Date type="earliest">[loadingDate]</Date>
|
<Date type="earliest">[shippingHoursEarly]</Date>
|
||||||
<Date type="latest">[loadingDate]</Date>
|
<Date type="latest">[shippingHoursLate]</Date>
|
||||||
</Pickup>
|
</Pickup>
|
||||||
<Drop>
|
<Drop>
|
||||||
<Date type="earliest">[deliveryDate]</Date>
|
<Date type="earliest">[deliveryDate]</Date>
|
||||||
<Date type="latest">[deliveryDate]</Date>
|
<Date type="latest">[deliveryDate]</Date>
|
||||||
</Drop>
|
</Drop>
|
||||||
</Dates>
|
</Dates>
|
||||||
<PriceSheets>
|
[priceSheet]
|
||||||
<PriceSheet type="Carrier" isSelected="false">
|
|
||||||
<ContractId/>
|
|
||||||
<SCAC/>
|
|
||||||
<Mode/>
|
|
||||||
</PriceSheet>
|
|
||||||
</PriceSheets>
|
|
||||||
<Shipper>
|
<Shipper>
|
||||||
<Address type="" isResidential="" isPrimary="false">
|
<Address type="" isResidential="" isPrimary="false">
|
||||||
<LocationCode/>
|
<LocationCode/>
|
||||||
@@ -160,7 +152,7 @@ export let xmlPayloadTI = `
|
|||||||
<Consignee>
|
<Consignee>
|
||||||
<Address type="" isResidential="" isPrimary="false">
|
<Address type="" isResidential="" isPrimary="false">
|
||||||
<LocationCode/>
|
<LocationCode/>
|
||||||
<Name>[customer]</Name>
|
<Name>[customerName]</Name>
|
||||||
<AddrLine1>[customerStreetAddress]</AddrLine1>
|
<AddrLine1>[customerStreetAddress]</AddrLine1>
|
||||||
<AddrLine2/>
|
<AddrLine2/>
|
||||||
<City>[customerCity]</City>
|
<City>[customerCity]</City>
|
||||||
@@ -168,6 +160,17 @@ export let xmlPayloadTI = `
|
|||||||
<PostalCode>[customerZip]</PostalCode>
|
<PostalCode>[customerZip]</PostalCode>
|
||||||
<CountryCode>USA</CountryCode>
|
<CountryCode>USA</CountryCode>
|
||||||
<Contacts />
|
<Contacts />
|
||||||
|
<!-- Location contacts are optional -->
|
||||||
|
<Contacts>
|
||||||
|
<Contact type="">
|
||||||
|
<Name>Alpla</Name>
|
||||||
|
<ContactMethods>
|
||||||
|
<!-- Valid contactMethod types are phone, fax, and email -->
|
||||||
|
<ContactMethod sequenceNum="1" type="phone">[contactNum]</ContactMethod>
|
||||||
|
<ContactMethod sequenceNum="1" type="email">[contactEmail]</ContactMethod>
|
||||||
|
</ContactMethods>
|
||||||
|
</Contact>
|
||||||
|
</Contacts>
|
||||||
|
|
||||||
</Address>
|
</Address>
|
||||||
</Consignee>
|
</Consignee>
|
||||||
|
|||||||
@@ -1,413 +1,10 @@
|
|||||||
import { xmlPayloadTI } from "./tiFullFlow/tiXmlPayload.js";
|
|
||||||
import axios from "axios";
|
|
||||||
import querystring from "querystring";
|
|
||||||
import { getOrderToSend } from "../../../sqlServer/querys/notifications/ti/getOrderToSend.js";
|
|
||||||
import { getHeaders } from "../../../sqlServer/querys/notifications/ti/getHeaders.js";
|
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
|
||||||
import { db } from "../../../../../database/dbclient.js";
|
|
||||||
import { settings } from "../../../../../database/schema/settings.js";
|
|
||||||
import { serverData } from "../../../../../database/schema/serverData.js";
|
|
||||||
import { eq, sql } from "drizzle-orm";
|
|
||||||
import { notifications } from "../../../../../database/schema/notifications.js";
|
|
||||||
import { query } from "../../../sqlServer/prodSqlServer.js";
|
|
||||||
import { createLog } from "../../../logger/logger.js";
|
|
||||||
import { freightClass } from "../../../../globalUtils/freightClass.js";
|
|
||||||
import { delay } from "../../../../globalUtils/delay.js";
|
import { delay } from "../../../../globalUtils/delay.js";
|
||||||
|
import { createLog } from "../../../logger/logger.js";
|
||||||
const dateCorrection = (newDate: any) => {
|
import { tiImport } from "./tiFullFlow/tiImport.js";
|
||||||
return new Date(newDate)
|
|
||||||
.toLocaleString("en-US", {
|
|
||||||
timeZone: "UTC",
|
|
||||||
year: "numeric",
|
|
||||||
month: "2-digit",
|
|
||||||
day: "2-digit",
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
second: "2-digit",
|
|
||||||
hourCycle: "h23", // Ensures 24-hour format
|
|
||||||
})
|
|
||||||
.replace(",", "");
|
|
||||||
};
|
|
||||||
|
|
||||||
const tiImport = async () => {
|
|
||||||
//await initializePool();
|
|
||||||
|
|
||||||
// get the plant token
|
|
||||||
const { data: plantData, error: plantError } = await tryCatch(
|
|
||||||
db.select().from(settings)
|
|
||||||
);
|
|
||||||
//await initializePool();
|
|
||||||
if (plantError) return;
|
|
||||||
const plantToken = plantData?.filter((n) => n.name === "plantToken");
|
|
||||||
|
|
||||||
const { data: plantInfo, error: plantEr } = await tryCatch(
|
|
||||||
db
|
|
||||||
.select()
|
|
||||||
.from(serverData)
|
|
||||||
.where(eq(serverData.plantToken, plantToken[0].value))
|
|
||||||
);
|
|
||||||
|
|
||||||
// parsing posting window
|
|
||||||
const plantI = plantInfo!;
|
|
||||||
//const postTime = JSON.parse(plantI[0]?.tiPostTime!);
|
|
||||||
|
|
||||||
// order notifications
|
|
||||||
const { data: notificationSet, error: notificationSettingsErr } =
|
|
||||||
await tryCatch(
|
|
||||||
db
|
|
||||||
.select()
|
|
||||||
.from(notifications)
|
|
||||||
.where(eq(notifications.name, "tiIntergration"))
|
|
||||||
);
|
|
||||||
if (notificationSettingsErr) return;
|
|
||||||
|
|
||||||
const notiSet: any = notificationSet;
|
|
||||||
//creds
|
|
||||||
const userid = "ALPLAWSTEST";
|
|
||||||
const password = "oe39U1LuLX9ZdY0XKobG";
|
|
||||||
|
|
||||||
// const requestID = `ALPLAPBTEST1`; // production will be alpla01-dateTime - this will be the time it was sent over.
|
|
||||||
const requestUser = "ALPLAWSTEST"; // if alplaprod_rs -- confirm we can use a user name vs the AlplapIMPORT // needs to stay the same as provied
|
|
||||||
|
|
||||||
const customerAccountNum = plantI[0].customerTiAcc as string; // ti
|
|
||||||
|
|
||||||
// it we dont get anything here we want to make sure we add it in
|
|
||||||
|
|
||||||
// get current releaes not in the already sent oders
|
|
||||||
let orders = getHeaders;
|
|
||||||
orders = orders
|
|
||||||
.replaceAll("test1", plantToken[0].value)
|
|
||||||
.replaceAll("[from]", notiSet?.notifiySettings.start)
|
|
||||||
.replaceAll("[to]", notiSet?.notifiySettings.end)
|
|
||||||
.replaceAll(
|
|
||||||
"[exclude]",
|
|
||||||
notiSet.notifiySettings.processed
|
|
||||||
.map((num: any) => `'${num}'`)
|
|
||||||
.join(", ")
|
|
||||||
);
|
|
||||||
|
|
||||||
//console.log(orders);
|
|
||||||
let headerPending = [];
|
|
||||||
try {
|
|
||||||
headerPending = await query(orders, "Ti get open headers");
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headerPending.length === 0) {
|
|
||||||
createLog(
|
|
||||||
"info",
|
|
||||||
"notification",
|
|
||||||
"notify",
|
|
||||||
"There are no pending orders to be sent over to ti."
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
code: 1,
|
|
||||||
message: "There are no pending orders to be sent over to ti.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
createLog(
|
|
||||||
"info",
|
|
||||||
"notification",
|
|
||||||
"notify",
|
|
||||||
`There are a total of ${headerPending.length} to send over`
|
|
||||||
);
|
|
||||||
// update query to have the correct plant token
|
|
||||||
let orderToSend = getOrderToSend;
|
|
||||||
orderToSend = orderToSend
|
|
||||||
.replaceAll("test1", plantToken[0].value)
|
|
||||||
.replaceAll("[releaseToProcess]", `'${headerPending[0].releaseNumber}'`)
|
|
||||||
.replaceAll("[from]", notiSet.notifiySettings.start)
|
|
||||||
.replaceAll("[to]", notiSet.notifiySettings.end);
|
|
||||||
|
|
||||||
// console.log(orderToSend);
|
|
||||||
let records = [];
|
|
||||||
try {
|
|
||||||
records = await query(orderToSend, "Ti send order");
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
}
|
|
||||||
//console.log(headerPending.length);
|
|
||||||
|
|
||||||
// update the header
|
|
||||||
let webHeader = `
|
|
||||||
<request-id>[requestID]</request-id>
|
|
||||||
<data>
|
|
||||||
<WebImport>
|
|
||||||
<WebImportHeader>
|
|
||||||
<FileName>[requestID].XML</FileName>
|
|
||||||
<Type>SOTransportLoader</Type>
|
|
||||||
<UserName>[requestUser]</UserName>
|
|
||||||
</WebImportHeader>
|
|
||||||
`;
|
|
||||||
|
|
||||||
webHeader = webHeader.replaceAll(
|
|
||||||
"[requestID]",
|
|
||||||
`${records[0].releaseNumber}-${plantToken[0].value}`
|
|
||||||
);
|
|
||||||
webHeader = webHeader.replaceAll("[requestUser]", requestUser);
|
|
||||||
|
|
||||||
// update the special instructions section
|
|
||||||
const otherSettings = plantI[0]?.otherSettings as {
|
|
||||||
specialInstructions: string;
|
|
||||||
active: boolean;
|
|
||||||
}[];
|
|
||||||
|
|
||||||
const specialInfo = otherSettings[0].specialInstructions.replaceAll(
|
|
||||||
"[header]",
|
|
||||||
records[0].Header
|
|
||||||
);
|
|
||||||
// this part will link into the <ItemGroups></ItemGroups>
|
|
||||||
let itemGroups = "";
|
|
||||||
|
|
||||||
for (let i = 0; i < records.length; i++) {
|
|
||||||
let newItem = `
|
|
||||||
<ItemGroup id="" isShipUnit="false" isHandlingUnit="false" sequence="${
|
|
||||||
i + 1
|
|
||||||
}">
|
|
||||||
<ContainedBy id=""/>
|
|
||||||
<LineItem lineNumber="${i + 1}"/>
|
|
||||||
<Dimensions>
|
|
||||||
<Dimension type="Length" uom="IN">${(
|
|
||||||
records[i].pkgLengh / 25.4
|
|
||||||
).toFixed(2)}</Dimension>
|
|
||||||
<Dimension type="Width" uom="IN">${(
|
|
||||||
records[i].pkgWidth / 25.4
|
|
||||||
).toFixed(2)}</Dimension>
|
|
||||||
<Dimension type="Height" uom="IN">${Math.round(
|
|
||||||
records[i].pkgHeight / 25.4
|
|
||||||
).toFixed(2)}</Dimension>
|
|
||||||
</Dimensions>
|
|
||||||
<Description>${`av ${records[i].article} ${records[i].articleAlias}`}</Description>
|
|
||||||
<FreightClasses>
|
|
||||||
<FreightClass type="">${freightClass(
|
|
||||||
records[i].pkgWeight,
|
|
||||||
records[i].pkgLengh,
|
|
||||||
records[i].pkgWidth,
|
|
||||||
records[i].pkgHeight
|
|
||||||
)}</FreightClass>
|
|
||||||
</FreightClasses>
|
|
||||||
<Commodity/>
|
|
||||||
<NmfcCode/>
|
|
||||||
<HazardousMaterial>false</HazardousMaterial>
|
|
||||||
<HazMatDetail/>
|
|
||||||
<Weights>
|
|
||||||
<Weight type="actual" uom="KG">${
|
|
||||||
records[i].pkgWeight * records[i].Pallets
|
|
||||||
}</Weight>
|
|
||||||
</Weights>
|
|
||||||
<Quantities>
|
|
||||||
<Quantity type="actual" uom="pallet">${
|
|
||||||
records[i].Pallets
|
|
||||||
}</Quantity>
|
|
||||||
</Quantities>
|
|
||||||
</ItemGroup>
|
|
||||||
`;
|
|
||||||
|
|
||||||
itemGroups += newItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the full amount of pallets sending over
|
|
||||||
let fullPalToSend = records.reduce(
|
|
||||||
(acc: any, o: any) => acc + o.Pallets,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
// rebuild the xml to be properly
|
|
||||||
let payload = xmlPayloadTI;
|
|
||||||
payload = payload
|
|
||||||
.replaceAll(`[WebImportHeader]`, webHeader)
|
|
||||||
.replaceAll(`[items]`, itemGroups)
|
|
||||||
.replaceAll(`[customerAccountNum]`, customerAccountNum)
|
|
||||||
.replaceAll("[fullTotalPal]", fullPalToSend);
|
|
||||||
|
|
||||||
// update the main release
|
|
||||||
//[loadNumber],[shipNumber]
|
|
||||||
payload = payload.replaceAll(`[shipNumber]`, records[0].releaseNumber);
|
|
||||||
payload = payload.replaceAll(`[loadNumber]`, records[0].releaseNumber);
|
|
||||||
|
|
||||||
// do the multie release if needed
|
|
||||||
// <ReferenceNumber type="Release Number" isPrimary="false">[multieReleaseNumber]</ReferenceNumber>
|
|
||||||
|
|
||||||
let multiRelease = ``;
|
|
||||||
if (records.length > 0) {
|
|
||||||
for (let i = 0; i < records.length; i++) {
|
|
||||||
const newRelease = `
|
|
||||||
<ReferenceNumber type="Release Number" isPrimary="false">${records[i].releaseNumber}</ReferenceNumber>`;
|
|
||||||
multiRelease += newRelease;
|
|
||||||
}
|
|
||||||
|
|
||||||
payload = payload.replaceAll("[multieReleaseNumber]", multiRelease);
|
|
||||||
} else {
|
|
||||||
payload = payload.replaceAll("[multieReleaseNumber]", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
//update the delivery section
|
|
||||||
payload = payload.replaceAll(
|
|
||||||
"[loadingDate]",
|
|
||||||
dateCorrection(records[0].LoadingDate)
|
|
||||||
);
|
|
||||||
|
|
||||||
payload = payload.replaceAll(
|
|
||||||
"[deliveryDate]",
|
|
||||||
dateCorrection(records[0].DeliveryDate)
|
|
||||||
);
|
|
||||||
|
|
||||||
// shipping hours
|
|
||||||
//<Date type="earliest">[shippingHoursEarly]</Date>
|
|
||||||
//<Date type="latest">[shippingHoursLate]</Date>
|
|
||||||
|
|
||||||
// update teh shipping hours
|
|
||||||
|
|
||||||
const now = new Date();
|
|
||||||
const formattedDate = records[0].LoadingDate.toLocaleDateString("en-US", {
|
|
||||||
month: "2-digit",
|
|
||||||
day: "2-digit",
|
|
||||||
year: "numeric",
|
|
||||||
});
|
|
||||||
|
|
||||||
const shippingHours = JSON.parse(plantI[0]?.shippingHours!);
|
|
||||||
//console.log(shippingHours);
|
|
||||||
|
|
||||||
payload = payload
|
|
||||||
.replaceAll(
|
|
||||||
"[shippingHoursEarly]",
|
|
||||||
`${formattedDate} ${shippingHours[0].early}`
|
|
||||||
)
|
|
||||||
.replaceAll(
|
|
||||||
"[shippingHoursLate]",
|
|
||||||
`${formattedDate} ${shippingHours[0].late}`
|
|
||||||
);
|
|
||||||
|
|
||||||
payload = payload
|
|
||||||
.replaceAll("[plantName]", `Alpla ${plantI[0]?.sName!}`)
|
|
||||||
.replaceAll("[plantStreetAddress]", plantI[0]?.streetAddress!)
|
|
||||||
.replaceAll("[plantCity]", plantI[0]?.cityState!.split(",")[0])
|
|
||||||
.replaceAll("[plantState]", plantI[0]?.cityState!.split(",")[1])
|
|
||||||
.replaceAll("[plantZipCode]", plantI[0]?.zipcode!)
|
|
||||||
.replaceAll("[contactNum]", plantI[0]?.contactPhone!)
|
|
||||||
.replaceAll("[contactEmail]", plantI[0]?.contactEmail!)
|
|
||||||
|
|
||||||
// customer info
|
|
||||||
.replaceAll("[customerName]", records[0].addressAlias)
|
|
||||||
.replaceAll("[customerStreetAddress]", records[0].streetAddress)
|
|
||||||
.replaceAll("[customerCity]", records[0].city.split(",")[0])
|
|
||||||
.replaceAll("[customerState]", records[0].city.split(",")[1])
|
|
||||||
.replaceAll("[customerZip]", records[0].zipCode)
|
|
||||||
.replaceAll("[customerPO]", records[0].Header)
|
|
||||||
.replaceAll(
|
|
||||||
"[glCoding]",
|
|
||||||
`52410-${
|
|
||||||
records[0].artileType.toLowerCase() === "preform" ||
|
|
||||||
records[0].artileType.toLowerCase() === "metalCage"
|
|
||||||
? 31
|
|
||||||
: plantI[0].greatPlainsPlantCode
|
|
||||||
}`
|
|
||||||
) // {"52410 - " + (artileType.toLowerCase() === "preform" || artileType.toLowerCase() === "metalCage" ? 31: plantInfo[0].greatPlainsPlantCode)}
|
|
||||||
.replaceAll(
|
|
||||||
"[pfc]",
|
|
||||||
`${
|
|
||||||
records[0].artileType.toLowerCase() === "preform" ||
|
|
||||||
records[0].artileType.toLowerCase() === "metalCage"
|
|
||||||
? 40
|
|
||||||
: records[0].costCenter
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
|
|
||||||
// special instructions
|
|
||||||
if (otherSettings[0].specialInstructions.length != 0) {
|
|
||||||
payload = payload.replaceAll("[specialInstructions]", specialInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update the carrier info if any is needed.
|
|
||||||
|
|
||||||
// check the address has a real carrier on it and change to true and put the sacs code in
|
|
||||||
const hasCarrier = true;
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`Checking if ${records[0].addressAlias} has scac: ${
|
|
||||||
records[0].remark.split(",")[0] ? "there was one" : "no scac"
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
|
|
||||||
const priceSheet = `
|
|
||||||
<PriceSheets>
|
|
||||||
<PriceSheet type="Carrier" isSelected="${
|
|
||||||
records[0].remark.split(",")[0] ? "true" : "false"
|
|
||||||
}">
|
|
||||||
<ContractId/>
|
|
||||||
${
|
|
||||||
records[0].remark.split(",")[0]
|
|
||||||
? `<SCAC>${records[0].remark
|
|
||||||
.split(",")[0]
|
|
||||||
.split(":")[1]
|
|
||||||
.toUpperCase()}</SCAC>`
|
|
||||||
: `<SCAC/>`
|
|
||||||
}
|
|
||||||
<Mode/>
|
|
||||||
</PriceSheet>
|
|
||||||
</PriceSheets>
|
|
||||||
`;
|
|
||||||
|
|
||||||
payload = payload.replaceAll("[priceSheet]", priceSheet);
|
|
||||||
// console.log(payload);
|
|
||||||
//await closePool();
|
|
||||||
|
|
||||||
//put the xml into a form
|
|
||||||
const formBody = querystring.stringify({
|
|
||||||
userid,
|
|
||||||
password,
|
|
||||||
request: payload,
|
|
||||||
});
|
|
||||||
axios
|
|
||||||
.post(
|
|
||||||
"https://t-insightws.mercurygate.net/MercuryGate/common/remoteService.jsp",
|
|
||||||
formBody,
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/x-www-form-urlencoded",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
//console.log(response.data)
|
|
||||||
console.log("Data was sent over to TI");
|
|
||||||
})
|
|
||||||
.catch((error) => console.error(error));
|
|
||||||
|
|
||||||
// console.log(payload);
|
|
||||||
|
|
||||||
// the order is done so we want to update the processed.
|
|
||||||
|
|
||||||
// add the new processed order to this
|
|
||||||
let notiSettingArray = notiSet.notifiySettings;
|
|
||||||
|
|
||||||
if (
|
|
||||||
!notiSettingArray[0].processed.includes(headerPending[0].releaseNumber)
|
|
||||||
) {
|
|
||||||
notiSettingArray[0].processed.push(headerPending[0].releaseNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data, error } = await tryCatch(
|
|
||||||
db
|
|
||||||
.update(notifications)
|
|
||||||
.set({
|
|
||||||
lastRan: sql`NOW()`,
|
|
||||||
notifiySettings: {
|
|
||||||
...notiSettingArray,
|
|
||||||
prodID: 1,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.where(eq(notifications.name, "tiIntergration"))
|
|
||||||
);
|
|
||||||
createLog("info", "ti", "notify", "done with this order");
|
|
||||||
return { success: true, code: 0, message: "done with this order" };
|
|
||||||
};
|
|
||||||
|
|
||||||
// add a running check so we cant flag it twice
|
// add a running check so we cant flag it twice
|
||||||
export let tiExportRunning = false;
|
export let tiExportRunning = false;
|
||||||
|
|
||||||
export const runTiImport = async () => {
|
export const runTiImport = async () => {
|
||||||
let finished = false;
|
let finished = false;
|
||||||
let test: any;
|
let test: any;
|
||||||
@@ -420,14 +17,20 @@ export const runTiImport = async () => {
|
|||||||
"info",
|
"info",
|
||||||
"ti",
|
"ti",
|
||||||
"notify",
|
"notify",
|
||||||
`Still more to process? ${test.code === 1 ? "No" : "Yes"}`
|
`Still more to process? ${test.success ? "No" : "Yes"}`
|
||||||
);
|
);
|
||||||
if (test.code === 1) {
|
if (test.success) {
|
||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!test.success) {
|
||||||
|
//errors are handled in the tiImport function
|
||||||
|
tiExportRunning = false;
|
||||||
|
}
|
||||||
await delay(1000 * 5);
|
await delay(1000 * 5);
|
||||||
} while (!finished);
|
} while (!finished);
|
||||||
tiExportRunning = false;
|
tiExportRunning = false;
|
||||||
|
return { success: true, message: "Finished processing all data." };
|
||||||
};
|
};
|
||||||
|
|
||||||
export default tiImport;
|
export default runTiImport;
|
||||||
|
|||||||
@@ -9,10 +9,12 @@ import { createLog } from "../logger/logger.js";
|
|||||||
import { note, notificationCreate } from "./utils/masterNotifications.js";
|
import { note, notificationCreate } from "./utils/masterNotifications.js";
|
||||||
import { startNotificationMonitor } from "./utils/processNotifications.js";
|
import { startNotificationMonitor } from "./utils/processNotifications.js";
|
||||||
import notifyStats from "./routes/getActiveNotifications.js";
|
import notifyStats from "./routes/getActiveNotifications.js";
|
||||||
|
import tiTrigger from "./routes/manualTiggerTi.js";
|
||||||
|
import blocking from "./routes/qualityBlocking.js";
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
|
|
||||||
const routes = [sendemail, notifyStats] as const;
|
const routes = [sendemail, notifyStats, tiTrigger, blocking] as const;
|
||||||
|
|
||||||
const appRoutes = routes.forEach((route) => {
|
const appRoutes = routes.forEach((route) => {
|
||||||
app.route("/notify", route);
|
app.route("/notify", route);
|
||||||
@@ -41,21 +43,9 @@ if (notesError) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note.length != notes?.length) {
|
setTimeout(() => {
|
||||||
notificationCreate();
|
notificationCreate();
|
||||||
createLog("info", "notify", "notify", `New notifcations being added.`);
|
startNotificationMonitor();
|
||||||
setTimeout(() => {
|
}, 5 * 1000);
|
||||||
startNotificationMonitor();
|
|
||||||
}, 5 * 1000);
|
|
||||||
} else {
|
|
||||||
createLog(
|
|
||||||
"info",
|
|
||||||
"notify",
|
|
||||||
"notify",
|
|
||||||
`There are know new notifcations. no need to run the update. reminder all changes happen per server.`
|
|
||||||
);
|
|
||||||
setTimeout(() => {
|
|
||||||
startNotificationMonitor();
|
|
||||||
}, 5 * 1000);
|
|
||||||
}
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|||||||
@@ -1,22 +1,26 @@
|
|||||||
// import {Router} from "express";
|
// an external way to creating logs
|
||||||
// import {tiExportRunning, runTiImport} from "../../notification/notification/tiFullFlow/tiImports.js";
|
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||||
|
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||||
|
|
||||||
// const router = Router();
|
import runTiImport from "../controller/notifications/tiIntergration.js";
|
||||||
|
|
||||||
// router.get("/tiTrigger", async (req, res): Promise<void> => {
|
const app = new OpenAPIHono({ strict: false });
|
||||||
// if (tiExportRunning) {
|
|
||||||
// res.status(200).json({
|
|
||||||
// success: false,
|
|
||||||
// message: "There is already a current sesion of the Export running please try again later.",
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // trigger the import
|
app.openapi(
|
||||||
// runTiImport();
|
createRoute({
|
||||||
|
tags: ["notify"],
|
||||||
// res.status(200).json({
|
summary: "Manually trigger TI intergrations.",
|
||||||
// success: true,
|
method: "get",
|
||||||
// message: "The Ti Export has been manually started and will continue to run in the background.",
|
path: "/tiTrigger",
|
||||||
// });
|
//middleware: authMiddleware,
|
||||||
// });
|
responses: responses(),
|
||||||
// export default router;
|
}),
|
||||||
|
async (c) => {
|
||||||
|
const tiImport = await runTiImport();
|
||||||
|
return c.json({
|
||||||
|
success: tiImport?.success,
|
||||||
|
message: tiImport?.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
|
|||||||
50
server/services/notifications/routes/qualityBlocking.ts
Normal file
50
server/services/notifications/routes/qualityBlocking.ts
Normal 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 qualityBlockingMonitor from "../controller/notifications/qualityBlocking.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
|
||||||
|
import { notifications } from "../../../../database/schema/notifications.js";
|
||||||
|
import { db } from "../../../../database/dbclient.js";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
|
const app = new OpenAPIHono({ strict: false });
|
||||||
|
|
||||||
|
app.openapi(
|
||||||
|
createRoute({
|
||||||
|
tags: ["notify"],
|
||||||
|
summary: "Manually trigger TI intergrations.",
|
||||||
|
method: "get",
|
||||||
|
path: "/blockingTrigger",
|
||||||
|
//middleware: authMiddleware,
|
||||||
|
responses: responses(),
|
||||||
|
}),
|
||||||
|
async (c) => {
|
||||||
|
/**
|
||||||
|
* get the blocking notification stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { data, error } = await tryCatch(
|
||||||
|
db
|
||||||
|
.select()
|
||||||
|
.from(notifications)
|
||||||
|
.where(eq(notifications.name, "qualityBlocking"))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return c.json({
|
||||||
|
success: false,
|
||||||
|
message: "Error Getting Notification Settings.",
|
||||||
|
data: error,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const blocking = await qualityBlockingMonitor(data[0]);
|
||||||
|
|
||||||
|
return c.json({
|
||||||
|
success: blocking?.success,
|
||||||
|
message: blocking?.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
export default app;
|
||||||
@@ -31,7 +31,10 @@ export const note: any = [
|
|||||||
timeType: "min",
|
timeType: "min",
|
||||||
emails: "",
|
emails: "",
|
||||||
active: false,
|
active: false,
|
||||||
notifiySettings: { prodID: 1, sentBlockingOrders: [1] },
|
notifiySettings: {
|
||||||
|
prodID: 1,
|
||||||
|
sentBlockingOrders: [{ timeStamp: "0", blockingOrder: 1 }],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "productionCheck",
|
name: "productionCheck",
|
||||||
@@ -72,8 +75,8 @@ export const note: any = [
|
|||||||
notifiySettings: {
|
notifiySettings: {
|
||||||
prodID: 1,
|
prodID: 1,
|
||||||
start: 36,
|
start: 36,
|
||||||
end: 720,
|
end: 36,
|
||||||
releases: [1, 2, 3],
|
releases: [{ timeStamp: "0", releaseNumber: 1 }],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -86,7 +89,7 @@ export const note: any = [
|
|||||||
notifiySettings: {
|
notifiySettings: {
|
||||||
prodID: 1,
|
prodID: 1,
|
||||||
start: 36,
|
start: 36,
|
||||||
end: 720,
|
end: 36,
|
||||||
releases: [1, 2, 3],
|
releases: [1, 2, 3],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -98,7 +101,14 @@ export const notificationCreate = async () => {
|
|||||||
const notify = await db
|
const notify = await db
|
||||||
.insert(notifications)
|
.insert(notifications)
|
||||||
.values(note[i])
|
.values(note[i])
|
||||||
.onConflictDoNothing();
|
.onConflictDoUpdate({
|
||||||
|
target: notifications.name,
|
||||||
|
set: {
|
||||||
|
name: note[i].name,
|
||||||
|
description: note[i].description,
|
||||||
|
//notifiySettings: note[i].notifiySettings,
|
||||||
|
},
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
createLog(
|
createLog(
|
||||||
"error",
|
"error",
|
||||||
@@ -110,4 +120,10 @@ export const notificationCreate = async () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"lst",
|
||||||
|
"nofity",
|
||||||
|
"notifications were just added/updated due to server startup"
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,23 +43,43 @@ export const startNotificationMonitor = async () => {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
!note.active ||
|
!note.active ||
|
||||||
note.emails === "" ||
|
// note.emails === "" ||
|
||||||
runningNotifications[note.name]
|
runningNotifications[note.name]
|
||||||
) {
|
) {
|
||||||
//console.log(`Skipping ${note.name} hes already scheduled`);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!runningNotifications[note.name] && note.active) {
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"notify",
|
||||||
|
"notify",
|
||||||
|
`${note.name} Is active and not already running.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let time = `*/30 * * * *`; // default to be every 30 min
|
let time = `*/30 * * * *`; // default to be every 30 min
|
||||||
|
|
||||||
if (note.timeType === "min") {
|
if (note.timeType === "min") {
|
||||||
console.log(`Creating the min mark here`);
|
//console.log(`Creating the min mark here`);
|
||||||
time = `*/${note.checkInterval} * * * *`;
|
const totalMinutes = note.checkInterval;
|
||||||
|
if (note.checkInterval > 60) {
|
||||||
|
const hours = Math.floor(totalMinutes / 60); // 1 hour
|
||||||
|
const minutes = totalMinutes % 60; // 45 minutes
|
||||||
|
time = `*/${minutes} */${hours} * * *`;
|
||||||
|
} else {
|
||||||
|
time = `*/${note.checkInterval} * * * *`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note.timeType === "hour") {
|
if (note.timeType === "hour") {
|
||||||
console.log(`Creating the hour mark here`);
|
const totalHours = note.checkInterval;
|
||||||
time = `* */${note.checkInterval} * * *`;
|
if (note.checkInterval > 60) {
|
||||||
|
const days = Math.floor(totalHours / 24); // 1 hour
|
||||||
|
const hours = totalHours % 24; // 45 minutes
|
||||||
|
time = `* */${hours} */${days} * *`;
|
||||||
|
} else {
|
||||||
|
time = `* */${note.checkInterval} * * *`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createJob(note.name, time, async () => {
|
createJob(note.name, time, async () => {
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
import { db } from "../../../../database/dbclient.js";
|
|
||||||
import { settings } from "../../../../database/schema/settings.js";
|
|
||||||
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
|
||||||
import type { User } from "../../../types/users.js";
|
import type { User } from "../../../types/users.js";
|
||||||
import { alplaStockInv } from "./cycleCount/alplaStockInventory.js";
|
import { alplaStockInv } from "./cycleCount/alplaStockInventory.js";
|
||||||
import { emptyCount } from "./cycleCount/emptyCycleCount.js";
|
import { emptyCount } from "./cycleCount/emptyCycleCount.js";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { eq, gte, sql } from "drizzle-orm";
|
import { eq, gte, sql } from "drizzle-orm";
|
||||||
import { db } from "../../../../../database/dbclient.js";
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
import { printers } from "../../../../../database/schema/printers.js";
|
import { printerData } from "../../../../../database/schema/printers.js";
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
import { createLog } from "../../../logger/logger.js";
|
import { createLog } from "../../../logger/logger.js";
|
||||||
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
||||||
@@ -15,8 +15,8 @@ export const createLabel = async (data: any, userPrinted: any) => {
|
|||||||
const { data: printer, error: printerError } = await tryCatch(
|
const { data: printer, error: printerError } = await tryCatch(
|
||||||
db
|
db
|
||||||
.select()
|
.select()
|
||||||
.from(printers)
|
.from(printerData)
|
||||||
.where(eq(printers.humanReadableId, data.printerID))
|
.where(eq(printerData.humanReadableId, data.printerID))
|
||||||
);
|
);
|
||||||
const { data: settingsData, error: settingsError } = await tryCatch(
|
const { data: settingsData, error: settingsError } = await tryCatch(
|
||||||
db.select().from(settings)
|
db.select().from(settings)
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import { db } from "../../../../../database/dbclient.js";
|
import { db } from "../../../../../database/dbclient.js";
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
import { printers } from "../../../../../database/schema/printers.js";
|
import { printerData } from "../../../../../database/schema/printers.js";
|
||||||
|
|
||||||
export const getPrinters = async () => {
|
export const getPrinters = async () => {
|
||||||
const currentTime = new Date(Date.now());
|
const { data: printers, error: printerError } = await tryCatch(
|
||||||
|
db.select().from(printerData)
|
||||||
const { data: printerData, error: printerError } = await tryCatch(
|
|
||||||
db.select().from(printers)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (printerError) {
|
if (printerError) {
|
||||||
@@ -17,5 +15,5 @@ export const getPrinters = async () => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { success: true, message: "Printers", data: printerData };
|
return { success: true, message: "Printers", data: printers };
|
||||||
};
|
};
|
||||||
|
|||||||
20
server/services/ocp/controller/printers/printerCycle.ts
Normal file
20
server/services/ocp/controller/printers/printerCycle.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { getPrinters } from "./getPrinters.js";
|
||||||
|
|
||||||
|
export const printerCycle = async () => {
|
||||||
|
/**
|
||||||
|
* We will cycle through the printers to check there states.
|
||||||
|
*/
|
||||||
|
let printers = await getPrinters();
|
||||||
|
/**
|
||||||
|
* if the last timeprinted would be greater than x well just change the status to idle and extended based on the 2 times.
|
||||||
|
*
|
||||||
|
* to get a printer going again label will need to come from the front end as that will just unpause the printer and start the labeling, or the api for manual print
|
||||||
|
* well need to adjust this to actually print the label then unpause it.
|
||||||
|
*
|
||||||
|
* it will be
|
||||||
|
*
|
||||||
|
* less than x since time printed run the printer status
|
||||||
|
* greater than x but less than y change the status to idle, but ping to make sure its online,
|
||||||
|
* if greater than y change to extended idle but stil also ping to make sure its online.
|
||||||
|
*/
|
||||||
|
};
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { printers } from "../../../../../database/schema/printers.js";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { printerData } from "../../../../../database/schema/printers.js";
|
||||||
import { sql } from "drizzle-orm";
|
import { sql } from "drizzle-orm";
|
||||||
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
import { prodEndpointCreation } from "../../../../globalUtils/createUrl.js";
|
||||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||||
@@ -47,10 +46,10 @@ export const updatePrinters = async () => {
|
|||||||
};
|
};
|
||||||
const { data, error } = await tryCatch(
|
const { data, error } = await tryCatch(
|
||||||
db
|
db
|
||||||
.insert(printers)
|
.insert(printerData)
|
||||||
.values(printerStuff)
|
.values(printerStuff)
|
||||||
.onConflictDoUpdate({
|
.onConflictDoUpdate({
|
||||||
target: printers.humanReadableId,
|
target: printerData.humanReadableId,
|
||||||
set: {
|
set: {
|
||||||
//humanReadableId: prodPrinterInfo[i].humanReadableId,
|
//humanReadableId: prodPrinterInfo[i].humanReadableId,
|
||||||
name: prodPrinterInfo[i].name,
|
name: prodPrinterInfo[i].name,
|
||||||
|
|||||||
87
server/services/ocp/utils/checkAssignments.ts
Normal file
87
server/services/ocp/utils/checkAssignments.ts
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import { delay } from "../../../globalUtils/delay.js";
|
||||||
|
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||||
|
import { getLots } from "../controller/lots/lots.js";
|
||||||
|
import { getPrinters } from "../controller/printers/getPrinters.js";
|
||||||
|
|
||||||
|
export const assignedPrinters = async () => {
|
||||||
|
const { data: l, error: lotError } = await tryCatch(getLots());
|
||||||
|
|
||||||
|
if (lotError) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting lots",
|
||||||
|
data: lotError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const { data: print, error: printerError } = await tryCatch(getPrinters());
|
||||||
|
|
||||||
|
if (printerError) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
message: "Error getting lots",
|
||||||
|
data: printerError,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const printers: any = print;
|
||||||
|
const lots: any = l;
|
||||||
|
|
||||||
|
for (let i = 0; i < printers.data.length; i++) {
|
||||||
|
// is the printer assinged in alplalabel online?
|
||||||
|
const assigned = lots.data.filter(
|
||||||
|
(p: any) => p.printerID === printers[i].humanReadableId
|
||||||
|
);
|
||||||
|
let assignedPrinter = false;
|
||||||
|
// if true update the assigned field to true
|
||||||
|
if (assigned.length >= 1) {
|
||||||
|
assignedPrinter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the last time printed is greater than 5 min change the status to 10
|
||||||
|
// const lastTime = new Date(printers[i].lastTimePrinted);
|
||||||
|
// let status = printers[i].status;
|
||||||
|
// let statusText = printers[i].statusText;
|
||||||
|
|
||||||
|
// // states we consider idle
|
||||||
|
// const printerStateCheck = [1, 2, 3, 4, 5, 6, 10];
|
||||||
|
// if (
|
||||||
|
// differenceInMinutes(currentTime, lastTime) >= 60 &&
|
||||||
|
// printerStateCheck.includes(printers[i].status) &&
|
||||||
|
// printers[i].assigned
|
||||||
|
// ) {
|
||||||
|
// createLog(
|
||||||
|
// "printerState",
|
||||||
|
// "info",
|
||||||
|
// `${printers[i].name} has been idle for more than 60 min, doing a heartbeat check`
|
||||||
|
// );
|
||||||
|
|
||||||
|
// status = 11;
|
||||||
|
// statusText = "idle";
|
||||||
|
|
||||||
|
// // printerState({printerCheck: printers[i]});
|
||||||
|
// } else if (differenceInMinutes(currentTime, lastTime) > 5 && printers[i].status === 7) {
|
||||||
|
// createLog(
|
||||||
|
// "printerState",
|
||||||
|
// "info",
|
||||||
|
// `${printers[i].name} has been errored for more 5 min changing to idle until, until it gets checked at the hour heartbeat.`
|
||||||
|
// );
|
||||||
|
// status = 10;
|
||||||
|
// statusText = "idle";
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const updatePrinter = await prisma.printers.update({
|
||||||
|
// where: {
|
||||||
|
// humanReadableId: printers[i].humanReadableId,
|
||||||
|
// },
|
||||||
|
// data: {
|
||||||
|
// assigned: assignedPrinter,
|
||||||
|
// // status,
|
||||||
|
// // statusText,
|
||||||
|
// upd_date: new Date(Date.now()).toISOString(),
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
//delaying 250ms
|
||||||
|
await delay(250);
|
||||||
|
}
|
||||||
|
};
|
||||||
52
server/services/ocp/utils/pausePrinter.ts
Normal file
52
server/services/ocp/utils/pausePrinter.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import net from "net";
|
||||||
|
import { createLog } from "../../logger/logger.js";
|
||||||
|
|
||||||
|
export const pausePrinter = async (printerData: any) => {
|
||||||
|
const pause = new net.Socket();
|
||||||
|
|
||||||
|
if (printerData.name) {
|
||||||
|
createLog(
|
||||||
|
"debug",
|
||||||
|
"printerState",
|
||||||
|
"ocp",
|
||||||
|
`${printerData.name}: paused printed`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"printerState",
|
||||||
|
"ocp",
|
||||||
|
`Unknown name on printer was just paused, Body sent over: ${printerData.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
pause.connect(printerData.port, printerData.ipAddress, async () => {
|
||||||
|
// console.log("Connected to printer");
|
||||||
|
pause.write("~PP");
|
||||||
|
pause.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
pause.on("error", (error) => {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"printerState",
|
||||||
|
"ocp",
|
||||||
|
`There was an error pausing the printer: ${JSON.stringify(
|
||||||
|
error
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
reject({
|
||||||
|
success: true,
|
||||||
|
message: "There was an error pausing the printer",
|
||||||
|
data: error,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
message: `${
|
||||||
|
printerData?.name || printerData.ipAddress
|
||||||
|
} Printer was paused`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
55
server/services/ocp/utils/unpausePrinter.ts
Normal file
55
server/services/ocp/utils/unpausePrinter.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import net from "net";
|
||||||
|
import { createLog } from "../../logger/logger.js";
|
||||||
|
|
||||||
|
export const unPausePrinter = async (printerData: any) => {
|
||||||
|
const pause = new net.Socket();
|
||||||
|
|
||||||
|
if (printerData.name) {
|
||||||
|
createLog(
|
||||||
|
"debug",
|
||||||
|
"printerState",
|
||||||
|
"ocp",
|
||||||
|
`${printerData.name}: unpaused printed`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"printerState",
|
||||||
|
"ocp",
|
||||||
|
`Unknown name on printer was just unpaused, Body sent over: ${JSON.stringify(
|
||||||
|
printerData
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
pause.connect(printerData.port, printerData.ipAddress, async () => {
|
||||||
|
// console.log("Connected to printer");
|
||||||
|
pause.write("~PS");
|
||||||
|
pause.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
pause.on("error", (error) => {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"printerState",
|
||||||
|
"ocp",
|
||||||
|
`There was an error unpausing the printer: ${JSON.stringify(
|
||||||
|
error
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
reject({
|
||||||
|
success: true,
|
||||||
|
message: "There was an error unpausing the printer",
|
||||||
|
data: error,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
message: `${
|
||||||
|
printerData?.name || printerData.ipAddress
|
||||||
|
} Printer was unpaused`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||||
import {authMiddleware} from "../../../auth/middleware/authMiddleware.js";
|
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
||||||
import {updateServer} from "../../../../scripts/updateServers.js";
|
import {
|
||||||
|
processAllServers,
|
||||||
|
updateServer,
|
||||||
|
} from "../../../../scripts/updateServers.js";
|
||||||
|
|
||||||
// Define the request body schema
|
// Define the request body schema
|
||||||
const requestSchema = z.object({
|
const requestSchema = z.object({
|
||||||
@@ -13,26 +16,33 @@ const requestSchema = z.object({
|
|||||||
// Define the response schema
|
// Define the response schema
|
||||||
const responseSchema = z.object({
|
const responseSchema = z.object({
|
||||||
message: z.string().optional(),
|
message: z.string().optional(),
|
||||||
module_id: z.string().openapi({example: "6c922c6c-7de3-4ec4-acb0-f068abdc"}).optional(),
|
module_id: z
|
||||||
name: z.string().openapi({example: "Production"}).optional(),
|
.string()
|
||||||
active: z.boolean().openapi({example: true}).optional(),
|
.openapi({ example: "6c922c6c-7de3-4ec4-acb0-f068abdc" })
|
||||||
roles: z.string().openapi({example: `["viewer","technician"]`}).optional(),
|
.optional(),
|
||||||
|
name: z.string().openapi({ example: "Production" }).optional(),
|
||||||
|
active: z.boolean().openapi({ example: true }).optional(),
|
||||||
|
roles: z
|
||||||
|
.string()
|
||||||
|
.openapi({ example: `["viewer","technician"]` })
|
||||||
|
.optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const ParamsSchema = z.object({
|
const ParamsSchema = z.object({
|
||||||
server: z
|
server: z
|
||||||
.string()
|
.string()
|
||||||
.min(3)
|
.min(3)
|
||||||
.openapi({
|
.openapi({
|
||||||
param: {
|
param: {
|
||||||
name: "server",
|
name: "server",
|
||||||
in: "path",
|
in: "path",
|
||||||
},
|
},
|
||||||
example: "usbow1",
|
example: "usbow1",
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const UpdateServer = z.object({
|
const UpdateServer = z.object({
|
||||||
devDir: z.string().openapi({example: "C:\\something\\Something"}),
|
devDir: z.string().openapi({ example: "C:\\something\\Something" }),
|
||||||
|
all: z.boolean().optional().openapi({ example: true }),
|
||||||
});
|
});
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
@@ -48,30 +58,38 @@ app.openapi(
|
|||||||
params: ParamsSchema,
|
params: ParamsSchema,
|
||||||
body: {
|
body: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {schema: UpdateServer},
|
"application/json": { schema: UpdateServer },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {schema: responseSchema},
|
"application/json": { schema: responseSchema },
|
||||||
},
|
},
|
||||||
description: "Response message",
|
description: "Response message",
|
||||||
},
|
},
|
||||||
400: {
|
400: {
|
||||||
content: {
|
content: {
|
||||||
"application/json": {schema: responseSchema},
|
"application/json": { schema: responseSchema },
|
||||||
},
|
},
|
||||||
description: "Response message",
|
description: "Response message",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const {server} = c.req.valid("param");
|
const { server } = c.req.valid("param");
|
||||||
const body = await c.req.json();
|
const body = await c.req.json();
|
||||||
|
|
||||||
// fire off the update we wont make this way
|
// fire off the update we wont make this way
|
||||||
|
if (body.all) {
|
||||||
|
const update = await processAllServers(body.devDir);
|
||||||
|
return c.json({
|
||||||
|
success: update?.success ?? false,
|
||||||
|
message: update?.message,
|
||||||
|
data: [],
|
||||||
|
});
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const update = await updateServer(body.devDir, server);
|
const update = await updateServer(body.devDir, server);
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ import { serversCheckPoint } from "./utils/serverData.js";
|
|||||||
import getServers from "./route/servers/getServers.js";
|
import getServers from "./route/servers/getServers.js";
|
||||||
import updateServer from "./route/updates/updateServer.js";
|
import updateServer from "./route/updates/updateServer.js";
|
||||||
import { setPerms } from "./utils/testServerPerms.js";
|
import { setPerms } from "./utils/testServerPerms.js";
|
||||||
import serviceControl from './route/servers/serverContorl.js'
|
import serviceControl from "./route/servers/serverContorl.js";
|
||||||
|
import { areSubModulesIn } from "./utils/subModuleCheck.js";
|
||||||
|
|
||||||
// making sure all modules are in properly
|
// making sure all modules are in properly
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
@@ -21,6 +22,7 @@ setTimeout(async () => {
|
|||||||
await areModulesIn();
|
await areModulesIn();
|
||||||
await serversCheckPoint();
|
await serversCheckPoint();
|
||||||
await setPerms();
|
await setPerms();
|
||||||
|
await areSubModulesIn();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|
||||||
const app = new OpenAPIHono();
|
const app = new OpenAPIHono();
|
||||||
@@ -36,7 +38,7 @@ const routes = [
|
|||||||
// serverData
|
// serverData
|
||||||
getServers,
|
getServers,
|
||||||
updateServer,
|
updateServer,
|
||||||
serviceControl
|
serviceControl,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
// app.route("/server", modules);
|
// app.route("/server", modules);
|
||||||
|
|||||||
@@ -20,7 +20,12 @@ export const serversCheckPoint = async () => {
|
|||||||
const serverData = JSON.parse(data);
|
const serverData = JSON.parse(data);
|
||||||
servers = serverData.servers;
|
servers = serverData.servers;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error reading JSON file:", err);
|
createLog(
|
||||||
|
"error",
|
||||||
|
"server",
|
||||||
|
"server",
|
||||||
|
`Error reading JSON file: ${JSON.stringify(err)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the roles
|
// get the roles
|
||||||
|
|||||||
177
server/services/server/utils/subModuleCheck.ts
Normal file
177
server/services/server/utils/subModuleCheck.ts
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
/**
|
||||||
|
* check if the modules are in and if not add them.
|
||||||
|
* this will only run on a server start up
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { db } from "../../../../database/dbclient.js";
|
||||||
|
import { subModules } from "../../../../database/schema/subModules.js";
|
||||||
|
import { createLog } from "../../logger/logger.js";
|
||||||
|
// "view", "technician", "supervisor","manager", "admin", "systemAdmin"
|
||||||
|
const newSubModules = [
|
||||||
|
{
|
||||||
|
name: "Silo Adjustmnet",
|
||||||
|
moduleName: "logistics",
|
||||||
|
description: "Do a silo adjustmnet",
|
||||||
|
link: "/sa",
|
||||||
|
icon: "Cylinder",
|
||||||
|
active: false,
|
||||||
|
roles: ["tester", "systemAdmin"],
|
||||||
|
subSubModule: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bulk orders",
|
||||||
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "#",
|
||||||
|
icon: "Truck",
|
||||||
|
role: ["systemAdmin"],
|
||||||
|
active: false,
|
||||||
|
subSubModule: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Forecast",
|
||||||
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "#",
|
||||||
|
icon: "Truck",
|
||||||
|
role: ["systemAdmin"],
|
||||||
|
active: false,
|
||||||
|
subSubModule: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ocme cycle counts",
|
||||||
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "#",
|
||||||
|
icon: "Package",
|
||||||
|
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
|
active: false,
|
||||||
|
subSubModule: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Material Helper",
|
||||||
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "/materialHelper/consumption",
|
||||||
|
icon: "Package",
|
||||||
|
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
|
active: false,
|
||||||
|
subSubModule: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Ocme Cyclecount",
|
||||||
|
moduleName: "logistics",
|
||||||
|
description: "",
|
||||||
|
link: "/cyclecount",
|
||||||
|
icon: "Package",
|
||||||
|
role: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||||
|
active: false,
|
||||||
|
subSubModule: [],
|
||||||
|
},
|
||||||
|
|
||||||
|
// admin module
|
||||||
|
{
|
||||||
|
name: "Servers",
|
||||||
|
moduleName: "admin",
|
||||||
|
description: "Do a silo adjustmnet",
|
||||||
|
link: "/servers",
|
||||||
|
icon: "Server",
|
||||||
|
roles: ["tester", "systemAdmin"],
|
||||||
|
isActive: true,
|
||||||
|
subSubModule: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Admin",
|
||||||
|
moduleName: "admin",
|
||||||
|
description: "Do a silo adjustmnet",
|
||||||
|
link: "#", // when link is # this will mean its a button
|
||||||
|
icon: "ShieldCheck",
|
||||||
|
active: true,
|
||||||
|
roles: ["tester", "systemAdmin"],
|
||||||
|
subSubModule: [
|
||||||
|
{
|
||||||
|
name: "Settings",
|
||||||
|
link: "/settings",
|
||||||
|
icon: "Settings",
|
||||||
|
newWindow: false,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Modules",
|
||||||
|
link: "/modules",
|
||||||
|
icon: "Settings",
|
||||||
|
newWindow: false,
|
||||||
|
isActive: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Swagger",
|
||||||
|
link: "#",
|
||||||
|
icon: "Webhook",
|
||||||
|
newWindow: false,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Logs",
|
||||||
|
link: "#",
|
||||||
|
icon: "Logs",
|
||||||
|
newWindow: false,
|
||||||
|
isActive: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Users",
|
||||||
|
link: "/users",
|
||||||
|
icon: "Users",
|
||||||
|
newWindow: false,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "UCD",
|
||||||
|
link: "https://ucd.alpla.net:8443/",
|
||||||
|
icon: "Atom",
|
||||||
|
newWindow: false,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Lst Api",
|
||||||
|
link: "/api/docs",
|
||||||
|
icon: "Webhook",
|
||||||
|
newWindow: false,
|
||||||
|
isActive: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export const areSubModulesIn = async () => {
|
||||||
|
try {
|
||||||
|
for (let i = 0; i < newSubModules.length; i++) {
|
||||||
|
const subModuleUpdate = await db
|
||||||
|
.insert(subModules)
|
||||||
|
.values(newSubModules[i])
|
||||||
|
.onConflictDoUpdate({
|
||||||
|
target: subModules.name,
|
||||||
|
set: {
|
||||||
|
name: newSubModules[i].name,
|
||||||
|
moduleName: newSubModules[i].moduleName,
|
||||||
|
description: newSubModules[i].description,
|
||||||
|
roles: newSubModules[i].roles,
|
||||||
|
link: newSubModules[i].link,
|
||||||
|
subSubModule: newSubModules[i].subSubModule,
|
||||||
|
},
|
||||||
|
}) // this will only update the ones that are new :D
|
||||||
|
.returning({ name: subModules.name });
|
||||||
|
}
|
||||||
|
createLog(
|
||||||
|
"info",
|
||||||
|
"lst",
|
||||||
|
"server",
|
||||||
|
"SubModules were just added due to missing them on server startup"
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
createLog(
|
||||||
|
"error",
|
||||||
|
"lst",
|
||||||
|
"server",
|
||||||
|
"There was an error adding new subModules to the db"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
export const customerInvNoHold = `
|
||||||
|
select x.idartikelVarianten as av
|
||||||
|
,ArtikelVariantenAlias as Alias
|
||||||
|
--x.Lfdnr as RunningNumber,
|
||||||
|
--,round(sum(EinlagerungsMengeVPKSum),0) as Total_Pallets
|
||||||
|
--,sum(EinlagerungsMengeSum) as Total_PalletQTY
|
||||||
|
,round(sum(VerfuegbareMengeVPKSum),0) as Avalible_Pallets
|
||||||
|
,sum(VerfuegbareMengeSum) as Avaliable_PalletQTY
|
||||||
|
,sum(case when c.Description LIKE '%COA%' then GesperrteMengeVPKSum else 0 end) as COA_Pallets
|
||||||
|
,sum(case when c.Description LIKE '%COA%' then GesperrteMengeSum else 0 end) as COA_QTY
|
||||||
|
--,sum(case when c.Description NOT LIKE '%COA%' then GesperrteMengeVPKSum else 0 end) as Held_Pallets
|
||||||
|
--,sum(case when c.Description NOT LIKE '%COA%' then GesperrteMengeSum else 0 end) as Held_QTY
|
||||||
|
,IdProdPlanung as Lot
|
||||||
|
--,IdAdressen
|
||||||
|
--,x.AdressBez
|
||||||
|
--,*
|
||||||
|
from [AlplaPROD_test1].dbo.[V_LagerPositionenBarcodes] (nolock) x
|
||||||
|
|
||||||
|
left join
|
||||||
|
[AlplaPROD_test1].dbo.T_EtikettenGedruckt (nolock) on
|
||||||
|
x.Lfdnr = T_EtikettenGedruckt.Lfdnr AND T_EtikettenGedruckt.Lfdnr > 1
|
||||||
|
|
||||||
|
left join
|
||||||
|
|
||||||
|
(SELECT *
|
||||||
|
FROM [AlplaPROD_test1].[dbo].[T_BlockingDefects] (nolock) where Active = 1) as c
|
||||||
|
on x.IdMainDefect = c.IdBlockingDefect
|
||||||
|
/*
|
||||||
|
The data below will be controlled by the user in excell by default everything will be passed over
|
||||||
|
IdAdressen = 3
|
||||||
|
*/
|
||||||
|
where IdArtikelTyp = 1
|
||||||
|
and x.IdWarenlager not in (6, 1)
|
||||||
|
--and IdAdressen
|
||||||
|
|
||||||
|
|
||||||
|
group by x.IdArtikelVarianten
|
||||||
|
,ArtikelVariantenAlias
|
||||||
|
,IdProdPlanung
|
||||||
|
--,c.Description
|
||||||
|
,IdAdressen
|
||||||
|
,x.AdressBez
|
||||||
|
--, x.Lfdnr
|
||||||
|
order by x.IdArtikelVarianten
|
||||||
|
`;
|
||||||
27
server/services/sqlServer/querys/dataMart/openOrders.ts
Normal file
27
server/services/sqlServer/querys/dataMart/openOrders.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
export const openOrders = `
|
||||||
|
Select LEFT(ArtikelVariantenAlias, charindex(' ', ArtikelVariantenAlias) - 1) customerItemNumber,
|
||||||
|
x.IdArtikelVarianten AS article,
|
||||||
|
ArtikelVariantenAlias AS articleDescription,
|
||||||
|
IdAuftragsAbruf as releaseNumber,
|
||||||
|
AuftragsNummer AS header,
|
||||||
|
AuftragsNummer as customerLineItemNo,
|
||||||
|
AbrufNummer AS customerReleaseNumber,
|
||||||
|
AbrufMengeVPK AS pallets,
|
||||||
|
AbrufMenge AS qty,
|
||||||
|
y.TradeUnits AS cartons,
|
||||||
|
IdAdresse AS customerID,
|
||||||
|
LieferAdressBez as DeliveryAddressDescription,
|
||||||
|
AbrufLadeDatum AS loadingDate,
|
||||||
|
AbrufLiefertermin AS deliveryDate
|
||||||
|
--,OrderStatus = 'loading'
|
||||||
|
--,*
|
||||||
|
FROM alplaprod_test1.dbo.V_TrackerAuftragsAbrufe (nolock) x
|
||||||
|
|
||||||
|
left join
|
||||||
|
[test1_AlplaPROD2.0_Read].[order].[Release] (nolock) y on
|
||||||
|
x.IdAuftragsAbruf = y.ReleaseNumber
|
||||||
|
|
||||||
|
--WHERE AbrufStatus = 1 AND AbrufLiefertermin < getdate() + 5 AND GelieferteMenge = 0
|
||||||
|
WHERE AbrufStatus = 1 AND AbrufLiefertermin between getDate() + -[sDay] and getdate() + [eDay] AND GelieferteMenge = 0
|
||||||
|
ORDER BY AbrufLiefertermin
|
||||||
|
`;
|
||||||
45
server/services/sqlServer/querys/notifications/blocking.ts
Normal file
45
server/services/sqlServer/querys/notifications/blocking.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
export const blockQuery = `
|
||||||
|
SELECT
|
||||||
|
'Alert! new blocking order: #' + cast(HumanReadableId as varchar) + ' - ' + ArticleVariantDescription as subject,
|
||||||
|
cast([HumanReadableId] as varchar) as blockingNumber,
|
||||||
|
[ArticleVariantDescription] as article,
|
||||||
|
cast([CustomerHumanReadableId] as varchar) + ' - ' + [CustomerDescription] as customer,
|
||||||
|
convert(varchar(10), [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].[BlockingDate], 101) + ' - ' + convert(varchar(5), [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].[BlockingDate], 108) as blockingDate,
|
||||||
|
cast(ArticleVariantHumanReadableId as varchar) + ' - ' + ArticleVariantDescription as av,
|
||||||
|
case when [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].Remark = '' or [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].Remark is NULL then 'Please reach out to quality for the reason this was placed on hold as a remark was not entered during the blocking processs' else [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].Remark end as remark,
|
||||||
|
cast(FORMAT(TotalAmountOfPieces, '###,###') as varchar) + ' / ' + cast(LoadingUnit as varchar) as peicesAndLoadingUnits,
|
||||||
|
[test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].ProductionLotHumanReadableId as lotNumber,
|
||||||
|
cast(IdGlobalBlockingDefectsGroup as varchar) + ' - ' + BD.Description as mainDefectGroup,
|
||||||
|
cast(IdGlobalBlockingDefect as varchar) + ' - ' + MD.Description as mainDefect,
|
||||||
|
sent=0,
|
||||||
|
lot.MachineLocation as line,
|
||||||
|
HumanReadableId
|
||||||
|
FROM [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder] (nolock)
|
||||||
|
|
||||||
|
/*** Join 1.0 table to get correct id info to link ***/
|
||||||
|
join
|
||||||
|
[AlplaPROD_test1].[dbo].[T_BlockingOrders] (nolock) AS BO
|
||||||
|
on [HumanReadableId] = BO.[IdBlockingOrder]
|
||||||
|
|
||||||
|
|
||||||
|
/*** Get the main defect info ***/
|
||||||
|
Inner join
|
||||||
|
[AlplaPROD_test1].[dbo].[T_BlockingDefectsGroups] (nolock) as BD
|
||||||
|
ON BO.IdMainDefectGroup = BD.IdBlockingDefectsGroup
|
||||||
|
|
||||||
|
INNER join
|
||||||
|
[AlplaPROD_test1].[dbo].[T_BlockingDefects] as MD
|
||||||
|
ON BO.IdMainDefect = MD.IdBlockingDefect
|
||||||
|
/*** get lot info ***/
|
||||||
|
|
||||||
|
left join
|
||||||
|
(SELECT [MachineLocation]
|
||||||
|
,[MachineDescription]
|
||||||
|
,[ProductionLotHumanReadableId]
|
||||||
|
FROM [test1_AlplaPROD2.0_Reporting].[reporting_productionControlling].[ProducedLot]) as lot
|
||||||
|
on [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].ProductionLotHumanReadableId = lot.ProductionLotHumanReadableId
|
||||||
|
|
||||||
|
where [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].[BlockingDate] between getdate() - 1 and getdate() + 1
|
||||||
|
and [test1_AlplaPROD2.0_Reporting].[reporting_blocking].[BlockingOrder].BlockingTrigger = 1
|
||||||
|
and HumanReadableId NOT IN ([sentBlockingOrders])
|
||||||
|
`;
|
||||||
Reference in New Issue
Block a user