diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 034d4f8..a776e7f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -16,6 +16,7 @@ "@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-popover": "^1.1.6", + "@radix-ui/react-scroll-area": "^1.2.3", "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-slot": "^1.1.2", @@ -1740,6 +1741,37 @@ } } }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.3.tgz", + "integrity": "sha512-l7+NNBfBYYJa9tNqVcP2AGvxdE3lmE6kFTBXdvHgUaZuy+4wGCL1Cl2AfaR7RKyimj7lZURGLwFO59k4eBnDJQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.0", + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-select": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.1.6.tgz", diff --git a/frontend/package.json b/frontend/package.json index 66917e4..683b9af 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "@radix-ui/react-dropdown-menu": "^2.1.6", "@radix-ui/react-label": "^2.1.2", "@radix-ui/react-popover": "^1.1.6", + "@radix-ui/react-scroll-area": "^1.2.3", "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.2", "@radix-ui/react-slot": "^1.1.2", diff --git a/frontend/src/components/production/ocp/Lots.tsx b/frontend/src/components/production/ocp/Lots.tsx index 64564e4..83bdd7c 100644 --- a/frontend/src/components/production/ocp/Lots.tsx +++ b/frontend/src/components/production/ocp/Lots.tsx @@ -1,14 +1,22 @@ -import {LstCard} from "@/components/extendedUI/LstCard"; +import { LstCard } from "@/components/extendedUI/LstCard"; -import {Skeleton} from "@/components/ui/skeleton"; -import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table"; -import {useSessionStore} from "@/lib/store/sessionStore"; -import {useSettingStore} from "@/lib/store/useSettings"; -import {LotType} from "@/types/lots"; -import {getlots} from "@/utils/querys/production/lots"; -import {useQuery} from "@tanstack/react-query"; +import { Skeleton } from "@/components/ui/skeleton"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { useSessionStore } from "@/lib/store/sessionStore"; +import { useSettingStore } from "@/lib/store/useSettings"; +import { LotType } from "@/types/lots"; +import { getlots } from "@/utils/querys/production/lots"; +import { useQuery } from "@tanstack/react-query"; import ManualPrint from "./ManualPrinting/ManualPrint"; import ManualPrintForm from "./ManualPrinting/ManualPrintForm"; +import { ScrollArea } from "@/components/ui/scroll-area"; let lotColumns = [ { @@ -57,12 +65,12 @@ let lotColumns = [ // }, ]; export default function Lots() { - const {data, isError, isLoading} = useQuery(getlots()); - const {user} = useSessionStore(); - const {settings} = useSettingStore(); + const { data, isError, isLoading } = useQuery(getlots()); + const { user } = useSessionStore(); + const { settings } = useSettingStore(); const server = settings.filter((n) => n.name === "server")[0]?.value || ""; - console.log(server); + console.log(data); const roles = ["admin", "manager", "operator"]; @@ -83,140 +91,167 @@ export default function Lots() { if (isError) { return (
- -

Current Assigned lots

- - - - {lotColumns.map((l) => ( - {l.label} - ))} - - - - - {Array(10) - .fill(0) - .map((_, i) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +

Current Assigned lots

+
+ + + {lotColumns.map((l) => ( + + {l.label} + + ))} - ))} - -
-
+ + + + {Array(10) + .fill(0) + .map((_, i) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ))} + + + +
); } return ( -

Current Assigned lots

- - - - {lotColumns.map((l) => ( - {l.label} - ))} - - - {isLoading ? ( - <> + +

Current Assigned lots

+
+ + + {lotColumns.map((l) => ( + {l.label} + ))} + + + {isLoading ? ( + <> + + {Array(10) + .fill(0) + .map((_, i) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ))} + + + ) : ( - {Array(10) - .fill(0) - .map((_, i) => ( - + {data?.map((lot: LotType) => ( + - + {lot.MachineLocation} - - + + {lot.AV} - - + + {lot.Alias} - - + + {lot.LOT} - - + + {lot.ProlinkLot} - - + + {lot.PlannedQTY} - - + + {lot.Produced} - - + + {lot.Remaining} - - + + {lot.overPrinting} + {user && roles.includes(user.role) && ( + <> + {server === "usday1vms006" || + server === "localhost" ? ( + <> + + + + + ) : ( + + + + )} + + )} ))} - - ) : ( - - {data?.map((lot: LotType) => ( - - {lot.MachineLocation} - {lot.AV} - {lot.Alias} - {lot.LOT} - {lot.ProlinkLot} - {lot.PlannedQTY} - {lot.Produced} - {lot.Remaining} - {lot.overPrinting} - {user && roles.includes(user.role) && ( - <> - {server === "usday1vms006" || server === "localhost" ? ( - <> - - - - - ) : ( - - - - )} - - )} - - ))} - - )} -
+ )} + +
); } diff --git a/frontend/src/components/ui/scroll-area.tsx b/frontend/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..b9327c0 --- /dev/null +++ b/frontend/src/components/ui/scroll-area.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +function ScrollArea({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + {children} + + + + + ) +} + +function ScrollBar({ + className, + orientation = "vertical", + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +export { ScrollArea, ScrollBar } diff --git a/frontend/src/utils/querys/production/lots.tsx b/frontend/src/utils/querys/production/lots.tsx index c9ce178..417d690 100644 --- a/frontend/src/utils/querys/production/lots.tsx +++ b/frontend/src/utils/querys/production/lots.tsx @@ -1,4 +1,4 @@ -import {queryOptions} from "@tanstack/react-query"; +import { queryOptions } from "@tanstack/react-query"; import axios from "axios"; export function getlots() { @@ -13,7 +13,7 @@ export function getlots() { } const fetchSettings = async () => { - const {data} = await axios.get("/api/v1/ocp/lots"); + const { data } = await axios.get("/api/ocp/getlots"); // if we are not localhost ignore the devDir setting. //const url: string = window.location.host.split(":")[0]; let lotData = data.data; diff --git a/server/services/ocp/controller/lots/lots.ts b/server/services/ocp/controller/lots/lots.ts new file mode 100644 index 0000000..a56351e --- /dev/null +++ b/server/services/ocp/controller/lots/lots.ts @@ -0,0 +1,23 @@ +import { tryCatch } from "../../../../globalUtils/tryCatch.js"; +import { query } from "../../../sqlServer/prodSqlServer.js"; +import { lotQuery } from "../../../sqlServer/querys/ocp/lots.js"; + +export const getLots = async () => { + const { data: lotInfo, error: lotError } = await tryCatch( + query(lotQuery, "Alplalabel online lots") + ); + + if (lotError) { + return { + success: false, + message: "There was an error getting the lots", + data: lotError, + }; + } + + return { + success: true, + message: "Current active lots that are technically released.", + data: lotInfo, + }; +}; diff --git a/server/services/ocp/ocpService.ts b/server/services/ocp/ocpService.ts index ed20a02..2a4025d 100644 --- a/server/services/ocp/ocpService.ts +++ b/server/services/ocp/ocpService.ts @@ -6,7 +6,8 @@ import getPrinters from "./routes/printers/getPritners.js"; import { db } from "../../../database/dbclient.js"; import { settings } from "../../../database/schema/settings.js"; import updateprinters from "./routes/printers/updatePrinters.js"; -import { updatePrinters } from "./controller/updatePrinters.js"; +import { updatePrinters } from "./controller/printers/updatePrinters.js"; +import getLots from "./routes/lots/getLots.js"; const app = new OpenAPIHono(); @@ -15,6 +16,8 @@ const routes = [ //printer getPrinters, updateprinters, + // lots + getLots, ] as const; const setting = await db.select().from(settings); diff --git a/server/services/ocp/routes/lots/getLots.ts b/server/services/ocp/routes/lots/getLots.ts new file mode 100644 index 0000000..039dba5 --- /dev/null +++ b/server/services/ocp/routes/lots/getLots.ts @@ -0,0 +1,35 @@ +// an external way to creating logs +import { createRoute, OpenAPIHono, z } from "@hono/zod-openapi"; +import { responses } from "../../../../globalUtils/routeDefs/responses.js"; +import { tryCatch } from "../../../../globalUtils/tryCatch.js"; +import { getPrinters } from "../../controller/printers/getPrinters.js"; +import { getLots } from "../../controller/lots/lots.js"; + +const app = new OpenAPIHono({ strict: false }); + +app.openapi( + createRoute({ + tags: ["ocp"], + summary: "Returns current active lots that are tech released", + method: "get", + path: "/getlots", + responses: responses(), + }), + async (c) => { + const { data: lotData, error: lotError } = await tryCatch(getLots()); + + if (lotError) { + return c.json({ + success: false, + message: "There was an error getting the printers", + }); + } + + return c.json({ + success: lotData.success, + message: lotData.message, + data: lotData.data, + }); + } +); +export default app; diff --git a/server/services/sqlServer/querys/ocp/lots.ts b/server/services/sqlServer/querys/ocp/lots.ts new file mode 100644 index 0000000..cfafbdb --- /dev/null +++ b/server/services/sqlServer/querys/ocp/lots.ts @@ -0,0 +1,55 @@ +export const lotQuery = ` +select IdMaschinen_ProdPlanung as LabelOnlineID, + IdMaschine as machineID, + MaschinenStandort as MachineLocation, + MaschinenBez as MachineDescription, + IdProdPlanung as LOT, + prolink.lot as ProlinkLot, + IdArtikelvarianten as AV, + ArtikelVariantenBez as Alias, + convert(varchar, add_date, 20) as Add_Date, + Add_user, + idEtikettenDrucker as printerID, + b.name as PrinterName, + CAST(TotalPlannedLoadingUnits as float) as PlannedQTY, + CAST(TotalProducedLoadingUnits as float) as Produced, + ROUND(CAST(TotalPlannedLoadingUnits as float) - CAST(TotalProducedLoadingUnits as float),2) as Remaining, + case + -- checks if someone changed the criteria to something else to trigger the over run + when x.ProzentReserveAnzahlPaletten > 0 then 'yes' + + -- if the lot has a decimal in it to allow over running with no intervention + when CAST(TotalPlannedLoadingUnits as float) - floor(CAST(TotalPlannedLoadingUnits as float)) > 0 then 'yes' + else 'no' end as overPrinting, + CustomerHumanReadableId as CustomerId, + CustomerName as CustomerName, + idMaschine as MachineID, + prolink.lastProlinkUpdate as lastProlinkUpdate, + IdEtikettenLayoutPalette as palletLabel, + AnzahlKopienPalette as pallerCopies, + IdEtikettenLayoutKarton as cartonLabel, + AnzahlKopienKarton as cartonCopies, + IsTechnicallyReleased + --* + from AlplaPROD_test1.dbo.V_Maschinen_ProdPlanungen x (nolock) + join + [test1_AlplaPROD2.0_Read].[productionControlling].[ProducedLot] on + x.IdProdPlanung = + [test1_AlplaPROD2.0_Read].[productionControlling].[ProducedLot].ProductionLotHumanReadableId + left join + [test1_AlplaPROD2.0_Read].masterData.Printer as b on + x.IdEtikettenDrucker = b.HumanReadableId + -- adding in prolink lot + left join + (SELECT * from (SELECT IdMaschine as prolinkMachineId, + Produktionslos as lot, + Upd_Date as lastProlinkUpdate, + ROW_NUMBER() OVER (PARTITION BY IdMaschine ORDER BY Upd_Date DESC) RN_Prolink + FROM AlplaPROD_test1.dbo.T_HistoryProduktionsdaten (nolock) + WHERE Upd_Date BETWEEN DATEADD(DD, - 300, getdate()) AND DATEADD(DD, 1, getdate())) p + WHERE RN_Prolink = 1 + ) as prolink on + x.idMaschine = prolink.prolinkMachineId + + where IsTechnicallyReleased = 1 +`;