# WMS A multi-tenant Warehouse Management System (WMS) built with PHP, MySQL, and vanilla JavaScript. Designed for small-to-medium operations that need barcode-driven stock control, lot/serial traceability, and multi-warehouse support — accessible from any browser without installing a native app. --- ## Features ### Dashboard - Live stock overview with key metrics (total SKUs, low-stock count, near-expiry alerts) - Low-stock product list with one-click restock shortcut to Stock In - Dashboard widgets per warehouse ### Inventory Management - **Product master** — SKU, name, unit of measure, barcode, category, cost/price/margin tracking - **Categories** — group products for filtering and reporting - **Warehouse master** — multi-warehouse support; simple or advanced location mode (warehouse → rack, or warehouse → zone → aisle → rack) - **Storage / rack master** — define physical rack locations per warehouse - **Product lots** — lot number, expiry date, per-lot traceability across all warehouses ### Stock Control (ICS) - **Stock In** — receive stock into a specific location; supports lot, expiry, serial, unit price, and contact (supplier) - **Stock Out** — remove stock from a location; cascaded lot/serial dropdowns filtered to available stock - **Stock Transfer** — move stock between any two locations (same or different warehouse) - **Stock Overview** — real-time balance per SKU across all warehouses and locations - Two-step approval flow: transactions created as `pending` and approved separately ### Barcode System - **SKU barcode labels** — generate `SKU|{sku}|{lot}|{serial}` labels; print, disable, re-enable per serial - **Location barcode labels** — generate `LOC|{warehouse}|{rack}` (simple) or `LOC|{warehouse}|{zone}|{aisle}|{rack}` (advanced) labels - **Scanner support** — USB scanner, handheld scanner, phone camera (Html5Qrcode), and clipboard paste all handled by a unified `scanner.js` module - Scan-driven stock flows: scan SKU label → scan location label → press F2 to save (no mouse required) - Disabled barcodes are rejected at scan time with a clear error message ### Orders - **Sales orders** — create, confirm, and track customer orders - **Returns** — manage product returns linked to original orders - **Invoices** — generate and print invoices per order - **Purchase orders (PO)** — create and track supplier purchase orders ### Contacts - Supplier and customer contact management - Contact types (supplier, customer, other) - Linked to stock-in, stock-out, orders, and POs ### Reports - **Stock Movement** — full transaction history with in/out/net summary; filterable by date, SKU, warehouse - **Product Lots** — lot-level stock balance with expiry dates across all warehouses - **Expired / Near Expiry** — products approaching or past their expiry date - **Rack Occupancy** — visual overview of which racks are occupied, empty, or locked ### Settings - **Company profile** — name, logo, branch details - **System config** — location mode (simple/advanced), custom zone/aisle/rack labels, stock uniqueness rules - **User management** — invite users by email, assign roles (admin / staff / viewer), remove members - **SMTP** — configure outbound email for notifications - **Profile** — per-user name, username, password, profile picture ### Multi-Tenant / Branch Support - Each company is isolated; users can belong to multiple companies - Branch switcher in the topbar for users with access to more than one company - All data (products, stock, orders, contacts) is scoped to the active company ### Security - Session-based authentication with TOTP-style OTP validation on every API request - CSRF token enforcement on all POST requests - Role-based access control: `owner`, `admin`, `staff`, `viewer`; enforced in protected write APIs with `require_role()` and mirrored in page/sidebar UI (see `docs/ROLES.md`) - Passwords hashed; profile picture uploads sandboxed to `uploads/profile/` --- ## Tech Stack | Layer | Technology | |-------|-----------| | Backend | PHP 8.x, Apache, Composer | | Databases | MySQL — `wms` (system/auth), `wms2` (operational data) | | Frontend | Bootstrap 5, jQuery, Flatpickr, ApexCharts, JsBarcode, Html5Qrcode | | Build | Vite (`npm run dev` / `npm run build`) | | Auth | Session + HMAC-SHA1 OTP + CSRF tokens | | Tests | PHPUnit 10 integration tests under `tests/` | --- ## Module Layout ``` app/ ├── dashboard/ # Dashboard and low-stock widgets ├── ics/ # Stock In / Out / Transfer, barcode labels ├── inventory/ # Product, warehouse, rack, category masters ├── order/ # Sales orders, returns, invoices ├── po/ # Purchase orders ├── reports/ # Stock movement, lots, expiry, rack occupancy ├── contact/ # Supplier / customer contacts ├── setting/ # Company, users, SMTP, system config, profile ├── assets/ │ ├── js/ # main.js, scanner.js, custom.js │ ├── css/ # main.css, custom.css │ └── utils/ # db_auth.php, db_helpers.php, shared classes └── login/ # Login, OTP, onboarding ``` --- ## Installation ### Fresh server ```bash # 1. Create schema and both databases mysql -uroot -p < install.sql # 2. Register baseline — must run once after install.sql php migrate.php ``` ### Updating an existing install ```bash # Apply any pending migrations php migrate.php ``` Add new migrations as `migrations/YYYYMMDD_NNN_description.sql`. The first line must declare the target database: ```sql -- db: wms2 ALTER TABLE md_product ADD COLUMN weight decimal(10,2) NOT NULL DEFAULT 0.00; ``` See `docs/DEPLOYMENT.md` for full setup (Apache, PHP config, uploads directory, HTTPS checklist). --- ## Local Development ```bash # PHP dependencies / integration tests composer install vendor/bin/phpunit # Front-end assets (Vite) npm run dev npm run build # Syntax-check a PHP file php -l app/ics/manage_stock_in.php ``` App is served by Apache at `http://localhost/wms/app/`. The PHPUnit suite uses real local `wms` and `wms2` databases and fixture IDs defined in `tests/bootstrap.php`; run it only against a development database. --- ## Documentation | File | Contents | |------|----------| | `docs/CHANGELOG.md` | Version history and notable changes | | `docs/ROLES.md` | Role-based access control spec (admin / staff / viewer) | | `docs/DATABASE.md` | Full schema for both databases — tables, columns, relationships | | `docs/API.md` | All API endpoints — request fields, response format, error codes | | `docs/DEPLOYMENT.md` | Installation, Apache/PHP/MySQL setup, environment checklist | | `docs/TESTING.md` | Manual test checklists — barcode flow, stock ops, regression | | `docs/SECURITY.md` | Auth model, OTP flow, CSRF, session management, XSS/SQL rules | | `docs/STOCK.md` | Stock ledger, approval flow, rack lifecycle, StockManager/WarehouseManager | | `docs/SCANNER.md` | scanner.js internals, device support, integrating scanning into new pages | | `docs/CONTRIBUTING.md` | Patterns for adding new APIs, pages, modules, settings, and schema changes | | `docs/V2PLAN.md` | Planned supervisor role and warehouse-scoped access design | Security hardening note: protected API engines must include `assets/utils/db_auth.php`, must reject unauthenticated sessions server-side, and must define role requirements with `require_role()` where the action is not viewer-safe.