# 📋 Course Purchase Module - Implementation Summary

**Date Created**: June 8, 2026  
**Status**: ✅ Ready for Testing

---

## 📁 Module Location
```
/Users/Praveen kumar/Node js/buddymentor_api/src/modules/users/coursePurchase/
```

---

## 🎯 API Endpoints Overview

| # | Endpoint | Method | Purpose | Status |
|---|----------|--------|---------|--------|
| 1 | `/api/v1/coursePurchase/initiate` | POST | Initiate purchase with validations | ✅ Complete |
| 2 | `/api/v1/coursePurchase/check-status/:courseId` | GET | Check if course already purchased | ✅ Complete |
| 3 | `/api/v1/coursePurchase/my-purchases` | GET | Get user's purchase history | ✅ Complete |
| 4 | `/api/v1/coursePurchase/:purchaseId` | GET | Get detailed purchase info | ✅ Complete |

---

## ✅ Validations Implemented

When initiating a purchase, the system checks:

```
1. PROFILE VALIDATION
   ✓ Email verified
   ✓ First Name present
   ✓ Last Name present
   ✓ Discipline Code selected
   
2. ACCOUNT VALIDATION
   ✓ User not suspended
   ✓ User account is active
   
3. COURSE VALIDATION
   ✓ Course exists
   ✓ Course is purchasable (not free)
   ✓ Course is active
   
4. PURCHASE HISTORY VALIDATION
   ✓ User hasn't already purchased (PENDING/SUCCESS)
   ✓ User hasn't already enrolled (ACTIVE enrollment)
```

---

## 📊 Data Saved in Database

### CoursePurchase Table

**On Purchase Initiation**:
```
purchaseId       → Auto-generated (PRIMARY KEY)
userId           → From JWT token
courseId         → From request body
streamId         → From course master data
productVerticalId → From course master data
orderId          → AUTO: ORD-{timestamp}-{random}
invoiceNumber    → AUTO: INV-{date}-{random}
amount           → From course.price
taxAmount        → From course.taxAmount
discountAmount   → From course.discountAmount
totalAmount      → Calculated: amount + tax - discount
currency         → INR (default)
purchaseStatus   → PENDING (until payment verified)
purchasedBy      → SELF or ADMIN
notes            → Optional custom notes
paymentGateway   → NULL (set after Razorpay integration)
createdAt        → CURRENT_TIMESTAMP
updatedAt        → CURRENT_TIMESTAMP
```

---

## 🔄 Complete Request-Response Flow

### Example: Initiate Purchase

**REQUEST**:
```bash
POST /api/v1/coursePurchase/initiate
Authorization: Bearer {JWT_TOKEN}
Content-Type: application/json

{
  "courseId": 5,
  "purchasedBy": "SELF",
  "notes": "Interested in web development"
}
```

**VALIDATION FLOW**:
1. Extract userId from JWT token
2. Fetch user profile → Check if completed
3. Fetch user account → Check if suspended/active
4. Fetch course → Check if exists, purchasable, active
5. Query existing purchases → Check for duplicates
6. Query existing enrollments → Check for conflicts

**DATABASE OPERATIONS**:
- Generate unique orderId and invoiceNumber
- Create CoursePurchase record with PENDING status
- Retrieve created record with timestamps

**RESPONSE** (201 Created):
```json
{
  "statusCode": 201,
  "success": true,
  "message": "Purchase initiated successfully. Ready for payment.",
  "data": {
    "purchase": {
      "purchaseId": 1,
      "orderId": "ORD-20260608-ABC123",
      "invoiceNumber": "INV-20260608-ABC123",
      "courseId": 5,
      "courseName": "Web Development Fundamentals",
      "amount": 5000.00,
      "taxAmount": 900.00,
      "discountAmount": 0.00,
      "totalAmount": 5900.00,
      "currency": "INR",
      "purchaseStatus": "PENDING",
      "purchasedBy": "SELF",
      "createdAt": "2026-06-08T10:30:00Z"
    }
  }
}
```

---

## 📦 Files Created

### 1. **purchase.validation.js**
- Request body validation schema
- Using Joi for input validation
- Validates: courseId, purchasedBy, notes

### 2. **purchase.service.js**
- Business logic layer
- Database operations
- Validation helpers
- Methods:
  - `initiatePurchase()` - Main purchase flow
  - `validatePurchaseEligibility()` - All checks
  - `checkPurchaseStatus()` - Quick duplicate check
  - `getUserPurchases()` - History with pagination
  - `getPurchaseDetails()` - Detailed info
  - `generateOrderId()` - Order ID generator
  - `generateInvoiceNumber()` - Invoice generator

### 3. **purchase.controller.js**
- HTTP request handlers
- Response formatting
- Methods:
  - `initiatePurchase()` - POST handler
  - `checkPurchaseStatus()` - GET handler
  - `getUserPurchases()` - GET handler (paginated)
  - `getPurchaseDetails()` - GET handler

### 4. **purchase.routes.js**
- Express route definitions
- All 4 endpoints
- Middleware: authenticateUser, validateRequest
- Base path: `/api/v1/coursePurchase`

### 5. **README.md**
- Complete API documentation
- Request/response examples
- Data model reference
- Error handling guide
- Integration points

---

## 🔌 Integration Points

**Integrated Into**:
- ✅ `/src/routes/index.js` - Route mounting
  ```javascript
  apiRouter.use("/coursePurchase", coursePurchaseRoutes);
  ```

**Dependencies Used**:
- ✅ AuthService - Profile validation, account validation
- ✅ Database Models - CoursePurchase, Course, User, UserCourseEnrollment
- ✅ Middleware - authenticateUser, validateRequest
- ✅ Utilities - ApiError, ApiResponse, asyncHandler

