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:
- โข 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
- โ Coupon creation and configuration
- โ Multiple discount type support
- โ Usage limit management (per user and global)
- โ Date range campaign scheduling
- โ Category-based coupon restrictions
- โ Auto-apply coupon functionality
- โ Coupon status management
- โ Usage tracking and reporting
Related Controllers
- โข sellbillController.php - Sales operations (coupon application)
- โข clientController.php - Customer management
- โข productCatController.php - Category restrictions
- โข userController.php - 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 |
-- 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:
- โข 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
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:
- โข 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
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
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
elseif ($do == "success") {
$smarty->display("succes.html");
} elseif ($do == "error") {
$smarty->display("error.html");
}
---
๐ Workflows
Workflow 1: Coupon Creation Process
---
Workflow 2: Coupon Management Operations
---
๐ 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 |
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
// 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
- โข 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:
// 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
- โข CLAUDE.md - PHP 8.2 migration guide
- โข sellbillController.md - Sales operations (coupon application)
- โข productCatController.md - Category management
- โข userController.php - User management
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur