refactor(dockscanning): more work on the dock door scanning
All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 1m47s
All checks were successful
Build and Push LST Docker Image / docker (push) Successful in 1m47s
ref #12
This commit is contained in:
23
backend/db/schema/dockdoor.scans.schema.ts
Normal file
23
backend/db/schema/dockdoor.scans.schema.ts
Normal 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>;
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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 [];
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
94
frontend/src/components/Sidebar/Warhouse.tsx
Normal file
94
frontend/src/components/Sidebar/Warhouse.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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" ||
|
||||
|
||||
21
frontend/src/lib/queries/getActiveDockScanners.ts
Normal file
21
frontend/src/lib/queries/getActiveDockScanners.ts
Normal 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 ?? [];
|
||||
};
|
||||
25
frontend/src/lib/queries/getActiveLoadingOrders.ts
Normal file
25
frontend/src/lib/queries/getActiveLoadingOrders.ts
Normal 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 ?? [];
|
||||
};
|
||||
@@ -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)
|
||||
|
||||
118
frontend/src/routes/warehouse/dockdoorscanning/$dock.tsx
Normal file
118
frontend/src/routes/warehouse/dockdoorscanning/$dock.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
@@ -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>;
|
||||
}
|
||||
120
frontend/src/routes/warehouse/dockdoorscanning/index.tsx
Normal file
120
frontend/src/routes/warehouse/dockdoorscanning/index.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
13
migrations/0060_freezing_hercules.sql
Normal file
13
migrations/0060_freezing_hercules.sql
Normal 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")
|
||||
);
|
||||
1
migrations/0061_wide_marrow.sql
Normal file
1
migrations/0061_wide_marrow.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "dock_door_scans" ADD COLUMN "dock_id" text NOT NULL;
|
||||
2691
migrations/meta/0060_snapshot.json
Normal file
2691
migrations/meta/0060_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
2697
migrations/meta/0061_snapshot.json
Normal file
2697
migrations/meta/0061_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user