๐Ÿ“š ERP Documentation Viewer

Beautiful, colorful documentation for your ERP system

Clients Expense Report Controller Documentation

File: /controllers/clientsexpensereport.php

Purpose: Generates comprehensive customer expense and transaction analysis reports using RedBeanPHP for database operations

Last Updated: December 20, 2024

Total Functions: 2

Lines of Code: ~119

---

๐Ÿ“‹ Overview

The Clients Expense Report Controller is a modern reporting module that provides detailed customer expense and transaction analysis. Unlike other controllers in the system that use traditional DAO classes, this controller leverages RedBeanPHP ORM for direct database operations, making it more agile for complex reporting queries. The system features:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct RedBeanPHP Access)

Table NamePurposeKey Columns
**client**Customer master dataclientid, clientname, clientdebt, conditions
**sellbill**Sales transactionssellbillid, sellbillclientid, sellbilltotalpayed, sellbilldate, conditions
**returnsellbill**Return transactionsreturnsellbillid, returnsellbillclientid, returnsellbillaftertotalbill, returnsellbilldate, conditions
**expenses**Customer expensesexpensesid, clientid, expensesValue, expensesdate, conditions
**clientdebtchange**Debt trackingclientdebtchangeid, clientid, clientdebtchangeamount, clientdebtchangedate
### Detail Tables (Product-Level Analysis)

Table NamePurposeKey Columns
**sellbilldetail**Sales line itemssellbilldetailid, sellbillid, sellbilldetailproductid, sellbilldetailquantity
**returnsellbilldetail**Return line itemsreturnsellbilldetailid, returnsellbillid, returnsellbilldetailproductid, returnsellbilldetailquantity
**product**Product masterproductId, productName, productCatId
**productcat**Product categoriesproductCatId, productCatName
---

๐Ÿ”‘ Key Functions

1. Default Action - Report Interface Display

Location: Line 6-9

Purpose: Display the client expense report interface

Process Flow:

if (empty($do)) {  
    $smarty->display("header.html");
    $smarty->display("clientsexpensereportview/show.html");
    $smarty->display("footer.html");
}

Simple Interface:

---

2. getdata Action - Comprehensive Expense Analysis Engine

Location: Line 10-116

Purpose: Process expense analysis requests and generate detailed reports

Function Signature:

// Form Parameters
$start_date = filter_input(INPUT_POST, 'start_date');  
$end_date = filter_input(INPUT_POST, 'end_date');  
$clientid = filter_input(INPUT_POST, 'clientid');

Dual Reporting Modes:

Mode 1: Individual Customer Detailed Analysis

When: $clientid is provided

Purpose: Detailed breakdown for specific customer

Process Flow:

