# 🎟️ Complete Coupon System Guide ## 📦 What's Included ### Backend 1. **Admin Coupon Controller** - Full CRUD + Statistics 2. **User Coupon Controller** - Validation & Application 3. **Coupon Routes** - Both admin and user endpoints ### Frontend 1. **CouponApply Component** - For checkout page 2. **Available Coupons Modal** - Browse & select coupons --- ## 🚀 Setup Instructions ### Step 1: Backend Setup #### 1.1 Add Controllers Create two controller files: **File 1:** `src/controllers/admin/couponController.js` (Use the `couponController_Admin.js` file) **File 2:** `src/controllers/couponController.js` (Use the `couponController_User.js` file) #### 1.2 Add Routes Create: `src/routes/couponRoutes.js` (Use the `couponRoutes.js` file) #### 1.3 Register Routes in App In your `server.js` or `app.js`: ```javascript const couponRoutes = require('./routes/couponRoutes'); app.use('/api/coupons', couponRoutes); ``` --- ### Step 2: Frontend Setup #### 2.1 Create Component Create: `src/components/CouponApply.jsx` (Use the `CouponApply.jsx` file) #### 2.2 Use in Checkout Page ```javascript // pages/Checkout.jsx import CouponApply from '../components/CouponApply'; import { useState } from 'react'; const Checkout = () => { const [appliedCoupon, setAppliedCoupon] = useState(null); const [orderTotal, setOrderTotal] = useState(2599); const handleCouponApplied = (couponData) => { setAppliedCoupon(couponData); setOrderTotal(couponData.finalAmount); }; const handleCouponRemoved = () => { setAppliedCoupon(null); setOrderTotal(2599); // Reset to original amount }; return (
{/* Cart Items */} {/* Coupon Section */} {/* Order Summary */}
Subtotal: ₹2,599
{appliedCoupon && (
Discount ({appliedCoupon.couponCode}): -₹{appliedCoupon.discountAmount}
)}
Total: ₹{orderTotal.toLocaleString()}
); }; ``` --- ## 📡 API Endpoints ### Admin Endpoints #### 1. Get All Coupons ```http GET /api/coupons/admin?page=1&limit=20&isActive=true&type=PERCENTAGE&search=SAVE Authorization: Bearer ``` **Response:** ```json { "status": true, "message": "Coupons fetched successfully", "data": { "coupons": [ { "id": "...", "code": "SAVE20", "description": "20% off on all items", "type": "PERCENTAGE", "value": 20, "minOrderAmount": 1000, "maxUses": 100, "usedCount": 25, "usagePercentage": 25, "isExpired": false, "remainingUses": 75, "isActive": true, "validFrom": "2024-01-01", "validUntil": "2024-12-31" } ], "pagination": { "total": 50, "page": 1, "limit": 20, "pages": 3 } } } ``` #### 2. Create Coupon ```http POST /api/coupons/admin Authorization: Bearer Content-Type: application/json { "code": "SAVE20", "description": "Get 20% off on orders above ₹1000", "type": "PERCENTAGE", "value": 20, "minOrderAmount": 1000, "maxUses": 100, "validFrom": "2024-01-01T00:00:00Z", "validUntil": "2024-12-31T23:59:59Z", "isActive": true } ``` **Coupon Types:** - `PERCENTAGE` - Percentage discount (e.g., 20%) - `FIXED_AMOUNT` - Fixed amount off (e.g., ₹500) - `FREE_SHIPPING` - Free shipping #### 3. Update Coupon ```http PUT /api/coupons/admin/:id Authorization: Bearer { "value": 25, "maxUses": 150 } ``` #### 4. Toggle Coupon Status ```http PATCH /api/coupons/admin/:id/toggle Authorization: Bearer ``` #### 5. Get Coupon Statistics ```http GET /api/coupons/admin/stats Authorization: Bearer ``` **Response:** ```json { "status": true, "data": { "totalCoupons": 50, "activeCoupons": 35, "expiredCoupons": 10, "totalRedemptions": 2450, "mostUsedCoupons": [...] } } ``` --- ### User Endpoints #### 1. Get Available Coupons ```http GET /api/coupons/available?orderAmount=2599 ``` **Response:** ```json { "status": true, "data": [ { "code": "SAVE20", "description": "20% off on orders above ₹1000", "type": "PERCENTAGE", "value": 20, "minOrderAmount": 1000, "discountPreview": "20% OFF", "remainingUses": 75, "validUntil": "2024-12-31" } ] } ``` #### 2. Validate Coupon ```http POST /api/coupons/validate Content-Type: application/json { "code": "SAVE20", "orderAmount": 2599 } ``` **Response:** ```json { "status": true, "message": "Coupon applied successfully", "data": { "couponCode": "SAVE20", "couponType": "PERCENTAGE", "discountAmount": 519.80, "originalAmount": 2599, "finalAmount": 2079.20, "savings": 519.80, "savingsPercentage": 20 } } ``` #### 3. Apply Coupon to Order ```http POST /api/coupons/apply Authorization: Bearer { "couponCode": "SAVE20", "orderId": "order_123" } ``` #### 4. Remove Coupon ```http POST /api/coupons/remove Authorization: Bearer { "orderId": "order_123" } ``` --- ## 💡 Usage Examples ### Example 1: Admin Creates Percentage Coupon ```javascript const createCoupon = async () => { const response = await axios.post( 'http://localhost:3000/api/coupons/admin', { code: 'WELCOME10', description: 'Get 10% off on your first order', type: 'PERCENTAGE', value: 10, minOrderAmount: 500, maxUses: 1000, validFrom: new Date(), validUntil: new Date('2024-12-31'), isActive: true, }, { headers: { Authorization: `Bearer ${adminToken}`, }, } ); }; ``` ### Example 2: Admin Creates Fixed Amount Coupon ```javascript { code: 'FLAT500', description: 'Flat ₹500 off on orders above ₹2000', type: 'FIXED_AMOUNT', value: 500, minOrderAmount: 2000, maxUses: 500, validFrom: new Date(), validUntil: new Date('2024-12-31'), } ``` ### Example 3: Admin Creates Free Shipping Coupon ```javascript { code: 'FREESHIP', description: 'Free shipping on all orders', type: 'FREE_SHIPPING', value: 0, minOrderAmount: null, maxUses: null, validFrom: new Date(), validUntil: new Date('2024-12-31'), } ``` ### Example 4: Customer Applies Coupon ```javascript // In your checkout component const [discount, setDiscount] = useState(0); { setDiscount(data.discountAmount); console.log('Saved:', data.savings); }} onCouponRemoved={() => { setDiscount(0); }} /> ``` --- ## 🎨 Coupon Validation Rules ### Automatic Validations 1. **Active Status** - Must be active 2. **Date Range** - Must be within validFrom and validUntil 3. **Usage Limit** - Must have remaining uses 4. **Minimum Order** - Order amount must meet minimum requirement 5. **Code Uniqueness** - Code must be unique (enforced on creation) ### Error Messages ``` ❌ "This coupon is no longer active" ❌ "This coupon is not yet valid" ❌ "This coupon has expired" ❌ "This coupon has reached its usage limit" ❌ "Minimum order amount of ₹1000 required" ❌ "Invalid coupon code" ``` --- ## 📊 Coupon Types Explained ### 1. PERCENTAGE Discount ``` Order Amount: ₹2,599 Coupon: 20% OFF Discount: ₹519.80 Final Amount: ₹2,079.20 ``` ### 2. FIXED_AMOUNT Discount ``` Order Amount: ₹2,599 Coupon: ₹500 OFF Discount: ₹500 Final Amount: ₹2,099 ``` ### 3. FREE_SHIPPING ``` Order Amount: ₹2,599 Shipping: ₹50 Coupon: FREE SHIPPING Discount: ₹50 Final Amount: ₹2,549 ``` --- ## 🔧 Advanced Features ### Feature 1: User-Specific Coupons Add a `userId` field to restrict coupons: ```prisma model Coupon { // ... existing fields userId String? // Optional: restrict to specific user user User? @relation(fields: [userId], references: [id]) } ``` ### Feature 2: Product-Specific Coupons ```prisma model Coupon { // ... existing fields applicableCategories String[] // Only for these categories applicableProducts String[] // Only for these products } ``` ### Feature 3: First-Time User Coupons ```javascript // In validation logic const userOrders = await prisma.order.count({ where: { userId, status: 'DELIVERED' } }); if (coupon.firstTimeOnly && userOrders > 0) { return { isValid: false, message: 'Coupon only for first-time users' }; } ``` --- ## ✅ Testing Checklist ### Backend Testing - [ ] Create percentage coupon - [ ] Create fixed amount coupon - [ ] Create free shipping coupon - [ ] Validate active coupon - [ ] Validate expired coupon - [ ] Validate coupon below min order - [ ] Validate coupon at usage limit - [ ] Apply coupon to order - [ ] Remove coupon from order - [ ] Toggle coupon status - [ ] Get coupon statistics ### Frontend Testing - [ ] Apply valid coupon - [ ] Apply invalid coupon - [ ] View available coupons - [ ] Remove applied coupon - [ ] See discount in order summary - [ ] Responsive design - [ ] Loading states - [ ] Error handling --- ## 🎯 Common Use Cases ### Use Case 1: Flash Sale ```javascript { code: 'FLASH50', type: 'PERCENTAGE', value: 50, validFrom: new Date('2024-12-25T00:00:00'), validUntil: new Date('2024-12-25T23:59:59'), maxUses: 100 } ``` ### Use Case 2: Minimum Purchase Promotion ```javascript { code: 'BUY1000GET200', type: 'FIXED_AMOUNT', value: 200, minOrderAmount: 1000, } ``` ### Use Case 3: New Customer Welcome ```javascript { code: 'WELCOME', type: 'PERCENTAGE', value: 15, description: 'Welcome! Get 15% off on your first order', maxUses: null, // Unlimited } ``` --- ## 📈 Analytics & Reporting Track coupon performance: ```javascript // Get most successful coupons const topCoupons = await prisma.coupon.findMany({ orderBy: { usedCount: 'desc' }, take: 10, }); // Calculate total savings given const totalSavings = await calculateTotalDiscounts(); // Conversion rate const conversionRate = (usedCount / impressions) * 100; ``` --- **Your coupon system is ready! 🎉** Full features: ✅ Admin CRUD operations ✅ Smart validation ✅ Multiple coupon types ✅ Usage tracking ✅ Statistics & analytics ✅ User-friendly UI ✅ Mobile responsive 1. User applies coupon "WELCOME10" ↓ 2. CouponApply validates coupon ↓ 3. Coupon data stored in state { couponCode: "WELCOME10", discountAmount: 259.90, ... } ↓ 4. User clicks "Place Order" ↓ 5. Frontend sends: { items: [...], couponCode: "WELCOME10" ✅ } ↓ 6. Backend validates coupon again ↓ 7. Creates order in transaction: - Creates order - Increments coupon.usedCount ✅ ↓ 8. Admin panel shows: "usedCount": 1 ✅