Client Payments Controller Documentation
File: /controllers/clientpayments.php
Purpose: Generates client payment reports aggregating payments from all sales channels and bill types
Last Updated: December 20, 2024
Total Functions: 3
Lines of Code: ~422
---
๐ Overview
The Client Payments Controller is a comprehensive payment reporting module that aggregates and displays customer payments across all sales channels and bill types in the ERP system. It provides:
- โข Combined payment data from multiple billing sources
- โข Area and government-based customer filtering
- โข Date range reporting with intelligent defaults
- โข Payment aggregation across different transaction types
- โข Real-time payment reconciliation and totals
- โข Regional customer grouping for management reporting
Primary Functions
- โ Aggregate payments from all sales bill types
- โ Aggregate payments from optical bills
- โ Aggregate payments from return bills
- โ Include customer debt change payments
- โ Filter by customer area or government
- โ Date range filtering with smart defaults
- โ Real-time payment totals calculation
- โ Customer-wise payment aggregation
- โ Multi-source payment reconciliation
Related Controllers
- โข sellbillController.php - Sales operations
- โข returnsellbillController.php - Sales returns
- โข clientPayedDeptController.php - Direct payments
- โข billreceiptController.php - Optical bill receipts
- โข clientController.php - Customer management
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **sellbill** | Sales bills | sellbillid, sellbillclientid, sellbilltotalpayed, sellbilldate, conditions | |
| **returnsellbill** | Sales return bills | returnsellbillid, returnsellbillclientid, returnsellbilltotalpayed, returnsellbilldate, conditions | |
| **sellbillandrutern** | Combined sell/return bills | sellbillid, sellbillclientid, sellbilltotalpayed, sellbillaftertotalbill, sellbilldate | |
| **bills** | Optical bills | billid, clientid, cashvalue, cardvalue, billdate, deleted | |
| **billsreturn** | Optical return bills | billid, clientid, clientreceivevalue, date, deleted | |
| **clientdebtchange** | Customer debt changes | clientdebtchangeid, clientid, clientdebtchangeamount, tablename, clientdebtchangedate |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **client** | Customer master data | clientid, clientname, clientarea, clientgovernmentid, conditions | |
| **clientarea** | Customer areas | id, name, description | |
| **government** | Government/state data | governmentid, governmentname | |
| **user** | System users | userid, username | |
| **youtubelink** | Tutorial links | youtubelinkid, title, url | |
| **programsettings** | System settings | programsettingsid, settingkey, settingvalue, reportsPlusHours |
๐ Key Functions
1. Default Action - Payment Report Display
Location: Line 128-203
Purpose: Display payment report form and process search parameters
Function Signature:
// Triggered when: empty($do)
$datefrom = filter_input(INPUT_POST, 'datefrom');
$dateto = filter_input(INPUT_POST, 'dateto');
$govid = filter_input(INPUT_POST, 'govid');
$areaid = filter_input(INPUT_POST, 'areaid');
Process Flow:
1. Load government and area data for filters
2. Load YouTube tutorial links
3. Parse search parameters from form
4. Build dynamic query strings for each table type
5. Handle date formatting with program settings
6. Filter clients by area or government if specified
7. Call getData() function to aggregate payments
8. Display results via clientpaymentsviw/show.html
Query String Building:
$queryString = " where 1 and bills.deleted = 0 "; // Optical bills
$queryStringR = " where 1 and billsreturn.deleted = 0 "; // Return bills
$queryString1 = " where 1 and sellbill.conditions = 0 "; // Sales bills
$queryString1R = " where 1 and returnsellbill.conditions = 0 "; // Sales returns
$queryString1SR = " where 1 and sellbillandrutern.conditions = 0 "; // Combined bills
$queryStringCDC = " where 1 and clientdebtchange.del = 0 "; // Debt changes
Date Handling:
if (isset($Programsetting->reportsPlusHours) && !empty($Programsetting->reportsPlusHours)) {
$reportsPlusHours = $Programsetting->reportsPlusHours + 24;
$datefrom = date('Y-m-d H:i:s', strtotime('+' . $Programsetting->reportsPlusHours . ' hour', strtotime($datefrom)));
} else {
$datefrom = $datefrom . " 00:00:00";
}
---
2. getData() - Payment Aggregation Engine
Location: Line 211-421
Purpose: Aggregate payments from all sources and calculate customer totals
Function Signature:
function getData($datefrom, $dateto, $govid, $areaid, $queryString, $queryStringR,
$queryString1, $queryString1R, $queryString1SR, $queryStringCDC, $clientString)
Data Aggregation Process:
1. Sales Bills Processing (Lines 278-298):
foreach ($sellBillData as $key => $value) {
if (in_array($value->sellbillclientid, $existId)) {
$key = array_search($value->sellbillclientid, $existId);
$myclient = $sellbillDataArr[$key];
} else {
$myclient = new clientData();
$myclient->clientid = $value->sellbillclientid;
array_push($existId, $value->sellbillclientid);
}
$myclient->totalpayed += $value->sellbilltotalpayed;
// Load client name if not set
if ($myclient->clientname == "") {
$client = $clientDAO->load($myclient->clientid);
$myclient->clientname = $client->clientname;
}
}
2. Return Bills Processing (Lines 300-320):
foreach ($sellBillDataReturn as $key => $value) {
// Same client lookup logic as sales
$myclient->totalpayed -= $value->returnsellbilltotalpayed; // Subtract returns
}
3. Combined Bills Processing (Lines 322-345):
foreach ($sellBillDataSellAndReturn as $key => $value) {
if ($value->sellbillaftertotalbill >= 0) {
$myclient->totalpayed += $value->sellbilltotalpayed; // Add sales
} else {
$myclient->totalpayed -= $value->sellbilltotalpayed; // Subtract returns
}
}
4. Optical Bills Processing (Lines 347-367):
foreach ($billsData as $key => $value) {
$myclient->totalpayed += $value->cashvalue + $value->cardvalue;
}
5. Optical Returns Processing (Lines 369-389):
foreach ($billsDataReturn as $key => $value) {
$myclient->totalpayed -= $value->clientreceivevalue;
}
6. Direct Payments Processing (Lines 391-411):
foreach ($clientDeptChange as $key => $value) {
$myclient->totalpayed += $value->clientdebtchangeamount;
}
Smart Defaults:
if (empty($datefrom) && empty($dateto) && empty($govid) && empty($areaid)) {
$today = date("Y-m-d");
// Apply today's date to all query strings
$queryString .= ' and date(bills.billdate) = "' . $today . '" ';
}
Cash Customer Exclusion:
// Exclude cash customer (ID = 1) from all queries
$queryString .= 'and bills.clientid != 1 ';
$queryString1 .= 'and sellbill.sellbillclientid != 1 ';
---
3. clientData Class - Data Structure
Location: Line 226-232
Purpose: Define structure for aggregated client payment data
Class Definition:
class clientData {
public $clientid;
public $clientname;
public $totalpayed = 0;
}
---
๐ Workflows
Workflow 1: Payment Report Generation
---
Workflow 2: Multi-Source Payment Aggregation
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description |
|---|---|---|
| `do=` (empty) | Default action | Display payment report form and process search |
Payment Report Form:
- โข
datefrom- Start date (YYYY-MM-DD) - โข
dateto- End date (YYYY-MM-DD) - โข
govid- Government/state ID filter - โข
areaid- Customer area ID filter
---
๐งฎ Calculation Methods
Payment Aggregation Logic
// Sales bills - Add payments
$myclient->totalpayed += $value->sellbilltotalpayed;
// Return bills - Subtract payments (refunds)
$myclient->totalpayed -= $value->returnsellbilltotalpayed;
// Combined bills - Check direction
if ($value->sellbillaftertotalbill >= 0) {
$myclient->totalpayed += $value->sellbilltotalpayed; // Sale
} else {
$myclient->totalpayed -= $value->sellbilltotalpayed; // Return
}
// Optical bills - Add cash and card payments
$myclient->totalpayed += $value->cashvalue + $value->cardvalue;
// Optical returns - Subtract refund amount
$myclient->totalpayed -= $value->clientreceivevalue;
// Direct debt changes - Add payment amount
$myclient->totalpayed += $value->clientdebtchangeamount;
Grand Total Calculation
$sum = 0;
foreach ($sellbillDataArr as $myclient) {
$sum += $myclient->totalpayed;
}
---
๐ Security & Permissions
Access Control
- โข Requires authentication via
../public/authentication.php - โข No specific permission level checks (accessible to all authenticated users)
Input Sanitization
- โข Uses
filter_input(INPUT_POST, ...)for all form parameters - โข Date strings validated before SQL inclusion
- โข SQL injection prevented by DAO layer parameterized queries
Cash Customer Handling
// Exclude cash customer (ID = 1) from all payment reports
if ($value->clientid != 1) {
$clientString .= $value->clientid . ',';
}
---
๐ Performance Considerations
Database Optimization Tips
1. Indexes Required:
- sellbill(sellbillclientid, sellbilldate, conditions)
- returnsellbill(returnsellbillclientid, returnsellbilldate, conditions)
- sellbillandrutern(sellbillclientid, sellbilldate, conditions)
- bills(clientid, billdate, deleted)
- billsreturn(clientid, date, deleted)
- clientdebtchange(clientid, clientdebtchangedate, del, tablename)
2. Query Optimization:
- Multiple separate queries instead of complex JOINs
- Date filtering at database level
- Early filtering of deleted/cancelled records
3. Memory Management:
- Client deduplication in PHP reduces memory usage
- Large date ranges may return many records
- Consider pagination for high-volume systems
Smart Defaults Performance
// If no search criteria, default to today only
if (empty($datefrom) && empty($dateto) && empty($govid) && empty($areaid)) {
$today = date("Y-m-d");
// Apply date filter to all queries
}
---
๐ Common Issues & Troubleshooting
1. Missing Payments in Report
Issue: Customer payments not appearing in report
Cause: Multiple possible sources
Debug Steps:
-- Check if payment exists in sellbill
SELECT sellbillid, sellbillclientid, sellbilltotalpayed, sellbilldate
FROM sellbill WHERE sellbillclientid = [ID] AND sellbilldate = '[DATE]';
-- Check if payment exists in clientdebtchange
SELECT * FROM clientdebtchange
WHERE clientid = [ID] AND tablename = 'clientPayedDeptController.php';
-- Check bill conditions (0 = valid)
SELECT conditions FROM sellbill WHERE sellbillid = [ID];
2. Incorrect Payment Totals
Issue: Payment amounts don't match expected values
Cause: Double counting or missing data sources
Debug:
// Add debugging to getData() function
echo "Sales Bills: " . count($sellBillData) . "<br>";
echo "Return Bills: " . count($sellBillDataReturn) . "<br>";
echo "Combined Bills: " . count($sellBillDataSellAndReturn) . "<br>";
echo "Optical Bills: " . count($billsData) . "<br>";
echo "Direct Payments: " . count($clientDeptChange) . "<br>";
3. Date Filter Issues
Issue: Reports show wrong date ranges
Cause: Timezone settings or date format problems
Fix:
// Check programsettings for reportsPlusHours
SELECT * FROM programsettings WHERE settingkey = 'reportsPlusHours';
// Verify date format consistency
echo "From: " . $datefrom . "<br>";
echo "To: " . $dateto . "<br>";
4. Area/Government Filter Not Working
Issue: Geographic filters not filtering correctly
Cause: Client area/government assignments missing
Debug:
-- Check client area assignments
SELECT c.clientid, c.clientname, c.clientarea, ca.name as area_name
FROM client c
LEFT JOIN clientarea ca ON c.clientarea = ca.id
WHERE c.clientid IN (1,2,3);
-- Check government assignments
SELECT c.clientid, c.clientname, c.clientgovernmentid, g.governmentname
FROM client c
LEFT JOIN government g ON c.clientgovernmentid = g.governmentid
WHERE c.clientid IN (1,2,3);
---
๐งช Testing Scenarios
Test Case 1: Basic Payment Report
1. Select date range with known payments
2. Run report without filters
3. Verify total matches manual calculation
4. Check individual customer totals
5. Confirm all payment sources included
Test Case 2: Geographic Filtering
1. Create test customers in different areas/governments
2. Add known payment amounts
3. Filter by area
4. Verify only customers in selected area appear
5. Verify payment totals remain accurate
Test Case 3: Date Range Filtering
1. Create payments on different dates
2. Set narrow date range
3. Verify only payments in range included
4. Test edge cases (start/end of day)
5. Test timezone handling if applicable
Test Case 4: Multi-Source Validation
1. Create payments in each source type:
- Sales bill payment
- Return bill payment
- Optical bill payment
- Direct customer payment
2. Run report
3. Verify each source contributes correctly
4. Check for double counting
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข sellbillController.md - Sales operations
- โข clientPayedDeptController.md - Direct payments
- โข clientController.php - Customer management
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur