Clientpayments Documentation

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:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**sellbill**Sales billssellbillid, sellbillclientid, sellbilltotalpayed, sellbilldate, conditions
**returnsellbill**Sales return billsreturnsellbillid, returnsellbillclientid, returnsellbilltotalpayed, returnsellbilldate, conditions
**sellbillandrutern**Combined sell/return billssellbillid, sellbillclientid, sellbilltotalpayed, sellbillaftertotalbill, sellbilldate
**bills**Optical billsbillid, clientid, cashvalue, cardvalue, billdate, deleted
**billsreturn**Optical return billsbillid, clientid, clientreceivevalue, date, deleted
**clientdebtchange**Customer debt changesclientdebtchangeid, clientid, clientdebtchangeamount, tablename, clientdebtchangedate
### Reference Tables

Table NamePurposeKey Columns
**client**Customer master dataclientid, clientname, clientarea, clientgovernmentid, conditions
**clientarea**Customer areasid, name, description
**government**Government/state datagovernmentid, governmentname
**user**System usersuserid, username
**youtubelink**Tutorial linksyoutubelinkid, title, url
**programsettings**System settingsprogramsettingsid, 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

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Access Payment Report
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Form Filters
- Government dropdown
- Area dropdown
- Date range fields
- YouTube tutorials
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Process Search Parameters
- Parse date range
- Handle timezone adjustments
- Filter by government/area
- Build client filter string
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Build Query Strings
- Sales bills query
- Return bills query
- Optical bills query
- Combined bills query
- Debt change query
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Execute getData() Function
- Query all payment sources
- Aggregate by customer
- Calculate totals
- Handle duplicates
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Display Results
- Customer list with payments
- Grand total
- Results count
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Multi-Source Payment Aggregation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: getData() Function
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Initialize Data Structures
- clientData array
- existId tracking array
- Results counter
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Query All Payment Sources
FOR EACH payment source:
โ”‚
โ†’ Sales bills (sellbill table)
โ†’ Return bills (returnsellbill table)
โ†’ Combined bills (sellbillandrutern table)
โ†’ Optical bills (bills table)
โ†’ Optical returns (billsreturn table)
โ”‚ โ””โ”€โ†’ Direct payments (clientdebtchange table) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Process Each Payment Source
FOR EACH payment record:
โ”‚
โ†’ Check if customer exists in results
โ”‚ โ”œโ”€ YES: Update existing client data
โ”‚ โ”‚ โ””โ”€ NO: Create new clientData object โ”‚
โ”‚
โ†’ Add/subtract payment amount
โ”‚ โ”œโ”€ Sales: Add to total
โ”‚ โ”œโ”€ Returns: Subtract from total
โ”‚ โ”‚ โ””โ”€ Combined: Check sign for add/subtract โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ Load client name if missing โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Calculate Final Totals
- Sum all customer payments
- Count total records processed
- Assign data to Smarty templates
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default actionDisplay payment report form and process search
### Form Parameters

Payment Report Form:

---

๐Ÿงฎ 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

Input Sanitization

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

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur