Couponscontroller Documentation

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:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Table

Table NamePurposeKey Columns
**coupons**Coupon managementid, 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

-- 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

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

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:

---

3. edit Action - Coupon Editing Interface

Location: Line 26-31

Purpose: Load and display existing coupon for editing

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:

$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:

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:

---

5. delete Action - Coupon Deletion

Location: Line 75-83

Purpose: Soft delete coupons with unique code handling

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:

---

6. toggleStatus Action - Status Management

Location: Line 84-93

Purpose: Toggle coupon active/inactive status

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:

---

7. Success/Error Actions - User Feedback

Location: Line 94-100

Purpose: Display operation result messages

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

---

๐Ÿ”„ Workflows

Workflow 1: Coupon Creation Process

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Create New Coupon
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Access Coupon Creation Form
- Navigate to couponscontroller.php
- Display coupon creation interface
- Show all configuration options
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Configure 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 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Submit 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 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Confirmation 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
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Access Coupon Management Interface
- Navigate to couponscontroller.php?do=show
- Load all active coupons
- Display in management grid
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Select 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 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Execute Operation and Confirm
- Process selected operation
- Handle any errors gracefully
- Update database records
- Refresh management interface
- Display success/error message
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default actionDisplay coupon creation form
`do=show`Show actionDisplay coupon management interface
`do=edit`Edit actionLoad coupon for editing
`do=savedata`savedata actionProcess coupon creation/update
`do=delete`delete actionSoft delete coupon
`do=toggleStatus`toggleStatus actionToggle coupon active status
`do=success`Success pageDisplay success message
`do=error`Error pageDisplay error message
### Form Parameters for Coupon Operations

Coupon Creation/Update (do=savedata):

Status Management (do=toggleStatus):

Deletion (do=delete):

---

๐Ÿงฎ Calculation Methods

Discount Type Handling

// 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

// 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

// 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

// 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

// Track who created/modified coupons
$coupon->user_id = $_SESSION['userid'];

Code Uniqueness (Application Level)

// 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

Recommended Addition:

// 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

// 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:

// 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:

-- 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:

// 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:

// 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:

-- 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:

// 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

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur