7.5 KiB
7.5 KiB
📦 Complete Inventory Management System - Implementation Guide
What You Get
✅ Auto Stock Reduction - Stock reduces when order delivered
✅ Low Stock Alerts - Dashboard shows products needing restock
✅ Real Top Sellers - Based on actual sales, not fake data
✅ Inventory Logs - Track every stock change
✅ Stock Status - OUT_OF_STOCK, CRITICAL, LOW, IN_STOCK
🚀 Setup (5 Steps)
Step 1: Update Prisma Schema
Add this to your schema.prisma:
model InventoryLog {
id String @id @default(cuid())
productId String
productName String
type InventoryLogType
quantityChange Int
previousStock Int
newStock Int
orderId String?
adjustedBy String?
notes String?
createdAt DateTime @default(now())
@@index([productId])
@@index([orderId])
@@index([type])
@@map("inventory_logs")
}
enum InventoryLogType {
SOLD
RESTOCK
ADJUSTMENT
RETURN
DAMAGED
}
Step 2: Run Migration
npx prisma migrate dev --name add_inventory_logs
Step 3: Add Inventory Service
Create src/services/inventoryService.js with the provided code.
Step 4: Update Order Controller
Replace your order controller with the version that includes auto stock reduction.
Step 5: Update Dashboard Controller
Replace dashboard controller to show real top sellers + low stock alerts.
📊 Dashboard API Response
{
"data": {
"totalUsers": 150,
"totalOrders": 450,
"totalProducts": 89,
"totalRevenue": 125000,
"inventory": {
"totalProducts": 89,
"outOfStock": 5,
"criticalStock": 8,
"lowStock": 12,
"inStock": 64
},
"topProducts": [
{
"_id": "prod123",
"name": "Rare Rabbit",
"basePrice": 2500,
"totalSold": 45,
"totalOrders": 32,
"revenue": 112500,
"stock": 12,
"stockStatus": "LOW",
"displayImage": "https://..."
}
],
"lowStockProducts": [
{
"_id": "prod456",
"name": "Product Name",
"stock": 3,
"status": "CRITICAL",
"basePrice": 1500,
"displayImage": "https://..."
}
]
}
}
⚙️ How Auto Stock Reduction Works
When Admin Updates Order to DELIVERED:
1. Admin: PUT /api/admin/orders/:id/status
Body: { "status": "DELIVERED" }
2. Order Controller:
✅ Updates order status
✅ Creates status history
✅ Calls reduceStockOnDelivery()
3. Inventory Service:
✅ Gets order items
✅ For each item:
- Get product from MongoDB
- Calculate: newStock = currentStock - quantity
- Update product.stock in MongoDB
- Create inventory log in PostgreSQL
4. Response:
{
"success": true,
"message": "Order status updated",
"stockReduction": [
{
"productName": "Rare Rabbit",
"reduced": 1,
"previousStock": 15,
"newStock": 14
}
]
}
📋 Inventory Log Example
Every stock change creates a log:
{
"id": "log123",
"productId": "prod456",
"productName": "Rare Rabbit",
"type": "SOLD",
"quantityChange": -1,
"previousStock": 15,
"newStock": 14,
"orderId": "order789",
"notes": "Order ORD1234567 delivered",
"createdAt": "2026-02-11T14:30:00.000Z"
}
🎯 Stock Status Logic
stock === 0 → OUT_OF_STOCK (Red)
stock <= 5 → CRITICAL (Orange)
stock <= 10 → LOW (Yellow)
stock > 10 → IN_STOCK (Green)
📊 Top Selling Products Logic
OLD (Wrong):
// ❌ Used purchaseCount from MongoDB (never updated)
Product.find().sort({ purchaseCount: -1 })
NEW (Correct):
// ✅ Query actual order data from PostgreSQL
SELECT productId, SUM(quantity), COUNT(*)
FROM order_items
GROUP BY productId
ORDER BY SUM(quantity) DESC
// ✅ Join with MongoDB for product details
// ✅ Add stock info
// ✅ Calculate revenue
🎨 Frontend Display
Dashboard - Top Sellers
{topProducts.map(product => (
<div key={product._id} className="flex items-center gap-4 p-4 bg-white rounded-lg shadow">
<img src={product.displayImage} className="w-16 h-16 rounded" />
<div className="flex-1">
<h3 className="font-bold">{product.name}</h3>
<div className="flex items-center gap-4 text-sm text-gray-600">
<span>Sold: {product.totalSold}</span>
<span>Revenue: ₹{product.revenue.toLocaleString()}</span>
<span className={`px-2 py-1 rounded text-xs ${
product.stockStatus === 'OUT_OF_STOCK' ? 'bg-red-100 text-red-800' :
product.stockStatus === 'CRITICAL' ? 'bg-orange-100 text-orange-800' :
product.stockStatus === 'LOW' ? 'bg-yellow-100 text-yellow-800' :
'bg-green-100 text-green-800'
}`}>
{product.stock} in stock
</span>
</div>
</div>
</div>
))}
Dashboard - Low Stock Alerts
{lowStockProducts.length > 0 && (
<div className="bg-orange-50 border border-orange-200 rounded-lg p-6">
<h3 className="text-lg font-bold text-orange-900 mb-4">
⚠️ Low Stock Alert ({lowStockProducts.length})
</h3>
<div className="space-y-3">
{lowStockProducts.map(product => (
<div key={product._id} className="flex items-center justify-between p-3 bg-white rounded">
<div className="flex items-center gap-3">
<img src={product.displayImage} className="w-12 h-12 rounded" />
<div>
<p className="font-semibold">{product.name}</p>
<p className="text-sm text-gray-600">
{product.stock === 0 ? 'Out of Stock' : `Only ${product.stock} left`}
</p>
</div>
</div>
<button className="px-4 py-2 bg-orange-600 text-white rounded">
Restock
</button>
</div>
))}
</div>
</div>
)}
🔧 Manual Stock Adjustment (Future)
// POST /api/admin/inventory/adjust
{
"productId": "prod123",
"quantity": 50,
"type": "ADD", // ADD, REMOVE, SET
"notes": "Received new shipment"
}
📈 Benefits
- Accurate Inventory - Always know real stock levels
- Prevent Overselling - Stock reduces on delivery
- Early Warnings - Low stock alerts
- Better Planning - See what's selling
- Full Audit Trail - Every change logged
- Automated - No manual work needed
✅ Testing Checklist
- Prisma migration ran successfully
- Place test order
- Mark order as DELIVERED
- Check product stock reduced
- Check inventory log created
- Dashboard shows correct stock
- Low stock products appear
- Top sellers show real data
🎯 What Happens
Before (Old System):
Order Delivered → Nothing happens
Stock: Always same (never changes)
Top Products: Fake/old data
Dashboard: No inventory info
After (New System):
Order Delivered → Auto stock reduction
Stock: Real-time accurate
Top Products: Based on actual sales
Dashboard: Full inventory overview
Alerts: Low stock warnings
Logs: Complete audit trail
Your inventory system is now production-ready! 📦✨