+
Document total (incl. VAT)
{lines.reduce((sum, l) => sum + computeLine(l).lineTotal, 0).toFixed(2)}
diff --git a/Frontend/erp-system/app/dashboard/stock/page.tsx b/Frontend/erp-system/app/dashboard/stock/page.tsx
index 83cc12a..8a7b165 100644
--- a/Frontend/erp-system/app/dashboard/stock/page.tsx
+++ b/Frontend/erp-system/app/dashboard/stock/page.tsx
@@ -1,69 +1,3 @@
-import Link from "next/link"
-import {
- AlertOctagon,
- AlertTriangle,
- ArrowLeftRight,
- BadgeDollarSign,
- ClipboardList,
- PackageSearch,
- ScrollText,
- SlidersHorizontal,
- type LucideIcon,
-} from "lucide-react"
-
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
-
-const areas: { title: string; description: string; href: string; icon: LucideIcon }[] = [
- {
- title: "Stock Enquiry",
- description: "On-hand, available, on-hold, and in-transit quantities by item and warehouse.",
- href: "/dashboard/stock/enquiry",
- icon: PackageSearch,
- },
- {
- title: "Stock Ledger",
- description: "The immutable, append-only movement journal β every in/out with running balance.",
- href: "/dashboard/stock/ledger",
- icon: ScrollText,
- },
- {
- title: "Valuation",
- description: "FIFO cost-layer breakdown and total stock value by item and warehouse.",
- href: "/dashboard/stock/valuation",
- icon: BadgeDollarSign,
- },
- {
- title: "Transfers",
- description: "Move stock between warehouses: create, dispatch, and receive (in-transit).",
- href: "/dashboard/stock/transfers",
- icon: ArrowLeftRight,
- },
- {
- title: "Adjustments",
- description: "Increase, decrease, or write off stock with a mandatory reason code.",
- href: "/dashboard/stock/adjustments",
- icon: SlidersHorizontal,
- },
- {
- title: "Counts",
- description: "Cycle or full physical counts β snapshot, enter counts, post variance.",
- href: "/dashboard/stock/counts",
- icon: ClipboardList,
- },
- {
- title: "Reorder Alerts",
- description: "Items at or below their reorder point, with a one-click requisition.",
- href: "/dashboard/stock/reorder-alerts",
- icon: AlertTriangle,
- },
- {
- title: "Wastage",
- description: "Damage, theft/loss, and expiry write-offs β reason-coded adjustments with a totals report.",
- href: "/dashboard/stock/wastage",
- icon: AlertOctagon,
- },
-]
-
export default function StockHubPage() {
return (
@@ -73,26 +7,6 @@ export default function StockHubPage() {
FIFO-costed stock across multiple warehouses (FR-STK-01..14).
-
-
- {areas.map((area) => (
-
-
-
-
-
-
- {area.description}
-
-
-
- ))}
-
)
}
diff --git a/Frontend/erp-system/components/Layouts/AppSidebar.tsx b/Frontend/erp-system/components/Layouts/AppSidebar.tsx
index 4d86d3d..a1fada5 100644
--- a/Frontend/erp-system/components/Layouts/AppSidebar.tsx
+++ b/Frontend/erp-system/components/Layouts/AppSidebar.tsx
@@ -4,6 +4,9 @@ import { useEffect, useState } from "react"
import Link from "next/link"
import { usePathname } from "next/navigation"
import {
+ AlertOctagon,
+ AlertTriangle,
+ ArrowLeftRight,
Banknote,
BadgeDollarSign,
BookOpen,
@@ -29,6 +32,7 @@ import {
Menu,
Package,
PackageCheck,
+ PackageSearch,
PackageX,
PlayCircle,
PieChart,
@@ -36,6 +40,7 @@ import {
ReceiptText,
Ruler,
Scale,
+ ScrollText,
Settings,
ShieldCheck,
ShoppingCart,
@@ -116,7 +121,26 @@ const navItems: {
],
},
{ title: "Receiving", code: "receiving", href: "/dashboard/receiving/grn", icon: PackageCheck, chevron: true },
- { title: "Stock", code: "stock", href: "/dashboard/stock", icon: Warehouse, chevron: true },
+ {
+ title: "Stock",
+ code: "stock",
+ href: "/dashboard/stock",
+ // Clicking "Stock" itself lands on Stock Ledger β the hub page underneath has nothing on
+ // it (its card grid was removed once the sidebar grew these sub-items), same as Procurement.
+ landingHref: "/dashboard/stock/ledger",
+ icon: Warehouse,
+ chevron: true,
+ children: [
+ { title: "Stock Ledger", code: "stock.ledger", href: "/dashboard/stock/ledger", icon: ScrollText },
+ { title: "Stock Enquiry", code: "stock.enquiry", href: "/dashboard/stock/enquiry", icon: PackageSearch },
+ { title: "Valuation", code: "stock.valuation", href: "/dashboard/stock/valuation", icon: BadgeDollarSign },
+ { title: "Transfers", code: "stock.transfers", href: "/dashboard/stock/transfers", icon: ArrowLeftRight },
+ { title: "Adjustments", code: "stock.adjustments", href: "/dashboard/stock/adjustments", icon: SlidersHorizontal },
+ { title: "Counts", code: "stock.counts", href: "/dashboard/stock/counts", icon: ClipboardList },
+ { title: "Reorder Alerts", code: "stock.reorder-alerts", href: "/dashboard/stock/reorder-alerts", icon: AlertTriangle },
+ { title: "Wastage", code: "stock.wastage", href: "/dashboard/stock/wastage", icon: AlertOctagon },
+ ],
+ },
{ title: "Warehouses", code: "warehouses", href: "/dashboard/warehouse", icon: Building2, chevron: true },
{ title: "Orders", code: "orders", href: "/dashboard/orders", icon: ShoppingCart, chevron: true },
{
@@ -402,14 +426,15 @@ export function AppSidebar() {
// flashing the full menu to a restricted role. Once resolved, a nav item
// is visible if its own code is granted, or (for parents) if any child is.
//
- // "procurement", "hrm", "sales" and "production" are exempted from that check (frontend-only): no
- // role is currently seeded with NAV:procurement/NAV:hrm/NAV:production or their children
- // server-side, which would hide the whole section for everyone. Remove each bypass once roles are granted
- // the permission properly (Settings β Roles β Sidebar permissions) or a backend seed
- // grants it. This is also flagged in 02-SECURITY.md as the AR-09 sidebar-visibility
+ // "procurement", "hrm", "sales", "production" and "stock" are exempted from that check
+ // (frontend-only): no role is currently seeded with NAV:procurement/NAV:hrm/NAV:production
+ // or their children server-side (stock's children specifically have no SubNavItem rows at
+ // all yet), which would hide the whole section for everyone. Remove each bypass once roles
+ // are granted the permission properly (Settings β Roles β Sidebar permissions) or a backend
+ // seed grants it. This is also flagged in 02-SECURITY.md as the AR-09 sidebar-visibility
// stopgap for HRM's salary/PII data β it hides HRM from the UI but doesn't enforce
// anything server-side.
- const bypassCodes = new Set(["procurement", "sales", "hrm", "production"])
+ const bypassCodes = new Set(["procurement", "sales", "hrm", "production", "stock"])
const visibleItems = loading
? []
: navItems