Premium Report Controller Documentation
File: /controllers/premiumReportController.php
Purpose: Generates comprehensive reports for client premium payments and installment schedules
Last Updated: December 20, 2024
Total Functions: 4
Lines of Code: ~242
---
๐ Overview
The Premium Report Controller provides detailed reporting capabilities for the premium/installment payment system. It allows filtering and analysis of premium payments by various criteria including client, area, client type, and date ranges. This controller serves as the primary reporting interface for monitoring premium payment schedules and tracking payment performance.
Primary Functions
- โ Filter premium reports by multiple criteria
- โ Date range filtering with system timezone adjustments
- โ Client-specific premium payment tracking
- โ Area-based premium reporting
- โ Client type filtering for targeted reports
- โ Dynamic query building for flexible filtering
- โ Client type name resolution and display
- โ Tutorial video integration
Related Controllers
- โข premiumController.php - Premium schedule management
- โข allpremiumReportController.php - Comprehensive premium reports
- โข premiumReportDelayController.php - Delayed payment reports
- โข clientReportsController.php - General client reporting
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **premium** | Premium payment records | id, date, value, premiumclientId, payed, rest, conditions | |
| **premiumclient** | Premium client master | id, client_id, userid, date | |
| **client** | Customer information | clientid, clientname, typeclientid, clientareaid | |
| **clientarea** | Customer areas | clientareaid, name | |
| **typeclient** | Client type definitions | typeId, typeName |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **programsettings** | System configuration | programsettingsid, reportsPlusHours | |
| **youtubelink** | Tutorial videos | youtubelinkid, title, url |
The controller performs complex joins across multiple tables:
-- Conceptual query structure
SELECT premium.*, premiumclient.*, client.*, clientarea.name, typeclient.typeName
FROM premium
JOIN premiumclient ON premium.premiumclientId = premiumclient.id
JOIN client ON premiumclient.client_id = client.clientid
LEFT JOIN clientarea ON client.clientareaid = clientarea.clientareaid
---
๐ Key Functions
1. Default Action / show() - Generate Premium Report
Location: Lines 91-212
Purpose: Main reporting function with comprehensive filtering capabilities
Function Signature:
// Triggered when: do=show or empty $do
$startDate = $_REQUEST['from'];
$endDate = $_REQUEST['to'];
$clientId = $_REQUEST['clientId'];
$areaId = $_REQUEST['areaId'];
$typeclientId = $_REQUEST['typeclientId'];
Process Flow:
1. Load system settings and reference data
2. Extract filter parameters from request
3. Set default date range if not provided
4. Build dynamic SQL query string based on filters
5. Execute premium query with filters
6. Process client type information for display
7. Display report via template
Filter Parameters:
- โข
from/to- Date range for payment dates - โข
clientId- Specific client filter (-1 for all) - โข
areaId- Client area filter (-1 for all) - โข
typeclientId- Client type filter (-1 for all)
---
2. Dynamic Query Building - Core Filtering Logic
Location: Lines 122-181
Purpose: Build flexible SQL WHERE clause based on selected filters
Query String Construction:
$queryString = ' WHERE';
// Client filter
if ($clientId != '' && $clientId != '-1') {
$queryString .= ' premiumclient.client_id = ' . $clientId . ' AND';
}
// Area filter
if ($areaId != '' && $areaId != '-1') {
$queryString .= ' client.clientareaid = ' . $areaId . ' AND';
}
// Client type filter
if ($typeclientId != '' && $typeclientId != '-1') {
$queryString .= ' (client.typeclientid like "%,' . $typeclientId . ',%") AND';
}
// Date range filter with timezone adjustment
if ($startDate != '' && $endDate != '') {
$queryString .= ' premium.date >= "' . $startDate . '" AND premium.date <= "' . $endDate . '" AND';
}
Query Cleanup Logic:
$arr = explode(' ', $queryString);
$lastWord = end($arr);
if ($lastWord == 'AND') {
array_pop($arr);
$queryString = implode(' ', $arr);
} else if ($lastWord == 'WHERE') {
array_pop($arr);
$queryString = ' ';
}
---
3. Date Range Processing - Timezone Adjustment
Location: Lines 149-164
Purpose: Handle date filtering with system timezone settings
Date Adjustment Logic:
if ($startDate != '' && $endDate != '') {
$Programsetting = $ProgramsettingDAO->load(1);
if (isset($Programsetting->reportsPlusHours) && !empty($Programsetting->reportsPlusHours)) {
$reportsPlusHours = $Programsetting->reportsPlusHours + 24; // 24 to get end of day
$endDate = date('Y-m-d', strtotime('+' . $reportsPlusHours . ' hour', strtotime($endDate)));
$startDate = date('Y-m-d', strtotime('+' . $Programsetting->reportsPlusHours . ' hour', strtotime($startDate)));
} else {
$endDate = $endDate . ' 23:59:59';
$startDate = $startDate . " 00:00:00";
}
}
Default Date Logic:
if (empty($startDate) && empty($endDate)) {
$startDate = date('Y-m-d');
$endDate = date('Y-m-d');
}
---
4. Client Type Processing - Name Resolution
Location: Lines 183-205
Purpose: Convert client type IDs to human-readable names
Type Resolution Logic:
foreach ($allData as $allDatum) {
$allDatum->typeclientid = explode(',', $allDatum->typeclientid);
foreach ($allDatum->typeclientid as $item) {
$typeClient = $TypeClientDAO->queryAll();
foreach ($typeClient as $az) {
if ($az->typeId == $item) {
array_push($azmy, $az->typeName);
}
}
}
// Special handling for "all client types"
if (in_array('-20', $allDatum->typeclientid)) {
array_push($azmy, "ูู ุงููุงุน ุงูุนู
ูุงุก");
}
$aaaa = implode(",", $azmy);
$allDatum->typeName = $aaaa;
}
Performance Issue: This creates N+1 query pattern by loading all types for each data record.
---
5. getClients() - Load Client Dropdown Data
Location: Lines 220-224
Purpose: Load active clients for filter dropdown
Function Signature:
function getClients()
Implementation:
global $clientDAO;
$clientsData = $clientDAO->queryByCondition(0);
return $clientsData;
---
6. getClientarea() - Load Area Dropdown Data
Location: Lines 226-230
Purpose: Load all client areas for filter dropdown
Function Signature:
function getClientarea()
---
7. getTypeclient() - Load Client Type Dropdown Data
Location: Lines 232-236
Purpose: Load client types for filter dropdown
Function Signature:
function getTypeclient()
Uses Extended DAO: $TypeClientEX->queryAllsup() for enhanced type data
---
๐ Workflows
Workflow 1: Generate Filtered Premium Report
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | Authentication |
|---|---|---|---|
| `do=show` or empty | Default | Generate premium report | Required |
Date Range:
- โข
from- Start date (YYYY-MM-DD format) - โข
to- End date (YYYY-MM-DD format)
Client Filters:
- โข
clientId- Specific client ID (-1 for all clients) - โข
areaId- Client area ID (-1 for all areas) - โข
typeclientId- Client type ID (-1 for all types)
URL Examples
/controllers/premiumReportController.php
/controllers/premiumReportController.php?do=show
/controllers/premiumReportController.php?from=2024-01-01&to=2024-12-31
/controllers/premiumReportController.php?clientId=123&from=2024-01-01&to=2024-12-31
/controllers/premiumReportController.php?areaId=5&typeclientId=2
---
๐งฎ Calculation Methods
Date Range Calculation with Timezone
if (isset($Programsetting->reportsPlusHours) && !empty($Programsetting->reportsPlusHours)) {
// Add system timezone hours plus 24 for end of day
$reportsPlusHours = $Programsetting->reportsPlusHours + 24;
$endDate = date('Y-m-d', strtotime('+' . $reportsPlusHours . ' hour', strtotime($endDate)));
$startDate = date('Y-m-d', strtotime('+' . $Programsetting->reportsPlusHours . ' hour', strtotime($startDate)));
} else {
// Standard day boundaries
$endDate = $endDate . ' 23:59:59';
$startDate = $startDate . " 00:00:00";
}
Client Type Filtering Logic
// For multiple client types stored as comma-separated values
$queryString .= ' (client.typeclientid like "%,' . $typeclientId . ',%") AND';
Filter Message Generation
$message = '';
if ($clientId != '-1') $message .= "ุงูุนู
ูู :" . $clientName;
if ($areaId != '-1') $message .= "/ ุงูู
ูุทูู: " . $areaName;
if ($typeclientId != '-1') $message .= "/ ููุน ุงูุนู
ูู: " . $TypeClientName;
if ($startDate && $endDate) $message .= "<br> ู
ู ุชุงุฑูุฎ: " . $startDate . " ุฅูู ุชุงุฑูุฎ: " . $endDate;
---
๐ Security & Permissions
Authentication & Session Management
include_once("../public/authentication.php");
Security Features:
- โข Authentication required for all operations
- โข Uses
$_REQUESTfor parameter access (supports GET/POST) - โข DAO pattern prevents direct SQL injection
Input Handling
Security Concerns:
1. Direct inclusion of request parameters in SQL without sanitization:
$queryString .= ' premiumclient.client_id = ' . $clientId . ' AND';
2. LIKE query construction vulnerable to injection:
$queryString .= ' (client.typeclientid like "%,' . $typeclientId . ',%") AND';
Recommendations:
- โข Use parameterized queries or proper escaping
- โข Validate numeric parameters as integers
- โข Sanitize string parameters
---
๐ Performance Considerations
Critical Performance Issues
1. N+1 Query Problem in Client Type Processing:
foreach ($allData as $allDatum) {
$typeClient = $TypeClientDAO->queryAll(); // Executes for EVERY record!
foreach ($typeClient as $az) {
// Process types
}
}
Solution: Load all types once before the loop:
$allTypes = $TypeClientDAO->queryAll();
$typeMap = array();
foreach ($allTypes as $type) {
$typeMap[$type->typeId] = $type->typeName;
}
2. Complex Join Queries: The extended DAO method getpremium() likely performs complex joins
Database Optimization Recommendations
1. Indexes Required:
- premium(date, conditions, payed) - For date range filtering
- premiumclient(client_id) - For client filtering
- client(clientareaid, typeclientid) - For area/type filtering
- Composite index: premium(premiumclientId, date, conditions)
2. Query Optimization:
- Pre-load reference data (types, areas)
- Use prepared statements for dynamic queries
- Consider pagination for large date ranges
---
๐ Common Issues & Troubleshooting
1. Performance Degradation on Large Datasets
Issue: Report becomes slow with many premium records
Cause: N+1 query pattern in type processing
Fix:
// Pre-load all types
$allTypes = $TypeClientDAO->queryAll();
$typeMap = array();
foreach ($allTypes as $type) {
$typeMap[$type->typeId] = $type->typeName;
}
// Use map for lookups instead of queries
foreach ($allData as $allDatum) {
$allDatum->typeclientid = explode(',', $allDatum->typeclientid);
$azmy = array();
foreach ($allDatum->typeclientid as $item) {
if (isset($typeMap[$item])) {
array_push($azmy, $typeMap[$item]);
}
}
// ... rest of processing
}
2. SQL Injection Vulnerability
Issue: Direct parameter inclusion in SQL queries
Cause: No input sanitization before SQL construction
Fix:
// Cast numeric parameters
$clientId = (int) $_REQUEST['clientId'];
$areaId = (int) $_REQUEST['areaId'];
$typeclientId = (int) $_REQUEST['typeclientId'];
// Or use parameterized queries in DAO layer
3. Date Timezone Issues
Issue: Reports show incorrect data due to timezone problems
Debug:
echo "Start Date: " . $startDate . "<br>";
echo "End Date: " . $endDate . "<br>";
echo "System Hours: " . $Programsetting->reportsPlusHours . "<br>";
4. Client Type Filter Not Working
Issue: Client type filter shows no results
Cause: LIKE pattern assumes comma-wrapped values
Check: Verify client.typeclientid format:
SELECT clientid, clientname, typeclientid FROM client WHERE typeclientid IS NOT NULL;
---
๐งช Testing Scenarios
Test Case 1: Basic Report Generation
1. Navigate to /controllers/premiumReportController.php
2. Leave all filters as default
3. Verify current date range applied
4. Check premium records display correctly
5. Verify client type names resolved
Test Case 2: Date Range Filtering
1. Set specific from/to date range
2. Submit report
3. Verify only premiums in date range shown
4. Test timezone adjustment if configured
5. Check edge cases (same day, large ranges)
Test Case 3: Multi-Filter Combination
1. Select specific client
2. Select specific area
3. Select specific client type
4. Set date range
5. Verify all filters applied correctly
6. Check filter message displays all criteria
Test Case 4: Performance Testing
1. Generate report with large date range
2. Monitor query execution time
3. Check for multiple type queries in logs
4. Test with many premium records
5. Verify memory usage
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข premiumController.md - Premium schedule management
- โข allpremiumReportController.php - Comprehensive premium reports
- โข clientReportsController.md - Client reporting patterns
- โข Database Performance Guide - Query optimization
---
Documented By: AI Assistant
Review Status: โ ๏ธ Contains critical performance issues
Next Review: After N+1 query optimization implemented