# Coupon System Implementation Summary

## Files Created

### 1. `app/Enums/CouponApplyOn.php`
- New enum for coupon application types
- Values: GENERAL, VENDOR, CATEGORY, BRAND, FIRST_ORDER

### 2. `database/migrations/2026_04_20_000001_add_apply_on_fields_to_coupons_table.php`
- Adds `vendor_id`, `category_id`, `brand_id` foreign keys
- Adds `is_first_order` boolean field

### 3. `COUPON_SYSTEM_DOCUMENTATION.md`
- Complete documentation for the coupon system
- API examples, validation rules, error messages
- Testing scenarios

## Files Modified

### 1. `app/Models/Coupon.php`
**Changes:**
- Added `CouponApplyOn` enum import and cast
- Added `is_first_order` to casts
- Added relationships: `vendor()`, `category()`, `brand()`
- Enhanced `isValid()` method to check first order restriction
- Added new method `isApplicableToCart()` to validate cart items against coupon rules

**Key Logic:**
```php
// Checks if all cart items match coupon criteria
public function isApplicableToCart($cartItems): array
{
    // Returns [bool $isApplicable, ?string $errorMessage]
}
```

### 2. `app/Services/App/CouponService.php`
**Changes:**
- Updated `applyCoupon()` signature to accept `$cartItems` parameter
- Added cart validation before applying coupon
- Loads coupon relationships (vendor.profile, category, brand)

**Key Logic:**
```php
public function applyCoupon(?string $code, User $user, float $amount, $cartItems = null): array
{
    // Validates coupon exists, is valid, and applicable to cart items
}
```

### 3. `app/Services/App/CartService.php`
**Changes:**
- Updated coupon application to pass `$items` (cart items) to `applyCoupon()`

**Key Change:**
```php
[$coupon, $discountAmount, $couponMessage, $couponStatus] =
    $this->couponService->applyCoupon($couponCode, $user, $cartSubTotal, $items);
```

### 4. `app/Services/General/OrderService.php`
**Changes:**
- Updated coupon application to pass `$cartItems` to `applyCoupon()`

**Key Change:**
```php
[$coupon, $totalDiscountAmount, $couponMessage, $couponStatus] =
    $this->coupon->applyCoupon($couponCode, $user, $cartSubTotalForCoupon, $cartItems);
```

### 5. `app/Http/Requests/Api/Dashboard/Admin/Coupon/CouponRequest.php`
**Changes:**
- Added `apply_on` field validation (required)
- Added `is_first_order` field validation
- Added conditional validation for `vendor_id`, `category_id`, `brand_id`
- Each ID is required only when corresponding `apply_on` value is selected

**Key Validation:**
```php
'apply_on' => ['required', Rule::in(CouponApplyOn::values())],
'vendor_id' => [Rule::requiredIf($this->apply_on === CouponApplyOn::VENDOR->value)],
'category_id' => [Rule::requiredIf($this->apply_on === CouponApplyOn::CATEGORY->value)],
'brand_id' => [Rule::requiredIf($this->apply_on === CouponApplyOn::BRAND->value)],
```

### 6. `app/Http/Resources/Api/Dashboard/Admin/Coupon/CouponResource.php`
**Changes:**
- Added `apply_on` field
- Added `is_first_order` field
- Added vendor, category, brand IDs and names

### 7. `app/Http/Resources/Api/Dashboard/Admin/Coupon/CouponDetailsResource.php`
**Changes:**
- Added `apply_on` field
- Added `is_first_order` field
- Added vendor, category, brand IDs and names

### 8. `app/Http/Resources/Api/App/Coupon/CouponResource.php`
**Changes:**
- Added `apply_on` field
- Added `is_first_order` field
- Added vendor, category, brand IDs and names

### 9. `app/Http/Controllers/Api/Dashboard/Admin/Coupon/CouponController.php`
**Changes:**
- Added eager loading of relationships: `vendor.profile`, `category`, `brand`

