refactor(dockscanning): more work on the dock door scanning
All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 1m47s

ref #12
This commit is contained in:
2026-06-08 07:49:41 -05:00
parent 6dd1a5b332
commit 7671172d97
18 changed files with 6040 additions and 37 deletions

View File

@@ -0,0 +1,23 @@
import { pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
import { createInsertSchema, createSelectSchema } from "drizzle-zod";
import type { z } from "zod";
export const dockDoorScans = pgTable("dock_door_scans", {
id: uuid("id").defaultRandom().primaryKey(),
dockId: text("dock_id").notNull(),
loadingOrder: text("loading_order").notNull(),
loadingUnit: text("loading_Unit").unique(), // can be running number or sscc depending on where it came from
loadingUnitStatus: text("loading_unit_status").default("loaded"), // TODO: add enums on the status of each load.
message: text("message"), // the response it gave when scanning
status: text("status").default("active"), // TODO: add in enums for this
add_date: timestamp("add_date", { withTimezone: true }).defaultNow(),
add_user: text("add_user").default("lst-system"),
upd_date: timestamp("upd_date", { withTimezone: true }).defaultNow(),
upd_user: text("upd_user").default("lst-system"),
});
export const dockDoorScansSchema = createSelectSchema(dockDoorScans);
export const newDockDoorScansSchema = createInsertSchema(dockDoorScans);
export type DockDoorScans = z.infer<typeof dockDoorScansSchema>;
export type NewDockDoorScans = z.infer<typeof newDockDoorScansSchema>;

View File

@@ -2,7 +2,9 @@ import { eq, sql } from "drizzle-orm";
import { Router } from "express";
import z from "zod";
import { db } from "../db/db.controller.js";
import { dockDoorScans } from "../db/schema/dockdoor.scans.schema.js";
import { dockDoorScanners } from "../db/schema/dockdoor.schema.js";
import { runProdApi } from "../utils/prodEndpoint.utils.js";
import { apiReturn } from "../utils/returnHelper.utils.js";
import { tryCatch } from "../utils/trycatch.utils.js";
@@ -14,20 +16,52 @@ const endLoading = z.object({
});
r.post("/", async (req, res) => {
// close the loading order
// clear the loading order off the dock
// TODO: setup the emitter to just emit the data when we post to the db
try {
const validated = endLoading.parse(req.body);
const orders = (await runProdApi({
method: "post",
endpoint: `/public/v1.0/OutboundDeliveries/LoadingOrders/${req.body.loadingOrder}/Finish`,
data: [
{
printDeliveryDocuments: true,
},
],
})) as any;
if (orders?.data.errors) {
console.log(orders.data.errors);
return apiReturn(res, {
success: false,
level: "error",
module: "dockdoor",
subModule: "loadingOrder",
message: `Failed to finish the order.`,
data: (orders.data.errors as any) ?? [],
status: 400,
});
}
await tryCatch(
db
.update(dockDoorScans)
.set({
upd_date: sql`NOW()`,
upd_user: req.user?.username ?? "lst-dock-system",
})
.where(eq(dockDoorScanners.currentLoadingOrder, validated.loadingOrder))
.returning(),
);
const { data, error } = await tryCatch(
db
.update(dockDoorScanners)
.set({
currentLoadingOrder: "",
upd_date: sql`NOW()`,
upd_user: req.user?.username,
upd_user: req.user?.username ?? "lst-dock-system",
})
.where(eq(dockDoorScanners.dockId, validated.dockId))
.returning(),
@@ -46,13 +80,15 @@ r.post("/", async (req, res) => {
}
return apiReturn(res, {
success: true,
level: "info",
success: orders.data.errors ? false : true,
level: orders.data.errors ? "error" : "info",
module: "dockdoor",
subModule: "loadingOrder",
message: `Loading order ${validated.loadingOrder} was just closed.`,
message: orders.data.errors
? `Loading order was cleared but encountered an error: \n${orders.data.errors[0].message} \nPossible reason for this is the loading order was completed via scanner or other means.`
: `Loading order ${validated.loadingOrder} was just closed.`,
data: data ?? [],
status: 200,
status: orders.data.errors ? 400 : 200,
});
} catch (error) {
return apiReturn(res, {
@@ -60,7 +96,7 @@ r.post("/", async (req, res) => {
level: "error",
module: "dockdoor",
subModule: "loadingOrder",
message: `Failed to start loading order.`,
message: `Failed to Close loading order.`,
data: (error as any) ?? [],
status: 400,
});

View File

@@ -2,6 +2,7 @@
import { eq } from "drizzle-orm";
import { db } from "../db/db.controller.js";
import { dockDoorScans } from "../db/schema/dockdoor.scans.schema.js";
import { dockDoorScanners } from "../db/schema/dockdoor.schema.js";
import { emitToRoom } from "../socket.io/roomEmitter.socket.js";
import { runProdApi } from "../utils/prodEndpoint.utils.js";
@@ -15,12 +16,35 @@ type Data = {
runningNo?: string;
};
const postScan = async (data: any) => {
try {
await db.insert(dockDoorScans).values({
dockId: data.dockId,
loadingOrder: data.loadingOrder,
loadingUnit: data.unit, // can be running number or sscc depending on where it came from
loadingUnitStatus: data.unitStatus, // TODO: add enums on the status of each load.
message: data.message, // the response it gave when scanning
});
} catch (error) {
console.log("Error: ", error);
}
};
const loadUnit = async (data: Data) => {
// are we even active at this time?
const dockDoorActive = await db.query.settings.findFirst({
where: (u, { eq }) => eq(u.name, "dockDoorScanning"),
});
const unitToScan = data.sscc
? { sscc: data.sscc?.slice(2) }
: { runningNo: Number(data.runningNo) };
const dock = await db
.select()
.from(dockDoorScanners)
.where(eq(dockDoorScanners.dockId, data.dockId as string));
if (!dockDoorActive?.active) {
return returnFunc({
success: false,
@@ -33,29 +57,18 @@ const loadUnit = async (data: Data) => {
room: "",
});
}
// check if its a valids an sscc
if (data.sscc === "noread") {
return returnFunc({
success: false,
level: "error",
module: "dockdoor",
subModule: "loadUnit",
message:
"Failed to load the unit to the truck, there was no pallet read.",
data: [],
notify: false,
room: `dockDoorLoading:${data.dockId}`,
});
}
// check if we currently have a loading order attached to the dock door.
const dock = await db
.select()
.from(dockDoorScanners)
.where(eq(dockDoorScanners.dockId, data.dockId as string));
if (dock[0]?.currentLoadingOrder === "") {
postScan({
dockId: data.dockId,
loadingOrder: dock[0]?.currentLoadingOrder,
loadingUnit: unitToScan,
loadingUnitStatus: "notLoaded",
message:
"There are know current active loading orders please start one and try again.",
});
return returnFunc({
success: true,
level: "error",
@@ -68,6 +81,30 @@ const loadUnit = async (data: Data) => {
room: `dockDoorLoading:${data.dockId}`,
});
}
// check if its a valids an sscc
if (data.sscc === "noread") {
postScan({
dockId: data.dockId,
loadingOrder: dock[0]?.currentLoadingOrder,
loadingUnit: unitToScan,
loadingUnitStatus: "noread",
message:
"Failed to load the unit to the truck, there was no pallet read.",
});
return returnFunc({
success: false,
level: "error",
module: "dockdoor",
subModule: "loadUnit",
message:
"Failed to load the unit to the truck, there was no pallet read.",
data: [],
notify: false,
room: `dockDoorLoading:${data.dockId}`,
});
}
// TODO: pallet validation, check if we are on hold, then check if we have been in the staging warehouse for more than x time.
@@ -77,10 +114,6 @@ const loadUnit = async (data: Data) => {
// add the loading units
try {
const unitToScan = data.sscc
? { sscc: data.sscc?.slice(2) }
: { runningNo: Number(data.runningNo) };
const prod = (await runProdApi({
method: "post",
endpoint: `/public/v1.0/OutboundDeliveries/LoadingOrders/${dock[0]?.currentLoadingOrder}/LoadUnit`,
@@ -90,6 +123,13 @@ const loadUnit = async (data: Data) => {
//emitToRoom(`dockDoorLoading:${data.dockId}`, prod?.data ?? []);
if (!prod?.success) {
postScan({
dockId: data.dockId,
loadingOrder: dock[0]?.currentLoadingOrder,
loadingUnit: unitToScan,
loadingUnitStatus: "notLoaded",
message: prod?.data.errors[0].message,
});
emitToRoom(`dockDoorLoading:${data.dockId}`, prod?.data.errors[0]);
return returnFunc({
success: false,
@@ -107,6 +147,14 @@ const loadUnit = async (data: Data) => {
data: prod.data,
code: 0,
};
postScan({
dockId: data.dockId,
loadingOrder: dock[0]?.currentLoadingOrder,
loadingUnit: unitToScan,
loadingUnitStatus: "loaded",
message: emitData.message,
});
emitToRoom(`dockDoorLoading:${data.dockId}`, emitData as any);
return returnFunc({
success: true,

View File

@@ -22,7 +22,6 @@ r.patch(
requirePermission({ notifications: ["update"] }),
async (req, res: Response) => {
const { id } = req.params;
try {
const validated = updateNote.parse(req.body);
@@ -37,6 +36,7 @@ r.patch(
await modifiedNotification(id as string);
if (nError) {
return apiReturn(res, {
success: false,
level: "error",
@@ -58,6 +58,7 @@ r.patch(
status: 200,
});
} catch (err) {
if (err instanceof z.ZodError) {
const flattened = z.flattenError(err);
// return res.status(400).json({

View File

@@ -1,7 +1,8 @@
import { desc } from "drizzle-orm";
import { desc, eq } from "drizzle-orm";
import { db } from "../db/db.controller.js";
import { logs } from "../db/schema/logs.schema.js";
import { ppoRun } from "../warehousing/warehousing.ppooMonitor.js";
import { dockDoorScans } from "../db/schema/dockdoor.scans.schema.js";
type RoomDefinition<T = unknown> = {
seed: (limit: number) => Promise<T[]>;
@@ -103,7 +104,18 @@ export const roomDefinition: Record<RoomId, RoomDefinition> = {
"dockDoorLoading:2": {
seed: async (limit) => {
console.log(limit);
try {
const rows = await db
.select()
.from(dockDoorScans).where(eq(dockDoorScans.status, "active"))
.orderBy(desc(dockDoorScans.upd_date))
.limit(limit);
return rows; //.reverse();
} catch (e) {
console.error("Failed to seed logs:", e);
return [];
}
},
},
};

View File

@@ -0,0 +1,94 @@
import { useQuery } from "@tanstack/react-query";
import { Link } from "@tanstack/react-router";
import { ChevronRight, Link as link } from "lucide-react";
import { permissionQuery } from "../../lib/queries/permsCheck";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "../ui/collapsible";
import {
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarMenuSub,
SidebarMenuSubButton,
SidebarMenuSubItem,
useSidebar,
} from "../ui/sidebar";
export default function WarehouseBar() {
const { data: canCreate = false } = useQuery(
permissionQuery({
warehouse: ["read"],
}),
);
const { setOpen } = useSidebar();
const items = [
{
title: "Dock Door Scanning",
url: "/warehouse",
//icon,
isActive: canCreate,
items: [
{
title: "DockDoorScanning",
icon: link,
url: "/warehouse/dockdoorscanning",
},
],
},
];
return (
<SidebarGroup>
<SidebarGroupLabel>Warehouse</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item) => (
<div key={item.title}>
{item.isActive && (
<Collapsible
asChild
//defaultOpen={isNotifications}
className="group/collapsible"
>
<SidebarMenuItem>
<CollapsibleTrigger asChild>
<SidebarMenuButton tooltip={item.title}>
{item.title}
<ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" />
</SidebarMenuButton>
</CollapsibleTrigger>
<CollapsibleContent>
<SidebarMenuSub>
{item.items?.map((subItem) => (
<SidebarMenuSubItem key={subItem.title}>
<SidebarMenuSubButton asChild>
<Link
to={subItem.url}
onClick={() => setOpen(false)}
>
<subItem.icon />
<span>{subItem.title}</span>
</Link>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
))}
</SidebarMenuSub>
</CollapsibleContent>
</SidebarMenuItem>
</Collapsible>
)}
</div>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
);
}

View File

@@ -13,16 +13,23 @@ import AdminSidebar from "./AdminBar";
import DocBar from "./DocBar";
import MobileBar from "./MobileBar";
import TransportationBar from "./TransportationBar";
import WarehouseBar from "./Warhouse";
export function AppSidebar() {
const { data: session } = useSession();
const { data: settings, isLoading } = useSuspenseQuery(getSettings());
const { data: canRead = false } = useQuery(
const { data: canReadOpenDock = false } = useQuery(
permissionQuery({
openDock: ["read"],
}),
);
const { data: canReadWarehouse = false } = useQuery(
permissionQuery({
warehouse: ["read"],
}),
);
return (
<Sidebar
variant="sidebar"
@@ -42,7 +49,12 @@ export function AppSidebar() {
{!isLoading &&
settings.filter((n: any) => n.name === "opendock_sync")[0]
?.active &&
canRead && <TransportationBar />}
canReadOpenDock && <TransportationBar />}
{!isLoading &&
settings.filter((n: any) => n.name === "dockDoorScanning")[0]
?.active &&
canReadWarehouse && <WarehouseBar />}
{session &&
(session.user.role === "admin" ||

View File

@@ -0,0 +1,21 @@
import { keepPreviousData, queryOptions } from "@tanstack/react-query";
import { api } from "../apiHelper";
export function getActiveLoadingOrders() {
return queryOptions({
queryKey: ["getActiveLoadingOrders"],
queryFn: () => dataFetch(),
staleTime: 5000,
refetchOnWindowFocus: true,
placeholderData: keepPreviousData,
});
}
const dataFetch = async () => {
const { data } = await api.get("/dockDoor/activeLoadingOrders");
if (!data.success) {
throw new Error(data.message ?? "Failed to load articles");
}
return data.data ?? [];
};

View File

@@ -0,0 +1,25 @@
import { keepPreviousData, queryOptions } from "@tanstack/react-query";
import { api } from "../apiHelper";
export function getActiveDockScanners() {
return queryOptions({
queryKey: ["getActiveDockScanners"],
queryFn: () => dataFetch(),
staleTime: 5000,
refetchOnWindowFocus: true,
placeholderData: keepPreviousData,
});
}
const dataFetch = async () => {
if (window.location.hostname === "localhost") {
await new Promise((res) => setTimeout(res, 1500));
}
const { data } = await api.get("/dockDoor/scanners");
if (!data.success) {
throw new Error(data.message ?? "Failed to load articles");
}
return data.data ?? [];
};

View File

@@ -22,7 +22,10 @@ import { Route as AdminScanUsersRouteImport } from './routes/admin/scanUsers'
import { Route as AdminNotificationsRouteImport } from './routes/admin/notifications'
import { Route as AdminLogsRouteImport } from './routes/admin/logs'
import { Route as authLoginRouteImport } from './routes/(auth)/login'
import { Route as WarehouseDockdoorscanningIndexRouteImport } from './routes/warehouse/dockdoorscanning/index'
import { Route as TransportationOpendockIndexRouteImport } from './routes/transportation/opendock/index'
import { Route as WarehouseDockdoorscanningDockScansRouteImport } from './routes/warehouse/dockdoorscanning/$dockScans'
import { Route as WarehouseDockdoorscanningDockRouteImport } from './routes/warehouse/dockdoorscanning/$dock'
import { Route as authUserSignupRouteImport } from './routes/(auth)/user.signup'
import { Route as authUserResetpasswordRouteImport } from './routes/(auth)/user.resetpassword'
import { Route as authUserProfileRouteImport } from './routes/(auth)/user.profile'
@@ -92,12 +95,30 @@ const authLoginRoute = authLoginRouteImport.update({
path: '/login',
getParentRoute: () => rootRouteImport,
} as any)
const WarehouseDockdoorscanningIndexRoute =
WarehouseDockdoorscanningIndexRouteImport.update({
id: '/warehouse/dockdoorscanning/',
path: '/warehouse/dockdoorscanning/',
getParentRoute: () => rootRouteImport,
} as any)
const TransportationOpendockIndexRoute =
TransportationOpendockIndexRouteImport.update({
id: '/transportation/opendock/',
path: '/transportation/opendock/',
getParentRoute: () => rootRouteImport,
} as any)
const WarehouseDockdoorscanningDockScansRoute =
WarehouseDockdoorscanningDockScansRouteImport.update({
id: '/warehouse/dockdoorscanning/$dockScans',
path: '/warehouse/dockdoorscanning/$dockScans',
getParentRoute: () => rootRouteImport,
} as any)
const WarehouseDockdoorscanningDockRoute =
WarehouseDockdoorscanningDockRouteImport.update({
id: '/warehouse/dockdoorscanning/$dock',
path: '/warehouse/dockdoorscanning/$dock',
getParentRoute: () => rootRouteImport,
} as any)
const authUserSignupRoute = authUserSignupRouteImport.update({
id: '/(auth)/user/signup',
path: '/user/signup',
@@ -131,7 +152,10 @@ export interface FileRoutesByFullPath {
'/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute
'/user/signup': typeof authUserSignupRoute
'/warehouse/dockdoorscanning/$dock': typeof WarehouseDockdoorscanningDockRoute
'/warehouse/dockdoorscanning/$dockScans': typeof WarehouseDockdoorscanningDockScansRoute
'/transportation/opendock/': typeof TransportationOpendockIndexRoute
'/warehouse/dockdoorscanning/': typeof WarehouseDockdoorscanningIndexRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
@@ -150,7 +174,10 @@ export interface FileRoutesByTo {
'/user/profile': typeof authUserProfileRoute
'/user/resetpassword': typeof authUserResetpasswordRoute
'/user/signup': typeof authUserSignupRoute
'/warehouse/dockdoorscanning/$dock': typeof WarehouseDockdoorscanningDockRoute
'/warehouse/dockdoorscanning/$dockScans': typeof WarehouseDockdoorscanningDockScansRoute
'/transportation/opendock': typeof TransportationOpendockIndexRoute
'/warehouse/dockdoorscanning': typeof WarehouseDockdoorscanningIndexRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
@@ -170,7 +197,10 @@ export interface FileRoutesById {
'/(auth)/user/profile': typeof authUserProfileRoute
'/(auth)/user/resetpassword': typeof authUserResetpasswordRoute
'/(auth)/user/signup': typeof authUserSignupRoute
'/warehouse/dockdoorscanning/$dock': typeof WarehouseDockdoorscanningDockRoute
'/warehouse/dockdoorscanning/$dockScans': typeof WarehouseDockdoorscanningDockScansRoute
'/transportation/opendock/': typeof TransportationOpendockIndexRoute
'/warehouse/dockdoorscanning/': typeof WarehouseDockdoorscanningIndexRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
@@ -191,7 +221,10 @@ export interface FileRouteTypes {
| '/user/profile'
| '/user/resetpassword'
| '/user/signup'
| '/warehouse/dockdoorscanning/$dock'
| '/warehouse/dockdoorscanning/$dockScans'
| '/transportation/opendock/'
| '/warehouse/dockdoorscanning/'
fileRoutesByTo: FileRoutesByTo
to:
| '/'
@@ -210,7 +243,10 @@ export interface FileRouteTypes {
| '/user/profile'
| '/user/resetpassword'
| '/user/signup'
| '/warehouse/dockdoorscanning/$dock'
| '/warehouse/dockdoorscanning/$dockScans'
| '/transportation/opendock'
| '/warehouse/dockdoorscanning'
id:
| '__root__'
| '/'
@@ -229,7 +265,10 @@ export interface FileRouteTypes {
| '/(auth)/user/profile'
| '/(auth)/user/resetpassword'
| '/(auth)/user/signup'
| '/warehouse/dockdoorscanning/$dock'
| '/warehouse/dockdoorscanning/$dockScans'
| '/transportation/opendock/'
| '/warehouse/dockdoorscanning/'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
@@ -249,7 +288,10 @@ export interface RootRouteChildren {
authUserProfileRoute: typeof authUserProfileRoute
authUserResetpasswordRoute: typeof authUserResetpasswordRoute
authUserSignupRoute: typeof authUserSignupRoute
WarehouseDockdoorscanningDockRoute: typeof WarehouseDockdoorscanningDockRoute
WarehouseDockdoorscanningDockScansRoute: typeof WarehouseDockdoorscanningDockScansRoute
TransportationOpendockIndexRoute: typeof TransportationOpendockIndexRoute
WarehouseDockdoorscanningIndexRoute: typeof WarehouseDockdoorscanningIndexRoute
}
declare module '@tanstack/react-router' {
@@ -345,6 +387,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof authLoginRouteImport
parentRoute: typeof rootRouteImport
}
'/warehouse/dockdoorscanning/': {
id: '/warehouse/dockdoorscanning/'
path: '/warehouse/dockdoorscanning'
fullPath: '/warehouse/dockdoorscanning/'
preLoaderRoute: typeof WarehouseDockdoorscanningIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/transportation/opendock/': {
id: '/transportation/opendock/'
path: '/transportation/opendock'
@@ -352,6 +401,20 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof TransportationOpendockIndexRouteImport
parentRoute: typeof rootRouteImport
}
'/warehouse/dockdoorscanning/$dockScans': {
id: '/warehouse/dockdoorscanning/$dockScans'
path: '/warehouse/dockdoorscanning/$dockScans'
fullPath: '/warehouse/dockdoorscanning/$dockScans'
preLoaderRoute: typeof WarehouseDockdoorscanningDockScansRouteImport
parentRoute: typeof rootRouteImport
}
'/warehouse/dockdoorscanning/$dock': {
id: '/warehouse/dockdoorscanning/$dock'
path: '/warehouse/dockdoorscanning/$dock'
fullPath: '/warehouse/dockdoorscanning/$dock'
preLoaderRoute: typeof WarehouseDockdoorscanningDockRouteImport
parentRoute: typeof rootRouteImport
}
'/(auth)/user/signup': {
id: '/(auth)/user/signup'
path: '/user/signup'
@@ -393,7 +456,11 @@ const rootRouteChildren: RootRouteChildren = {
authUserProfileRoute: authUserProfileRoute,
authUserResetpasswordRoute: authUserResetpasswordRoute,
authUserSignupRoute: authUserSignupRoute,
WarehouseDockdoorscanningDockRoute: WarehouseDockdoorscanningDockRoute,
WarehouseDockdoorscanningDockScansRoute:
WarehouseDockdoorscanningDockScansRoute,
TransportationOpendockIndexRoute: TransportationOpendockIndexRoute,
WarehouseDockdoorscanningIndexRoute: WarehouseDockdoorscanningIndexRoute,
}
export const routeTree = rootRouteImport
._addFileChildren(rootRouteChildren)

View File

@@ -0,0 +1,118 @@
import { useSuspenseQuery } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router";
import { format } from "date-fns";
import { Button } from "../../../components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
} from "../../../components/ui/card";
import { Separator } from "../../../components/ui/separator";
import { getActiveLoadingOrders } from "../../../lib/queries/getActiveDockScanners";
import { getActiveDockScanners } from "../../../lib/queries/getActiveLoadingOrders";
import { finishLoadingOrder} from './index'
import { api } from "../../../lib/apiHelper";
import { toast } from "sonner";
export const Route = createFileRoute("/warehouse/dockdoorscanning/$dock")({
component: RouteComponent,
});
export const startOrder = async (loadingOrder: string, dockId: string, refetch:any, refetchActiveLoading:any) => {
try {
const res = await api.post("/dockDoor/startLoad", {
"loadingOrder":String(loadingOrder),
"dockId":dockId
},{validateStatus: (status) => status < 500,})
if (!res.data.success) {
toast.error(res.data.message)
refetch()
refetchActiveLoading()
return
}
toast.success(res.data.message)
refetch()
refetchActiveLoading()
} catch (error) {
console.log(error)
toast.error(`Encountered error: ${JSON.stringify(error)}`)
}
}
function RouteComponent() {
const { dock } = Route.useParams();
const { data, refetch } = useSuspenseQuery(getActiveDockScanners());
const { data: loadingPlanItems, refetch: refetchActiveLoading } = useSuspenseQuery(getActiveLoadingOrders());
const dockData = data.filter((i: any) => i.dockId === dock);
const loadingPlans = loadingPlanItems.filter(
(l: any) => l.dockId === Number(dock),
);
console.log(dockData[0].currentLoadingOrder === "");
return (
<div className="flex flex-col">
<div className="flex justify-center">
<p>Please select an active loading order for {dockData[0].name}</p>
</div>
<div className="flex justify-center mt-5 gap-2">
{loadingPlans &&
loadingPlans.length > 0 &&
loadingPlans.map((i: any) => {
return (
<Card key={i.id} className="max-w-96">
<CardHeader>
Loading order ID: {i.id}{" "}
<p>
Loading Date: {format(i.loadingDate, "MM/dd/yyyy HH:mm")}
</p>
</CardHeader>
<CardDescription className="">
<p className="p-3">
Below are the loading order details please validate the
loading order you are selecting before pressing start.
</p>
</CardDescription>
{/* Mapping the items out so in case we have more than 1 it will display correctly */}
<CardContent>
{i?.loadingPlanItems?.map((l: any) => {
return (
<div key={i.id}>
<p>Loading Sequence {l.loadingSequence}</p>
<p>
Article: {l.articleId} - {l.articleDescription}
</p>
<p>
Current loaded: {l.loadedQuantityLUs}/
{l.plannedQuantityLUs}
</p>
{l.remark !== "" && <p>Remark: {l.remark}</p>}
{i?.loadingPlanItems.length > 1 && (
<Separator className="m-2" />
)}
</div>
);
})}
</CardContent>
<CardFooter>
<div className="flex flex-row justify-between">
<Button
onClick={()=> startOrder(i.id, dock, refetch, refetchActiveLoading)}
disabled={dockData[0].currentLoadingOrder !== "" ? true : false}>Start Loading</Button>
<Button>Scan progress</Button>
<Button onClick={()=> finishLoadingOrder(String(i.id), dock, refetch, refetchActiveLoading)}
disabled={dockData[0].currentLoadingOrder === "" ? true : false}>Finish Loading</Button>
</div>
</CardFooter>
</Card>
);
})}
</div>
</div>
);
}

View File

@@ -0,0 +1,10 @@
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/warehouse/dockdoorscanning/$dockScans")({
component: RouteComponent,
});
function RouteComponent() {
const { dockScans } = Route.useParams();
return <div>Hello "/warehouse/dockdoorscanning/$docScans"! {dockScans}</div>;
}

View File

@@ -0,0 +1,120 @@
import { useSuspenseQuery } from "@tanstack/react-query";
import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { Card, CardContent, CardDescription, CardHeader } from "../../../components/ui/card";
import { getActiveLoadingOrders } from "../../../lib/queries/getActiveDockScanners";
import { getActiveDockScanners } from "../../../lib/queries/getActiveLoadingOrders";
import { Button } from "../../../components/ui/button";
import { api } from "../../../lib/apiHelper";
import { toast } from "sonner";
export const Route = createFileRoute("/warehouse/dockdoorscanning/")({
component: RouteComponent,
});
export const finishLoadingOrder = async (loadingOrder: string, dockId: string, refetch:any, refetchActiveLoading:any) => {
try {
const res = await api.post("/dockDoor/finishOrder", {
"loadingOrder":loadingOrder,
"dockId":dockId
},{validateStatus: (status) => status < 500,})
if (!res.data.success) {
toast.error(res.data.message)
refetch()
refetchActiveLoading()
return
}
toast.info(res.data.message)
refetch()
refetchActiveLoading()
} catch (error) {
console.log(error)
toast.error(`Encountered error: ${JSON.stringify(error)}`)
}
}
function RouteComponent() {
const { data, isLoading, refetch } = useSuspenseQuery(getActiveDockScanners());
const { data: loadingPlanItems, refetch : refetchActiveLoading } = useSuspenseQuery(getActiveLoadingOrders());
const navigate = useNavigate();
if (isLoading) {
return (
<div className="flex justify-center-safe">
<p>Loading active dock scanners....</p>
</div>
);
}
return (
<div className="flex flex-col ">
<div className="flex justify-center-safe">
<p className="text-2xl underline">
Select a dock you would like to work with
</p>
</div>
<div className="flex justify-center gap-3 mt-5">
{!isLoading &&
data.length > 0 &&
data.map((i: any) => {
const loadingPlan =
i.currentLoadingOrder !== ""
? loadingPlanItems.filter(
(x: any) => x.id === Number(i.currentLoadingOrder),
)
: [];
return (
<Card
key={i.id}
className="max-w-96"
onClick={() => {
if (i.currentLoadingOrder === "") {
navigate({
to: "/warehouse/dockdoorscanning/$dock",
params: { dock: i.dockId },
search: {
name: i.name,
},
});
}
}}
>
<CardHeader className="text-center">{i.name}</CardHeader>
<CardDescription>For Abbott loads reminder: 3 lots per load max.</CardDescription>
{i.currentLoadingOrder !== "" ? (
<CardContent>
<div className="flex flex-col gap-2">
Current loading order: {i.currentLoadingOrder}
</div>
<div>
{loadingPlan && loadingPlan.length !== 0 ? (<>
<p>{`${loadingPlan[0].loadingPlanItems[0].articleId} - ${loadingPlan[0].loadingPlanItems[0].articleDescription}`}</p>
<p>Current Loaded :{" "}
{loadingPlan[0].loadingPlanItems[0].loadedQuantityLUs} /{" "}
{loadingPlan[0].loadingPlanItems[0].plannedQuantityLUs}</p></>
): <><p>The Current Loading order is invalid</p>
<p> It appears it could have been finished via another process</p>
<div className="m-2 flex justify-center">
<Button onClick={()=> finishLoadingOrder(i.currentLoadingOrder, i.dockId, refetch, refetchActiveLoading)}>Clear {i.currentLoadingOrder}</Button></div></>}</div>
</CardContent>
) : (
<CardContent>
No active loading orders please click me to select an order
</CardContent>
)}
</Card>
);
})}
</div>
</div>
);
}

View File

@@ -0,0 +1,13 @@
CREATE TABLE "dock_door_scans" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"loading_order" text NOT NULL,
"loading_Unit" text,
"loading_unit_status" text DEFAULT 'loaded',
"message" text,
"status" text DEFAULT 'active',
"add_date" timestamp with time zone DEFAULT now(),
"add_user" text DEFAULT 'lst-system',
"upd_date" timestamp with time zone DEFAULT now(),
"upd_user" text DEFAULT 'lst-system',
CONSTRAINT "dock_door_scans_loading_Unit_unique" UNIQUE("loading_Unit")
);

View File

@@ -0,0 +1 @@
ALTER TABLE "dock_door_scans" ADD COLUMN "dock_id" text NOT NULL;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -421,6 +421,20 @@
"when": 1780349486711,
"tag": "0059_sparkling_joystick",
"breakpoints": true
},
{
"idx": 60,
"version": "7",
"when": 1780584999699,
"tag": "0060_freezing_hercules",
"breakpoints": true
},
{
"idx": 61,
"version": "7",
"when": 1780692629119,
"tag": "0061_wide_marrow",
"breakpoints": true
}
]
}