diff --git a/apps/edr-freight-api/src/modules/warehouses/warehouse-dashboard.service.ts b/apps/edr-freight-api/src/modules/warehouses/warehouse-dashboard.service.ts index fcc09f668..0bbcdee48 100644 --- a/apps/edr-freight-api/src/modules/warehouses/warehouse-dashboard.service.ts +++ b/apps/edr-freight-api/src/modules/warehouses/warehouse-dashboard.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { DataSource, IsNull } from 'typeorm'; +import { DataSource, FindManyOptions, IsNull, ObjectLiteral, Repository } from 'typeorm'; import { Warehouse } from './entities/warehouse.entity'; import { WarehouseInventory } from './entities/warehouse-inventory.entity'; @@ -26,6 +26,29 @@ export interface WarehouseDashboard { export class WarehouseDashboardService { constructor(private readonly dataSource: DataSource) {} + private async safeCount( + repo: Repository, + options?: FindManyOptions, + ): Promise { + try { + return await repo.count(options); + } catch { + return 0; + } + } + + private async safeReceivedToday(startOfToday: Date): Promise { + try { + return await this.dataSource + .getRepository(WarehouseInventory) + .createQueryBuilder('inv') + .where('inv.arrived_at >= :start', { start: startOfToday }) + .getCount(); + } catch { + return 0; + } + } + async getDashboard(): Promise { const warehouseRepo = this.dataSource.getRepository(Warehouse); const inventoryRepo = this.dataSource.getRepository(WarehouseInventory); @@ -47,21 +70,18 @@ export class WarehouseDashboardService { delivered, receivedToday, ] = await Promise.all([ - warehouseRepo.count(), - inventoryRepo.count(), - inventoryRepo.count({ where: { status: 'RECEIVED', inspectionStatus: IsNull() } }), - inventoryRepo.count({ where: { inspectionStatus: 'PASSED' } }), - inventoryRepo.count({ where: { status: 'STORED' } }), - inventoryRepo.count({ where: { status: 'RESERVED' } }), - inventoryRepo.count({ where: { status: 'READY_FOR_LOADING' } }), - inventoryRepo.count({ where: { status: 'LOADED' } }), - inventoryRepo.count({ where: { status: 'DISPATCHED' } }), - inventoryRepo.count({ where: { status: 'READY_FOR_PICKUP' } }), - inventoryRepo.count({ where: { status: 'DELIVERED' } }), - inventoryRepo - .createQueryBuilder('inv') - .where('inv.arrived_at >= :start', { start: startOfToday }) - .getCount(), + this.safeCount(warehouseRepo), + this.safeCount(inventoryRepo), + this.safeCount(inventoryRepo, { where: { status: 'RECEIVED', inspectionStatus: IsNull() } }), + this.safeCount(inventoryRepo, { where: { inspectionStatus: 'PASSED' } }), + this.safeCount(inventoryRepo, { where: { status: 'STORED' } }), + this.safeCount(inventoryRepo, { where: { status: 'RESERVED' } }), + this.safeCount(inventoryRepo, { where: { status: 'READY_FOR_LOADING' } }), + this.safeCount(inventoryRepo, { where: { status: 'LOADED' } }), + this.safeCount(inventoryRepo, { where: { status: 'DISPATCHED' } }), + this.safeCount(inventoryRepo, { where: { status: 'READY_FOR_PICKUP' } }), + this.safeCount(inventoryRepo, { where: { status: 'DELIVERED' } }), + this.safeReceivedToday(startOfToday), ]); return { diff --git a/apps/edr-freight-web/backoffice/src/App.tsx b/apps/edr-freight-web/backoffice/src/App.tsx index 680e86858..ba465b962 100644 --- a/apps/edr-freight-web/backoffice/src/App.tsx +++ b/apps/edr-freight-web/backoffice/src/App.tsx @@ -1,569 +1,3 @@ -<<<<<<< HEAD -import { Navigate, Outlet, Route, Routes, useLocation, useNavigate } from "react-router-dom"; -import { - Boxes, - FileText, - LayoutDashboard, - LayoutGrid, - Network, - Paperclip, - PackageCheck, - Send, - Settings, - SlidersHorizontal, - Train, - Truck, - Container, - Package, - PackageOpen, - Users, - Wallet, -} from "lucide-react"; - -import { FreightDashboardLayout, type SidebarItem, type SidebarSection } from "@/components/layout"; -import LoadingScreen from "./components/LoadingScreen"; -import { useAuth } from "./auth/useAuth"; -import LoginPage from "./pages/auth/LoginPage"; -import BookingContractPage from "./pages/bookings/BookingContractPage"; -import BookingRequestDetailPage from "./pages/bookings/BookingRequestDetailPage"; -import BookingRequestsPage from "./pages/bookings/BookingRequestsPage"; -import PaymentsPage from "./pages/payments/PaymentsPage"; -import NewBookingPage from "./pages/bookings/NewBookingPage"; -import UserManagementHostPage from "./pages/dashboard/user-management/UserManagementHostPage"; -import DemoUser1Page from "./pages/dashboard/demo/DemoUser1Page"; -import DemoUser2Page from "./pages/dashboard/demo/DemoUser2Page"; -import OverviewPage from "./pages/dashboard/OverviewPage"; -import MyProfilePage from "./pages/dashboard/MyProfilePage"; -//import EmployeesPage from "./pages/dashboard/user-management/EmployeesPage"; -import PermissionsPage from "./pages/dashboard/user-management/PermissionsPage"; -import PositionTypesPage from "./pages/dashboard/user-management/PositionTypesPage"; -import RolesPage from "./pages/dashboard/user-management/RolesPage"; -import UserManagementPage from "./pages/dashboard/user-management/UserManagementPage"; -import UsersPage from "./pages/dashboard/user-management/UsersPage"; -import DropdownSettingsPage from "./pages/dropdown_settings/DropdownSettingsPage"; -import FileUploadSettingsPage from "./pages/documents/FileUploadSettingsPage"; -import RuleEngineLegacyRedirect from "./pages/ruleEngine/RuleEngineLegacyRedirect"; -import RuleEngineResourcePage from "./pages/ruleEngine/RuleEngineResourcePage"; -import CargoTypesPage from "./pages/ruleEngine/CargoTypesPage"; -import TrainScheduleV2ListPage from "./pages/trainScheduling/TrainScheduleV2ListPage"; -import BatchBoardPage from "./pages/trainScheduling/BatchBoardPage"; -import BatchScheduleDetailPage from "./pages/trainScheduling/BatchScheduleDetailPage"; -import TrainScheduleV2DetailPage from "./pages/trainScheduling/TrainScheduleV2DetailPage"; -import TrainScheduleTrackPage from "./pages/trainScheduling/TrainScheduleTrackPage"; -import TrainSchedulingGlobalRulesPage from "./pages/trainScheduling/TrainSchedulingGlobalRulesPage"; -import FleetResourcePage from "./pages/fleet/FleetResourcePage"; -import { getCategorySidebarChildren } from "./pages/ruleEngine/config/resources"; -import { FREIGHT_PERMS, hasPermission as hasFreightPermission } from "./lib/permissions"; -import { RequirePermission } from "./components/auth/RequirePermission"; -import TrainDetailPage from "./pages/trains/TrainDetailPage"; -import RoutesPage from "./pages/fleet/RoutesPage"; -import WarehouseDashboardPage from "./pages/warehouses/WarehouseDashboardPage"; -import WarehouseListPage from "./pages/warehouses/WarehouseListPage"; -import WarehouseDetailPage from "./pages/warehouses/WarehouseDetailPage"; -import WarehouseInventoryPage from "./pages/warehouses/WarehouseInventoryPage"; -import InventoryInquiryPage from "./pages/warehouses/InventoryInquiryPage"; -import LoadingQueuePage from "./pages/warehouses/LoadingQueuePage"; -import LoadedInventoryPage from "./pages/warehouses/LoadedInventoryPage"; -import DispatchQueuePage from "./pages/warehouses/DispatchQueuePage"; -import ArrivalQueuePage from "./pages/warehouses/ArrivalQueuePage"; -import WarehouseRulesPage from "./pages/warehouses/WarehouseRulesPage"; -import WarehouseInvoicesPage from "./pages/warehouses/WarehouseInvoicesPage"; - -const buildSidebarSections = (demoItems: SidebarItem[]): SidebarSection[] => [ - { - title: "Main menu", - mutedTitle: true, - items: [ - { - label: "Overview", - href: "/dashboard/overview", - icon: , - }, - { - label: "UM", - href: "/um", - icon: , - }, - { - label: "Booking requests", - href: "/dashboard/booking-requests", - icon: , - }, - { - label: "Payments", - href: "/dashboard/payments", - icon: , - permission: FREIGHT_PERMS.bookings.view, - }, - ...demoItems, - ], - }, - { - title: "Operations", - items: [ - { - label: "Train Schedules", - href: "/dashboard/operations/train-scheduling-v2", - icon: , - permission: FREIGHT_PERMS.trainScheduling.view, - }, - { - label: "Batch Board", - href: "/dashboard/operations/batch-board", - icon: , - permission: FREIGHT_PERMS.trainScheduling.view, - }, - ], - }, - { - title: "Fleet Management", - items: [ - { - label: "Routes", - href: "/dashboard/routes", - icon: , - permission: FREIGHT_PERMS.fleet.view, - }, - { - label: "Locomotives", - href: "/dashboard/locomotives", - icon: , - permission: FREIGHT_PERMS.fleet.view, - }, - // { - // label: "Trains", - // href: "/dashboard/trains", - // icon: , - // }, - // { - // label: "Wagon types", - // href: "/dashboard/wagon-types", - // icon: , - // }, - { - label: "Wagons", - href: "/dashboard/wagons", - icon: , - permission: FREIGHT_PERMS.fleet.view, - }, - { - label: "Vehicles", - href: "/dashboard/vehicles", - icon: , - permission: FREIGHT_PERMS.fleet.view, - }, - { - label: "Drivers", - href: "/dashboard/drivers", - icon: , - permission: FREIGHT_PERMS.fleet.view, - }, - // { - // label: "Containers", - // href: "/dashboard/containers", - // icon: , - // }, - // { - // label: "Cargoes", - // href: "/dashboard/cargoes", - // icon: , - // }, - ], - }, - { - title: "Warehouse Management", - items: [ - { - label: "Warehouse Dashboard", - href: "/dashboard/warehouse-dashboard", - icon: , - }, - { - label: "Warehouses", - href: "/dashboard/warehouses", - icon: , - }, - { - label: "Inventory", - href: "/dashboard/warehouse-inventory", - icon: , - }, - { - label: "Arrival Queue", - href: "/dashboard/arrival-queue", - icon: , - }, - { - label: "Loading Queue", - href: "/dashboard/loading-queue", - icon: , - }, - { - label: "Loaded Inventory", - href: "/dashboard/loaded-inventory", - icon: , - }, - { - label: "Dispatch Queue", - href: "/dashboard/dispatch-queue", - icon: , - }, - { - label: "Inventory Inquiry", - href: "/dashboard/inventory-inquiry", - icon: , - }, - { - label: "Allocation & Fees", - href: "/dashboard/warehouse-rules", - icon: , - }, - { - label: "Fee Invoices", - href: "/dashboard/warehouse-fee-invoices", - icon: , - }, - ], - }, - { - title: "Administration", - items: [ - { - label: "File settings", - href: "/dashboard/file-settings", - icon: , - permission: FREIGHT_PERMS.admin, - }, - { - label: "Dropdown settings", - href: "/dashboard/dropdown-settings", - icon: , - permission: FREIGHT_PERMS.admin, - }, - ], - }, - { - title: "Freight configuration", - mutedTitle: true, - items: [ - { - label: "Configuration", - href: "/dashboard/configuration", - icon: , - children: [ - ...getCategorySidebarChildren("configuration"), - // { - // label: "Train scheduling rules", - // href: "/dashboard/configuration/train-scheduling-rules", - // }, - ], - }, - { - label: "Rules", - href: "/dashboard/rules", - icon: , - children: getCategorySidebarChildren("rules"), - }, - ], - }, -]; - -/** Keep only items the user is permitted to see; drop now-empty sections. */ -const filterSidebarByPermission = ( - sections: SidebarSection[], - user: ReturnType["user"], -): SidebarSection[] => { - const itemAllowed = (item: SidebarItem): boolean => { - if (!item.permission) return true; - const keys = Array.isArray(item.permission) - ? item.permission - : [item.permission]; - return keys.some((key) => hasFreightPermission(user, key)); - }; - - return sections - .map((section) => ({ - ...section, - items: section.items.filter(itemAllowed), - })) - .filter((section) => section.items.length > 0); -}; - -const DashboardShell = () => { - const navigate = useNavigate(); - const location = useLocation(); - const { user, logout } = useAuth(); - - const demoItems: SidebarItem[] = []; - - const sidebarSections = filterSidebarByPermission( - buildSidebarSections(demoItems), - user, - ); - const displayName = user?.name?.en || user?.username || user?.email || "User"; - - return ( - - - - ); -}; - -const App = () => { - const { user, loading } = useAuth(); - - if (loading) { - return ; - } - - if (!user) { - return ( - - } /> - } /> - } /> - - ); - } - - return ( - - } /> - } /> - }> - } /> - } /> - } /> - - } /> - - - - } - /> - } /> - } /> - } - /> - - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - - - } - /> - - {/* iframe-based user management module */} - } /> - - {/* Legacy embedded user management routes */} - } /> - } /> - } /> - {/* } /> */} - } /> - } /> - - - - - } - /> - - - - } - /> - - } - /> - - - - } - /> - } /> - } /> - } /> - - } - /> - } /> - - } - /> - } /> - - } /> - } /> - - } - /> - } - /> - - - } /> - - ); -}; - -export default App; -======= import { Boxes, Building2, @@ -578,7 +12,6 @@ import { Paperclip, Send, Settings, - ShieldCheck, SlidersHorizontal, Train, Truck, @@ -594,7 +27,6 @@ import LoginPage from "./pages/auth/LoginPage"; import BookingContractPage from "./pages/bookings/BookingContractPage"; import BookingRequestDetailPage from "./pages/bookings/BookingRequestDetailPage"; import BookingRequestsPage from "./pages/bookings/BookingRequestsPage"; -import GlClearancePage from "./pages/bookings/GlClearancePage"; import NewBookingPage from "./pages/bookings/NewBookingPage"; import CustomerDetailPage from "./pages/customers/CustomerDetailPage"; import CustomersPage from "./pages/customers/CustomersPage"; @@ -677,12 +109,6 @@ const buildSidebarSections = (demoItems: SidebarItem[]): SidebarSection[] => [ { title: "Operations", items: [ - { - label: "Document Clearance", - href: "/dashboard/clearance", - icon: , - permission: FREIGHT_PERMS.bookings.reviewDocuments, - }, { label: "Train Schedules", href: "/dashboard/operations/train-scheduling-v2", @@ -950,14 +376,6 @@ const App = () => { path="booking-requests/:id/contract" element={} /> - - - - } - /> } /> } /> } /> @@ -1269,4 +687,3 @@ const App = () => { }; export default App; ->>>>>>> ee94833a9ead8a825391bb18604e405ac76c70ca