Inventory Management System - API Documentation
A comprehensive RESTful API for managing inventory, suppliers, purchase orders, and stock movements. Built with Node.js, Express.js, and Sequelize ORM with support for MySQL and PostgreSQL databases.
📋 Table of Contents
Inventory Management System - API Documentation
A comprehensive RESTful API for managing inventory, suppliers, purchase orders, and stock movements. Built with Node.js, Express.js, and Sequelize ORM with support for MySQL and PostgreSQL databases.
📋 Table of Contents
- Features
- Tech Stack
- Prerequisites
- Installation
- Configuration
- Database Setup
- Running the Application
- API Endpoints
- Request & Response Examples
- Error Handling
- Database Schema
- Project Structure
- Development
- Testing
- Deployment
- Contributing
- License
✨ Features
Core Functionality
- ✅ User Authentication & Authorization - JWT-based secure login system
- ✅ Role-Based Access Control - Admin, Manager, and Staff roles
- ✅ Product Management - Complete CRUD operations for inventory items
- ✅ Supplier Management - Manage supplier information and relationships
- ✅ Purchase Order Processing - Create and track purchase orders
- ✅ Stock Movement Tracking - Complete audit trail of all inventory changes
- ✅ Dashboard Analytics - Real-time statistics and insights
- ✅ Automatic Stock Status - Auto-update stock levels (In Stock/Low Stock/Out of Stock)
Advanced Features
- 🔐 Secure Authentication - Password hashing with bcrypt, JWT tokens
- 👥 User Management - Admin can create, update, and manage users
- 🔄 Transaction Support - Database transactions for data integrity
- 📊 Analytics & Reporting - Stock trends and category distribution
- 🔍 Advanced Filtering - Search, filter, and sort capabilities
- 📄 Pagination - Efficient data loading for large datasets
- 🔗 Relational Data - Proper foreign key relationships
- 📝 Audit Trail - Track all stock movements with reasons and references
🛠 Tech Stack
| Technology | Purpose |
|---|---|
| Node.js | Runtime environment |
| Express.js | Web framework |
| Sequelize | ORM for database operations |
| MySQL / PostgreSQL | Database options |
| JWT | JSON Web Tokens for authentication |
| bcryptjs | Password hashing |
| dotenv | Environment variable management |
| CORS | Cross-origin resource sharing |
| Morgan | HTTP request logger |
| express-validator | Request validation |
📋 Prerequisites
Before you begin, ensure you have the following installed:
- Node.js (v18 or higher) - Download
- npm (v9 or higher) - Comes with Node.js
- MySQL (v8.0+) OR PostgreSQL (v14+) - MySQL | PostgreSQL
- Git (optional) - For version control
Check your installations:
node --version # Should show v18.x.x or higher
npm --version # Should show v9.x.x or higher
mysql --version # OR psql --version
🚀 Installation
Step 1: Clone or Create Project
Option A: Clone from repository
git clone https://github.com/rostamsadiqi/inventory-backend-api-nodejs.git
cd inventory-backend
Option B: Create manually
mkdir inventory-backend
cd inventory-backend
Step 2: Install Dependencies
npm install
This will install:
- express (^4.18.2)
- sequelize (^6.35.2)
- mysql2 (^3.7.0) OR pg (^8.11.3)
- bcryptjs (^2.4.3)
- jsonwebtoken (^9.0.2)
- dotenv (^16.3.1)
- cors (^2.8.5)
- express-validator (^7.0.1)
- morgan (^1.10.0)
- nodemon (^3.0.2) - Dev dependency
⚙️ Configuration
Environment Variables
Create a .env file in the root directory:
cp .env.example .env
For MySQL:
NODE_ENV=development
PORT=5000
# Database Configuration
DB_HOST=localhost
DB_PORT=3306
DB_NAME=inventory_db
DB_USER=root
DB_PASSWORD=your_mysql_password
DB_DIALECT=mysql
# JWT Configuration
JWT_SECRET=your_super_secret_jwt_key_change_this_in_production
JWT_EXPIRE=7d
# Initial Admin User
ADMIN_EMAIL=admin@inventory.com
ADMIN_PASSWORD=Admin@123
For PostgreSQL:
NODE_ENV=development
PORT=5000
# Database Configuration
DB_HOST=localhost
DB_PORT=5432
DB_NAME=inventory_db
DB_USER=postgres
DB_PASSWORD=your_postgres_password
DB_DIALECT=postgres
# JWT Configuration
JWT_SECRET=your_super_secret_jwt_key_change_this_in_production
JWT_EXPIRE=7d
Environment Variables Reference
| Variable | Description | Default | Required |
|---|---|---|---|
NODE_ENV | Environment mode | development | Yes |
PORT | Server port | 5000 | Yes |
DB_HOST | Database host | localhost | Yes |
DB_PORT | Database port | 3306 (MySQL) | Yes |
DB_NAME | Database name | inventory_db | Yes |
DB_USER | Database username | root | Yes |
DB_PASSWORD | Database password | - | Yes |
DB_DIALECT | Database type | mysql | Yes |
JWT_SECRET | Secret key for JWT | - | Yes |
JWT_EXPIRE | Token expiration time | 7d | Yes |
ADMIN_EMAIL | Initial admin email | - | No |
ADMIN_PASSWORD | Initial admin password | - | No |
💾 Database Setup
MySQL Setup
- Login to MySQL:
mysql -u root -p
- Create Database:
CREATE DATABASE inventory_db;
- Create User (Optional):
CREATE USER 'inventory_user'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON inventory_db.* TO 'inventory_user'@'localhost';
FLUSH PRIVILEGES;
PostgreSQL Setup
- Login to PostgreSQL:
psql -U postgres
- Create Database:
CREATE DATABASE inventory_db;
- Create User (Optional):
CREATE USER inventory_user WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE inventory_db TO inventory_user;
Database Tables
The application will automatically create these tables on first run:
users- User accounts and authenticationcategories- Product categoriessuppliers- Supplier informationproducts- Inventory itemspurchase_orders- Purchase ordersorder_items- Order line itemsstock_movements- Stock change audit trail
🏃 Running the Application
Development Mode (with auto-reload)
npm run dev
Production Mode
npm start
Seed Database (Optional)
Populate database with sample data:
npm run seed
Create Initial Admin User
npm run create-admin
This will create an admin user with credentials from your .env file:
- Email:
ADMIN_EMAIL(default: admin@inventory.com) - Password:
ADMIN_PASSWORD(default: Admin@123)
⚠️ Important: Change the admin password after first login!
Verify Server is Running
You should see:
Database connection established successfully.
Database synchronized.
Server is running on port 5000
Test the health endpoint:
curl http://localhost:5000/api/health
Expected response:
{
"success": true,
"message": "Server is running"
}
📡 API Endpoints
Base URL
http://localhost:5000/api
🔐 Authentication
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /auth/register | Register new user | No |
| POST | /auth/login | Login user | No |
| GET | /auth/profile | Get current user profile | Yes |
| PUT | /auth/profile | Update user profile | Yes |
| PUT | /auth/change-password | Change password | Yes |
| POST | /auth/logout | Logout user | Yes |
👥 User Management
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /users | Get all users | Admin |
| GET | /users/:id | Get single user | Admin |
| POST | /users | Create new user | Admin |
| PUT | /users/:id | Update user | Admin |
| DELETE | /users/:id | Delete user | Admin |
| PATCH | /users/:id/toggle-status | Toggle user active status | Admin |
Query Parameters for GET /users:
search- Search by name or emailrole- Filter by role (admin, manager, staff)isActive- Filter by active status (true/false)page- Page number (default: 1)limit- Items per page (default: 10)
User Roles:
admin- Full access to all featuresmanager- Can manage products, orders, and view reportsstaff- Can view and update inventory
📁 Categories
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /categories | Get all categories | No |
| GET | /categories/:id | Get single category | No |
| GET | /categories/stats | Get category statistics | No |
| POST | /categories | Create new category | No |
| PUT | /categories/:id | Update category | No |
| DELETE | /categories/:id | Delete category | No |
Query Parameters for GET /categories:
search- Search by category nameincludeProducts- Include products in response (true/false)
📦 Products
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /products | Get all products with filters | No |
| GET | /products/:id | Get single product by ID | No |
| POST | /products | Create new product | No |
| PUT | /products/:id | Update product | No |
| DELETE | /products/:id | Delete product | No |
| POST | /products/stock/update | Update product stock | No |
Query Parameters for GET /products:
search- Search by name or SKUstatus- Filter by status (In Stock, Low Stock, Out of Stock)categoryId- Filter by categorysupplierId- Filter by supplierpage- Page number (default: 1)limit- Items per page (default: 10)
👥 Suppliers
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /suppliers | Get all suppliers | No |
| GET | /suppliers/:id | Get single supplier | No |
| POST | /suppliers | Create new supplier | No |
| PUT | /suppliers/:id | Update supplier | No |
| DELETE | /suppliers/:id | Delete supplier | No |
Query Parameters for GET /suppliers:
search- Search by name or contact personisActive- Filter by active status (true/false)
📋 Purchase Orders
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /purchase-orders | Get all purchase orders | No |
| GET | /purchase-orders/:id | Get single order | No |
| POST | /purchase-orders | Create new order | No |
| PUT | /purchase-orders/:id/status | Update order status | No |
| DELETE | /purchase-orders/:id | Delete order | No |
Query Parameters for GET /purchase-orders:
status- Filter by status (Pending, Processing, Shipped, Delivered, Cancelled)supplierId- Filter by supplier
📊 Dashboard
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /dashboard/statistics | Get dashboard statistics | No |
| GET | /dashboard/stock-trends | Get stock level trends | No |
| GET | /dashboard/category-distribution | Get category distribution | No |
| GET | /dashboard/recent-movements | Get recent stock movements | No |
📝 Request & Response Examples
1. Register User
Request:
POST /api/auth/register
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"password": "Password123",
"role": "staff",
"phone": "+1-555-1234"
}
Response: 201 Created
{
"success": true,
"message": "User registered successfully",
"data": {
"user": {
"id": 1,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "staff",
"phone": "+1-555-1234",
"isActive": true
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
2. Login User
Request:
POST /api/auth/login
Content-Type: application/json
{
"email": "john@example.com",
"password": "Password123"
}
Response: 200 OK
{
"success": true,
"message": "Login successful",
"data": {
"user": {
"id": 1,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "staff",
"lastLogin": "2024-01-12T10:30:00.000Z"
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
3. Get User Profile (Protected)
Request:
GET /api/auth/profile
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Response: 200 OK
{
"success": true,
"data": {
"id": 1,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"role": "staff",
"phone": "+1-555-1234",
"isActive": true,
"lastLogin": "2024-01-12T10:30:00.000Z"
}
}
4. Change Password
Request:
PUT /api/auth/change-password
Authorization: Bearer <token>
Content-Type: application/json
{
"currentPassword": "Password123",
"newPassword": "NewPassword456"
}
Response: 200 OK
{
"success": true,
"message": "Password changed successfully"
}
5. Get All Users (Admin Only)
Request:
GET /api/users?page=1&limit=10&role=staff
Authorization: Bearer <admin_token>
Response: 200 OK
{
"success": true,
"data": [
{
"id": 2,
"firstName": "Jane",
"lastName": "Smith",
"email": "jane@example.com",
"role": "staff",
"isActive": true
}
],
"pagination": {
"total": 1,
"page": 1,
"limit": 10,
"total_pages": 1
}
}
6. Create Category
Request:
POST /api/categories
Content-Type: application/json
{
"name": "Electronics",
"description": "Electronic devices and accessories"
}
Response: 201 Created
{
"success": true,
"message": "Category created successfully",
"data": {
"id": 1,
"name": "Electronics",
"description": "Electronic devices and accessories",
"createdAt": "2024-01-11T10:30:00.000Z",
"updatedAt": "2024-01-11T10:30:00.000Z"
}
}
2. Get All Categories
Request:
GET /api/categories
Response: 200 OK
{
"success": true,
"data": [
{
"id": 1,
"name": "Electronics",
"description": "Electronic devices and accessories"
},
{
"id": 2,
"name": "Office Supplies",
"description": "Office furniture and supplies"
}
],
"count": 2
}
3. Get Categories with Products
Request:
GET /api/categories?includeProducts=true
Response: 200 OK
{
"success": true,
"data": [
{
"id": 1,
"name": "Electronics",
"description": "Electronic devices",
"products": [
{
"id": 1,
"name": "Wireless Mouse",
"sku": "PRD-001",
"quantity": 100,
"status": "In Stock"
}
]
}
],
"count": 1
}
4. Get Category Statistics
Request:
GET /api/categories/stats
Response: 200 OK
{
"success": true,
"data": [
{
"id": 1,
"name": "Electronics",
"productCount": 10,
"totalQuantity": 500,
"totalValue": 15000.50,
"inStock": 8,
"lowStock": 2,
"outOfStock": 0
}
]
}
5. Update Category
Request:
PUT /api/categories/1
Content-Type: application/json
{
"name": "Electronics & Gadgets",
"description": "Updated description for electronics"
}
Response: 200 OK
{
"success": true,
"message": "Category updated successfully",
"data": {
"id": 1,
"name": "Electronics & Gadgets",
"description": "Updated description for electronics",
"updatedAt": "2024-01-11T11:00:00.000Z"
}
}
6. Delete Category
Request:
DELETE /api/categories/2
Response (Success): 200 OK
{
"success": true,
"message": "Category deleted successfully"
}
Response (Has Products): 400 Bad Request
{
"success": false,
"message": "Cannot delete category. It has 5 product(s) associated with it. Please reassign or delete the products first."
}
12. Create Product (Protected)
Request:
POST /api/products
Authorization: Bearer <token>
Content-Type: application/json
{
"sku": "PRD-001",
"name": "Wireless Mouse",
"description": "Ergonomic wireless mouse with USB receiver",
"categoryId": 1,
"supplierId": 1,
"quantity": 100,
"reorderLevel": 20,
"price": 29.99,
"costPrice": 15.00
}
7. Create Product
Request:
POST /api/products
Content-Type: application/json
{
"sku": "PRD-001",
"name": "Wireless Mouse",
"description": "Ergonomic wireless mouse with USB receiver",
"categoryId": 1,
"supplierId": 1,
"quantity": 100,
"reorderLevel": 20,
"price": 29.99,
"costPrice": 15.00
}
Response: 201 Created
{
"success": true,
"data": {
"id": 1,
"sku": "PRD-001",
"name": "Wireless Mouse",
"description": "Ergonomic wireless mouse with USB receiver",
"categoryId": 1,
"supplierId": 1,
"quantity": 100,
"reorderLevel": 20,
"price": "29.99",
"costPrice": "15.00",
"status": "In Stock",
"createdAt": "2024-01-11T10:30:00.000Z",
"updatedAt": "2024-01-11T10:30:00.000Z"
}
}
13. Get All Products with Filters
Request:
GET /api/products?search=mouse&status=In Stock&page=1&limit=10
Response: 200 OK
{
"success": true,
"data": [
{
"id": 1,
"sku": "PRD-001",
"name": "Wireless Mouse",
"quantity": 100,
"reorderLevel": 20,
"price": "29.99",
"status": "In Stock",
"category": {
"id": 1,
"name": "Electronics"
},
"supplier": {
"id": 1,
"name": "TechSupply Co.",
"contactPerson": "John Smith"
}
}
],
"pagination": {
"total": 1,
"page": 1,
"limit": 10,
"total_pages": 1
}
}
14. Create Supplier
Request:
POST /api/suppliers
Content-Type: application/json
{
"name": "TechSupply Co.",
"contactPerson": "John Smith",
"email": "john@techsupply.com",
"phone": "+1-555-0123",
"address": "123 Tech Street, Silicon Valley, CA 94025",
"rating": 4.8,
"isActive": true
}
Response: 201 Created
{
"success": true,
"data": {
"id": 1,
"name": "TechSupply Co.",
"contactPerson": "John Smith",
"email": "john@techsupply.com",
"phone": "+1-555-0123",
"address": "123 Tech Street, Silicon Valley, CA 94025",
"rating": "4.8",
"isActive": true,
"createdAt": "2024-01-11T10:30:00.000Z",
"updatedAt": "2024-01-11T10:30:00.000Z"
}
}
15. Create Purchase Order
Request:
POST /api/purchase-orders
Content-Type: application/json
{
"supplierId": 1,
"expectedDeliveryDate": "2024-02-15",
"items": [
{
"productId": 1,
"quantity": 50,
"unitPrice": 15.00
},
{
"productId": 2,
"quantity": 100,
"unitPrice": 6.00
}
],
"notes": "Urgent order for Q1 inventory"
}
Response: 201 Created
{
"success": true,
"data": {
"id": 1,
"orderNumber": "PO-2024-0001",
"supplierId": 1,
"orderDate": "2024-01-11T10:30:00.000Z",
"expectedDeliveryDate": "2024-02-15T00:00:00.000Z",
"status": "Pending",
"totalAmount": "1350.00",
"notes": "Urgent order for Q1 inventory",
"supplier": {
"id": 1,
"name": "TechSupply Co.",
"contactPerson": "John Smith"
},
"items": [
{
"id": 1,
"productId": 1,
"quantity": 50,
"unitPrice": "15.00",
"totalPrice": "750.00",
"product": {
"id": 1,
"name": "Wireless Mouse",
"sku": "PRD-001"
}
},
{
"id": 2,
"productId": 2,
"quantity": 100,
"unitPrice": "6.00",
"totalPrice": "600.00",
"product": {
"id": 2,
"name": "USB-C Cable",
"sku": "PRD-002"
}
}
]
}
}
16. Update Stock
Request:
POST /api/products/stock/update
Content-Type: application/json
{
"productId": 1,
"quantity": 10,
"movementType": "OUT",
"reason": "Sold to customer - Invoice #12345"
}
Response: 200 OK
{
"success": true,
"data": {
"id": 1,
"sku": "PRD-001",
"name": "Wireless Mouse",
"quantity": 90,
"status": "In Stock",
"updatedAt": "2024-01-11T10:35:00.000Z"
}
}
17. Update Purchase Order Status
Request:
PUT /api/purchase-orders/1/status
Content-Type: application/json
{
"status": "Delivered"
}
Response: 200 OK
{
"success": true,
"data": {
"id": 1,
"orderNumber": "PO-2024-0001",
"status": "Delivered",
"actualDeliveryDate": "2024-01-11T10:40:00.000Z"
}
}
Note: When status is set to "Delivered", product quantities are automatically updated.
18. Get Dashboard Statistics
Request:
GET /api/dashboard/statistics
Response: 200 OK
{
"success": true,
"data": {
"totalProducts": 156,
"lowStockItems": 12,
"outOfStockItems": 3,
"activeSuppliers": 8,
"totalValue": 45623.50,
"recentOrders": 15
}
}
⚠️ Error Handling
Error Response Format
All errors follow this structure:
{
"success": false,
"message": "Error description",
"errors": [
{
"field": "fieldName",
"message": "Specific error message"
}
]
}
HTTP Status Codes
| Code | Description | Example |
|---|---|---|
| 200 | Success | Data retrieved successfully |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Validation error, invalid data |
| 404 | Not Found | Resource not found |
| 500 | Server Error | Database error, server issue |
Common Error Examples
Authentication Error (401):
{
"success": false,
"message": "Not authorized to access this route. Please login."
}
Invalid Token (401):
{
"success": false,
"message": "Invalid or expired token"
}
Forbidden Access (403):
{
"success": false,
"message": "User role 'staff' is not authorized to access this route"
}
Validation Error (400):
{
"success": false,
"message": "Validation error",
"errors": [
{
"field": "email",
"message": "Validation isEmail on email failed"
}
]
}
Not Found (404):
{
"success": false,
"message": "Product not found"
}
Duplicate Entry (400):
{
"success": false,
"message": "Duplicate entry",
"errors": [
{
"field": "sku",
"message": "sku must be unique"
}
]
}
Insufficient Stock (400):
{
"success": false,
"message": "Insufficient stock"
}
🗄️ Database Schema
Entity Relationship Diagram
┌─────────────┐
│ User │
├─────────────┤
│ id (PK) │
│ firstName │
│ lastName │
│ email │
│ password │
│ role (ENUM) │
│ isActive │
└─────────────┘
┌─────────────┐ ┌─────────────┐
│ Category │ │ Supplier │
├─────────────┤ ├─────────────┤
│ id (PK) │ │ id (PK) │
│ name │ │ name │
│ description │ │ contact │
└─────┬───────┘ │ email │
│ │ phone │
│ │ rating │
│ └──────┬──────┘
│ │
│ │
┌─────▼──────────────────────▼───┐
│ Product │
├────────────────────────────────┤
│ id (PK) │
│ sku (UNIQUE) │
│ name │
│ categoryId (FK) ───────────────┤
│ supplierId (FK) ───────────────┤
│ quantity │
│ reorderLevel │
│ price │
│ status (ENUM) │
└────────┬───────────────────────┘
│
│
┌────▼─────────┐ ┌──────────────┐
│ OrderItem │ │ StockMovement│
├──────────────┤ ├──────────────┤
│ id (PK) │ │ id (PK) │
│ productId(FK)│◄──────┤ productId(FK)│
│ orderId (FK) │ │ type (ENUM) │
│ quantity │ │ quantity │
│ unitPrice │ │ reason │
└────┬─────────┘ └──────────────┘
│
┌────▼──────────┐
│ PurchaseOrder │
├───────────────┤
│ id (PK) │
│ orderNumber │
│ supplierId(FK)│
│ status (ENUM) │
│ totalAmount │
└───────────────┘
Table Details
Users
id- Auto-increment primary keyfirstName- User’s first namelastName- User’s last nameemail- Unique email address (validated)password- Hashed password (bcrypt)role- ENUM: admin, manager, staffphone- Phone numberisActive- Active status (boolean)lastLogin- Last login timestamprefreshToken- JWT refresh tokencreatedAt,updatedAt- Timestamps
Categories
id- Auto-increment primary keyname- Unique category namedescription- Optional descriptioncreatedAt,updatedAt- Timestamps
Suppliers
id- Auto-increment primary keyname- Supplier company namecontactPerson- Contact person nameemail- Email address (validated)phone- Phone numberaddress- Physical addressrating- Supplier rating (0.0-5.0)isActive- Active status (boolean)createdAt,updatedAt- Timestamps
Products
id- Auto-increment primary keysku- Unique stock keeping unitname- Product namedescription- Product descriptioncategoryId- Foreign key to categoriessupplierId- Foreign key to suppliersquantity- Current stock quantityreorderLevel- Minimum stock thresholdprice- Selling pricecostPrice- Purchase coststatus- ENUM: In Stock, Low Stock, Out of StockcreatedAt,updatedAt- Timestamps
Purchase Orders
id- Auto-increment primary keyorderNumber- Unique order number (auto-generated)supplierId- Foreign key to suppliersorderDate- Date order was createdexpectedDeliveryDate- Expected arrival dateactualDeliveryDate- Actual delivery datestatus- ENUM: Pending, Processing, Shipped, Delivered, CancelledtotalAmount- Total order valuenotes- Additional notescreatedAt,updatedAt- Timestamps
Order Items
id- Auto-increment primary keypurchaseOrderId- Foreign key to purchase_ordersproductId- Foreign key to productsquantity- Quantity orderedunitPrice- Price per unittotalPrice- Calculated total (quantity × unitPrice)createdAt,updatedAt- Timestamps
Stock Movements
id- Auto-increment primary keyproductId- Foreign key to productsmovementType- ENUM: IN, OUT, ADJUSTMENTquantity- Amount movedpreviousQuantity- Stock before movementnewQuantity- Stock after movementreason- Reason for movementreferenceId- Reference to related entity (e.g., order ID)movementDate- Date of movementcreatedAt,updatedAt- Timestamps
📁 Project Structure
inventory-backend/
├── config/
│ └── database.js # Database configuration
├── models/
│ ├── index.js # Model associations
│ ├── User.js # User model
│ ├── Category.js # Category model
│ ├── Supplier.js # Supplier model
│ ├── Product.js # Product model
│ ├── PurchaseOrder.js # Purchase order model
│ ├── OrderItem.js # Order items model
│ └── StockMovement.js # Stock movement model
├── controllers/
│ ├── authController.js # Authentication logic
│ ├── userController.js # User management logic
│ ├── categoryController.js # Category business logic
│ ├── productController.js # Product business logic
│ ├── supplierController.js # Supplier business logic
│ ├── purchaseOrderController.js # Order business logic
│ └── dashboardController.js # Dashboard analytics
├── routes/
│ ├── authRoutes.js # Auth endpoints
│ ├── userRoutes.js # User endpoints
│ ├── categoryRoutes.js # Category endpoints
│ ├── productRoutes.js # Product endpoints
│ ├── supplierRoutes.js # Supplier endpoints
│ ├── purchaseOrderRoutes.js # Order endpoints
│ └── dashboardRoutes.js # Dashboard endpoints
├── Middleware
│ ├── auth.js # JWT authentication
│ ├── errorHandler.js # Global error handler
│ └── validation.js # Request validation
├── utils/
│ └── helpers.js # Helper functions
├── scripts/
│ ├── seedData.js # Database seeding script
│ └── createAdmin.js # Create admin user script
├── .env # Environment variables (not in git)
├── .env.example # Environment template
├── .gitignore # Git ignore rules
├── package.json # Dependencies
├── README.md # This file
└── server.js # Application entry point
🔧 Development
Code Style
- Use camelCase for variables and functions
- Use PascalCase for model names
- Use async/await for asynchronous operations
- Always use try-catch blocks for error handling
- Follow REST conventions for API endpoints
Adding New Features
- Create Model in
models/directory - Add Associations in
models/index.js - Create Controller in
controllers/directory - Define Routes in
routes/directory - Register Routes in
server.js - Test using Postman or curl
- Update this README
Debugging
Enable detailed SQL logging:
// In config/database.js
logging: console.log // Shows all SQL queries
🧪 Testing
Manual Testing with cURL
Health Check:
curl http://localhost:5000/api/health
Authentication:
# Register user
curl -X POST http://localhost:5000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"password": "Password123",
"role": "staff"
}'
# Login
curl -X POST http://localhost:5000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "john@example.com",
"password": "Password123"
}'
# Get profile (use token from login)
curl http://localhost:5000/api/auth/profile \
-H "Authorization: Bearer YOUR_TOKEN_HERE"
# Change password
curl -X PUT http://localhost:5000/api/auth/change-password \
-H "Authorization: Bearer YOUR_TOKEN_HERE" \
-H "Content-Type: application/json" \
-d '{
"currentPassword": "Password123",
"newPassword": "NewPassword456"
}'
Categories:
# Get all categories
curl http://localhost:5000/api/categories
# Get categories with products
curl http://localhost:5000/api/categories?includeProducts=true
# Get category statistics
curl http://localhost:5000/api/categories/stats
# Create category
curl -X POST http://localhost:5000/api/categories \
-H "Content-Type: application/json" \
-d '{
"name": "Electronics",
"description": "Electronic devices and accessories"
}'
# Update category
curl -X PUT http://localhost:5000/api/categories/1 \
-H "Content-Type: application/json" \
-d '{
"name": "Electronics & Gadgets",
"description": "Updated description"
}'
# Delete category
curl -X DELETE http://localhost:5000/api/categories/1
Products:
# Get all products
curl http://localhost:5000/api/products
# Create product
curl -X POST http://localhost:5000/api/products \
-H "Content-Type: application/json" \
-d '{
"sku": "TEST-001",
"name": "Test Product",
"categoryId": 1,
"supplierId": 1,
"quantity": 10,
"reorderLevel": 5,
"price": 99.99
}'
Using Postman
- Import the API endpoints
- Set base URL to
http://localhost:5000/api - Test each endpoint with sample data
🚀 Deployment
Production Checklist
- Set
NODE_ENV=productionin.env - Use strong database passwords
- Configure proper CORS settings
- Set up SSL/TLS certificates
- Enable database connection pooling
- Set up logging (Winston, Morgan)
- Configure rate limiting
- Set up monitoring (PM2, New Relic)
- Create database backups
- Use environment-specific configs
Deployment Options
Option 1: Traditional Server (VPS)
# Install PM2
npm install -g pm2
# Start application
pm2 start server.js --name inventory-api
# Monitor
pm2 monit
Option 2: Docker
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 5000
CMD ["node", "server.js"]
Option 3: Cloud Platforms
- Heroku - Easy deployment with Git
- AWS - EC2, Elastic Beanstalk, or Lambda
- DigitalOcean - App Platform or Droplet
- Railway - Simple deployment from GitHub
🤝 Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
📄 License
This project is licensed under the MIT License.
MIT License
Copyright (c) 2024
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT limitED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
📞 Support
For questions or issues:
- Create an issue in the repository
- Email: support@example.com
- Documentation: Wiki
🙏 Acknowledgments
- Express.js team for the excellent web framework
- Sequelize team for the powerful ORM
- Node.js community for continuous support
Built with ❤️ using Node.js, Express, and Sequelize
📚 Additional Resources
- Express.js Documentation
- Sequelize Documentation
- MySQL Documentation
- PostgreSQL Documentation
- REST API Best Practices
Last Updated: January 12, 2024 Version: 1.0.1