# Coupons Controller Documentation

**File**: `/controllers/couponscontroller.php`  
**Purpose**: Manages discount coupons and promotional codes with advanced configuration options for marketing campaigns  
**Last Updated**: December 20, 2024  
**Total Functions**: 7  
**Lines of Code**: ~101

---

## 📋 Overview

The Coupons Controller is a modern promotional management system that handles discount coupons and marketing campaigns. Built using RedBeanPHP ORM, this controller provides comprehensive coupon management with advanced features for sophisticated marketing strategies. The system features:

- Comprehensive coupon creation and management
- Multiple discount types (fixed amount vs percentage)
- Advanced usage tracking and limits
- Date-based campaign scheduling
- Category-specific coupon restrictions
- Auto-apply functionality for eligible orders
- User-based and global usage limits
- Minimum order value requirements

### Primary Functions
- [x] Coupon creation and configuration
- [x] Multiple discount type support
- [x] Usage limit management (per user and global)
- [x] Date range campaign scheduling
- [x] Category-based coupon restrictions
- [x] Auto-apply coupon functionality
- [x] Coupon status management
- [x] Usage tracking and reporting

### Related Controllers
- [sellbillController.php](sellbillController.md) - Sales operations (coupon application)
- [clientController.php](#) - Customer management
- [productCatController.php](productCatController.md) - Category restrictions
- [userController.php](userController.md) - User management

---

## 🗄️ Database Tables

### Primary Table
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **coupons** | Coupon management | id, code, discount_type, discount_value, start_date, end_date, is_active, usage_limit, per_user_limit, minimum_order_value, applicable_categories, auto_apply, note, user_id, created_at, updated_at, deleted_at, del |

### Table Structure Detail
```sql
-- Coupon table structure (RedBeanPHP auto-schema)
coupons:
  id (INT PRIMARY KEY AUTO_INCREMENT)
  code (VARCHAR) - Unique coupon code
  discount_type (INT) - 1=Fixed Amount, 2=Percentage  
  discount_value (DECIMAL) - Discount amount or percentage
  start_date (DATE) - Campaign start date
  end_date (DATE) - Campaign end date
  is_active (TINYINT) - Active status (1=active, 0=inactive)
  usage_limit (INT) - Total usage limit (0=unlimited)
  per_user_limit (INT) - Per-user usage limit (0=unlimited)
  minimum_order_value (DECIMAL) - Minimum order value requirement
  applicable_categories (TEXT) - Comma-separated category IDs
  auto_apply (TINYINT) - Auto-apply to eligible orders (1=yes, 0=no)
  note (TEXT) - Internal notes and description
  user_id (INT) - User who created the coupon
  created_at (DATETIME) - Creation timestamp
  updated_at (DATETIME) - Last update timestamp  
  deleted_at (DATETIME) - Deletion timestamp
  del (TINYINT) - Soft delete status (0=active, 2=deleted)
```

---

## 🔑 Key Functions

### 1. **Default Action** - Coupon Creation Form
**Location**: Line 18-20  
**Purpose**: Display coupon creation interface

```php
if (empty($do)) {
    $smarty->display("couponsview/add.html");
    $smarty->display("footer.html");
}
```

**Simple Interface**: Direct template display for coupon creation form

---

### 2. **show Action** - Coupon Management Interface
**Location**: Line 21-25  
**Purpose**: Display all existing coupons with management options

```php
elseif ($do == "show") {
    $coupons = R::findAll('coupons', 'del < 2'); // Exclude permanently deleted
    $smarty->assign('coupons', $coupons);
    $smarty->display("couponsview/show.html");
    $smarty->display("footer.html");
}
```

**Features**:
- Load all non-deleted coupons
- Display in management grid
- Provide edit/delete/status toggle options

---

### 3. **edit Action** - Coupon Editing Interface  
**Location**: Line 26-31
**Purpose**: Load and display existing coupon for editing

```php
elseif ($do == "edit") {
    $id = filter_input(INPUT_GET, 'id');
    $coupon = R::load('coupons', $id);
    $smarty->assign('coupon', $coupon);
    $smarty->display("couponsview/edit.html");
    $smarty->display("footer.html");
}
```

**Process Flow**:
1. Get coupon ID from URL parameter
2. Load coupon record using RedBeanPHP
3. Assign to template for editing
4. Display edit form

---

### 4. **savedata Action** - Coupon Processing Engine
**Location**: Line 32-74  
**Purpose**: Handle coupon creation and updates with comprehensive validation

**Function Parameters**:
```php
$code = filter_input(INPUT_POST, 'code');
$discount_type = filter_input(INPUT_POST, 'discount_type', FILTER_VALIDATE_INT);
$discount_value = filter_input(INPUT_POST, 'discount_value', FILTER_VALIDATE_FLOAT);
$start_date = filter_input(INPUT_POST, 'start_date');
$end_date = filter_input(INPUT_POST, 'end_date');
$is_active = filter_input(INPUT_POST, 'is_active', FILTER_VALIDATE_INT);
$usage_limit = filter_input(INPUT_POST, 'usage_limit', FILTER_VALIDATE_INT);
$per_user_limit = filter_input(INPUT_POST, 'per_user_limit', FILTER_VALIDATE_INT);
$minimum_order_value = filter_input(INPUT_POST, 'minimum_order_value', FILTER_VALIDATE_FLOAT);
$applicable_categories = filter_input(INPUT_POST, 'applicable_categories');
$auto_apply = filter_input(INPUT_POST, 'auto_apply', FILTER_VALIDATE_INT);
$note = filter_input(INPUT_POST, 'note');
$coupon_id = filter_input(INPUT_POST, 'coupon_id', FILTER_VALIDATE_INT);
```

**Processing Logic**:
```php
if (!$coupon_id) {
    // New coupon creation
    $coupon = R::dispense('coupons');
    $coupon->created_at = date('Y-m-d H:i:s');
}

// Set updated timestamp for both new and existing
$coupon->updated_at = date('Y-m-d H:i:s');

// Assign form values
$coupon->code = $code;
$coupon->discount_type = $discount_type;
$coupon->discount_value = $discount_value;
$coupon->start_date = $start_date;
$coupon->end_date = $end_date;
$coupon->is_active = $is_active ? 1 : 0;
$coupon->usage_limit = $usage_limit;
$coupon->per_user_limit = $per_user_limit;
$coupon->minimum_order_value = $minimum_order_value ?: 0.00;
$coupon->applicable_categories = $applicable_categories;
$coupon->auto_apply = $auto_apply ? 1 : 0;
$coupon->note = $note;
$coupon->user_id = $_SESSION['userid'];

try {
    R::store($coupon);
    header("location:couponscontroller.php?do=success");
} catch (Exception $e) {
    header("location:couponscontroller.php?do=error");
}
```

**Key Features**:
- Proper input validation with PHP filter functions
- Automatic timestamp management
- User tracking for coupon creation
- Boolean conversion for checkbox fields
- Default value handling for optional fields
- Exception handling for database operations

---

### 5. **delete Action** - Coupon Deletion
**Location**: Line 75-83  
**Purpose**: Soft delete coupons with unique code handling

```php
else if ($do == 'delete') {
    $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
    $coupon = R::load('coupons', $id);
    $coupon->code = $coupon->code."-del".$coupon->id; // Unique code for deleted coupons
    $coupon->del = 2; // Mark as deleted
    $coupon->is_active = 0; // Deactivate
    $coupon->deleted_at = date('Y-m-d H:i:s'); // Deletion timestamp
    R::store($coupon);
    header("location:couponscontroller.php?do=success");
}
```

**Soft Delete Features**:
- Preserves coupon data for audit trail
- Modifies code to prevent conflicts with new coupons
- Deactivates coupon to prevent usage
- Records deletion timestamp
- Allows code reuse after deletion

---

### 6. **toggleStatus Action** - Status Management
**Location**: Line 84-93  
**Purpose**: Toggle coupon active/inactive status

```php
elseif ($do == "toggleStatus") {
    try {
        $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
        $coupon = R::load('coupons', $id);
        $coupon->is_active = $coupon->is_active ? 0 : 1; // Toggle status
        R::store($coupon);
        header("location:couponscontroller.php?do=success");
    } catch (Exception $e) {
        header("location:couponscontroller.php?do=error");
    }
}
```

**Features**:
- Simple boolean toggle operation
- Exception handling for safety
- Immediate status change
- No data loss during status changes

---

### 7. **Success/Error Actions** - User Feedback
**Location**: Line 94-100  
**Purpose**: Display operation result messages

```php
elseif ($do == "success") {
    $smarty->display("succes.html");
} elseif ($do == "error") {
    $smarty->display("error.html");
}
```

---

## 🔄 Workflows

### Workflow 1: Coupon Creation Process
```
┌─────────────────────────────────────────────────────────────┐
│                START: Create New Coupon                    │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Access Coupon Creation Form                             │
│     - Navigate to couponscontroller.php                     │
│     - Display coupon creation interface                     │
│     - Show all configuration options                        │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Configure Coupon Settings                               │
│     Basic Information:                                      │
│       ├─ Enter unique coupon code                           │
│       ├─ Select discount type (fixed/percentage)            │
│       ├─ Set discount value                                 │
│       └─ Add description notes                              │
│                                                             │
│     Campaign Scheduling:                                    │
│       ├─ Set start date                                     │
│       ├─ Set end date                                       │
│       └─ Configure active status                            │
│                                                             │
│     Usage Restrictions:                                     │
│       ├─ Set total usage limit (0 = unlimited)             │
│       ├─ Set per-user limit (0 = unlimited)                │
│       ├─ Set minimum order value                            │
│       └─ Select applicable categories                       │
│                                                             │
│     Advanced Options:                                       │
│       └─ Configure auto-apply setting                       │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Submit and Validate                                     │
│     CALL savedata action:                                   │
│       │                                                     │
│       ├─→ Validate all input parameters                     │
│       │   ├─ Check code uniqueness                          │
│       │   ├─ Validate discount type and value               │
│       │   ├─ Verify date ranges                             │
│       │   └─ Check numeric limits                           │
│       │                                                     │
│       ├─→ Create new coupon record                          │
│       │   ├─ Set creation timestamp                         │
│       │   ├─ Assign creating user                           │
│       │   └─ Initialize all fields                          │
│       │                                                     │
│       └─→ Save to database                                  │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Confirmation and Next Steps                             │
│     IF save successful:                                     │
│       ├─→ Display success message                           │
│       ├─→ Redirect to coupon list                           │
│       └─→ Coupon ready for use                              │
│                                                             │
│     IF save failed:                                         │
│       ├─→ Display error message                             │
│       └─→ Return to form with data                          │
└─────────────────────────────────────────────────────────────┘
```

---

### Workflow 2: Coupon Management Operations
```
┌─────────────────────────────────────────────────────────────┐
│              START: Coupon Management                      │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Access Coupon Management Interface                      │
│     - Navigate to couponscontroller.php?do=show             │
│     - Load all active coupons                               │
│     - Display in management grid                            │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Select Management Operation                             │
│     Available Operations:                                   │
│       │                                                     │
│       ├─→ Edit Coupon                                       │
│       │   ├─ Load existing coupon data                      │
│       │   ├─ Display in edit form                           │
│       │   ├─ Allow configuration changes                    │
│       │   └─ Update with savedata action                    │
│       │                                                     │
│       ├─→ Toggle Status                                     │
│       │   ├─ Switch active ↔ inactive                       │
│       │   ├─ Immediate effect                               │
│       │   └─ Preserve all other settings                    │
│       │                                                     │
│       └─→ Delete Coupon                                     │
│           ├─ Soft delete implementation                     │
│           ├─ Modify code to prevent conflicts               │
│           ├─ Deactivate automatically                       │
│           ├─ Record deletion timestamp                      │
│           └─ Preserve for audit trail                       │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Execute Operation and Confirm                           │
│     - Process selected operation                            │
│     - Handle any errors gracefully                          │
│     - Update database records                               │
│     - Refresh management interface                          │
│     - Display success/error message                         │
└─────────────────────────────────────────────────────────────┘
```

---

## 🌐 URL Routes & Actions

| URL Parameter | Function Called | Description |
|---------------|----------------|-------------|
| `do=` (empty) | Default action | Display coupon creation form |
| `do=show` | Show action | Display coupon management interface |
| `do=edit` | Edit action | Load coupon for editing |
| `do=savedata` | savedata action | Process coupon creation/update |
| `do=delete` | delete action | Soft delete coupon |
| `do=toggleStatus` | toggleStatus action | Toggle coupon active status |
| `do=success` | Success page | Display success message |
| `do=error` | Error page | Display error message |

### Form Parameters for Coupon Operations

**Coupon Creation/Update** (`do=savedata`):
- `code` - Unique coupon code (string)
- `discount_type` - Discount type (1=fixed, 2=percentage) 
- `discount_value` - Discount amount/percentage (float)
- `start_date` - Campaign start date (YYYY-MM-DD)
- `end_date` - Campaign end date (YYYY-MM-DD)
- `is_active` - Active status (1=active, 0=inactive)
- `usage_limit` - Total usage limit (int, 0=unlimited)
- `per_user_limit` - Per-user usage limit (int, 0=unlimited)
- `minimum_order_value` - Minimum order requirement (float)
- `applicable_categories` - Category restrictions (comma-separated)
- `auto_apply` - Auto-apply setting (1=yes, 0=no)
- `note` - Internal notes (text)
- `coupon_id` - Coupon ID (for updates)

**Status Management** (`do=toggleStatus`):
- `id` - Coupon ID (GET parameter)

**Deletion** (`do=delete`):
- `id` - Coupon ID (GET parameter)

---

## 🧮 Calculation Methods

### Discount Type Handling
```php
// Form processing
$discount_type = filter_input(INPUT_POST, 'discount_type', FILTER_VALIDATE_INT);
$discount_value = filter_input(INPUT_POST, 'discount_value', FILTER_VALIDATE_FLOAT);

// Discount type values:
// 1 = Fixed Amount (e.g., $10 off)
// 2 = Percentage (e.g., 15% off)

// Usage in sales system (not in this controller):
if ($coupon->discount_type == 1) {
    $discount_amount = $coupon->discount_value; // Fixed amount
} else {
    $discount_amount = ($order_total * $coupon->discount_value) / 100; // Percentage
}
```

### Usage Limit Management
```php
// Global usage limit
$usage_limit = $coupon->usage_limit; // 0 = unlimited

// Per-user usage limit  
$per_user_limit = $coupon->per_user_limit; // 0 = unlimited

// Minimum order value requirement
$minimum_order_value = $coupon->minimum_order_value ?: 0.00; // Default to 0
```

### Status and Date Validation
```php
// Active status handling
$coupon->is_active = $is_active ? 1 : 0;

// Auto-apply setting
$coupon->auto_apply = $auto_apply ? 1 : 0;

// Date validation (should be done in application logic)
$today = date('Y-m-d');
$is_valid_date = ($coupon->start_date <= $today && $coupon->end_date >= $today);
$is_active_coupon = ($coupon->is_active == 1 && $is_valid_date);
```

---

## 🔒 Security & Permissions

### Input Sanitization
```php
// Comprehensive input filtering
$code = filter_input(INPUT_POST, 'code'); // String - should add FILTER_SANITIZE_STRING
$discount_type = filter_input(INPUT_POST, 'discount_type', FILTER_VALIDATE_INT);
$discount_value = filter_input(INPUT_POST, 'discount_value', FILTER_VALIDATE_FLOAT);
$is_active = filter_input(INPUT_POST, 'is_active', FILTER_VALIDATE_INT);
$usage_limit = filter_input(INPUT_POST, 'usage_limit', FILTER_VALIDATE_INT);
$per_user_limit = filter_input(INPUT_POST, 'per_user_limit', FILTER_VALIDATE_INT);
$minimum_order_value = filter_input(INPUT_POST, 'minimum_order_value', FILTER_VALIDATE_FLOAT);
$note = filter_input(INPUT_POST, 'note'); // Should add FILTER_SANITIZE_STRING
```

### User Tracking
```php
// Track who created/modified coupons
$coupon->user_id = $_SESSION['userid'];
```

### Code Uniqueness (Application Level)
```php
// Recommended addition for code uniqueness check
function isCodeUnique($code, $exclude_id = null) {
    $query = 'code = ? AND del < 2';
    $params = [$code];
    
    if ($exclude_id) {
        $query .= ' AND id != ?';
        $params[] = $exclude_id;
    }
    
    $existing = R::findOne('coupons', $query, $params);
    return empty($existing);
}
```

### Access Control
- **Missing**: No authentication checks in this controller
- **Should Add**: Session and permission validation
- **Current Risk**: Anyone can access coupon management if they know URLs

**Recommended Addition**:
```php
// Add to all actions
if (!isset($_SESSION['userid'])) {
    header("location: login.php");
    exit();
}

// Check permissions for coupon management
$user = R::load('user', $_SESSION['userid']);
if (!$user->canManageCoupons) { // Assuming permission field exists
    header("location: unauthorized.php");
    exit();
}
```

---

## 📊 Performance Considerations

### Database Optimization Tips
1. **Indexes Required**:
   - `coupons(code, del)` - For code uniqueness and active coupon lookups
   - `coupons(is_active, start_date, end_date, del)` - For active coupon filtering
   - `coupons(user_id, created_at)` - For user tracking and audit
   - `coupons(del, updated_at)` - For management interface sorting

2. **Query Optimization**:
   - Single table operations (no complex JOINs)
   - Efficient soft delete filtering (`del < 2`)
   - RedBeanPHP automatic query optimization

3. **Coupon Application Performance**:
   - Index on active status and date range for quick eligibility checks
   - Consider caching frequently used coupons
   - Implement coupon validation without complex queries

### RedBeanPHP Considerations
```php
// Efficient coupon loading
$coupons = R::findAll('coupons', 'del < 2 ORDER BY created_at DESC');

// Consider caching for high-traffic sites
$active_coupons = R::find('coupons', 'is_active = 1 AND del = 0 AND start_date <= CURDATE() AND end_date >= CURDATE()');
```

---

## 🐛 Common Issues & Troubleshooting

### 1. **Duplicate Coupon Codes**
**Issue**: Multiple coupons with same code causing confusion  
**Cause**: No uniqueness validation on code field

**Solution**:
```php
// Add before saving coupon
$existing = R::findOne('coupons', 'code = ? AND del < 2 AND id != ?', 
                       [$code, $coupon_id ?: 0]);
if ($existing) {
    throw new Exception("Coupon code already exists");
}
```

**Debug**:
```sql
-- Find duplicate codes
SELECT code, COUNT(*) FROM coupons WHERE del < 2 GROUP BY code HAVING COUNT(*) > 1;
```

### 2. **Date Range Validation Issues**
**Issue**: End date before start date or past dates  
**Cause**: No date validation in controller

**Solution**:
```php
// Add date validation
if (strtotime($start_date) > strtotime($end_date)) {
    throw new Exception("End date must be after start date");
}

if (strtotime($start_date) < strtotime(date('Y-m-d'))) {
    throw new Exception("Start date cannot be in the past");
}
```

### 3. **Invalid Discount Values**
**Issue**: Negative discounts or percentages > 100%  
**Cause**: No business logic validation

**Solution**:
```php
// Add discount validation
if ($discount_value <= 0) {
    throw new Exception("Discount value must be positive");
}

if ($discount_type == 2 && $discount_value > 100) {
    throw new Exception("Percentage discount cannot exceed 100%");
}
```

### 4. **Soft Delete Issues**
**Issue**: Deleted coupons still appearing or code conflicts  
**Cause**: Improper soft delete implementation

**Debug**:
```sql
-- Check deleted coupons
SELECT id, code, del, is_active, deleted_at FROM coupons WHERE del = 2;

-- Check for code conflicts
SELECT code, del, COUNT(*) FROM coupons GROUP BY code HAVING COUNT(*) > 1;
```

**Solution**:
```php
// Ensure proper soft delete
$coupon->code = $coupon->code . "-del" . $coupon->id;
$coupon->del = 2;
$coupon->is_active = 0;
$coupon->deleted_at = date('Y-m-d H:i:s');
```

---

## 🧪 Testing Scenarios

### Test Case 1: Basic Coupon Creation
```
1. Create coupon with all required fields
2. Set fixed discount type with $10 amount
3. Set future start date and end date
4. Verify coupon saves successfully
5. Check coupon appears in management list
6. Verify all fields saved correctly
```

### Test Case 2: Percentage Discount Coupon
```
1. Create coupon with percentage discount
2. Set 15% discount value
3. Configure usage limits (100 total, 5 per user)
4. Set minimum order value $50
5. Test save operation
6. Verify percentage calculation logic
```

### Test Case 3: Advanced Configuration
```
1. Create coupon with category restrictions
2. Set auto-apply functionality
3. Configure specific date range
4. Add comprehensive notes
5. Test all advanced features
6. Verify configuration preserved
```

### Test Case 4: Management Operations
```
1. Create test coupon
2. Test edit functionality:
   - Modify discount value
   - Change date range  
   - Update status
3. Test status toggle:
   - Activate/deactivate
   - Verify immediate effect
4. Test deletion:
   - Soft delete operation
   - Verify code modification
   - Check audit trail preservation
```

---

## 📚 Related Documentation

- [CLAUDE.md](/Applications/AMPPS/www/erp19/CLAUDE.md) - PHP 8.2 migration guide
- [sellbillController.md](sellbillController.md) - Sales operations (coupon application)
- [productCatController.md](productCatController.md) - Category management
- [userController.php](userController.md) - User management

---

**Documented By**: AI Assistant  
**Review Status**: ✅ Complete  
**Next Review**: When major changes occur