Compare commits
32 Commits
d8edfaf05f
...
6665b77e09
| Author | SHA1 | Date | |
|---|---|---|---|
| 6665b77e09 | |||
| 2e2699ab3c | |||
| bad390ec17 | |||
| efc630f5f8 | |||
| ded074a1ce | |||
| ca0b027e67 | |||
| 1282f5efe4 | |||
| 77988477f6 | |||
| 37b26c4c92 | |||
| 72e2c6ea6a | |||
| ffe80d6a58 | |||
| 9dcd07bf2a | |||
| 4a36107ebb | |||
| fb03fc83e6 | |||
| 8c522c5b72 | |||
| e9c9a84a82 | |||
| ff2ecff146 | |||
| 3757b367d5 | |||
| 4d979089cb | |||
| b1e611c7b8 | |||
| 02fdc14769 | |||
| a794943740 | |||
| c2ad046fb0 | |||
| ba2b8036b8 | |||
| 26aa9d8f80 | |||
| 663f2f436c | |||
| 88f05eaf65 | |||
| b84d6f5186 | |||
| 410790e693 | |||
| f847ce423d | |||
| 27126cca35 | |||
| 04f524419d |
@@ -1,6 +1,15 @@
|
||||
import {text, pgTable, numeric, index, timestamp, boolean, uuid, uniqueIndex} from "drizzle-orm/pg-core";
|
||||
import {createInsertSchema, createSelectSchema} from "drizzle-zod";
|
||||
import {z} from "zod";
|
||||
import {
|
||||
text,
|
||||
pgTable,
|
||||
numeric,
|
||||
index,
|
||||
timestamp,
|
||||
boolean,
|
||||
uuid,
|
||||
uniqueIndex,
|
||||
} from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
export const logs = pgTable(
|
||||
"logs",
|
||||
@@ -11,7 +20,7 @@ export const logs = pgTable(
|
||||
service: text("service").notNull().default("system"),
|
||||
message: text("message").notNull(),
|
||||
checked: boolean("checked").default(false),
|
||||
checkedAt: timestamp("checkedAt"),
|
||||
//checkedAt: timestamp("checkedAt"),
|
||||
created_at: timestamp("add_Date").defaultNow(),
|
||||
},
|
||||
(table) => [
|
||||
|
||||
@@ -33,6 +33,7 @@ export type Servers = {
|
||||
idAddress: string;
|
||||
lastUpdated: string;
|
||||
isUpgrading: boolean;
|
||||
lstServerPort: string;
|
||||
};
|
||||
|
||||
export default function ServerPage() {
|
||||
@@ -144,7 +145,12 @@ export default function ServerPage() {
|
||||
return (
|
||||
<TableRow key={server.server_id}>
|
||||
<TableCell className="font-medium">
|
||||
{server.sName}
|
||||
<a
|
||||
href={`http://${server.serverDNS}:${server.lstServerPort}`}
|
||||
target={"_blank"}
|
||||
>
|
||||
<span>{server.sName}</span>
|
||||
</a>
|
||||
</TableCell>
|
||||
<TableCell className="font-medium">
|
||||
{server.serverDNS}
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/components/ui/accordion";
|
||||
import { getUsers } from "@/utils/querys/admin/users";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import UserCard from "./components/UserCard";
|
||||
@@ -22,22 +16,13 @@ export default function UserPage() {
|
||||
|
||||
return (
|
||||
<div className="m-2 w-dvw">
|
||||
<Accordion type="single" collapsible>
|
||||
{data.map((u: any) => {
|
||||
return (
|
||||
<AccordionItem key={u.user_id} value={u.user_id}>
|
||||
<AccordionTrigger>
|
||||
<span>{u.username}</span>
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div>
|
||||
<UserCard user={u} />
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
);
|
||||
})}
|
||||
</Accordion>
|
||||
{data.map((u: any) => {
|
||||
return (
|
||||
<div>
|
||||
<UserCard user={u} />
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,11 +19,13 @@ export default function ModuleAccess(data: any) {
|
||||
<div className="flex flex-row flex-wrap">
|
||||
{modules?.map((m: any) => {
|
||||
return (
|
||||
<ModuleForm
|
||||
key={m.module_id}
|
||||
i={m}
|
||||
username={data.user.username}
|
||||
/>
|
||||
<div key={m.module_id}>
|
||||
<ModuleForm
|
||||
module={m}
|
||||
user={data.user}
|
||||
refetch={data.refetch}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import {
|
||||
@@ -10,21 +9,26 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { getUserRoles } from "@/utils/querys/admin/userRoles";
|
||||
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
import axios from "axios";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export default function ModuleForm(props: any) {
|
||||
const { refetch } = useQuery(getUserRoles());
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const role =
|
||||
props.user?.moduleRoles?.filter(
|
||||
(m: any) => m.module_id === props.module.module_id
|
||||
)[0]?.role ?? " ";
|
||||
const form = useForm({
|
||||
defaultValues: { role: props.i.role },
|
||||
defaultValues: {
|
||||
role: role,
|
||||
},
|
||||
onSubmit: async ({ value }) => {
|
||||
const data = {
|
||||
username: props.username,
|
||||
module: props.i.name,
|
||||
const data: any = {
|
||||
username: props.user.username,
|
||||
module: props.module.name,
|
||||
role: value.role,
|
||||
};
|
||||
console.log(data);
|
||||
@@ -37,7 +41,7 @@ export default function ModuleForm(props: any) {
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(res.data.message);
|
||||
refetch();
|
||||
props.refetch();
|
||||
form.reset();
|
||||
} else {
|
||||
res.data.message;
|
||||
@@ -49,71 +53,67 @@ export default function ModuleForm(props: any) {
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="m-2 p-1">
|
||||
<LstCard>
|
||||
<p className="text-center">Module: {props.i.name}</p>
|
||||
|
||||
<p className="p-1">Current role: </p>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
<div className="">
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}}
|
||||
className="flex flex-row"
|
||||
>
|
||||
<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}>
|
||||
Module: {props.module.name}
|
||||
</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="technician">
|
||||
Technician
|
||||
</SelectItem>
|
||||
<SelectItem value="supervisor">
|
||||
Supervisor
|
||||
</SelectItem>
|
||||
<SelectItem value="manager">
|
||||
Manager
|
||||
</SelectItem>
|
||||
<SelectItem value="tester">
|
||||
Tester
|
||||
</SelectItem>
|
||||
<SelectItem value="admin">
|
||||
Admin
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</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="technician">
|
||||
Technician
|
||||
</SelectItem>
|
||||
<SelectItem value="supervisor">
|
||||
Supervisor
|
||||
</SelectItem>
|
||||
<SelectItem value="manager">
|
||||
Manager
|
||||
</SelectItem>
|
||||
<SelectItem value="tester">
|
||||
Tester
|
||||
</SelectItem>
|
||||
<SelectItem value="admin">
|
||||
Admin
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div className="mt-4">
|
||||
<Button type="submit" onClick={form.handleSubmit}>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</LstCard>
|
||||
/>
|
||||
<div className="mt-4">
|
||||
<Button type="submit" onClick={form.handleSubmit}>
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -22,13 +22,12 @@ import axios from "axios";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { CardHeader } from "@/components/ui/card";
|
||||
import ModuleAccess from "./ModuleAccess";
|
||||
|
||||
export default function UserCard(data: any) {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const { refetch } = useQuery(getUsers());
|
||||
|
||||
//console.log(modules);
|
||||
//console.log(data.user);
|
||||
//console.log(userRoles);
|
||||
const form = useForm({
|
||||
...userFormOptions(data.user),
|
||||
@@ -268,13 +267,17 @@ export default function UserCard(data: any) {
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<div className="mt-4 ml-4">
|
||||
<Button onClick={form.handleSubmit}>Save</Button>
|
||||
</div>
|
||||
</form>
|
||||
</LstCard>
|
||||
<div className="mt-4">
|
||||
<Button onClick={form.handleSubmit}>Save</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col"></div>
|
||||
<div>
|
||||
<LstCard>
|
||||
<ModuleAccess user={data.user} refetch={refetch} />
|
||||
</LstCard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
import {Sidebar, SidebarContent, SidebarFooter, SidebarTrigger} from "../ui/sidebar";
|
||||
import {ProductionSideBar} from "./side-components/production";
|
||||
import {Header} from "./side-components/header";
|
||||
import {LogisticsSideBar} from "./side-components/logistics";
|
||||
import {QualitySideBar} from "./side-components/quality";
|
||||
import {ForkliftSideBar} from "./side-components/forklift";
|
||||
import {EomSideBar} from "./side-components/eom";
|
||||
import {AdminSideBar} from "./side-components/admin";
|
||||
import {useSessionStore} from "../../lib/store/sessionStore";
|
||||
import {hasAccess} from "../../utils/userAccess";
|
||||
import {moduleActive} from "../../utils/moduleActive";
|
||||
import {useModuleStore} from "../../lib/store/useModuleStore";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarTrigger,
|
||||
} from "../ui/sidebar";
|
||||
import { ProductionSideBar } from "./side-components/production";
|
||||
import { Header } from "./side-components/header";
|
||||
import { LogisticsSideBar } from "./side-components/logistics";
|
||||
import { QualitySideBar } from "./side-components/quality";
|
||||
import { ForkliftSideBar } from "./side-components/forklift";
|
||||
import { EomSideBar } from "./side-components/eom";
|
||||
import { AdminSideBar } from "./side-components/admin";
|
||||
import { useSessionStore } from "../../lib/store/sessionStore";
|
||||
import { hasAccess } from "../../utils/userAccess";
|
||||
import { moduleActive } from "../../utils/moduleActive";
|
||||
import { useModuleStore } from "../../lib/store/useModuleStore";
|
||||
|
||||
export function AppSidebar() {
|
||||
const {user} = useSessionStore();
|
||||
const {modules} = useModuleStore();
|
||||
const { user } = useSessionStore();
|
||||
const { modules } = useModuleStore();
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="icon">
|
||||
@@ -22,19 +27,31 @@ export function AppSidebar() {
|
||||
{moduleActive("production") && (
|
||||
<ProductionSideBar
|
||||
user={user}
|
||||
moduleID={modules.filter((n) => n.name === "production")[0].module_id as string}
|
||||
moduleID={
|
||||
modules.filter((n) => n.name === "production")[0]
|
||||
.module_id as string
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{moduleActive("logistics") && (
|
||||
<LogisticsSideBar
|
||||
user={user}
|
||||
moduleID={modules.filter((n) => n.name === "logistics")[0].module_id as string}
|
||||
moduleID={
|
||||
modules.filter((n) => n.name === "logistics")[0]
|
||||
.module_id as string
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{moduleActive("forklift") && hasAccess(user, "forklift", modules) && <ForkliftSideBar />}
|
||||
{moduleActive("eom") && hasAccess(user, "eom", modules) && <EomSideBar />}
|
||||
{moduleActive("quality") && hasAccess(user, "quality", modules) && <QualitySideBar />}
|
||||
{moduleActive("admin") && hasAccess(user, "admin", modules) && <AdminSideBar />}
|
||||
{moduleActive("forklift") &&
|
||||
hasAccess(user, "forklift", modules) && <ForkliftSideBar />}
|
||||
{moduleActive("eom") && hasAccess(user, "eom", modules) && (
|
||||
<EomSideBar />
|
||||
)}
|
||||
{moduleActive("quality") &&
|
||||
hasAccess(user, "quality", modules) && <QualitySideBar />}
|
||||
{moduleActive("admin") && hasAccess(user, "admin", modules) && (
|
||||
<AdminSideBar />
|
||||
)}
|
||||
</SidebarContent>
|
||||
<SidebarFooter>
|
||||
<SidebarTrigger />
|
||||
|
||||
113
frontend/src/components/logistics/siloAdjustments/ChartData.tsx
Normal file
113
frontend/src/components/logistics/siloAdjustments/ChartData.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
import { Area, AreaChart, CartesianGrid, XAxis } from "recharts";
|
||||
|
||||
import { CardContent } from "@/components/ui/card";
|
||||
|
||||
import {
|
||||
ChartConfig,
|
||||
ChartContainer,
|
||||
ChartTooltip,
|
||||
ChartTooltipContent,
|
||||
} from "@/components/ui/chart";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { getAdjustments } from "@/utils/querys/logistics/siloAdjustments/getAdjustments";
|
||||
import { LstCard } from "@/components/extendedUI/LstCard";
|
||||
import { format } from "date-fns";
|
||||
|
||||
export default function ChartData(props: any) {
|
||||
const { data, isError, isLoading } = useQuery(getAdjustments());
|
||||
const chartConfig = {
|
||||
stock: {
|
||||
label: "Stock",
|
||||
color: "rgb(255, 99, 132)",
|
||||
},
|
||||
actual: {
|
||||
label: "Actual",
|
||||
color: "rgb(53, 162, 235)",
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
if (isLoading) return <div>Loading chart data</div>;
|
||||
if (isError) return <div>Error in loading chart data</div>;
|
||||
|
||||
let adjustments: any = data.filter(
|
||||
(l: any) => l.locationID === props.laneId
|
||||
);
|
||||
adjustments = adjustments.splice(0, 10).map((s: any) => {
|
||||
return {
|
||||
date: format(s.dateAdjusted.replace("Z", ""), "M/d/yyyy hh:mm"),
|
||||
stock: s.currentStockLevel,
|
||||
actual: s.newLevel,
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<LstCard className="w-[425px] h-[250px] m-1">
|
||||
<CardContent>
|
||||
{adjustments.length === 0 ? (
|
||||
<span>No silo data has been entered for this silo.</span>
|
||||
) : (
|
||||
<ChartContainer config={chartConfig}>
|
||||
<AreaChart
|
||||
accessibilityLayer
|
||||
data={adjustments}
|
||||
margin={{
|
||||
left: 35,
|
||||
right: 45,
|
||||
bottom: 50,
|
||||
}}
|
||||
>
|
||||
<CartesianGrid vertical={false} />
|
||||
<XAxis
|
||||
dataKey="date"
|
||||
tickLine={false}
|
||||
axisLine={false}
|
||||
tickMargin={14}
|
||||
angle={-45}
|
||||
textAnchor="end"
|
||||
dy={10}
|
||||
tickFormatter={(value) =>
|
||||
format(value, "M/d/yyyy")
|
||||
}
|
||||
/>
|
||||
<ChartTooltip
|
||||
cursor={false}
|
||||
content={
|
||||
<ChartTooltipContent indicator="dot" />
|
||||
}
|
||||
/>
|
||||
<Area
|
||||
dataKey="stock"
|
||||
type="natural"
|
||||
fill="rgba(53, 162, 235, 0.5)"
|
||||
fillOpacity={0.4}
|
||||
stroke="rgba(53, 162, 235, 0.5)"
|
||||
stackId="a"
|
||||
/>
|
||||
<Area
|
||||
dataKey="actual"
|
||||
type="natural"
|
||||
fill="rgba(255, 99, 132, 0.5)"
|
||||
fillOpacity={0.4}
|
||||
stroke="rgba(255, 99, 132, 0.5)"
|
||||
stackId="a"
|
||||
/>
|
||||
</AreaChart>
|
||||
</ChartContainer>
|
||||
)}
|
||||
</CardContent>
|
||||
{/* <CardFooter>
|
||||
<div className="flex w-full items-start gap-2 text-sm">
|
||||
<div className="grid gap-2">
|
||||
<div className="flex items-center gap-2 font-medium leading-none">
|
||||
Trending up by 5.2% this month{" "}
|
||||
<TrendingUp className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="flex items-center gap-2 leading-none text-muted-foreground">
|
||||
January - June 2024
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardFooter> */}
|
||||
</LstCard>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { getAdjustments } from "@/utils/querys/logistics/siloAdjustments/getAdjustments";
|
||||
import { columns } from "@/utils/tableData/siloAdjustmentHist/siloAdjHist";
|
||||
import { DataTable } from "@/utils/tableData/siloAdjustmentHist/siloDate";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
export default function HistoricalData(props: any) {
|
||||
const { data, isError, isLoading } = useQuery(getAdjustments());
|
||||
|
||||
if (isLoading) return <div>Loading adjustmnet data...</div>;
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p>There was an error getting the adjustments.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
//console.log(data[0].locationID, parseInt(props.laneId));
|
||||
const adjustments: any = data.filter(
|
||||
(l: any) => l.locationID === parseInt(props.laneId)
|
||||
);
|
||||
|
||||
console.log(adjustments);
|
||||
return (
|
||||
<div className="container mx-auto py-10">
|
||||
<DataTable columns={columns} data={adjustments} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,11 +12,13 @@ import {
|
||||
import { getStockSilo } from "@/utils/querys/logistics/siloAdjustments/getStockSilo";
|
||||
import { useForm } from "@tanstack/react-form";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import axios from "axios";
|
||||
import { format } from "date-fns";
|
||||
import { CircleAlert } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
import ChartData from "./ChartData";
|
||||
|
||||
export default function SiloCard(data: any) {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
@@ -183,9 +185,17 @@ export default function SiloCard(data: any) {
|
||||
)}
|
||||
</div>
|
||||
</LstCard>
|
||||
<div className="grow max-w-[400px]">
|
||||
<LstCard className="m-1 ">charts go here</LstCard>
|
||||
<LstCard className="m-1">extra options here</LstCard>
|
||||
<div className="grow max-w-[600px]">
|
||||
<ChartData laneId={silo.LocationID} />
|
||||
|
||||
<div className="flex justify-end m-1">
|
||||
<Link
|
||||
to={"/siloAdjustments/$hist"}
|
||||
params={{ hist: silo.LocationID }}
|
||||
>
|
||||
Historical Data
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LstCard>
|
||||
|
||||
@@ -12,23 +12,28 @@ import {
|
||||
TableRow,
|
||||
} from "../ui/table";
|
||||
import { toast } from "sonner";
|
||||
import { getOcmeInfo } from "@/utils/querys/production/getOcmeInfo";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { format } from "date-fns";
|
||||
import { Trash } from "lucide-react";
|
||||
|
||||
const currentPallets = [
|
||||
{ key: "line", label: "Line" },
|
||||
{ key: "runningNr", label: "Running #" },
|
||||
{ key: "runningNumber", label: "Running #" },
|
||||
{ key: "upd_date", label: "Date Scanned" },
|
||||
{ key: "waitingfor", label: "Waiting For" },
|
||||
{ key: "clear", label: "Clear" },
|
||||
];
|
||||
|
||||
const currentTags = [
|
||||
{ key: "line", label: "Line" },
|
||||
{ key: "printerName", label: "Printer" },
|
||||
{ key: "runningNr", label: "Running #" },
|
||||
{ key: "upd_date", label: "Label date" },
|
||||
{ key: "status", label: "Label Status" },
|
||||
];
|
||||
// const currentTags = [
|
||||
// { key: "line", label: "Line" },
|
||||
// { key: "printerName", label: "Printer" },
|
||||
// { key: "runningNr", label: "Running #" },
|
||||
// { key: "upd_date", label: "Label date" },
|
||||
// { key: "status", label: "Label Status" },
|
||||
// ];
|
||||
export default function WrapperManualTrigger() {
|
||||
const { data, isError, isLoading } = useQuery(getOcmeInfo());
|
||||
const cameraTrigger = async () => {
|
||||
try {
|
||||
const res = await axios.get("/ocme/api/v1/manualCameraTrigger");
|
||||
@@ -46,6 +51,42 @@ export default function WrapperManualTrigger() {
|
||||
//stoast.success(error.data.message);
|
||||
}
|
||||
};
|
||||
|
||||
const clearLabel = async (d: any) => {
|
||||
const data = {
|
||||
runningNr: d.runningNr,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await axios.patch("/ocme/api/v1/pickedUp", data);
|
||||
|
||||
if (res.data.success) {
|
||||
toast.success(
|
||||
`${d.runningNr} was just removed from being picked up.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!res.data.success) {
|
||||
toast.error(res.data.message);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
//stoast.success(error.data.message);
|
||||
}
|
||||
};
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<div>
|
||||
<p className="text-center text-pretty">
|
||||
There was an error getting wrapper scans
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const info = data?.filter((r: any) => r.areaFrom === "wrapper_1");
|
||||
return (
|
||||
<LstCard className="m-2 p-2">
|
||||
<ScrollArea className="max-h-[200px]">
|
||||
@@ -59,71 +100,66 @@ export default function WrapperManualTrigger() {
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{Array(3)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
{isLoading ? (
|
||||
<TableBody>
|
||||
{Array(3)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
) : (
|
||||
<TableBody>
|
||||
{info.map((i: any) => (
|
||||
<TableRow key={i.runningNr}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
{i.lineNum}
|
||||
</TableCell>
|
||||
<TableCell>{i.runningNr}</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
{format(
|
||||
i?.upd_date.replace("Z", ""),
|
||||
"M/d/yyyy hh:mm"
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>{i.waitingFor}</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
<Button
|
||||
variant="destructive"
|
||||
size="icon"
|
||||
onClick={() => clearLabel(i)}
|
||||
>
|
||||
<Trash />
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
<ScrollArea className="max-h-[200px]">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
{currentTags.map((l) => (
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{Array(3)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<TableRow key={i}>
|
||||
<TableCell className="font-medium">
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Skeleton className="h-4" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</TableBody>
|
||||
)}
|
||||
</Table>
|
||||
</ScrollArea>
|
||||
|
||||
<div>
|
||||
<hr />
|
||||
<p className="text-center mb-3">Manual Triggers</p>
|
||||
<p className="text-center mb-3">Manual Trigger</p>
|
||||
<div className="flex flex-row justify-between">
|
||||
<Button onClick={cameraTrigger}>Camera</Button>
|
||||
<Button>Rfid</Button>
|
||||
</div>
|
||||
</div>
|
||||
</LstCard>
|
||||
|
||||
@@ -184,7 +184,7 @@ export default function OcmeCycleCount() {
|
||||
{data.map((i: any) => {
|
||||
let classname = ``;
|
||||
if (
|
||||
i.info === "Quality Check Required"
|
||||
i.info === "Validate pallet is ok."
|
||||
) {
|
||||
classname = `bg-red-500`;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableFooter,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
@@ -26,17 +25,13 @@ const labelLogs = [
|
||||
];
|
||||
export default function LabelLog() {
|
||||
const { data, isError, isLoading } = useQuery(getlabels("4"));
|
||||
//const {user} = useSessionStore();
|
||||
//const {settings} = useSettingStore();
|
||||
//const server = settings.filter((n) => n.name === "server")[0]?.value || "";
|
||||
|
||||
//const roles = ["admin", "manager", "operator"];
|
||||
|
||||
if (isError) {
|
||||
return (
|
||||
<div className="m-2 p-2 min-h-2/5">
|
||||
<LstCard>
|
||||
<p className="text-center">Labels for the last 2 hours</p>
|
||||
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
@@ -77,7 +72,13 @@ export default function LabelLog() {
|
||||
const labelData = data ? data : [];
|
||||
return (
|
||||
<LstCard className="m-2 p-2 min-h-2/5">
|
||||
<p className="text-center">Labels for the last 2 hours</p>
|
||||
<p className="text-center">
|
||||
{labelData.length === 0 ? (
|
||||
<span>No labels have been printed in the last 2 hours</span>
|
||||
) : (
|
||||
<span>Labels for the last 2 hours</span>
|
||||
)}
|
||||
</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
@@ -115,7 +116,7 @@ export default function LabelLog() {
|
||||
) : (
|
||||
<TableBody>
|
||||
{labelData.map((label: any) => (
|
||||
<TableRow key={label.runningNr}>
|
||||
<TableRow key={label.label_id}>
|
||||
<TableCell className="font-medium">
|
||||
{label.line}
|
||||
</TableCell>
|
||||
@@ -139,15 +140,15 @@ export default function LabelLog() {
|
||||
</TableBody>
|
||||
)}
|
||||
|
||||
<TableFooter>
|
||||
{/* <TableFooter>
|
||||
{labelData.length === 0 && (
|
||||
<div>
|
||||
<div className="flex justify-center">
|
||||
<h2 className="text-center text-2xl">
|
||||
No labels have been printed in the last 2 hours
|
||||
</h2>
|
||||
</div>
|
||||
)}
|
||||
</TableFooter>
|
||||
</TableFooter> */}
|
||||
</Table>
|
||||
</LstCard>
|
||||
);
|
||||
|
||||
@@ -1,31 +1,43 @@
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {useSessionStore} from "@/lib/store/sessionStore";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useSessionStore } from "@/lib/store/sessionStore";
|
||||
//import {useSettingStore} from "@/lib/store/useSettings";
|
||||
import {LotType} from "@/types/lots";
|
||||
import {Tag} from "lucide-react";
|
||||
import {toast} from "sonner";
|
||||
import {manualPrintLabels} from "./ManualPrintLabel";
|
||||
import { LotType } from "@/types/lots";
|
||||
import { Tag } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { manualPrintLabels } from "./ManualPrintLabel";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function ManualPrint({lot}: {lot: LotType}) {
|
||||
const {user} = useSessionStore();
|
||||
export default function ManualPrint({ lot }: { lot: LotType }) {
|
||||
const { user } = useSessionStore();
|
||||
const [printing, setPrinting] = useState(false);
|
||||
//const {settings} = useSettingStore();
|
||||
//const server = settings.filter((n) => n.name === "server")[0]?.value;
|
||||
//const serverPort = settings.filter((n) => n.name === "serverPort")[0]?.value;
|
||||
//const serverUrl = `http://${server}:${serverPort}`;
|
||||
|
||||
const handlePrintLabel = async (lot: LotType) => {
|
||||
//console.log(lot);
|
||||
|
||||
const labels: any = await manualPrintLabels(lot, user);
|
||||
|
||||
if (labels.success) {
|
||||
toast.success(labels.message);
|
||||
setTimeout(() => {
|
||||
setPrinting(false);
|
||||
}, 5 * 1000);
|
||||
setPrinting(true);
|
||||
} else {
|
||||
toast.error(labels.message);
|
||||
setTimeout(() => {
|
||||
setPrinting(false);
|
||||
}, 5 * 1000);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<Button variant="outline" size="icon" onClick={() => handlePrintLabel(lot)}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePrintLabel(lot)}
|
||||
disabled={printing}
|
||||
>
|
||||
<Tag className="h-[16px] w-[16px]" />
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -86,7 +86,13 @@ export default function OcpLogs() {
|
||||
|
||||
return (
|
||||
<LstCard className="m-2 p-2 min-h-2/5">
|
||||
<p className="text-center">Labels for the last 2 hours</p>
|
||||
<p className="text-center">
|
||||
{data?.length === 0 ? (
|
||||
<span>No errors in the last 4 hours</span>
|
||||
) : (
|
||||
<span>Logs for the last 4 hours</span>
|
||||
)}
|
||||
</p>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import WrapperManualTrigger from "@/components/ocme/WrapperCard";
|
||||
import LabelLog from "./LabelLog";
|
||||
|
||||
import Lots from "./Lots";
|
||||
import OcpLogs from "./OcpLogs";
|
||||
import PrinterStatus from "./PrinterStatus";
|
||||
import { useSettingStore } from "@/lib/store/useSettings";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
||||
import LabelLog from "./LabelLog";
|
||||
|
||||
export default function OCPPage() {
|
||||
const { settings } = useSettingStore();
|
||||
|
||||
const server = settings.filter((n) => n.plantToken === "usday1");
|
||||
console.log(server);
|
||||
let server = settings.filter((n) => n.name === "server");
|
||||
return (
|
||||
<div className="h-screen w-full ">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
<div className="flex flex-row gap-2">
|
||||
<div className="flex flex-col w-4/5 h-dvh">
|
||||
<div className="">
|
||||
<Lots />
|
||||
@@ -33,15 +33,18 @@ export default function OCPPage() {
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="labels">
|
||||
<div className="w-full">
|
||||
<LabelLog />
|
||||
</div>
|
||||
<LabelLog />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-1/6 flex flex-col">
|
||||
{server.length >= 1 && (
|
||||
<div className="flex flex-col">
|
||||
{server[0].value === "usday1vms006" && (
|
||||
<div>
|
||||
<WrapperManualTrigger />
|
||||
</div>
|
||||
)}
|
||||
{server[0].value === "localhost" && (
|
||||
<div>
|
||||
<WrapperManualTrigger />
|
||||
</div>
|
||||
|
||||
@@ -81,7 +81,7 @@ export default function PrinterStatus() {
|
||||
<TableHead key={l.key}>{l.label}</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHeader>{" "}
|
||||
</TableHeader>
|
||||
{isLoading ? (
|
||||
<TableBody>
|
||||
{Array(5)
|
||||
|
||||
@@ -19,12 +19,18 @@ export const useGetUserRoles = create<SettingState>()((set) => ({
|
||||
try {
|
||||
//const response = await axios.get<{data: Setting[]}>(`${process.env.NEXT_PUBLIC_URL}/api/settings/client`);
|
||||
const token = localStorage.getItem("auth_token");
|
||||
const response = await axios.get("/api/auth/getuseraccess", {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
const data: FetchModulesResponse = response.data; //await response.json();
|
||||
//console.log(data);
|
||||
set({ userRoles: data.data });
|
||||
if (token) {
|
||||
const response = await axios.get("/api/auth/getuseraccess", {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
const data: FetchModulesResponse = response.data; //await response.json();
|
||||
|
||||
//console.log(data);
|
||||
set({ userRoles: data.data });
|
||||
} else {
|
||||
//console.log(data);
|
||||
set({ userRoles: [] });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch settings:", error);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import HistoricalData from "@/components/logistics/siloAdjustments/HistoricalData";
|
||||
import { createFileRoute, redirect } from "@tanstack/react-router";
|
||||
|
||||
export const Route = createFileRoute("/(logistics)/siloAdjustments/$hist")({
|
||||
@@ -22,10 +23,10 @@ export const Route = createFileRoute("/(logistics)/siloAdjustments/$hist")({
|
||||
});
|
||||
|
||||
function RouteComponent() {
|
||||
const { hist } = Route.useParams();
|
||||
return (
|
||||
<div>
|
||||
Hello "/(logistics)/siloAdjustments/$hist"! where the historical
|
||||
data will be shown in a table alone with a graph
|
||||
<HistoricalData laneId={hist} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export function getUsers() {
|
||||
queryFn: () => fetchUsers(token),
|
||||
enabled: !!token, // Prevents query if token is null
|
||||
staleTime: 1000,
|
||||
//refetchInterval: 2 * 2000,
|
||||
refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getStockSilo() {
|
||||
export function getAdjustments() {
|
||||
const token = localStorage.getItem("auth_token");
|
||||
return queryOptions({
|
||||
queryKey: ["getUsers"],
|
||||
queryKey: ["getAdjustments"],
|
||||
queryFn: () => fetchStockSilo(token),
|
||||
enabled: !!token, // Prevents query if token is null
|
||||
staleTime: 1000,
|
||||
//refetchInterval: 2 * 2000,
|
||||
refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
19
frontend/src/utils/querys/production/getOcmeInfo.tsx
Normal file
19
frontend/src/utils/querys/production/getOcmeInfo.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { queryOptions } from "@tanstack/react-query";
|
||||
import axios from "axios";
|
||||
|
||||
export function getOcmeInfo() {
|
||||
return queryOptions({
|
||||
queryKey: ["ocmeInfo"],
|
||||
queryFn: () => fetchSettings(),
|
||||
staleTime: 1000,
|
||||
refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
}
|
||||
|
||||
const fetchSettings = async () => {
|
||||
const { data } = await axios.get(`/ocme/api/v1/getInfo`);
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
return data.data ?? [];
|
||||
};
|
||||
@@ -6,7 +6,7 @@ export function getlabels(hours: string) {
|
||||
queryKey: ["labels"],
|
||||
queryFn: () => fetchSettings(hours),
|
||||
|
||||
staleTime: 1000,
|
||||
//staleTime: 1000,
|
||||
refetchInterval: 2 * 2000,
|
||||
refetchOnWindowFocus: true,
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@ export function getOcpLogs(hours: string) {
|
||||
|
||||
const fetchSettings = async (hours: string) => {
|
||||
const { data } = await axios.get(
|
||||
`/api/logger/logs?service=ocp&service=rfid&level=error&level=warn&hours=${hours}`
|
||||
`/api/logger/logs?service=ocp&service=rfid&service=dyco&level=error&level=warn&hours=${hours}`
|
||||
);
|
||||
// if we are not localhost ignore the devDir setting.
|
||||
//const url: string = window.location.host.split(":")[0];
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { ColumnDef } from "@tanstack/react-table";
|
||||
import { format } from "date-fns";
|
||||
|
||||
// This type is used to define the shape of our data.
|
||||
// You can use a Zod schema here if you want.
|
||||
export type Adjustmnets = {
|
||||
siloAdjust_id: string;
|
||||
currentStockLevel: string;
|
||||
newLevel: number;
|
||||
dateAdjusted: string;
|
||||
lastDateAdjusted: string;
|
||||
comment: string;
|
||||
commentAddedBy: string;
|
||||
commentDate: string;
|
||||
add_user: string;
|
||||
};
|
||||
|
||||
export const columns: ColumnDef<Adjustmnets>[] = [
|
||||
{
|
||||
accessorKey: "currentStockLevel",
|
||||
header: () => <div className="text-right">Stock At Post</div>,
|
||||
},
|
||||
{
|
||||
accessorKey: "newLevel",
|
||||
header: "Level Entered",
|
||||
},
|
||||
{
|
||||
accessorKey: "dateAdjusted",
|
||||
header: "Adjustmnet",
|
||||
cell: ({ row }) => {
|
||||
if (row.getValue("dateAdjusted")) {
|
||||
const correctDate = format(
|
||||
row.original.dateAdjusted?.replace("Z", ""),
|
||||
"M/d/yyyy hh:mm"
|
||||
);
|
||||
return (
|
||||
<div className="text-right font-medium">{correctDate}</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "lastDateAdjusted",
|
||||
header: "Last Adjusted",
|
||||
cell: ({ row }) => {
|
||||
if (row.getValue("lastDateAdjusted")) {
|
||||
const correctDate = format(
|
||||
row.original.lastDateAdjusted?.replace("Z", ""),
|
||||
"M/d/yyyy hh:mm"
|
||||
);
|
||||
return (
|
||||
<div className="text-right font-medium">{correctDate}</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "comment",
|
||||
header: "Comment",
|
||||
},
|
||||
{
|
||||
accessorKey: "commentAddedBy",
|
||||
header: "Commenter ",
|
||||
},
|
||||
{
|
||||
accessorKey: "commentDate",
|
||||
header: "Comment Date ",
|
||||
cell: ({ row }) => {
|
||||
if (row.getValue("commentDate")) {
|
||||
const correctDate = format(
|
||||
row.original.commentDate?.replace("Z", ""),
|
||||
"M/d/yyyy hh:mm"
|
||||
);
|
||||
return (
|
||||
<div className="text-right font-medium">{correctDate}</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "add_user",
|
||||
header: "Creator",
|
||||
},
|
||||
];
|
||||
110
frontend/src/utils/tableData/siloAdjustmentHist/siloDate.tsx
Normal file
110
frontend/src/utils/tableData/siloAdjustmentHist/siloDate.tsx
Normal file
@@ -0,0 +1,110 @@
|
||||
import {
|
||||
ColumnDef,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
useReactTable,
|
||||
getPaginationRowModel,
|
||||
} from "@tanstack/react-table";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
interface DataTableProps<TData, TValue> {
|
||||
columns: ColumnDef<TData, TValue>[];
|
||||
data: TData[];
|
||||
}
|
||||
|
||||
export function DataTable<TData, TValue>({
|
||||
columns,
|
||||
data,
|
||||
}: DataTableProps<TData, TValue>) {
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
});
|
||||
//console.log(data);
|
||||
return (
|
||||
<div className="rounded-md border w-[1028px]">
|
||||
<div>
|
||||
<Table>
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef
|
||||
.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
);
|
||||
})}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={
|
||||
row.getIsSelected() && "selected"
|
||||
}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
colSpan={columns.length}
|
||||
className="h-24 text-center"
|
||||
>
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<div className="flex items-center justify-end space-x-2 py-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
>
|
||||
Previous
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
>
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,25 +1,44 @@
|
||||
import {Modules} from "@/types/modules";
|
||||
import {User} from "@/types/users";
|
||||
import { Modules } from "@/types/modules";
|
||||
import { User } from "@/types/users";
|
||||
|
||||
// user will need access to the module.
|
||||
// users role will determine there visual access
|
||||
export function hasAccess(user: User | null, moduleName: string | null, modules: Modules[]): boolean {
|
||||
export function hasAccess(
|
||||
user: User | null,
|
||||
moduleName: string | null,
|
||||
modules: Modules[]
|
||||
): boolean {
|
||||
// get the modules for the id
|
||||
const filteredModule = modules?.filter((f) => f.name === moduleName);
|
||||
//console.log(filteredModule[0].module_id);
|
||||
//console.log(filteredModule[0]);
|
||||
// userroles and filter out by the module id,
|
||||
|
||||
return user?.roles.find((role) => role.module_id === filteredModule[0].module_id) ? true : false;
|
||||
const roleCheck: any = user?.roles.find(
|
||||
(role) => role.module_id === filteredModule[0].module_id
|
||||
);
|
||||
|
||||
if (filteredModule[0].roles.includes(roleCheck?.role)) {
|
||||
return true;
|
||||
}
|
||||
//if(filteredModule[0].roles.includes(roleCheck.))
|
||||
return false;
|
||||
}
|
||||
|
||||
export function hasPageAccess(user: User | null, role: any, module_id: string): boolean {
|
||||
export function hasPageAccess(
|
||||
user: User | null,
|
||||
role: any,
|
||||
module_id: string
|
||||
): boolean {
|
||||
if (role.includes("viewer")) return true;
|
||||
if (!user) return false;
|
||||
|
||||
// get only the module in the user profile
|
||||
//console.log(user);
|
||||
const userRole = user?.roles.filter((role) => role.module_id === module_id);
|
||||
console.log(userRole[0]?.role);
|
||||
// if (role.includes(userRole[0]?.role)) {
|
||||
|
||||
if (role.includes(userRole[0]?.role)) return true;
|
||||
|
||||
// return true};
|
||||
if (userRole.length !== 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
34
package-lock.json
generated
34
package-lock.json
generated
@@ -13,6 +13,7 @@
|
||||
"@hono/zod-openapi": "^0.19.2",
|
||||
"@scalar/hono-api-reference": "^0.7.2",
|
||||
"@tanstack/react-form": "^1.2.1",
|
||||
"@tanstack/react-table": "^8.21.2",
|
||||
"@types/jsonwebtoken": "^9.0.9",
|
||||
"@types/nodemailer-express-handlebars": "^4.0.5",
|
||||
"adm-zip": "^0.5.16",
|
||||
@@ -1788,6 +1789,26 @@
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/react-table": {
|
||||
"version": "8.21.2",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.21.2.tgz",
|
||||
"integrity": "sha512-11tNlEDTdIhMJba2RBH+ecJ9l1zgS2kjmexDPAraulc8jeNA4xocSNeyzextT0XJyASil4XsCYlJmf5jEWAtYg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@tanstack/table-core": "8.21.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8",
|
||||
"react-dom": ">=16.8"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/store": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.7.0.tgz",
|
||||
@@ -1798,6 +1819,19 @@
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tanstack/table-core": {
|
||||
"version": "8.21.2",
|
||||
"resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.21.2.tgz",
|
||||
"integrity": "sha512-uvXk/U4cBiFMxt+p9/G7yUWI/UbHYbyghLCjlpWZ3mLeIZiUBSKcUnw9UnKkdRz7Z/N4UBuFLWQdJCjUe7HjvA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
}
|
||||
},
|
||||
"node_modules/@tediousjs/connection-string": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@tediousjs/connection-string/-/connection-string-0.5.0.tgz",
|
||||
|
||||
179
package.json
179
package.json
@@ -1,91 +1,92 @@
|
||||
{
|
||||
"name": "lstv2",
|
||||
"version": "2.13.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
|
||||
"dev:server": "dotenvx run -f .env -- tsx watch server/index.ts",
|
||||
"dev:frontend": "cd frontend && npm run dev",
|
||||
"dev:dbgen": " drizzle-kit generate --config=drizzle-dev.config.ts",
|
||||
"dev:dbmigrate": " drizzle-kit migrate --config=drizzle-dev.config.ts",
|
||||
"build": "npm run build:server && npm run build:frontend",
|
||||
"build:server": "rimraf dist && tsc --build && npm run copy:scripts && xcopy server\\services\\notifications\\utils\\views\\ dist\\server\\services\\notifications\\utils\\views\\ /E /I /Y",
|
||||
"build:frontend": "cd frontend && npm run build",
|
||||
"copy:scripts": "tsx server/scripts/copyScripts.ts",
|
||||
"copy:servers": "xcopy server\\services\\server\\utils\\serverData.json dist\\server\\services\\server\\utils /E /I /Y",
|
||||
"start": "set NODE_ENV=production && npm run start:server",
|
||||
"start:server": "dotenvx run -f .env -- node dist/server/index.js",
|
||||
"db:generate": "npx drizzle-kit generate",
|
||||
"db:migrate": "npx drizzle-kit push",
|
||||
"db:dev": "npm run build && npm run db:generate && npm run db:migrate",
|
||||
"deploy": "standard-version --conventional-commits && npm run prodBuild",
|
||||
"zipServer": "dotenvx run -f .env -- tsx server/scripts/zipUpBuild.ts \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
||||
"v1Build": "cd C:\\Users\\matthes01\\Documents\\logisticsSupportTool && npm run oldBuilder",
|
||||
"scriptBuild": "powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
||||
"removeOld": "rimraf dist && rimraf frontend/dist",
|
||||
"prodBuild": "npm run v1Build && npm run build && npm run zipServer && npm run dev",
|
||||
"commit": "cz",
|
||||
"prodinstall": "npm i --omit=dev && npm run db:migrate",
|
||||
"checkupdates": "npx npm-check-updates",
|
||||
"testingCode": "dotenvx run -f .env -- tsx watch server/services/logistics/controller/siloAdjustments/migrateAdjustments.ts"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
"name": "lstv2",
|
||||
"version": "2.13.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "concurrently -n \"server,frontend\" -c \"#007755,#2f6da3\" \"npm run dev:server\" \"cd frontend && npm run dev\"",
|
||||
"dev:server": "dotenvx run -f .env -- tsx watch server/index.ts",
|
||||
"dev:frontend": "cd frontend && npm run dev",
|
||||
"dev:dbgen": " drizzle-kit generate --config=drizzle-dev.config.ts",
|
||||
"dev:dbmigrate": " drizzle-kit migrate --config=drizzle-dev.config.ts",
|
||||
"build": "npm run build:server && npm run build:frontend",
|
||||
"build:server": "rimraf dist && tsc --build && npm run copy:scripts && xcopy server\\services\\notifications\\utils\\views\\ dist\\server\\services\\notifications\\utils\\views\\ /E /I /Y",
|
||||
"build:frontend": "cd frontend && npm run build",
|
||||
"copy:scripts": "tsx server/scripts/copyScripts.ts",
|
||||
"copy:servers": "xcopy server\\services\\server\\utils\\serverData.json dist\\server\\services\\server\\utils /E /I /Y",
|
||||
"start": "set NODE_ENV=production && npm run start:server",
|
||||
"start:server": "dotenvx run -f .env -- node dist/server/index.js",
|
||||
"db:generate": "npx drizzle-kit generate",
|
||||
"db:migrate": "npx drizzle-kit push",
|
||||
"db:dev": "npm run build && npm run db:generate && npm run db:migrate",
|
||||
"deploy": "standard-version --conventional-commits && npm run prodBuild",
|
||||
"zipServer": "dotenvx run -f .env -- tsx server/scripts/zipUpBuild.ts \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
||||
"v1Build": "cd C:\\Users\\matthes01\\Documents\\logisticsSupportTool && npm run oldBuilder",
|
||||
"scriptBuild": "powershell -ExecutionPolicy Bypass -File server/scripts/build.ps1 -dir \"C:\\Users\\matthes01\\Documents\\lstv2\"",
|
||||
"removeOld": "rimraf dist && rimraf frontend/dist",
|
||||
"prodBuild": "npm run v1Build && npm run build && npm run zipServer && npm run dev",
|
||||
"commit": "cz",
|
||||
"prodinstall": "npm i --omit=dev && npm run db:migrate",
|
||||
"checkupdates": "npx npm-check-updates",
|
||||
"testingCode": "dotenvx run -f .env -- tsx watch server/services/logistics/controller/warehouse/cycleCountChecks/cyclecountCheck.ts"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "./node_modules/cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"admConfig": {
|
||||
"build": 207,
|
||||
"oldBuild": "backend-0.1.3.zip"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.5.7",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/mssql": "^9.1.7",
|
||||
"@types/node": "^22.13.11",
|
||||
"@types/node-cron": "^3.0.11",
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/pg": "^8.11.11",
|
||||
"@types/ws": "^8.18.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"standard-version": "^9.5.0",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.8.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dotenvx/dotenvx": "^1.39.0",
|
||||
"@hono/node-server": "^1.14.0",
|
||||
"@hono/zod-openapi": "^0.19.2",
|
||||
"@scalar/hono-api-reference": "^0.7.2",
|
||||
"@tanstack/react-form": "^1.2.1",
|
||||
"@tanstack/react-table": "^8.21.2",
|
||||
"@types/jsonwebtoken": "^9.0.9",
|
||||
"@types/nodemailer-express-handlebars": "^4.0.5",
|
||||
"adm-zip": "^0.5.16",
|
||||
"axios": "^1.8.4",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"croner": "^9.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"date-fns-tz": "^3.2.0",
|
||||
"drizzle-kit": "^0.30.5",
|
||||
"drizzle-orm": "^0.41.0",
|
||||
"drizzle-zod": "^0.7.0",
|
||||
"fast-xml-parser": "^5.0.9",
|
||||
"fs-extra": "^11.3.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mssql": "^11.0.1",
|
||||
"nodemailer": "^6.10.0",
|
||||
"nodemailer-express-handlebars": "^7.0.0",
|
||||
"pg": "^8.14.1",
|
||||
"pino": "^9.6.0",
|
||||
"pino-abstract-transport": "^2.0.0",
|
||||
"pino-pretty": "^13.0.0",
|
||||
"postgres": "^3.4.5",
|
||||
"rimraf": "^6.0.1",
|
||||
"st-ethernet-ip": "^2.7.3",
|
||||
"ws": "^8.18.1",
|
||||
"zod": "^3.24.2"
|
||||
}
|
||||
},
|
||||
"admConfig": {
|
||||
"build": 181,
|
||||
"oldBuild": "backend-0.1.3.zip"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/adm-zip": "^0.5.7",
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/js-cookie": "^3.0.6",
|
||||
"@types/mssql": "^9.1.7",
|
||||
"@types/node": "^22.13.11",
|
||||
"@types/node-cron": "^3.0.11",
|
||||
"@types/nodemailer": "^6.4.17",
|
||||
"@types/pg": "^8.11.11",
|
||||
"@types/ws": "^8.18.0",
|
||||
"concurrently": "^9.1.2",
|
||||
"cz-conventional-changelog": "^3.3.0",
|
||||
"standard-version": "^9.5.0",
|
||||
"tsx": "^4.19.3",
|
||||
"typescript": "^5.8.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@dotenvx/dotenvx": "^1.39.0",
|
||||
"@hono/node-server": "^1.14.0",
|
||||
"@hono/zod-openapi": "^0.19.2",
|
||||
"@scalar/hono-api-reference": "^0.7.2",
|
||||
"@tanstack/react-form": "^1.2.1",
|
||||
"@types/jsonwebtoken": "^9.0.9",
|
||||
"@types/nodemailer-express-handlebars": "^4.0.5",
|
||||
"adm-zip": "^0.5.16",
|
||||
"axios": "^1.8.4",
|
||||
"bcryptjs": "^3.0.2",
|
||||
"croner": "^9.0.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"date-fns-tz": "^3.2.0",
|
||||
"drizzle-kit": "^0.30.5",
|
||||
"drizzle-orm": "^0.41.0",
|
||||
"drizzle-zod": "^0.7.0",
|
||||
"fast-xml-parser": "^5.0.9",
|
||||
"fs-extra": "^11.3.0",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"mssql": "^11.0.1",
|
||||
"nodemailer": "^6.10.0",
|
||||
"nodemailer-express-handlebars": "^7.0.0",
|
||||
"pg": "^8.14.1",
|
||||
"pino": "^9.6.0",
|
||||
"pino-abstract-transport": "^2.0.0",
|
||||
"pino-pretty": "^13.0.0",
|
||||
"postgres": "^3.4.5",
|
||||
"rimraf": "^6.0.1",
|
||||
"st-ethernet-ip": "^2.7.3",
|
||||
"ws": "^8.18.1",
|
||||
"zod": "^3.24.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,42 @@
|
||||
import { db } from "../../../../../database/dbclient.js";
|
||||
import { userRoles } from "../../../../../database/schema/userRoles.js";
|
||||
import { users } from "../../../../../database/schema/users.js";
|
||||
import { returnRes } from "../../../../globalUtils/routeDefs/returnRes.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import { createLog } from "../../../logger/logger.js";
|
||||
|
||||
export const getAllUsers = async () => {
|
||||
/**
|
||||
* returns all users that are in lst
|
||||
*/
|
||||
createLog("info", "apiAuthedRoute", "auth", "Get all users");
|
||||
const { data, error } = await tryCatch(db.select().from(users));
|
||||
/**
|
||||
* returns all users that are in lst
|
||||
*/
|
||||
createLog("info", "apiAuthedRoute", "auth", "Get all users");
|
||||
|
||||
if (error) {
|
||||
returnRes(
|
||||
false,
|
||||
"There was an error getting users",
|
||||
new Error("No user exists.")
|
||||
);
|
||||
}
|
||||
// get all users
|
||||
const { data, error } = await tryCatch(db.select().from(users));
|
||||
|
||||
returnRes(true, "All users.", data);
|
||||
return { success: true, message: "All users", data };
|
||||
// add there modules they are in
|
||||
const { data: m, error: em } = await tryCatch(db.select().from(userRoles));
|
||||
|
||||
const user: any = data;
|
||||
const userData = user.map((i: any) => {
|
||||
// module in
|
||||
const module = m?.filter((x: any) => x.user_id === i.user_id);
|
||||
|
||||
if (module) {
|
||||
return { ...i, moduleRoles: module };
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
if (error) {
|
||||
returnRes(
|
||||
false,
|
||||
"There was an error getting users",
|
||||
new Error("No user exists.")
|
||||
);
|
||||
}
|
||||
|
||||
//returnRes(true, "All users.", data);
|
||||
return { success: true, message: "All users", data: userData };
|
||||
};
|
||||
|
||||
@@ -54,12 +54,18 @@ export const setUserAccess = async (
|
||||
|
||||
// set the user
|
||||
try {
|
||||
const userRole = await db.insert(userRoles).values({
|
||||
user_id: user[0].user_id,
|
||||
role_id: role[0].role_id,
|
||||
module_id: module[0].module_id,
|
||||
role: roleName,
|
||||
});
|
||||
const userRole = await db
|
||||
.insert(userRoles)
|
||||
.values({
|
||||
user_id: user[0].user_id,
|
||||
role_id: role[0].role_id,
|
||||
module_id: module[0].module_id,
|
||||
role: roleName,
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: userRoles.user_id,
|
||||
set: { role_id: role[0].role_id, role: roleName },
|
||||
});
|
||||
//.returning({user: users.username, email: users.email});
|
||||
|
||||
// return c.json({message: "User Registered", user}, 200);
|
||||
|
||||
@@ -59,7 +59,7 @@ app.openapi(
|
||||
{
|
||||
success: access.success,
|
||||
message: access.message,
|
||||
data: access.data,
|
||||
data: [], //access?.data,
|
||||
},
|
||||
200
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {eq, sql} from "drizzle-orm";
|
||||
import {db} from "../../../../database/dbclient.js";
|
||||
import {logs} from "../../../../database/schema/logs.js";
|
||||
import {createLog} from "../logger.js";
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
import { db } from "../../../../database/dbclient.js";
|
||||
import { logs } from "../../../../database/schema/logs.js";
|
||||
import { createLog } from "../logger.js";
|
||||
|
||||
export const clearLog = async (id: string) => {
|
||||
/**
|
||||
@@ -10,13 +10,21 @@ export const clearLog = async (id: string) => {
|
||||
|
||||
try {
|
||||
const clear = await db
|
||||
.update(logs)
|
||||
.set({checked: true, checkedAt: sql`NOW()`})
|
||||
.where(eq(logs.log_id, id));
|
||||
.update(logs)
|
||||
.set({ checked: true, created_at: sql`NOW()` })
|
||||
.where(eq(logs.log_id, id));
|
||||
createLog("info", "lst", "logger", "Log just cleared.");
|
||||
return {success: true, message: "Log was just cleared."};
|
||||
return { success: true, message: "Log was just cleared." };
|
||||
} catch (error) {
|
||||
createLog("error", "lst", "logger", "There was an error clearing the log.");
|
||||
return {success: false, message: "There was an error clearing the log."};
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"logger",
|
||||
"There was an error clearing the log."
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: "There was an error clearing the log.",
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { and, eq, gte, inArray, lte, sql } from "drizzle-orm";
|
||||
import { and, desc, eq, gte, inArray, lte, sql } from "drizzle-orm";
|
||||
import { db } from "../../../../database/dbclient.js";
|
||||
import { logs } from "../../../../database/schema/logs.js";
|
||||
import { createLog } from "../logger.js";
|
||||
@@ -21,7 +21,8 @@ export const getLogs = async (data: any) => {
|
||||
inArray(logs.level, data.level),
|
||||
eq(logs.checked, checked)
|
||||
)
|
||||
);
|
||||
)
|
||||
.orderBy(desc(logs.created_at));
|
||||
|
||||
return { success: true, message: "logs returned", data: logData };
|
||||
} catch (error) {
|
||||
|
||||
@@ -56,17 +56,17 @@ export const migrateAdjustments = async () => {
|
||||
/**
|
||||
* Migrate all the silo adjustments :D
|
||||
*/
|
||||
const silo: any = s?.data;
|
||||
const silo: any = s?.data.data;
|
||||
createLog("info", "silo", "logistics", "Starting migration.");
|
||||
for (let i = 0; i < silo.length; i++) {
|
||||
const migrate = await db.insert(siloAdjustments).values({
|
||||
warehouseID: silo[0].warehouseID,
|
||||
locationID: silo[0].locationID,
|
||||
currentStockLevel: silo[0].currentStockLevel,
|
||||
newLevel: silo[0].newLevel,
|
||||
dateAdjusted: new Date(silo[0].dateAdjusted),
|
||||
lastDateAdjusted: new Date(silo[0].lastDateAdjusted),
|
||||
add_user: silo[0].add_user,
|
||||
warehouseID: silo[i].warehouseID,
|
||||
locationID: silo[i].locationID,
|
||||
currentStockLevel: silo[i].currentStockLevel,
|
||||
newLevel: silo[i].newLevel,
|
||||
dateAdjusted: new Date(silo[i].dateAdjusted),
|
||||
lastDateAdjusted: new Date(silo[i].lastDateAdjusted),
|
||||
add_user: silo[i].add_user,
|
||||
});
|
||||
createLog(
|
||||
"info",
|
||||
@@ -87,5 +87,3 @@ export const migrateAdjustments = async () => {
|
||||
.where(eq(settings.name, "siloAdjMigrations"));
|
||||
createLog("info", "silo", "logistics", "Migration completed.");
|
||||
};
|
||||
|
||||
migrateAdjustments();
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { differenceInDays, differenceInSeconds, format } from "date-fns";
|
||||
import { timeZoneFix } from "../../../../../globalUtils/timeZoneFix.js";
|
||||
import { createLog } from "../../../../logger/logger.js";
|
||||
import { delay } from "../../../../../globalUtils/delay.js";
|
||||
import { tryCatch } from "../../../../../globalUtils/tryCatch.js";
|
||||
import { query } from "../../../../sqlServer/prodSqlServer.js";
|
||||
import { cycleCountCheck } from "../../../../sqlServer/querys/warehouse/cycleCountCheck.js";
|
||||
|
||||
// setting timer for updating stockCheck on a restart will always check.
|
||||
let lastCheck = 0;
|
||||
|
||||
export const lanes: any = [];
|
||||
|
||||
export const getLanesToCycleCount = async () => {
|
||||
const currentTime: any = timeZoneFix();
|
||||
// store the lanes in memeory
|
||||
createLog("info", "warehouse", "logistics", "Empty lane triggered update.");
|
||||
lastCheck = currentTime;
|
||||
const ageQuery = cycleCountCheck.replaceAll("[ageOfRow]", `1000`);
|
||||
const { data: prodLanes, error: pl } = await tryCatch(
|
||||
query(ageQuery, "Get Stock lane date.")
|
||||
);
|
||||
|
||||
// run the update on the lanes
|
||||
for (let i = 0; i < prodLanes.length; i++) {
|
||||
const createLane = {
|
||||
laneID: prodLanes[i]?.laneID,
|
||||
warehouseID: prodLanes[i]?.warehouseID,
|
||||
warehouseName: prodLanes[i]?.warehouseName || "na",
|
||||
Description: prodLanes[i]?.Description,
|
||||
LastMoveDate: prodLanes[i]?.LastMoveDate
|
||||
? format(prodLanes[i]?.LastInv, "M/d/yyyy")
|
||||
: undefined,
|
||||
LastInv: format(prodLanes[i]?.LastInv, "M/d/yyyy"),
|
||||
rowType: prodLanes[i].rowType,
|
||||
DaysSinceLast:
|
||||
differenceInDays(
|
||||
new Date(prodLanes[i].LastInv),
|
||||
new Date(prodLanes[i].LastMoveDate)
|
||||
) <= 0
|
||||
? 0
|
||||
: differenceInDays(
|
||||
new Date(prodLanes[i].LastInv),
|
||||
new Date(prodLanes[i].LastMoveDate)
|
||||
),
|
||||
upd_date: format(new Date(Date.now()), "M/d/yyyy"),
|
||||
};
|
||||
|
||||
lanes.push(createLane);
|
||||
createLog(
|
||||
"debug",
|
||||
"warehouse",
|
||||
"logistics",
|
||||
`${lanes[i].Description} was just added`
|
||||
);
|
||||
await delay(10);
|
||||
//delay to slow this thing down
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
import { lanes } from "./cyclecountCheck.js";
|
||||
|
||||
export const getCycleCountCheck = async (
|
||||
age: number = 1000,
|
||||
type: string = ""
|
||||
) => {
|
||||
/**
|
||||
* Get the lane data based on the age and type
|
||||
*/
|
||||
|
||||
let filteredLanes = lanes.filter((t: any) => t.DaysSinceLast >= age);
|
||||
|
||||
if (type != "") {
|
||||
return {
|
||||
sucess: true,
|
||||
message: `${filteredLanes.length} lanes that are of type ${type} and have not been cycle counted in the last ${age} days.`,
|
||||
data: filteredLanes.filter(
|
||||
(t: any) => t.rowType === type.toUpperCase()
|
||||
),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
success: true,
|
||||
message: `${filteredLanes.length} lanes grabed that have not been cycle counted in the last ${age} days.`,
|
||||
data: filteredLanes,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -7,6 +7,8 @@ import postComment from "./route/siloAdjustments/postComment.js";
|
||||
import getStockSilo from "./route/siloAdjustments/getStockData.js";
|
||||
import { migrateAdjustments } from "./controller/siloAdjustments/migrateAdjustments.js";
|
||||
import getSiloAdjustments from "./route/siloAdjustments/getSiloAdjustments.js";
|
||||
import { getLanesToCycleCount } from "./controller/warehouse/cycleCountChecks/cyclecountCheck.js";
|
||||
import getCycleCountCheck from "./route/getCycleCountChecks.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
@@ -19,6 +21,8 @@ const routes = [
|
||||
postComment,
|
||||
getStockSilo,
|
||||
getSiloAdjustments,
|
||||
//lanes
|
||||
getCycleCountCheck,
|
||||
] as const;
|
||||
|
||||
// app.route("/server", modules);
|
||||
@@ -28,6 +32,17 @@ const appRoutes = routes.forEach((route) => {
|
||||
|
||||
setTimeout(() => {
|
||||
migrateAdjustments();
|
||||
}, 10 * 1000);
|
||||
}, 120 * 1000);
|
||||
|
||||
/**
|
||||
* Start the cycle count check
|
||||
*/
|
||||
|
||||
setTimeout(() => {
|
||||
getLanesToCycleCount();
|
||||
}, 5 * 1000);
|
||||
setInterval(async () => {
|
||||
getLanesToCycleCount();
|
||||
}, 15 * 60 * 1000);
|
||||
|
||||
export default app;
|
||||
|
||||
60
server/services/logistics/route/getCycleCountChecks.ts
Normal file
60
server/services/logistics/route/getCycleCountChecks.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||
import { responses } from "../../../globalUtils/routeDefs/responses.js";
|
||||
import { tryCatch } from "../../../globalUtils/tryCatch.js";
|
||||
import { getCycleCountCheck } from "../controller/warehouse/cycleCountChecks/getCycleCountCheck.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
const Body = z
|
||||
.object({
|
||||
age: z.number().optional().openapi({ example: 90 }),
|
||||
//email: z.string().optional().openapi({example: "s.smith@example.com"}),
|
||||
type: z.string().optional().openapi({ example: "fg" }),
|
||||
})
|
||||
.openapi("User");
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["logistics"],
|
||||
summary: "Returns lanes that need cycle counted",
|
||||
method: "post",
|
||||
path: "/cyclecountcheck",
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
"application/json": { schema: Body },
|
||||
},
|
||||
},
|
||||
},
|
||||
// description:
|
||||
// "Provided a running number and lot number you can consume material.",
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c: any) => {
|
||||
//apiHit(c, { endpoint: "api/sqlProd/close" });
|
||||
const { data: body, error: be } = await tryCatch(c.req.json());
|
||||
|
||||
if (be) {
|
||||
return c.json({ success: false, message: "Missing Data." });
|
||||
}
|
||||
|
||||
const check: any = body;
|
||||
const { data: lanes, error: le } = await tryCatch(
|
||||
getCycleCountCheck(check.age, check.type)
|
||||
);
|
||||
|
||||
if (le) {
|
||||
return c.json({
|
||||
success: false,
|
||||
message: "Error getting lane data.",
|
||||
data: le,
|
||||
});
|
||||
}
|
||||
|
||||
return c.json({
|
||||
success: lanes.success,
|
||||
message: lanes.message,
|
||||
data: lanes.data,
|
||||
});
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
@@ -3,6 +3,7 @@ import { ocmeData } from "../../../../database/schema/ocme.js";
|
||||
import { differenceInMinutes } from "date-fns";
|
||||
import { createLog } from "../../logger/logger.js";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { timeZoneFix } from "../../../globalUtils/timeZoneFix.js";
|
||||
|
||||
export const getInfo = async () => {
|
||||
let ocmeInfo: any = [];
|
||||
@@ -16,7 +17,7 @@ export const getInfo = async () => {
|
||||
ocmeInfo = ocmeInfo.map((o: any) => {
|
||||
const now = new Date(Date.now());
|
||||
//const strippedDate = o.add_Date.replace("Z", "");
|
||||
const diff = differenceInMinutes(now, o.add_Date);
|
||||
const diff = differenceInMinutes(timeZoneFix(), o.add_Date);
|
||||
return { ...o, waitingFor: diff };
|
||||
});
|
||||
createLog(
|
||||
|
||||
@@ -32,7 +32,7 @@ export const createLabel = async (data: any, userPrinted: any) => {
|
||||
if (settingsError) {
|
||||
return {
|
||||
success: false,
|
||||
message: "There was an error getting the printer.",
|
||||
message: "There was an error getting the settings.",
|
||||
settingsError,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -60,11 +60,11 @@ export const labelingProcess = async ({
|
||||
"error",
|
||||
"labeling",
|
||||
"ocp",
|
||||
`There is not a lot assigned to ${macId[0]?.Name}.`
|
||||
`There is not a lot assigned to ${line}.`
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: `There is not a lot assigned to ${macId[0]?.Name}.`,
|
||||
message: `There is not a lot assigned to ${line}.`,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ export const labelingProcess = async ({
|
||||
}
|
||||
|
||||
// if there are more than 2 lots it might be an auto labeler, autolabeler will be defined by its id for now only dayton
|
||||
if (filteredLot.length > 2 && plantToken[0].value !== "usday1") {
|
||||
if (filteredLot?.length > 2 && plantToken[0].value !== "usday1") {
|
||||
createLog(
|
||||
"error",
|
||||
"labeling",
|
||||
@@ -214,15 +214,15 @@ export const labelingProcess = async ({
|
||||
// create the label
|
||||
const label = await createLabel(filteredLot[0], userPrinted);
|
||||
|
||||
if (!label.success) {
|
||||
createLog(
|
||||
"error",
|
||||
"labeling",
|
||||
"ocp",
|
||||
`There was an error creating the label: ${label.message}`
|
||||
);
|
||||
return { sucess: false, message: label.message, data: label.data };
|
||||
}
|
||||
// if (!label.success) {
|
||||
// createLog(
|
||||
// "error",
|
||||
// "labeling",
|
||||
// "ocp",
|
||||
// `There was an error creating the label: ${label.message}`
|
||||
// );
|
||||
// return { sucess: false, message: label.message, data: label.data };
|
||||
// }
|
||||
|
||||
// send over to be booked in if we can do it.
|
||||
const bookin = settingData.filter((s) => s.name === "bookin");
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { db } from "../../../../../database/dbclient.js";
|
||||
import { settings } from "../../../../../database/schema/settings.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import { createLog } from "../../../logger/logger.js";
|
||||
import { getPrinters } from "./getPrinters.js";
|
||||
import { autoLabelingStats } from "./printerStatus.js";
|
||||
|
||||
let isPrinterCycling = false;
|
||||
let actualPrinterCycle: any;
|
||||
|
||||
export const printerCycleAutoLabelers = async () => {
|
||||
/**
|
||||
* Will only check the auto labelers for status updates.
|
||||
*/
|
||||
|
||||
if (isPrinterCycling)
|
||||
return {
|
||||
success: false,
|
||||
message: "Printers are already being cycled.",
|
||||
};
|
||||
|
||||
createLog("info", "ocp", "ocp", "AutoLabeling cycle has started.");
|
||||
// get the printers
|
||||
const { data: s, error: se } = await tryCatch(
|
||||
db.select().from(settings).where(eq(settings.name, "ocpCycleDelay"))
|
||||
);
|
||||
if (se) {
|
||||
createLog(
|
||||
"error",
|
||||
"ocp",
|
||||
"ocp",
|
||||
"There was an error getting the ocpCycleDelay."
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: "Error getting printers.",
|
||||
};
|
||||
}
|
||||
|
||||
const ocpDelay: any = s;
|
||||
isPrinterCycling = true;
|
||||
// start the actual printer cycle
|
||||
actualPrinterCycle = setInterval(async () => {
|
||||
const { data, error } = await tryCatch(getPrinters());
|
||||
|
||||
if (error) {
|
||||
createLog(
|
||||
"error",
|
||||
"ocp",
|
||||
"ocp",
|
||||
"There was an error getting the printers."
|
||||
);
|
||||
return {
|
||||
success: false,
|
||||
message: "Error getting printers.",
|
||||
};
|
||||
}
|
||||
let printers: any = data.data;
|
||||
|
||||
// only keep the assigned ones
|
||||
printers = printers.filter((p: any) => p.assigned === true);
|
||||
|
||||
// for printers we want to ignore there must be a remark stateing to ignore.
|
||||
printers = printers.filter((p: any) => !p.remark.includes("ignore"));
|
||||
|
||||
printers.forEach(async (p: any) => {
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// ignore pdf printer as we want it here for testing purposes
|
||||
if (p.name.toLowerCase() === "pdf24") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p.name === "Autolabeler") {
|
||||
await autoLabelingStats(p);
|
||||
return;
|
||||
}
|
||||
});
|
||||
}, parseInt(ocpDelay[0]?.value) * 2 * 1000);
|
||||
|
||||
return { success: true, message: "AutoLabeling cycle has been started." };
|
||||
};
|
||||
|
||||
export const stopPrinterCycle = async () => {
|
||||
/**
|
||||
* We will stop the print cylce this is more an emergancy thing.
|
||||
*/
|
||||
if (actualPrinterCycle && !actualPrinterCycle._destroyed) {
|
||||
createLog("info", "ocp", "ocp", "AutoLabeling cycle is being stopped.");
|
||||
clearInterval(actualPrinterCycle);
|
||||
isPrinterCycling = false;
|
||||
return {
|
||||
success: true,
|
||||
message: "AutoLabeling cycle has been stopped.",
|
||||
};
|
||||
} else {
|
||||
createLog(
|
||||
"info",
|
||||
"ocp",
|
||||
"ocp",
|
||||
"AutoLabeling cycle is already stopped."
|
||||
);
|
||||
isPrinterCycling = false;
|
||||
return {
|
||||
success: true,
|
||||
message: "AutoLabeling cycle is already Stopped.",
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -75,8 +75,16 @@ export const labelerTagRead = async (tagData: any) => {
|
||||
|
||||
// check if we need to manual check due to 20 pallets.
|
||||
if (currentPalletCheck <= cameraPalletCheck) {
|
||||
currentPalletCheck = currentPalletCheck + 1;
|
||||
currentPalletCheck++;
|
||||
labelingProcess({ line: numericString });
|
||||
createLog(
|
||||
"info",
|
||||
"dyco",
|
||||
"ocp",
|
||||
`You have printed ${currentPalletCheck} pallets, remaining until ${
|
||||
cameraPalletCheck - currentPalletCheck
|
||||
}.`
|
||||
);
|
||||
} else {
|
||||
currentPalletCheck = 0;
|
||||
createLog(
|
||||
|
||||
@@ -17,6 +17,9 @@ import { assignedPrinters } from "./utils/checkAssignments.js";
|
||||
import { printerCycle } from "./controller/printers/printerCycle.js";
|
||||
import stopPrinterCycle from "./routes/printers/stopCycle.js";
|
||||
import startPrinterCycle from "./routes/printers/startCycle.js";
|
||||
import { printerCycleAutoLabelers } from "./controller/printers/printerCycleAutoLabelers.js";
|
||||
import AutostartPrinterCycle from "./routes/printers/autoLabelerStart.js";
|
||||
import AutostopPrinterCycle from "./routes/printers/autoLabelerStop.js";
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
|
||||
@@ -27,6 +30,8 @@ const routes = [
|
||||
updateprinters,
|
||||
startPrinterCycle,
|
||||
stopPrinterCycle,
|
||||
AutostartPrinterCycle,
|
||||
AutostopPrinterCycle,
|
||||
// lots
|
||||
getLots,
|
||||
// labeling
|
||||
@@ -76,6 +81,7 @@ setTimeout(async () => {
|
||||
await updatePrinters();
|
||||
await assignedPrinters();
|
||||
printerCycle();
|
||||
printerCycleAutoLabelers();
|
||||
}
|
||||
}, 10 * 1000);
|
||||
|
||||
|
||||
41
server/services/ocp/routes/printers/autoLabelerStart.ts
Normal file
41
server/services/ocp/routes/printers/autoLabelerStart.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
// an external way to creating logs
|
||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import { printerCycle } from "../../controller/printers/printerCycle.js";
|
||||
|
||||
const app = new OpenAPIHono({ strict: false });
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["ocp:printers"],
|
||||
summary: "starts the printers cycling.",
|
||||
method: "get",
|
||||
path: "/startsprintercycle",
|
||||
middleware: authMiddleware,
|
||||
//description: "This might be a temp soltuin during the transtion between versions",
|
||||
// request: {
|
||||
// body: {content: {"application/json": {schema: CreateLog}}},
|
||||
// },
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c) => {
|
||||
const { data, error } = await tryCatch(printerCycle());
|
||||
const dataError: any = error;
|
||||
if (error) {
|
||||
return c.json({
|
||||
success: false,
|
||||
message: "Error in stopping the printer cycle",
|
||||
data: dataError?.data,
|
||||
});
|
||||
}
|
||||
const getData: any = data;
|
||||
return c.json({
|
||||
success: getData?.success,
|
||||
message: getData?.message,
|
||||
data: getData.data ?? [],
|
||||
});
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
41
server/services/ocp/routes/printers/autoLabelerStop.ts
Normal file
41
server/services/ocp/routes/printers/autoLabelerStop.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
// an external way to creating logs
|
||||
import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi";
|
||||
import { authMiddleware } from "../../../auth/middleware/authMiddleware.js";
|
||||
import { responses } from "../../../../globalUtils/routeDefs/responses.js";
|
||||
import { tryCatch } from "../../../../globalUtils/tryCatch.js";
|
||||
import { stopPrinterCycle } from "../../controller/printers/printerCycle.js";
|
||||
|
||||
const app = new OpenAPIHono({ strict: false });
|
||||
|
||||
app.openapi(
|
||||
createRoute({
|
||||
tags: ["ocp:printers"],
|
||||
summary: "Stops the printers cycling.",
|
||||
method: "get",
|
||||
path: "/stopprintercycle",
|
||||
middleware: authMiddleware,
|
||||
//description: "This might be a temp soltuin during the transtion between versions",
|
||||
// request: {
|
||||
// body: {content: {"application/json": {schema: CreateLog}}},
|
||||
// },
|
||||
responses: responses(),
|
||||
}),
|
||||
async (c) => {
|
||||
const { data, error } = await tryCatch(stopPrinterCycle());
|
||||
const dataError: any = error;
|
||||
if (error) {
|
||||
return c.json({
|
||||
success: false,
|
||||
message: "Error in stopping the printer cycle",
|
||||
data: dataError?.data,
|
||||
});
|
||||
}
|
||||
const getData: any = data;
|
||||
return c.json({
|
||||
success: getData?.success,
|
||||
message: getData?.message,
|
||||
data: getData.data ?? [],
|
||||
});
|
||||
}
|
||||
);
|
||||
export default app;
|
||||
@@ -49,7 +49,7 @@ app.openapi(
|
||||
return c.json({
|
||||
success: getData?.success,
|
||||
message: getData?.message,
|
||||
data: getData.data ?? [],
|
||||
data: getData?.data ?? [],
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -28,8 +28,8 @@ export const assignedPrinters = async () => {
|
||||
};
|
||||
}
|
||||
|
||||
const printers: any = print.data;
|
||||
const lots: any = l.data;
|
||||
const printers: any = print.data ?? [];
|
||||
const lots: any = l.data ?? [];
|
||||
|
||||
for (let i = 0; i < printers.length; i++) {
|
||||
// is the printer assinged in alplalabel online?
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {z, createRoute, OpenAPIHono} from "@hono/zod-openapi";
|
||||
import {modules} from "../../../../../database/schema/modules.js";
|
||||
import {db} from "../../../../../database/dbclient.js";
|
||||
import { z, createRoute, OpenAPIHono } from "@hono/zod-openapi";
|
||||
import { modules } from "../../../../../database/schema/modules.js";
|
||||
import { db } from "../../../../../database/dbclient.js";
|
||||
import { desc } from "drizzle-orm";
|
||||
|
||||
// Define the request body schema
|
||||
const requestSchema = z.object({
|
||||
@@ -13,10 +14,16 @@ const requestSchema = z.object({
|
||||
// Define the response schema
|
||||
const responseSchema = z.object({
|
||||
message: z.string().optional(),
|
||||
module_id: z.string().openapi({example: "6c922c6c-7de3-4ec4-acb0-f068abdc"}).optional(),
|
||||
name: z.string().openapi({example: "Production"}).optional(),
|
||||
active: z.boolean().openapi({example: true}).optional(),
|
||||
roles: z.string().openapi({example: `["viewer","technician"]`}).optional(),
|
||||
module_id: z
|
||||
.string()
|
||||
.openapi({ example: "6c922c6c-7de3-4ec4-acb0-f068abdc" })
|
||||
.optional(),
|
||||
name: z.string().openapi({ example: "Production" }).optional(),
|
||||
active: z.boolean().openapi({ example: true }).optional(),
|
||||
roles: z
|
||||
.string()
|
||||
.openapi({ example: `["viewer","technician"]` })
|
||||
.optional(),
|
||||
});
|
||||
|
||||
const app = new OpenAPIHono();
|
||||
@@ -30,7 +37,7 @@ app.openapi(
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
"application/json": {schema: responseSchema},
|
||||
"application/json": { schema: responseSchema },
|
||||
},
|
||||
description: "Response message",
|
||||
},
|
||||
@@ -40,7 +47,7 @@ app.openapi(
|
||||
//console.log("system modules");
|
||||
let module: any = [];
|
||||
try {
|
||||
module = await db.select().from(modules); // .where(eq(modules.active, true));
|
||||
module = await db.select().from(modules).orderBy(modules.name); // .where(eq(modules.active, true));
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
module = [];
|
||||
@@ -49,7 +56,7 @@ app.openapi(
|
||||
// parse the roles
|
||||
const updateModules = module.map((m: any) => {
|
||||
if (m.roles) {
|
||||
return {...m, roles: m?.roles};
|
||||
return { ...m, roles: m?.roles };
|
||||
}
|
||||
return m;
|
||||
}); //JSON.parse(module[0]?.roles);
|
||||
|
||||
@@ -47,7 +47,10 @@ app.openapi(
|
||||
//console.log("system modules");
|
||||
let module: any = [];
|
||||
try {
|
||||
module = await db.select().from(subModules); // .where(eq(modules.active, true));
|
||||
module = await db
|
||||
.select()
|
||||
.from(subModules)
|
||||
.orderBy(subModules.name); // .where(eq(modules.active, true));
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
module = [];
|
||||
|
||||
@@ -3,42 +3,69 @@
|
||||
* this will only run on a server start up
|
||||
*/
|
||||
|
||||
import {db} from "../../../../database/dbclient.js";
|
||||
import {modules} from "../../../../database/schema/modules.js";
|
||||
import {createLog} from "../../logger/logger.js";
|
||||
import { db } from "../../../../database/dbclient.js";
|
||||
import { modules } from "../../../../database/schema/modules.js";
|
||||
import { createLog } from "../../logger/logger.js";
|
||||
// "view", "technician", "supervisor","manager", "admin", "systemAdmin"
|
||||
const newModules = [
|
||||
{name: "production", active: true, roles: ["viewer", "tester", "systemAdmin"]},
|
||||
{name: "logistics", active: false, roles: ["viewer", "tester", "systemAdmin"]},
|
||||
{name: "quality", active: false, roles: ["viewer", "manager", "tester", "systemAdmin"]},
|
||||
{name: "forklift", active: false, roles: ["manager", "admin", "tester", "systemAdmin"]},
|
||||
{name: "eom", active: false, roles: ["manager", "admin", "tester", "systemAdmin"]},
|
||||
{name: "admin", active: true, roles: ["admin", "systemAdmin"]},
|
||||
{name: "ocp", active: false, roles: ["viewer", "admin", "tester", "systemAdmin"]},
|
||||
const newModules: any = [
|
||||
{
|
||||
name: "production",
|
||||
active: true,
|
||||
roles: ["viewer", "tester", "systemAdmin"],
|
||||
},
|
||||
{
|
||||
name: "logistics",
|
||||
active: false,
|
||||
roles: ["viewer", "manager", "supervisor", "tester", "systemAdmin"],
|
||||
},
|
||||
{
|
||||
name: "quality",
|
||||
active: false,
|
||||
roles: ["viewer", "manager", "tester", "systemAdmin"],
|
||||
},
|
||||
{
|
||||
name: "forklift",
|
||||
active: false,
|
||||
roles: ["manager", "admin", "tester", "systemAdmin"],
|
||||
},
|
||||
{
|
||||
name: "eom",
|
||||
active: false,
|
||||
roles: ["manager", "admin", "tester", "systemAdmin"],
|
||||
},
|
||||
{ name: "admin", active: true, roles: ["admin", "systemAdmin"] },
|
||||
{
|
||||
name: "ocp",
|
||||
active: false,
|
||||
roles: ["viewer", "admin", "tester", "systemAdmin"],
|
||||
},
|
||||
];
|
||||
export const areModulesIn = async () => {
|
||||
// get the roles
|
||||
try {
|
||||
const moduleCheck = await db.select().from(modules);
|
||||
|
||||
if (moduleCheck.length !== newModules.length) {
|
||||
try {
|
||||
const newRole = await db
|
||||
for (let i = 0; i < newModules.length; i++) {
|
||||
try {
|
||||
const newRole = await db
|
||||
.insert(modules)
|
||||
.values(newModules)
|
||||
.onConflictDoNothing() // this will only update the ones that are new :D
|
||||
.returning({name: modules.name});
|
||||
createLog("info", "lst", "server", "Roles were just added due to missing them on server startup");
|
||||
} catch (error) {
|
||||
createLog("error", "lst", "server", "There was an error adding new roles to the db");
|
||||
}
|
||||
.values(newModules[i])
|
||||
.onConflictDoUpdate({
|
||||
target: modules.name,
|
||||
set: { roles: newModules[i].roles },
|
||||
}) // this will only update the ones that are new :D
|
||||
.returning({ name: modules.name });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"server",
|
||||
"There was an error adding new modules to the db"
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
createLog(
|
||||
"error",
|
||||
"lst",
|
||||
"server",
|
||||
`Error: ${JSON.stringify(error)}"There was an error getting or adding new roles"`
|
||||
);
|
||||
}
|
||||
createLog(
|
||||
"info",
|
||||
"lst",
|
||||
"server",
|
||||
"Modules were just added due to missing them on server startup"
|
||||
);
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@ const newSubModules = [
|
||||
link: "/siloAdjustments",
|
||||
icon: "Cylinder",
|
||||
active: false,
|
||||
roles: ["tester", "systemAdmin"],
|
||||
roles: ["technician", "supervisor", "manager", "admin", "systemAdmin"],
|
||||
subSubModule: [],
|
||||
},
|
||||
{
|
||||
@@ -38,16 +38,6 @@ const newSubModules = [
|
||||
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",
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
export const cycleCountCheck = `
|
||||
-- Define the structure of the result set from the stored procedure
|
||||
DECLARE @results TABLE (
|
||||
IdLocation INT,
|
||||
LastMoveDate Date
|
||||
|
||||
)
|
||||
-- insert into the temp table
|
||||
insert into @results
|
||||
select IdLagerAbteilung, MAX(CaSE WHEN CONVERT(char(10), Buchungsdatum, 120) IS NULL THEN '1900-01-01' ELSE CONVERT(char(10), Buchungsdatum, 120) END) AS LastLocMov
|
||||
from AlplaPROD_test1.dbo.V_LagerBuchungen x(nolock)
|
||||
|
||||
group by IdLagerAbteilung
|
||||
|
||||
select * from (
|
||||
select x.IdLagerAbteilung as laneID,
|
||||
x.IdWarenLager as warehouseID,
|
||||
w.Bezeichnung as warehouseName,
|
||||
w.LagerTyp as warehouseIDTyp,
|
||||
w.Standort as warehouseLocation,
|
||||
x.Bezeichnung as Description,
|
||||
LastMoveDate,
|
||||
CASE WHEN CONVERT(char(10), i.Datum, 120) is null then getdate() - 365 else CONVERT(char(10), i.Datum, 120) end as LastInv,
|
||||
--create the types of warehouses to choose from
|
||||
case
|
||||
-- empty
|
||||
when (sum(EinlagerungsMengeSum) is null and Datum < LastMoveDate) or (
|
||||
(sum(EinlagerungsMengeSum) is null and Datum < DATEADD(day, -[ageOfRow], getdate()))
|
||||
) then 'EMPTY'
|
||||
-- finished goods
|
||||
when w.LagerTyp = 2 and w.Standort = 10 then 'FG'
|
||||
-- external finished goods
|
||||
when w.LagerTyp = 2 and w.Standort = 20 then 'EXTERNAL'
|
||||
-- silos
|
||||
when w.LagerTyp in (3) and x.MaterialSilo = 1 then 'BULK'
|
||||
-- MATERIALS
|
||||
when w.LagerTyp = 3 and x.MaterialSilo = 0 then 'MATERIALS'
|
||||
|
||||
-- MATERIALS
|
||||
when w.LagerTyp = 11 then 'WASTE'
|
||||
-- MATERIALS
|
||||
when w.LagerTyp = 9 then 'PACKAGING'
|
||||
|
||||
end as rowType,
|
||||
CASE WHEN DateDiff(DAY,i.Datum,getDate()) is null then 1000 else DateDiff(DAY,i.Datum,getDate()) end as DaysSinceLast
|
||||
|
||||
from AlplaPROD_test1.dbo.T_LagerAbteilungen as x (NOLOCK)
|
||||
|
||||
-- last move
|
||||
left join
|
||||
@results as b on
|
||||
x.IdLagerAbteilung = b.IdLocation
|
||||
|
||||
-- last inv
|
||||
left join
|
||||
(select * from [AlplaPROD_test1].[dbo].[T_LagerAbteilungenInventuren] (nolock)) as i on x.IdLagerAbteilung =
|
||||
i.IdLagerAbteilung
|
||||
|
||||
-- useing this to determin only if the lane is empty
|
||||
left join
|
||||
(select * from [AlplaPROD_test1].dbo.V_LagerPositionenBarcodes (nolock)) as y on x.IdLagerAbteilung =
|
||||
y.IdLagerAbteilung
|
||||
|
||||
-- get the warehosue type
|
||||
left join
|
||||
(select * from [AlplaPROD_test1].dbo.T_WarenLager (nolock)) as w on x.IdWarenLager = w.IdWarenLager
|
||||
|
||||
where x.aktiv = 1 and x.IdWarenLager not in (1,5,6)
|
||||
|
||||
group by x.IdLagerAbteilung,
|
||||
x.IdWarenLager,
|
||||
w.LagerTyp,
|
||||
w.Standort,
|
||||
x.Bezeichnung,
|
||||
LastMoveDate,
|
||||
i.Datum,
|
||||
x.MaterialSilo,
|
||||
w.Bezeichnung
|
||||
) xb
|
||||
`;
|
||||
Reference in New Issue
Block a user