A comprehensive full-stack Material Management System built with React 18 + TypeScript, Node.js/Express, and PostgreSQL via Prisma ORM. Features JWT authentication, role-based access control, real-time dashboard analytics, inventory tracking, purchase order management, and more.
- Docker Desktop (includes Docker & Docker Compose)
git clone https://github.com/st4rboy1/Material-Management-System.git
cd Material-Management-System
docker-compose upIf you use WSL + Docker Desktop, keep this repository in the Linux filesystem (for example, ~/projects) instead of /mnt/c/....
Why this matters:
- Faster file I/O and npm operations
- More reliable file-watch events for hot reload
- Better VS Code source control responsiveness
Example move command:
mkdir -p ~/projects
cp -a "/mnt/c/Users/<you>/Material Management/Material-Management-System" ~/projects/
cd ~/projects/Material-Management-System
code .Open http://localhost:3000 in your browser. That's it! 🎉
The system automatically:
- ✅ Creates PostgreSQL database with migrations
- ✅ Seeds sample data
- ✅ Starts backend API (http://localhost:5000)
- ✅ Starts frontend (http://localhost:3000)
Use this quick status check to avoid ahead/behind confusion:
git status -sb
git rev-list --left-right --count @{upstream}...HEADInterpretation:
behind N: pull/rebase firstahead N: you have local commits to pushM <file>: local file modifications not committed yet
Email: admin@example.com
Password: Admin@123
See DOCKER_SETUP.md for advanced Docker options.
Once running, see TESTING.md for:
- Feature walkthroughs
- Test credentials
- Running automated tests
- API testing (Swagger docs)
- Load testing with k6
- Materials API sorting fix:
sort_by=quantitynow works reliably without server errors in the Materials module. - Materials table key stability: detailed view rows now use stable unique keys to prevent duplicate-key React warnings.
- Grouped materials pagination fix: grouped Materials view now paginates by material (not flattened stock rows), preventing multi-location items from appearing split across pages after edits.
- Per-location stock threshold editing: existing materials now support saving warehouse-level
minimum_stock,maximum_stock, andreorder_pointupdates via dedicated stock endpoint. - Material threshold input + accessibility hardening: warehouse Min/Max/Reorder fields now allow reliable decimal editing, and material form quantity/select controls now include explicit accessible names with instance-unique ids to prevent duplicate-id a11y violations.
- Location-scoped detail/edit context: opening a material from a specific warehouse row now carries stock context so detail metrics and threshold edits can be scoped to that selected storage location.
- Purchase Order preview theming: dark-mode preview styling now stays visually consistent while keeping print/PDF output forced to light mode.
- Category visual simplification: category logo/color fields were removed from category CRUD to keep taxonomy management focused on name/description hierarchy.
- Profile edit safeguards: avatar upload/remove actions are now gated by Edit mode so photo changes don't apply outside explicit profile editing flow.
- Notification activity readability: activity entries now display human-readable entity labels and normalized change details (no raw UUID/base64 noise).
- Audit-log detail clarity: audit update details now keep full field-by-field change lists (no
(+N more)truncation) for better traceability during reviews. - Docker backend startup hardening: backend dev container now starts through the workspace entrypoint script, auto-detects dependency/Prisma schema drift, and runs
npm install+ Prisma sync before boot to prevent missing-module and stale-client crash loops.
If you prefer to run locally without Docker:
- Node.js 20+
- npm 10+
- PostgreSQL 14+ (or Laragon for all-in-one Windows stack)
- Git
git clone https://github.com/st4rboy1/Material-Management-System.git
cd Material-Management-System
npm ciBackend (backend/.env):
cp backend/.env.example backend/.env
# Edit if needed (see copilot-instructions.md for all variables)Frontend (frontend/.env):
cp frontend/.env.example frontend/.env
# Update VITE_API_URL if backend is not on localhost:5000cd backend
# Run migrations
npx prisma migrate dev
# Seed sample data
npm run seed
cd ..# In one terminal (runs both frontend + backend)
npm run dev
# OR in separate terminals:
npm run backend # Terminal 1
npm run frontend # Terminal 2Access:
- Frontend: http://localhost:3000
- Backend: http://localhost:5000
- API Docs: http://localhost:5000/api-docs
- Dashboard — Real-time stats (total materials, low stock, reorder alerts, overstock, suppliers, pending POs), system status overview (PO statuses, material statuses, transaction counts), stock trends (LineChart), category distribution (PieChart), monthly usage (BarChart), low-stock alerts table, reorder alerts table with pending-PO indicator, overstock alerts, recent transactions; 3-column bottom grid layout
- Materials CRUD — Full inventory management with SKU, barcode/QR code generation, category/warehouse assignment, low-stock/reorder/max-stock thresholds, and Purchase Unit Conversion — set a purchase unit (e.g. "box") + conversion factor (e.g. 50) so the system auto-converts bulk orders into base-unit stock on PO receive
- Categories CRUD — Hierarchical category management with parent-child support; client-side search/filter
- Suppliers CRUD — Supplier profiles with contact info, rating, payment terms, and performance analytics (on-time rate, avg lead time, total received value, recent orders history)
- Inventory Transactions — Issue (stock-out), return (stock-in), and transfer tracking with automatic quantity updates; Purchase is handled exclusively via Purchase Orders (not manual transactions); Issue transactions require a Department + source Warehouse and can optionally target an Employee within that department for recipient-level traceability; Return transactions require a Department + return-to Warehouse (filtered to departments that previously received issued materials); Warehouse column shows transaction source/destination (e.g., "From: Warehouse A" for Issue, "To: Warehouse B" for Return); transaction list/detail now surface Company + Department + Employee context for clearer recipient traceability; Multi-warehouse material support with atomic transfers preventing inventory loss
- Departments CRUD — Track which department received issued materials; searchable by name/code; linked to transactions for full traceability (Admin/Manager only); supports company-aware filtering/sorting and department-issued-material views with employee-level recipient context
- Employees CRUD — Manage non-login employee recipients linked to companies/departments; archive/restore support for operational lifecycle tracking; includes an employee detail page for issued-material totals and recent issue/return history
- Interactive Floor Plan (Workspace) — New
/floor-planworkspace page showing seat maps by company/floor plan with zone-level department mapping, seat occupancy, low-stock seat highlighting, seat-to-employee assignment (Admin/Manager), and seat-level issued material summary; includes direct Issue/Return quick actions that open the existing Transaction form with locked seat context, neutral default view (explicit company selection), one-click floor plan creation/template start, rename/delete actions for selected floor plans, mouse-wheel zoom + click-drag canvas panning, and an in-editor Test Image URL helper that validates direct image links before saving canvas backgrounds - Purchase Orders — Create, approve/reject/receive/cancel workflow with line items and automatic stock update on receive; per-item partial receive (each line item has an editable received quantity); Purchase Order form locks the Order Items section until Supplier and Warehouse are both selected; material dropdown automatically filters by selected warehouse; PO receive auto-applies purchase unit conversion (e.g. receiving 2 boxes of a material configured as “1 box = 50 pcs” adds 100 pcs to stock; Stock Impact column in the receive dialog shows the exact base-unit change before confirming); includes a dedicated print preview page and server-generated PDF export for consistent A4 output
- Warehouses — Multi-warehouse support with user-linked manager assignment and strict hierarchy rules where only building-type warehouses can be selected as parents; view modal shows capacity utilization progress bar (color-coded: green/amber/red) alongside material drilldown table
- Centered Dialog Modals — All view (Eye) and edit (Pencil) actions across every entity open as centered overlay modals instead of navigating to separate pages; forms are reusable modal components embedded directly in list pages
- Grouped Sidebar Navigation — Sidebar items organized into enterprise-style labeled sections: Overview, Inventory Management, Supply Chain, Administration
- Internal-Only Access — Public registration removed from the UI and disabled at the API level; only admins can create new user accounts via the Users panel
- Authentication & Authorization — JWT tokens, bcrypt password hashing, role-based access (Admin / Manager / Staff); rate-limited login and register routes; change-password page for all users; password re-confirmation dialog before every create, update, and delete mutation
- Profile Management — Tabbed interface with Profile Information (editable fields: first name, last name, email) and Security Settings (password change form + display mode indicator); users can self-manage their account details
- Admin Settings Module — Admin-only configuration dashboard (
/settings) with three tabs: General (system info + configuration overview), Security (password policy matrix, JWT session config, RBAC permissions table), Preferences (display mode) - Dark/Light Mode (shadcn tokens) — Persistent dark/light mode with a single professional brand theme based on shadcn CSS tokens; theme preference saved to localStorage
- Enhanced User Management — View Profile modal for inspecting user details; manager privilege boundary enforcement prevents managers from editing, deactivating, or changing roles of admin accounts (enforced at both UI and API layers)
- CSV, Excel & PDF Export — Export materials (CSV + Excel), transactions, and purchase orders (including backend-rendered PDF for purchase orders)
- QR Code/Barcode — Generate QR codes for materials
- Email Notifications — Low-stock alert emails via Nodemailer
- Audit Log — Track all user actions with filters (action, entity, date range)
- User Management — Admin panel for managing users, roles, and account status
- API Documentation — Auto-generated Swagger/OpenAPI docs at
/api-docs - Loading Skeletons — Animated skeleton rows on all list pages while data loads
- Notification Bell — Topbar bell icon with three-tab dropdown: Low Stock alerts (progress bars + Critical/Low badges), Activity feed from the audit log (unread tracking via
localStorage), and Inbox (DB-backed notifications viaGET /notifications). Inbox supports per-item dismiss, mark-read, and mark-all-read backed by the database. Bell badge counts all three sources. 5-minute polling interval. Auto-notifications sent on PO approve/reject/receive/cancel and when stock drops below minimum. - Page Subtitles — Each module page (Materials, Categories, Suppliers, Warehouses, Transactions, Purchase Orders) displays a descriptive subtitle under the page title for improved UX clarity
- PO Category Filter — Per-row category selector in the Purchase Order form that filters the material dropdown to only show materials in the chosen category
- User Form Improvements — Confirm-password field with mismatch validation, show/hide eye-icon toggle on both password fields, username auto-generated from email prefix on create, verbose per-field validation error messages
| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite, Tailwind CSS v4, React Router 6, Recharts, Axios, Notistack |
| Backend | Node.js, Express.js, Prisma ORM, PostgreSQL, JWT, bcryptjs, express-validator |
| Database | PostgreSQL 14+ (managed via Prisma migrations) |
| Docs | Swagger (swagger-jsdoc + swagger-ui-express) |
| Security | Helmet, CORS, express-rate-limit, xss-clean, hpp, input validation, env var startup check |
| Export | xlsx, csv-writer, qrcode |
| Nodemailer |
Stock quantity changes occur through two independent workflows: Purchase Orders and Inventory Transactions. Understanding when to use each is critical to prevent double-counting and maintain accurate inventory levels.
Use Purchase Orders for:
- ✅ Formal supplier orders with optional approval workflow (create → approve/reject → receive)
- ✅ Tracked receipting with per-item received quantities and delivery confirmation
- ✅ Budget/approval records when orders need manager sign-off before procurement
- ✅ Expected delivery dates and order history tracking
Flow: Create PO → (Optional) Approve/Reject → Receive items (quantity per line item) → Auto-updates stock
Best for: Regular, recurring supplier orders with formal governance
Use Transactions for:
- ✅ Internal transfers between warehouses
- ✅ Stock issues to departments (tracked for allocation traceability)
- ✅ Stock returns from departments back to warehouse inventory
- ✅ Corrective stock movements using issue/return/transfer flows
Flow: Select type (issue/return/transfer) → Material → Quantity → Confirm
Best for: Daily operational stock movements outside procurement receipts
Materials can be configured with a purchase unit and conversion factor to handle the common scenario where you order in bulk units (Box, Case, Pallet) but track stock in base units (pcs, kg, etc.).
Setup: On the Material form, under Stock & Pricing, set:
- Purchase Unit — the unit used when ordering (e.g.
box) - Units per Purchase Unit — how many base units one purchase unit contains (e.g.
50→ "1 box = 50 pcs")
Effect on PO workflow:
- When creating a PO line item, the quantity input field shows a live Stock Impact hint (e.g. "2 boxes × 50 = 100 pcs added to stock")
- The receive dialog shows a Stock Impact column so Purchasing Managers can confirm the exact base-unit change before clicking Mark as Received
- On receive, the system multiplies:
received qty × conversion factorbefore updating material stock - The audit transaction record stores the base-unit quantity and carries a human-readable note (e.g. "Received 2 box(s) × 50 = 100 pcs")
Legacy materials (no purchase unit set) are unaffected — they behave as 1:1 (no conversion).
Examples of incorrect double-entry:
- ❌ Create PO for 100 units → Receive PO (+100 units) → Apply another stock-in adjustment for the same delivery (+100 units) = 200 recorded, 100 actual
- ❌ Mark PO as received (+50 units) → Import/apply an additional stock correction for that same 50 units without reversal = double counting
System Safeguards:
- Supplier receipts should be finalized through the PO receive flow once for each physical delivery
- At API level, purchase-type transaction attempts are blocked when open POs exist for the same material to reduce duplicate-entry risk
- Stock increases only when PO is marked as Received, not when approved
Do you need formal approval before buying?
├─ YES → Use Purchase Order
│ └─ Follow PO workflow: Create → Approve → Receive
│
└─ NO → Use Transaction (Issue, Return, or Transfer)
└─ Daily internal stock movement between warehouses/departments
Material-Management-System/
├── backend/
│ ├── package.json
│ ├── .env # Environment variables
│ ├── prisma/
│ │ └── schema.prisma # Single source of truth for DB schema
│ └── src/
│ ├── server.js # Entry point (env validation + DB connect)
│ ├── app.js # Express app setup, middleware, routes
│ ├── config/
│ │ ├── prisma.js # Prisma client singleton
│ │ └── swagger.js # Swagger config
│ ├── controllers/
│ │ ├── auth.controller.js
│ │ ├── user.controller.js
│ │ ├── material.controller.js
│ │ ├── category.controller.js
│ │ ├── supplier.controller.js
│ │ ├── transaction.controller.js
│ │ ├── purchaseOrder.controller.js
│ │ ├── warehouse.controller.js
│ │ ├── dashboard.controller.js
│ │ ├── audit.controller.js
│ │ ├── notification.controller.js
│ │ └── export.controller.js
│ ├── routes/
│ │ ├── auth.routes.js
│ │ ├── user.routes.js
│ │ ├── material.routes.js
│ │ ├── category.routes.js
│ │ ├── supplier.routes.js
│ │ ├── transaction.routes.js
│ │ ├── purchaseOrder.routes.js
│ │ ├── warehouse.routes.js
│ │ ├── dashboard.routes.js
│ │ ├── audit.routes.js
│ │ ├── notification.routes.js
│ │ └── export.routes.js
│ ├── middleware/
│ │ ├── auth.js # JWT verification
│ │ ├── roleCheck.js # Role-based guard
│ │ ├── errorHandler.js # Global error handler
│ │ ├── validators.js # express-validator rules
│ │ └── validate.js # Validation runner
│ ├── utils/
│ │ ├── auditLog.js # Audit logger
│ │ ├── createNotification.js # Notification helpers
│ │ ├── pagination.js # Pagination helpers
│ │ └── email.js # Email sender
│ └── database/
│ └── seed.js # Sample data seeder
│
└── frontend/
├── package.json
├── vite.config.ts
├── tsconfig.json
└── src/
├── index.tsx
├── App.tsx
├── theme.tsx
├── routes.tsx
├── services/api.ts # Axios instance with JWT interceptor
├── context/
│ ├── AuthContext.tsx # Auth state & methods
│ └── ThemeContext.tsx # Dark/light mode
├── components/
│ ├── layout/ # Sidebar + AppBar
│ └── common/
│ ├── StatCard.tsx
│ ├── PageHeader.tsx
│ ├── ConfirmDialog.tsx
│ ├── NotificationBell.tsx # Topbar notification bell (low-stock + activity)
│ └── TableSkeleton.tsx # Reusable animated loading skeleton
└── pages/
├── Login.tsx
├── Register.tsx
├── ChangePassword.tsx
├── Dashboard.tsx
├── AuditLog.tsx
├── NotFound.tsx
├── materials/
│ ├── MaterialList.tsx # Embeds view modal + MaterialForm modal
│ └── MaterialForm.tsx # Reusable modal component (create/edit)
├── categories/
│ └── CategoryList.tsx # Embeds inline create/edit dialog + view modal
├── suppliers/
│ ├── SupplierList.tsx # Embeds view modal + SupplierForm modal
│ └── SupplierForm.tsx # Reusable modal component (create/edit)
├── transactions/
│ ├── TransactionList.tsx # Embeds view modal + TransactionForm modal
│ └── TransactionForm.tsx # Reusable modal component (create/edit)
├── purchaseOrders/
│ ├── PurchaseOrderList.tsx # Embeds view+actions modal + PurchaseOrderForm modal
│ └── PurchaseOrderForm.tsx # Reusable modal component (create/edit)
├── warehouses/
│ └── WarehouseList.tsx # Embeds inline create/edit dialog + view modal
├── companies/
│ ├── CompanyList.tsx
│ └── CompanyDetail.tsx
├── departments/
│ ├── DepartmentList.tsx
│ └── DepartmentDetail.tsx
├── employees/
│ └── EmployeeList.tsx
├── users/
│ └── UserList.tsx # User management with View Profile modal + manager privilege guards
├── Profile.tsx # Tabbed user profile: Personal Info (editable) + Security Settings (password)
└── settings/
└── Settings.tsx # Admin-only system settings: General, Security, Preferences tabs (display mode)
- Node.js 18+ & npm
- PostgreSQL 14+
# Install all dependencies (root, backend, frontend)
npm ci
# Apply database migrations
cd backend && npx prisma migrate dev
# Seed sample data
cd .. && npm run seed
# Start both backend (port 5000) and frontend (port 3000) concurrently
npm run devOpen http://localhost:3000 in your browser.
Create backend/.env with the following:
# Required
DATABASE_URL=postgresql://postgres:your_password@localhost:5432/material_management
JWT_SECRET=your-secret-key-change-in-production
# Optional
PORT=5000
JWT_EXPIRES_IN=24h
NODE_ENV=development
FRONTEND_URL=http://localhost:3000
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password
NOTIFICATION_EMAIL=alerts@yourcompany.comNote: The server will refuse to start if
DATABASE_URLorJWT_SECRETare missing.
npm run backend # Backend only (nodemon, port 5000)
npm run frontend # Frontend only (Vite, port 3000)
npm run build # Build frontend for production
npm run migrate # Create + apply database migration
npm run seed # Re-seed sample dataDetailed guide: See Development Guide for when and how to use each command.
- Recommended production setup: Frontend on Vercel, Backend on Railway (or Render), and managed PostgreSQL.
- Full step-by-step instructions: Deployment Guide
| Command | Purpose | When to Use |
|---|---|---|
npm run dev |
Start backend + frontend (concurrently) | Every time you code |
npm run build |
Build frontend for production | Before deploying or committing |
npm run seed |
Populate DB with sample data | First-time setup or reset demo data |
npm run backend |
Backend only | Rare; testing API in isolation |
npm run frontend |
Frontend only | Rare; backend already running elsewhere |
npm run migrate |
Create + apply database migration | After modifying schema.prisma |
npx prisma studio |
Visual database browser | Inspecting/editing data via GUI |
npm run build |
Build frontend for production | Pre-deployment or pre-commit check |
| Command | Purpose |
|---|---|
cd backend && npm test |
Run all backend unit + integration tests (Jest) |
cd backend && npm run test:watch |
Backend tests in watch mode |
cd backend && npm run test:coverage |
Backend tests with coverage report |
cd frontend && npm test |
Run all frontend component tests (Vitest) |
cd frontend && npm run test:watch |
Frontend tests in watch mode |
cd frontend && npm run test:ui |
Frontend tests with browser UI |
npx playwright test |
Run E2E tests (requires both servers running) |
k6 run k6/auth.js |
Auth load test (requires k6 binary) |
k6 run k6/materials.js |
Materials load test |
k6 run k6/purchaseOrders.js |
Purchase orders load test |
→ For detailed explanations, examples, and troubleshooting, see Development Guide
| Role | Password | |
|---|---|---|
| Admin | admin@mms.com | Password123! |
| Manager | manager@mms.com | Password123! |
| Staff | staff1@mms.com | Password123! |
| Staff | staff2@mms.com | Password123! |
The project has comprehensive automated testing across all layers:
| Layer | Framework | Location | Tests |
|---|---|---|---|
| Backend unit | Jest 29 + jest-mock-extended | backend/src/__tests__/unit/ |
~55 tests |
| Backend integration | Jest 29 + Supertest | backend/src/__tests__/integration/ |
~37 tests |
| Frontend components | Vitest 4 + React Testing Library | frontend/src/__tests__/components/ |
14 tests |
| E2E | Playwright | e2e/ |
3 spec files |
| Load | k6 | k6/ |
3 scripts |
E2E setup (once, when network available):
npm install --save-dev @playwright/test
npx playwright install chromiumLoad test setup (requires k6 binary): See k6/README.md
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/register |
Register new user |
| POST | /api/auth/login |
Login & get JWT |
| GET | /api/auth/me |
Get current user |
| PUT | /api/auth/change-password |
Change password |
| POST | /api/auth/verify-password |
Verify current user password before sensitive actions |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/materials |
List (search, filter, paginate) |
| GET | /api/materials/:id |
Get by ID |
| POST | /api/materials |
Create (Admin/Manager) |
| PUT | /api/materials/:id |
Update (Admin/Manager) |
| DELETE | /api/materials/:id |
Delete (Admin) |
| GET | /api/materials/low-stock |
Low stock alerts |
| GET | /api/materials/:id/barcode |
Generate QR code |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/categories |
List all |
| GET | /api/categories/:id |
Get by ID |
| POST | /api/categories |
Create (Admin/Manager) |
| PUT | /api/categories/:id |
Update (Admin/Manager) |
| DELETE | /api/categories/:id |
Delete (Admin) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/suppliers |
List all |
| GET | /api/suppliers/:id |
Get by ID |
| GET | /api/suppliers/:id/performance |
Supplier performance analytics (on-time rate, lead time, totals, recent orders) |
| POST | /api/suppliers |
Create (Admin/Manager) |
| PUT | /api/suppliers/:id |
Update (Admin/Manager) |
| DELETE | /api/suppliers/:id |
Delete (Admin) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/transactions |
List (filter by type, department, employee, paginate) |
| GET | /api/transactions/:id |
Get by ID |
| POST | /api/transactions |
Create (auto-updates stock; supports transfer with from/to warehouse; supports optional employee recipient for issue flows) |
| PUT | /api/transactions/:id |
Update notes/type |
| DELETE | /api/transactions/:id |
Delete (soft delete) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/purchase-orders |
List all |
| GET | /api/purchase-orders/:id |
Get with items |
| POST | /api/purchase-orders |
Create new order (Admin/Manager) |
| PUT | /api/purchase-orders/:id |
Update pending order (Admin/Manager) |
| PUT | /api/purchase-orders/:id/approve |
Approve & update stock (Admin/Manager) |
| PUT | /api/purchase-orders/:id/reject |
Reject order (Admin/Manager) |
| PUT | /api/purchase-orders/:id/receive |
Mark approved order as received with optional per-item quantities (Admin/Manager) |
| PUT | /api/purchase-orders/:id/cancel |
Cancel pending order (Admin/Manager) |
| DELETE | /api/purchase-orders/:id |
Delete pending order (Admin only, soft delete) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/warehouses |
List all (filterable by search, is_active) |
| GET | /api/warehouses/:id |
Get by ID |
| POST | /api/warehouses |
Create (Admin/Manager) |
| PUT | /api/warehouses/:id |
Update (Admin/Manager) |
| DELETE | /api/warehouses/:id |
Delete (Admin) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/departments |
List all (search, include_inactive) |
| GET | /api/departments/:id |
Get by ID |
| POST | /api/departments |
Create (Admin/Manager) |
| PUT | /api/departments/:id |
Update (Admin/Manager) |
| DELETE | /api/departments/:id |
Deactivate (Admin/Manager — blocked if linked transactions exist) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/companies |
List all (search, include_inactive) |
| GET | /api/companies/:id |
Get by ID (with department and issuance metrics) |
| POST | /api/companies |
Create (Admin/Manager) |
| PUT | /api/companies/:id |
Update (Admin/Manager) |
| PATCH | /api/companies/:id |
Archive (Admin/Manager) |
| PUT | /api/companies/:id/restore |
Restore (Admin/Manager) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/employees |
List all (search, company_id, department_id, include_inactive) |
| GET | /api/employees/:id |
Get by ID |
| POST | /api/employees |
Create (Admin/Manager) |
| PUT | /api/employees/:id |
Update (Admin/Manager) |
| PATCH | /api/employees/:id |
Archive (Admin/Manager) |
| PUT | /api/employees/:id/restore |
Restore (Admin/Manager) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/dashboard/stats |
Summary statistics (includes reorder_alert_count, overstock_count) |
| GET | /api/dashboard/monthly-usage |
Monthly usage chart data |
| GET | /api/dashboard/stock-by-category |
Category distribution |
| GET | /api/dashboard/recent-transactions |
Latest 10 transactions |
| GET | /api/dashboard/low-stock-alerts |
Items below minimum stock |
| GET | /api/dashboard/reorder-alerts |
Items at or below reorder point (with pending PO count) |
| GET | /api/dashboard/overstock-alerts |
Items above maximum stock level |
| GET | /api/dashboard/stock-trends |
Stock trends over time |
| GET | /api/dashboard/status-summary |
System-wide status counts (PO statuses, material statuses, transaction types) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/users |
List users |
| POST | /api/users |
Create user |
| PUT | /api/users/:id |
Update user |
| DELETE | /api/users/:id |
Delete user |
| GET | /api/users/roles/list |
List roles |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/export/materials/excel |
Export materials as Excel (only Excel format supported) |
| GET | /api/export/qrcode/:materialId |
Generate QR code for material |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/notifications |
List notifications for current user (paginated) |
| GET | /api/notifications/unread-count |
Unread count for current user |
| PATCH | /api/notifications/:id/read |
Mark one as read |
| PATCH | /api/notifications/mark-all-read |
Mark all as read |
| DELETE | /api/notifications/:id |
Delete a notification |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/audit |
List logs (filter by action, entity) |
Once the backend is running, visit:
http://localhost:5000/api-docs
Interactive exploration of all endpoints with request/response schemas.
| Feature | Admin | Manager | Staff |
|---|---|---|---|
| View Dashboard | ✅ | ✅ | ✅ |
| View Materials | ✅ | ✅ | ✅ |
| Create/Edit Materials | ✅ | ✅ | ❌ |
| Delete Materials | ✅ | ❌ | ❌ |
| Manage Categories | ✅ | ✅ | ❌ |
| Manage Suppliers | ✅ | ✅ | ❌ |
| Create Transactions | ✅ | ✅ | ✅ |
| Create Purchase Orders | ✅ | ✅ | ✅ |
| Approve/Reject POs | ✅ | ✅ | ❌ |
| Manage Warehouses | ✅ | ✅ | ❌ |
| Manage Departments | ✅ | ✅ | ❌ |
| Manage Users | ✅ | ❌ | ❌ |
| View Audit Log | ✅ | ✅ | ❌ |
| Export Data | ✅ | ✅ | ✅ |
All view and edit interactions use centered overlay modals rather than separate routes. This means:
- Clicking the Eye icon on any list row opens a view detail modal in-place
- Clicking the Pencil icon or Add button opens the form modal (create or edit)
- The Purchase Order view modal includes the full Approve / Reject / Receive / Cancel workflow
- Form components (
MaterialForm,SupplierForm,TransactionForm,PurchaseOrderForm) are reusable modal components accepting{ id, onClose, onSaved }props - No separate detail pages or
/new,/:id,/:id/editroutes exist — all CRUD UX is handled within the list page
The entire frontend is written in TypeScript (.tsx/.ts). The @/ path alias maps to frontend/src/ (configured in vite.config.ts).
Automated security scanning is integrated into the CI/CD pipeline via GitHub Actions.
| Tool | Type | What it catches |
|---|---|---|
| Trivy | SCA + secret scanning | Vulnerable npm dependencies (CVEs) |
| Dependabot | Dependency updates | Auto-PRs for vulnerable/outdated packages |
| eslint-plugin-security | Lint rule | Node.js anti-patterns (eval, non-literal regex, object injection, etc.) |
| Gitleaks | Secret scanning | Leaked API keys, tokens, passwords in git history |
| Workflow | File | Trigger |
|---|---|---|
| Trivy dependency scan | .github/workflows/trivy.yml |
Push/PR to main/develop, weekly Monday 08:00 UTC |
| Gitleaks secret scan | .github/workflows/gitleaks.yml |
Push/PR to main/develop, weekly Monday 08:30 UTC |
| Dependabot | .github/dependabot.yml |
Weekly Monday 09:00 UTC per package ecosystem |
| CI validation | .github/workflows/ci.yml |
PR to main + push to main + push to feature/** and fix/** (feature/fix runs lint + typecheck only) |
cd backend
npm install # installs eslint + eslint-plugin-security
npm run lint # report issues
npm run lint:fix # auto-fix where possibleConfigured to scan three package ecosystems weekly:
/backend— Node.js server dependencies/frontend— React/Vite dependencies/— root workspace tooling- GitHub Actions — keeps action versions up to date
Minor and patch updates are grouped into a single PR per ecosystem to reduce noise.