if($clientid) {
    // Load customer master data
    $client = R::getRow('SELECT * FROM client WHERE clientid = ' . $clientid);
    
    // Load sales bills with date filtering
    $sellbill = R::getAll('SELECT * FROM sellbill WHERE sellbill.conditions = 0 
                           AND sellbill.sellbillclientid = ' . $clientid . $sellQuery);
    
    // Process each sales bill with product details
    $sellbilldata = []; 
    foreach($sellbill as $sell) {
        $sellbilldetail = R::getAll('SELECT * FROM sellbilldetail 
                                     JOIN product ON sellbilldetail.sellbilldetailproductid = product.productId
                                     JOIN productcat ON product.productCatId = productcat.productCatId 
                                     WHERE sellbilldetail.sellbillid = ?', [$sell['sellbillid']]);
        
        $sellbilldata[] = [
            'sellbillid' => $sell['sellbillid'],
            'sellbilldate' => $sell['sellbilldate'],
            'sellbilltotalpayed' => $sell['sellbilltotalpayed'],
            'sellbilldetail' => $sellbilldetail,
        ];
    }
    
    // Similar processing for returns, expenses, and debt changes
    // ...
}

Detailed Data Structure:

// Sales bills with product breakdown
$sellbilldata[] = [
    'sellbillid' => $sell['sellbillid'],
    'sellbilldate' => $sell['sellbilldate'],
    'sellbilltotalpayed' => $sell['sellbilltotalpayed'],
    'sellbilldetail' => $sellbilldetail, // Product-level details
];

// Return bills with product breakdown  
$returnsellbilldata[] = [
    'returnsellbillid' => $return['returnsellbillid'],
    'returnsellbilldate' => $return['returnsellbilldate'],
    'returnsellbillaftertotalbill' => $return['returnsellbillaftertotalbill'],
    'returnsellbilldetail' => $returnsellbilldetail,
];

Mode 2: All Customers Summary Analysis

When: $clientid is not provided

Purpose: High-level summary across all customers

Process Flow:

else {
    // Get all customers with debt changes (active customers)
    $clients = R::getAll('SELECT * FROM client 
                          JOIN clientdebtchange ON clientdebtchange.clientid = client.clientid 
                          WHERE client.conditions = 0 ' . $clientQuery . 
                          ' GROUP BY client.clientid');
    
    $clientsdata = [];
    foreach ($clients as $client) {
        // Aggregate totals for each customer
        $sellbill = R::getcell('SELECT sum(sellbilltotalpayed) FROM sellbill  
                               WHERE sellbill.conditions = 0 
                               AND sellbill.sellbillclientid = ' . $client['clientid'] . $sellQuery);
        
        $returnsellbill = R::getcell('SELECT sum(returnsellbillaftertotalbill) FROM returnsellbill  
                                     WHERE returnsellbill.conditions = 0  
                                     AND returnsellbill.returnsellbillclientid = ' . $client['clientid'] . $returnQuery);
        
        $expenses = R::getcell('SELECT sum(expensesValue) FROM expenses  
                               WHERE expenses.conditions = 0  
                               AND expenses.clientid = ' . $client['clientid'] . $expensehQuery);
        
        $clientdebtchange = R::getcell('SELECT sum(clientdebtchangeamount) FROM clientdebtchange 
                                       WHERE clientdebtchange.clientid = ' . $client['clientid'] . $changeQuery);
        
        $clientsdata[] = [
            'clientname' => $client['clientname'],
            'clientdebt' => $client['clientdebt'],
            'sellbill' => $sellbill,
            'returnsellbill' => $returnsellbill,
            'expenses' => $expenses,
            'clientdebtchange' => $clientdebtchange
        ];
    }
}

---

๐Ÿ”„ Workflows

Workflow 1: Individual Customer Analysis

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Individual Customer Analysis
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Form Submission
- Select specific customer ID
- Choose date range (optional)
- Submit getdata form
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Date Query Building
IF start_date AND end_date provided:
โ”œโ”€ Build sellQuery for sales bills
โ”œโ”€ Build returnQuery for return bills
โ”œโ”€ Build expensehQuery for expenses
โ”‚ โ””โ”€ Build changeQuery for debt changes โ”‚
ELSE:
โ”‚ โ””โ”€ Use empty queries (all time) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Customer Master Data Loading
- Load client record by clientid
- Get basic customer information
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Sales Bills Analysis
FOR EACH sales bill:
โ”‚
โ†’ Load bill header data
โ”‚
โ†’ Load product details:
โ”‚ โ”œโ”€ Join with product table
โ”‚ โ”œโ”€ Join with productcat table
โ”‚ โ”‚ โ””โ”€ Get quantity and product info โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ Build structured data array โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Return Bills Analysis
FOR EACH return bill:
โ”‚
โ†’ Load return header data
โ”‚
โ†’ Load returned product details:
โ”‚ โ”œโ”€ Join with product table
โ”‚ โ”œโ”€ Join with productcat table
โ”‚ โ”‚ โ””โ”€ Get returned quantities โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ Build structured return data โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Expenses and Debt Changes
- Load customer expenses for period
- Load debt change transactions
- Aggregate expense totals
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
7Display Detailed Report
- Customer information header
- Sales bills with product breakdown
- Return bills with product details
- Expense transactions
- Debt change history
- Display via getclient.html template
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: All Customers Summary

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: All Customers Summary
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Form Submission
- No customer ID specified
- Date range (optional)
- Submit getdata form
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Active Customers Discovery
- Query all customers with debt change activity
- Filter by conditions = 0 (active)
- Group by client.clientid
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Aggregate Data Collection
FOR EACH active customer:
โ”‚
โ†’ Sum total sales payments
โ”‚ (sellbilltotalpayed from sellbill)
โ”‚
โ†’ Sum total return amounts
โ”‚
โ†’ Sum total expenses
โ”‚ (expensesValue from expenses)
โ”‚
โ†’ Sum debt changes
โ”‚ (clientdebtchangeamount from clientdebtchange)
โ”‚
โ”‚ โ””โ”€โ†’ Build summary data structure โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Display Summary Report
- List all customers with totals
- Show aggregated amounts by category
- Display current customer debt
- Present via getdata.html template
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default actionDisplay expense report interface
`do=getdata`getdata actionProcess and display expense analysis
### Form Parameters for Analysis

All Customers Summary:

Individual Customer Analysis:

---

๐Ÿงฎ Calculation Methods

Date Query Building

if($start_date != '' && $end_date != '') {
    $sellQuery = ' and sellbill.sellbilldate >= "' . $start_date . ' 00-00-00" 
                   and sellbill.sellbilldate <= "' . $end_date . ' 23-59-55"';
    
    $returnQuery = ' and returnsellbill.returnsellbilldate >= "' . $start_date . ' 00-00-00" 
                     and returnsellbill.returnsellbilldate <= "' . $end_date . ' 23-59-55"';
    
    $expensehQuery = ' and expenses.expensesdate >= "' . $start_date . '" 
                      and expenses.expensesdate <= "' . $end_date . '"';
    
    $changeQuery = ' and clientdebtchange.clientdebtchangedate >= "' . $start_date . ' 00-00-00" 
                    and clientdebtchange.clientdebtchangedate <= "' . $end_date . ' 23-59-55"';
}

Aggregate Calculations (Summary Mode)

// Sales total for customer
$sellbill = R::getcell('SELECT sum(sellbilltotalpayed) FROM sellbill  
                       WHERE sellbill.conditions = 0 
                       AND sellbill.sellbillclientid = ' . $client['clientid'] . $sellQuery);

// Returns total for customer  
$returnsellbill = R::getcell('SELECT sum(returnsellbillaftertotalbill) FROM returnsellbill  
                             WHERE returnsellbill.conditions = 0  
                             AND returnsellbill.returnsellbillclientid = ' . $client['clientid'] . $returnQuery);

// Expenses total for customer
$expenses = R::getcell('SELECT sum(expensesValue) FROM expenses  
                       WHERE expenses.conditions = 0  
                       AND expenses.clientid = ' . $client['clientid'] . $expensehQuery);

// Debt changes total for customer
$clientdebtchange = R::getcell('SELECT sum(clientdebtchangeamount) FROM clientdebtchange 
                               WHERE clientdebtchange.clientid = ' . $client['clientid'] . $changeQuery);

---

๐Ÿ”’ Security & Permissions

Input Sanitization

$start_date = filter_input(INPUT_POST, 'start_date');  
$end_date = filter_input(INPUT_POST, 'end_date');  
$clientid = filter_input(INPUT_POST, 'clientid');

SQL Injection Prevention

Secure Pattern (Used):

$sellbilldetail = R::getAll('SELECT * FROM sellbilldetail 
                             JOIN product ON sellbilldetail.sellbilldetailproductid = product.productId
                             WHERE sellbilldetail.sellbillid = ?', [$sell['sellbillid']]);

Risky Pattern (Also Used):

$sellbill = R::getAll('SELECT * FROM sellbill WHERE sellbill.conditions = 0 
                       AND sellbill.sellbillclientid = ' . $clientid . $sellQuery);

Access Control

---

๐Ÿ“Š Performance Considerations

Database Optimization Tips

1. Indexes Required:

- sellbill(sellbillclientid, sellbilldate, conditions)

- returnsellbill(returnsellbillclientid, returnsellbilldate, conditions)

- expenses(clientid, expensesdate, conditions)

- clientdebtchange(clientid, clientdebtchangedate)

- client(conditions)

2. Query Optimization:

- Uses direct aggregate functions (SUM) for performance

- Separate queries avoid complex JOINs

- Date filtering applied at database level

3. RedBeanPHP Performance:

- Direct SQL queries for better performance

- Avoids ORM overhead for reporting

- Uses prepared statements where available

Performance Risks

// This GROUP BY query could be slow with large datasets
$clients = R::getAll('SELECT * FROM client 
                      JOIN clientdebtchange ON clientdebtchange.clientid = client.clientid 
                      WHERE client.conditions = 0 
                      GROUP BY client.clientid');

Improvement Suggestion:

-- Use DISTINCT instead of GROUP BY for better performance
SELECT DISTINCT c.clientid, c.clientname, c.clientdebt, c.conditions
FROM client c
INNER JOIN clientdebtchange cdc ON cdc.clientid = c.clientid  
WHERE c.conditions = 0;

---

๐Ÿ› Common Issues & Troubleshooting

1. RedBeanPHP Compatibility Issues

Issue: RedBeanPHP syntax conflicts with other ORM systems

Cause: Mixed ORM usage in single application

Debug:

// Check if RedBeanPHP is properly initialized
if (!class_exists('R')) {
    throw new Exception("RedBeanPHP not available");
}

// Test basic connectivity
$test = R::testConnection();

2. Date Format Issues

Issue: Date filtering not working correctly

Cause: Inconsistent date formats

Debug:

echo "Start Date: " . $start_date . "<br>";
echo "End Date: " . $end_date . "<br>";
echo "Sell Query: " . $sellQuery . "<br>";

// Validate date format
if (!DateTime::createFromFormat('Y-m-d', $start_date)) {
    throw new Exception("Invalid start date format");
}

3. Missing Product Details

Issue: Product information not showing in detailed report

Cause: JOINs failing due to data inconsistencies

Debug:

-- Check for missing product data
SELECT sbd.sellbillid, sbd.sellbilldetailproductid, p.productName
FROM sellbilldetail sbd
LEFT JOIN product p ON sbd.sellbilldetailproductid = p.productId  
WHERE p.productId IS NULL;

-- Check for missing category data
SELECT p.productId, p.productName, p.productCatId, pc.productCatName
FROM product p
LEFT JOIN productcat pc ON p.productCatId = pc.productCatId
WHERE pc.productCatId IS NULL;

4. Performance Issues with Large Datasets

Issue: Reports running slowly or timing out

Cause: Inefficient queries or missing indexes

Solutions:

// Add pagination for large datasets
$limit = 100;
$offset = ($page - 1) * $limit;
$clients = R::getAll('SELECT * FROM client 
                      WHERE conditions = 0 
                      LIMIT ' . $limit . ' OFFSET ' . $offset);

// Add execution time monitoring
$start_time = microtime(true);
// ... query execution ...
$end_time = microtime(true);
echo "Query took: " . ($end_time - $start_time) . " seconds";

---

๐Ÿงช Testing Scenarios

Test Case 1: Individual Customer Detailed Analysis

1. Create customer with various transaction types:
   - Sales bills with products
   - Return bills with products
   - Expense records
   - Debt change entries
2. Submit form with customer ID and date range
3. Verify all transaction types appear
4. Check product details are correctly joined
5. Validate date filtering works correctly

Test Case 2: All Customers Summary

1. Create multiple customers with different activity levels
2. Submit form without customer ID
3. Verify all active customers appear in summary
4. Check aggregated totals are correct
5. Verify inactive customers (no debt changes) are excluded

Test Case 3: Date Range Filtering

1. Create transactions on different dates
2. Test various date ranges:
   - Single day
   - Month range  
   - Year range
   - Empty dates (all time)
3. Verify filtering works across all transaction types
4. Test edge cases (start/end of day)

Test Case 4: Data Integrity

1. Test with missing product data
2. Test with missing category data
3. Test with deleted/cancelled transactions
4. Verify error handling for invalid customer IDs
5. Test with empty result sets

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur

โ†‘