### 10. `app/Http/Controllers/Api/App/Coupon/CouponController.php`
**Changes:**
- Added eager loading of relationships: `vendor.profile`, `category`, `brand`

## How It Works

### 1. Coupon Creation (Admin)
Admin creates a coupon and specifies:
- `apply_on`: Type of coupon (general, vendor, category, brand, first_order)
- Conditional fields based on `apply_on`:
  - If `vendor`: Must provide `vendor_id`
  - If `category`: Must provide `category_id`
  - If `brand`: Must provide `brand_id`
  - If `first_order`: Set `is_first_order = true`

### 2. Coupon Validation (User)
When user applies coupon:

**Step 1: Basic Validation (`isValid()`)**
- Coupon is active
- Within date range
- Client type matches
- Usage limits not exceeded
- If first_order, user has no completed orders

**Step 2: Cart Validation (`isApplicableToCart()`)**
- **General**: Always applicable
- **Vendor**: ALL cart items must be from specified vendor
- **Category**: ALL cart items must be from specified category
- **Brand**: ALL cart items must be from specified brand
- **First Order**: Always applicable (user check done in Step 1)

### 3. Error Handling
If validation fails, user receives specific error message:
- "This coupon requires all cart items to be from {vendor_name}"
- "This coupon requires all cart items to be from {category_name} category"
- "This coupon requires all cart items to be from {brand_name} brand"
- "Coupon is not valid or expired" (for first order when user has orders)

## Migration Instructions

1. **Run the migration:**
```bash
php artisan migrate
```

2. **Update existing coupons (if any):**
```sql
UPDATE coupons SET apply_on = 'general' WHERE apply_on IS NULL;
```

3. **Test the system:**
- Create test coupons for each type
- Test cart validation with mixed items
- Test first order restriction

## API Usage Examples

### Create Vendor-Specific Coupon
```json
POST /api/dashboard/admin/coupons
{
  "apply_on": "vendor",
  "vendor_id": 5,
  "code": "VENDOR20",
  "type": "percentage",
  "value": 20,
  "client_type": "normal",
  "start_at": "2024-01-01",
  "end_at": "2024-12-31",
  "limit": 100,
  "limit_for_user": 5,
  "is_active": true,
  "en": {
    "name": "Vendor Discount",
    "description": "20% off on vendor products"
  }
}
```

### Apply Coupon in Cart
```json
POST /api/app/cart/calculate
{
  "location_id": 1,
  "coupon_code": "VENDOR20"
}
```

### Response (Success)
```json
{
  "status": "success",
  "data": {
    "sub_total": 500.00,
    "discount": 100.00,
    "total": 462.00,
    "coupon_message": "Coupon applied successfully",
    "coupon_status": 200
  }
}
```

### Response (Error - Mixed Cart)
```json
{
  "status": "success",
  "data": {
    "sub_total": 500.00,
    "discount": 0.00,
    "total": 572.00,
    "coupon_message": "This coupon requires all cart items to be from Store Name",
    "coupon_status": 400
  }
}
```

## Testing Checklist

- [ ] Create general coupon and apply to mixed cart
- [ ] Create vendor coupon and apply to vendor-only cart
- [ ] Create vendor coupon and apply to mixed cart (should fail)
- [ ] Create category coupon and apply to category-only cart
- [ ] Create category coupon and apply to mixed cart (should fail)
- [ ] Create brand coupon and apply to brand-only cart
- [ ] Create brand coupon and apply to mixed cart (should fail)
- [ ] Create first order coupon and apply as new user
- [ ] Create first order coupon and apply as existing user (should fail)
- [ ] Test coupon usage limits
- [ ] Test coupon date restrictions
- [ ] Test client type restrictions (normal vs premium)

## Notes

1. **Breaking Change**: The `apply_on` field is now required for all new coupons
2. **Backward Compatibility**: Existing coupons should be updated to have `apply_on = 'general'`
3. **Performance**: Relationships are eager loaded to avoid N+1 queries
4. **Validation**: All cart items must match the coupon criteria (no partial application)
5. **Guest Users**: Cannot apply coupons (only authenticated users)
