PremiumReport Documentation

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

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**premium**Premium payment recordsid, date, value, premiumclientId, payed, rest, conditions
**premiumclient**Premium client masterid, client_id, userid, date
**client**Customer informationclientid, clientname, typeclientid, clientareaid
**clientarea**Customer areasclientareaid, name
**typeclient**Client type definitionstypeId, typeName
### Reference Tables

Table NamePurposeKey Columns
**programsettings**System configurationprogramsettingsid, reportsPlusHours
**youtubelink**Tutorial videosyoutubelinkid, title, url
### Query Relationships

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:

---

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

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Premium Report Request
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Reference Data
- Load all clients for dropdown
- Load all areas for dropdown
- Load all client types for dropdown
- Load system settings for timezone
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Extract Filter Parameters
- Get date range (from/to)
- Get client ID filter
- Get area ID filter
- Get client type filter
- Set defaults if parameters missing
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Build Dynamic SQL Query
- Start with base WHERE clause
- Add client filter if specified
- Add area filter if specified
- Add client type filter if specified
- Add date range with timezone adjustment
- Clean up trailing AND/WHERE
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Execute Premium Query
- Query premium data with joins
- Include client and area information
- Filter by constructed WHERE clause
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Process Client Type Names
FOR EACH premium record:
โ”‚
โ†’ Parse comma-separated type IDs
โ”‚
โ†’ Look up type names from type table
โ”‚
โ†’ Handle special "all types" case
โ”‚
โ”‚ โ””โ”€โ†’ Build display string of type names โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Generate Report Display
- Assign data to Smarty template
- Include filter message summary
- Display via premiumReportview/showNew.html
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescriptionAuthentication
`do=show` or emptyDefaultGenerate premium reportRequired
### Filter Parameters

Date Range:

Client Filters:

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:

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:

---

๐Ÿ“Š 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

---

Documented By: AI Assistant

Review Status: โš ๏ธ Contains critical performance issues

Next Review: After N+1 query optimization implemented