---

## 🚀 What Happens Next

### Immediate (Not Yet Implemented)
- [ ] Test all 4 endpoints
- [ ] Verify validation error messages
- [ ] Check database records creation

### Near Term (Razorpay Integration)
- [ ] Create Razorpay payment initiation
- [ ] Add payment verification endpoint
- [ ] Update purchaseStatus from PENDING → SUCCESS/FAILED
- [ ] Trigger automatic enrollment on success

### Medium Term
- [ ] Refund processing
- [ ] Invoice generation
- [ ] Email confirmations
- [ ] Payment receipts

---

## 🧪 Quick Testing

**Test 1: Initiate Purchase (Valid)**
```bash
curl -X POST http://localhost:3000/api/v1/coursePurchase/initiate \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"courseId": 5, "purchasedBy": "SELF"}'
```

**Expected**: 201 Created with purchase details

---

**Test 2: Check Status**
```bash
curl -X GET http://localhost:3000/api/v1/coursePurchase/check-status/5 \
  -H "Authorization: Bearer YOUR_TOKEN"
```

**Expected**: 200 OK with alreadyPurchased flag

---

**Test 3: Get My Purchases**
```bash
curl -X GET "http://localhost:3000/api/v1/coursePurchase/my-purchases?page=1&limit=10" \
  -H "Authorization: Bearer YOUR_TOKEN"
```

**Expected**: 200 OK with paginated purchase list

---

## 📝 Error Scenarios

| Scenario | Error Code | Message |
|----------|-----------|---------|
| Profile incomplete | 400 | "Profile is incomplete. Missing fields: ..." |
| User suspended | 403 | "User account is suspended. Reason: ..." |
| Course not found | 404 | "Course not found" |
| Already purchased | 409 | "You have already purchased this course ..." |
| Already enrolled | 409 | "You are already enrolled in this course" |
| No JWT token | 401 | "Unauthorized - No user found in token" |
| Free course | 400 | "This is a free course" |
| Inactive course | 400 | "This course is not available for purchase" |

---

## ✨ Key Features

1. **Complete Validation Chain** - Ensures data integrity before purchase
2. **Order Management** - Auto-generates unique order & invoice numbers
3. **Pagination Support** - For user purchase history
4. **Relationship Tracking** - Links courses, users, streams, verticals
5. **Audit Trail** - createdAt/updatedAt timestamps for all records
6. **Error Messaging** - Clear, actionable error messages
7. **JWT Protected** - All endpoints require authentication
8. **Ready for Payments** - Structure supports future Razorpay integration

---

## 📌 Important Notes

- **No Razorpay yet**: Currently returns PENDING status for all new purchases
- **Profile Required**: Users must complete mandatory fields before purchasing
- **Duplicate Prevention**: Cannot purchase same course twice
- **Enrollment Check**: Prevents purchasing if already enrolled
- **Data Consistency**: All related data (stream, vertical) auto-populated from course

---

**Module Status**: 🟢 Ready for Testing & Razorpay Integration

//📊 Complete Course Purchase Flow
┌─────────────────────────────────────────────────────────────────┐
│                    COURSE PURCHASE LIFECYCLE                    │
└─────────────────────────────────────────────────────────────────┘

STEP 1: User Decides to Buy Course
  ├─ User views course details
  └─ Clicks "Buy Course" button

STEP 2: Initiate Purchase (POST /initiate)
  ├─ Request: { courseId: "COURSE-001" }
  ├─ Service validates:
  │  ├─ User profile is complete ✓
  │  ├─ User not suspended ✓
  │  ├─ Course exists & purchasable ✓
  │  └─ User hasn't already purchased ✓
  ├─ Creates purchase record in DB
  ├─ Response: {
  │    purchaseId: 1,          ← ⭐ System generates this
  │    courseId: "COURSE-001",
  │    totalAmount: 5000,
  │    purchaseStatus: "PENDING"
  │  }
  └─ Status: PENDING (waiting for payment)

STEP 3: Initialize Payment (POST /:purchaseId/initialize-payment)
  ├─ Request: { purchaseId: 1 }        ← Use the ID from step 2
  ├─ Service:
  │  ├─ Fetches purchase by purchaseId
  │  ├─ Creates Razorpay order
  │  └─ Stores order details in DB
  ├─ Response: {
  │    purchaseId: 1,
  │    razorpayOrderId: "order_xyz123",
  │    amount: 5000,
  │    keyId: "rzp_test_xyz"
  │  }
  └─ Ready for payment

STEP 4: User Enters Payment Details
  ├─ Frontend shows Razorpay payment modal
  ├─ User enters card/UPI details
  ├─ Payment processed by Razorpay
  └─ Razorpay returns payment response

STEP 5: Verify Payment (POST /verify-payment)
  ├─ Request: {
  │    purchaseId: 1,              ← Same purchaseId from step 2
  │    paymentId: "pay_xyz123",    ← From Razorpay
  │    orderId: "order_xyz123",    ← From Razorpay
  │    signature: "sig_xyz123"     ← From Razorpay
  │  }
  ├─ Service:
  │  ├─ Verifies signature (confirm payment is real)
  │  ├─ Updates purchase status to SUCCESS
  │  ├─ Creates enrollment record
  │  └─ Sends confirmation email
  ├─ Response: {
  │    purchaseId: 1,
  │    paymentStatus: "SUCCESS",
  │    message: "✅ Payment successful!"
  │  }
  └─ Status: SUCCESS (payment complete)

STEP 6: User Access Course
  ├─ User gets enrollment
  ├─ Can now view course content
  └─ Learning begins 🎓