CashSaveFlow Documentation

Cash Save Flow Controller Documentation

File: /controllers/cashSaveFlowController.php

Purpose: Generates comprehensive cash flow reports for safes and bank accounts

Last Updated: December 20, 2024

Total Functions: 3

Lines of Code: ~829

---

๐Ÿ“‹ Overview

The Cash Save Flow Controller is a sophisticated financial reporting module that provides detailed cash flow analysis for both physical safes and bank accounts. It handles:

Primary Functions

Transaction Categories Tracked

Safe Transactions:

Bank Transactions:

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**savedaily**Safe transaction logsavedailyid, saveid, savedailychangeamount, savedailychangetype, tablename, processname, savedailysavebefore, savedailysaveafter
**save**Safe/cash register mastersaveid, savename, savecurrentvalue, conditions
**accountmovement**Bank account transactionsaccountmovementid, accountid, accountmovementamount, accountmovementtype, tablename, accountmovementbefore, accountmovementafter
### Financial Reference Tables

Table NamePurposeKey Columns
**bankaccount**Bank account masteraccountid, accountname, accountbeginingbalance
**bank**Bank master databankid, bankname
**client**Customer informationclientid, clientname
**supplier**Supplier informationsupplierid, suppliername
**user**System usersuserid, username, searchinonesave, saveid
### Transaction Source Tables

Table NamePurposeKey Columns
**sellbill**Sales billssellbillid, sellbillclientid, sellbilltotalpayed
**buybill**Purchase billsbuybillid, buybillsupplierid, buybilltotalpayed
**clientdebtchange**Customer debt trackingclientdebtchangeid, clientid, clientdebtchangeamount
**supplierdebtchange**Supplier debt trackingsupplierdebtchangeid, supplierid, supplierdebtchangeamount
**expenses**Expense recordsexpensesid, expensesname
**income**Income recordsincomeId, incomeName
**checkdeposit**Check depositscheckdepositid, clientid, checkamount
**checkwithdrawal**Check withdrawalscheckwithdrawalid, supplierid, checkamount
---

๐Ÿ”‘ Key Functions

1. Default Action - Today's Cash Flow Report

Location: Lines 323-376

Purpose: Display automatic cash flow report for current day

Function Signature:

// Triggered when: empty($do) or no action specified
if (empty($do)) {

Process Flow:

1. Permission Check: Include authentication

2. Load Configuration:

- Get user save privileges

- Load program settings for time zone handling

- Load YouTube tutorial links

3. Date Calculation:

- Calculate today's date range

- Apply program setting hour offsets for time zones

- Determine if current time is before/after daily cutoff

4. Data Loading:

- Load available safes based on user permissions

- Load available bank accounts

- Call search() function with calculated parameters

Time Zone Logic:

if (isset($Programsetting->reportsPlusHours) && !empty($Programsetting->reportsPlusHours)) {
    $reportsPlusHours = $Programsetting->reportsPlusHours + 24;
    $endToday = date('Y-m-d H:i:s', strtotime('+' . $reportsPlusHours . ' hour', strtotime($today)));
    $startToday = date('Y-m-d H:i:s', strtotime('+' . $Programsetting->reportsPlusHours . ' hour', strtotime($today)));
}

// Determine which day's data to show based on current hour
if (date('H') < $Programsetting->reportsPlusHours) {
    $startDate = $startYesterday;  // Show yesterday's data
    $endDate = $endYesterday;
} else {
    $startDate = $startToday;      // Show today's data
    $endDate = $endToday;
}

---

2. show - Custom Date Range Report

Location: Lines 377-438

Purpose: Generate cash flow report for user-specified criteria

Function Signature:

// Triggered when: do=show
elseif ($do == "show") {

Process Flow:

1. Parameter Processing:

- Parse save/account selection: $_REQUEST['saveId'] format: {type}_{id}

- Extract date range: $_REQUEST['from'], $_REQUEST['to']

- Handle search type: dateOnly vs exact datetime

2. Message Building:

- Build descriptive report title

- Include safe name or bank account name

- Include date range information

3. Date Range Processing:

if ($search == "dateOnly") {
    if (isset($Programsetting->reportsPlusHours)) {
        $endDate = date('Y-m-d H:i:s', strtotime('+' . $reportsPlusHours . ' hour', strtotime($endDate)));
        $startDate = date('Y-m-d H:i:s', strtotime('+' . $Programsetting->reportsPlusHours . ' hour', strtotime($startDate)));
    } else {
        $endDate = $endDate . ' 23:59:59';
        $startDate = $startDate . " 00:00:00";
    }
}

4. Report Generation: Call search() with processed parameters

Input Parameters:

---

3. loadSaveByUserPrivileg() - User Permission Filtering

Location: Lines 456-475

Purpose: Load safes based on user access privileges

Function Signature:

function loadSaveByUserPrivileg()

Process Flow:

1. Load current user data

2. Check searchinonesave permission:

- 0: User can see all safes

- 1: User restricted to assigned safe only

3. Return appropriate safe list

Permission Logic:

$userData = $myUserRecord->load($_SESSION['userid']);
if ($userData->searchinonesave == 0) {
    $saveData = $mySaveRecord->queryByConditions(0);  // All safes
} else {
    $saveData = array();
    $userSave = $mySaveRecord->load($userData->saveid);  // Only assigned safe
    array_push($saveData, $userSave);
}

---

4. search() - Core Report Generation Engine

Location: Lines 478-829

Purpose: Complex report generation with transaction analysis

Function Signature:

function search($saveid, $startDate, $endDate, $accountId)

Process Flow:

Phase 1: Parameter Processing

Phase 2: Safe Transaction Processing

if ($all == 1 || $type == 'save') {
    $savedailyData = $mySavedailyEx->searchInAdsindexWithUsername($queryString, $order);
    
    // Initialize aggregation objects
    $allSell = []; // Sales totals by safe
    $allBuy = [];  // Purchase totals by safe
    
    foreach ($savedailyData as $data) {
        // Process each transaction
    }
}

Phase 3: Transaction Categorization

Sales Transactions:

if (in_array($data->tablename, ["sellbillController.php", "sellbillandruternController.php", "returnsellbillController.php"])) {
    if ($data->savedailychangetype == 1) { // Decrease (refund)
        $data->savedailychangeamount = $data->savedailychangeamount * -1;
        $inSum = $data->savedailychangeamount;
    } else { // Increase (sale)
        $inSum = $data->savedailychangeamount;
    }
    $allSell[$data->saveid]->savedailychangeamount += $data->savedailychangeamount;
}

Purchase Transactions:

elseif (in_array($data->tablename, ["buyBillController.php", "returnBuyBillController.php"])) {
    if ($data->savedailychangetype == 1) { // Decrease (purchase)
        $outSum = $data->savedailychangeamount;
    } else { // Increase (return)
        $data->savedailychangeamount = $data->savedailychangeamount * -1;
        $outSum = $data->savedailychangeamount;
    }
    $allBuy[$data->saveid]->savedailychangeamount += $data->savedailychangeamount;
}

Other Transactions (Expenses, Income, Payments):

else {
    switch ($data->tablename) {
        case "supplierPayedDeptController.php":
            $data->savecurrentvalue = $supplierDebtChangeExt->getSupplierName($data->savedailymodelid)->suppliername;
            break;
        case "clientPayedDeptController.php":
            $data->savecurrentvalue = $clientDeptChangeExt->getClientName($data->savedailymodelid)->clientname;
            break;
        case "expensesController.php":
            $data->savecurrentvalue = R::getRow('SELECT expensesname FROM expenses WHERE expensesid =' . $data->savedailymodelid)['expensesname'];
            break;
        // ... more cases
    }
    
    if ($data->savedailychangetype == 1) { // Outflow
        $outData[] = $data;
    } else { // Inflow
        $inData[] = $data;
    }
}

Phase 4: Bank Account Processing

if ($all == 1 || $type == 'bank') {
    $allMovements = $accountMovementExt->queryAllMovements($accQueryString);
    
    foreach ($allMovements as $movement) {
        // Process bank movements by transaction type
        if ($movement->tablename == "depositcheckController.php") {
            $depositData = $CheckdepositEX->loadEX($movement->accountmovementmodelid);
            $movement->clientname = $depositData->clientname;
        }
        // ... handle other bank transaction types
    }
}

Phase 5: Balance Calculations

// For each safe
if (!array_key_exists($data->saveid, $savesData)) {
    $saveData = $mySaveRecord->load($data->saveid);
    $savesData[$data->saveid] = [
        'savename' => $data->savename,
        'balance' => $data->savedailysavebefore,     // Starting balance
        'currentBalance' => $saveData->savecurrentvalue, // Current balance
        'inSum' => $inSum,   // Total inflow
        'outSum' => $outSum  // Total outflow
    ];
}

---

๐Ÿ”„ Workflows

Workflow 1: Automatic Daily Report Generation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: User Accesses Controller
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1System Initialization
- Load user permissions and safe assignments
- Load program settings for time zones
- Determine today's date range
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Time Zone Calculation
- Apply reportsPlusHours offset
- Determine if showing today or yesterday data
- Calculate start and end timestamps
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Permission-Based Data Loading
IF searchinonesave = 0:
โ”‚ โ””โ”€โ†’ Load all safes user has access to โ”‚
ELSE:
โ”‚ โ””โ”€โ†’ Load only user's assigned safe โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Generate Report
- Call search() with calculated parameters
- Process safe and bank transactions
- Display results via show.html template
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Custom Report Generation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: User Submits Search Form
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Parse Search Parameters
- Extract safe/bank selection
- Parse date range
- Determine search type (dateOnly vs exact)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Build Report Message
- Include selected safe/bank name
- Format date range display
- Create descriptive title
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Process Date Range
IF search = "dateOnly":
โ†’ Apply time zone offsets
โ”‚ โ””โ”€โ†’ Set full day range (00:00:00 to 23:59:59) โ”‚
ELSE:
โ”‚ โ””โ”€โ†’ Use exact timestamps โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Execute Search and Display
- Call search() with processed parameters
- Generate comprehensive report
- Display formatted results
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 3: Transaction Processing Engine

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Search Function Called
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Build SQL Queries
- Apply safe/account filters
- Add date range restrictions
- Include user permission filters
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Process Safe Transactions
FOR EACH transaction in savedaily:
โ”‚
โ†’ Determine transaction category
โ”‚ โ”œโ”€ Sales (in/out based on type)
โ”‚ โ”œโ”€ Purchases (in/out based on type)
โ”‚ โ”‚ โ””โ”€ Other (expenses, income, payments) โ”‚
โ”‚
โ†’ Load related entity names
โ”‚ โ”œโ”€ Client/supplier names
โ”‚ โ”œโ”€ Expense/income descriptions
โ”‚ โ”‚ โ””โ”€ Employee names โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ Update safe totals and categorize โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Process Bank Transactions
FOR EACH movement in accountmovement:
โ”‚
โ†’ Identify transaction source
โ”‚ โ”œโ”€ Check deposits
โ”‚ โ”œโ”€ Check withdrawals
โ”‚ โ”œโ”€ Cash transfers
โ”‚ โ”‚ โ””โ”€ Sales receipts โ”‚
โ”‚
โ†’ Load source document details
โ”‚
โ”‚ โ””โ”€โ†’ Update account totals โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Calculate Totals and Balances
- Aggregate inflow and outflow by safe/account
- Calculate starting balances
- Determine current balances
- Handle safes/accounts with no transactions
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Assign Data to Template
- Safe transaction data
- Bank transaction data
- Summary totals
- Sales/purchase aggregations
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
(no parameters)Default actionToday's automatic cash flow report
`do=show`Custom reportUser-specified date range and criteria
`do=sucess`Success pageDisplay success message
`do=error`Error pageDisplay error message
### Required Parameters by Action

Today's Report (no parameters):

Custom Report (do=show):

---

๐Ÿงฎ Transaction Analysis & Calculations

Transaction Type Determination

// Sales and returns affect cash positively/negatively
if (in_array($data->tablename, ["sellbillController.php", "sellbillandruternController.php", "returnsellbillController.php"])) {
    if ($data->savedailychangetype == 1) { // Decrease (refund/return)
        $inSum = $data->savedailychangeamount * -1; // Convert to negative inflow
    } else { // Increase (sale)
        $inSum = $data->savedailychangeamount; // Positive inflow
    }
}

// Purchases affect cash negatively/positively
elseif (in_array($data->tablename, ["buyBillController.php", "returnBuyBillController.php"])) {
    if ($data->savedailychangetype == 1) { // Decrease (purchase payment)
        $outSum = $data->savedailychangeamount; // Outflow
    } else { // Increase (return refund)
        $outSum = $data->savedailychangeamount * -1; // Negative outflow
    }
}

Balance Calculations

// Calculate totals for each safe
$savesData[$data->saveid] = [
    'savename' => $data->savename,
    'balance' => $data->savedailysavebefore,        // Starting balance for period
    'currentBalance' => $saveData->savecurrentvalue, // Current actual balance
    'inSum' => $inSum,                              // Total period inflow
    'outSum' => $outSum                             // Total period outflow
];

// Net change = inSum - outSum
// Expected ending balance = balance + (inSum - outSum)

Entity Name Resolution

switch ($data->tablename) {
    case "supplierPayedDeptController.php":
        $data->savecurrentvalue = $supplierDebtChangeExt->getSupplierName($data->savedailymodelid)->suppliername;
        break;
    case "clientPayedDeptController.php":
        $data->savecurrentvalue = $clientDeptChangeExt->getClientName($data->savedailymodelid)->clientname;
        break;
    case "expensesController.php":
        $data->savecurrentvalue = R::getRow('SELECT expensesname FROM expenses WHERE expensesid =' . $data->savedailymodelid)['expensesname'];
        break;
    case "incomeController.php":
        $data->savecurrentvalue = R::getRow('SELECT incomeName FROM income WHERE incomeId =' . $data->savedailymodelid)['incomeName'];
        break;
}

---

๐Ÿ”’ Security & Permissions

User Permission System

// Load user data to check permissions
$userData = $myUserRecord->load($_SESSION['userid']);

// Safe access control
if ($userData->searchinonesave == 0) {
    // User can access all safes
    if ($_SESSION['saveids'] != 0) {
        $queryString .= ' savedaily.saveid in (' . $_SESSION['saveids'] . ') AND';
    }
} else {
    // User restricted to specific safe
    $queryString .= ' savedaily.saveid = ' . $_SESSION['saveid'] . ' AND';
}

Input Validation

Data Access Control

---

๐Ÿ“Š Performance Considerations

Database Optimization Tips

1. Critical Indexes:

- savedaily(saveid, savedailydate) - For date range queries

- accountmovement(accountid, accountmovementdate) - For bank queries

- savedaily(tablename, savedailymodelid) - For transaction linking

2. Query Optimization:

- Uses complex date range filtering

- Could benefit from materialized views for common aggregations

- N+1 query issues when loading entity names

3. Memory Management:

- Large date ranges can return thousands of records

- Consider pagination for very active periods

- Template variables accumulate across all transactions

Performance Issues

-- This query pattern appears frequently and could be slow
SELECT * FROM savedaily 
WHERE saveid IN (1,2,3,4,5) 
AND savedailydate >= '2024-01-01 00:00:00' 
AND savedailydate <= '2024-01-31 23:59:59'
ORDER BY savedailydate ASC;

-- Then for each record, loads entity names individually:
SELECT expensesname FROM expenses WHERE expensesid = ?;
SELECT incomeName FROM income WHERE incomeId = ?;
-- etc...

Optimization Approach:

-- Better to use JOINs where possible
SELECT sd.*, e.expensesname, i.incomeName, c.clientname, s.suppliername
FROM savedaily sd
LEFT JOIN expenses e ON sd.tablename = 'expensesController.php' AND e.expensesid = sd.savedailymodelid
LEFT JOIN income i ON sd.tablename = 'incomeController.php' AND i.incomeId = sd.savedailymodelid
-- etc...

---

๐Ÿ› Common Issues & Troubleshooting

1. Incorrect Time Zone Handling

Issue: Report shows wrong day's data

Cause: reportsPlusHours setting not properly configured

Debug:

// Check current hour vs setting
echo "Current hour: " . date('H') . "<br>";
echo "Reports plus hours: " . $Programsetting->reportsPlusHours . "<br>";
echo "Calculated start: " . $startDate . "<br>";
echo "Calculated end: " . $endDate . "<br>";

2. Missing Transactions

Issue: Some transactions don't appear in report

Cause: Permission restrictions or date range issues

Debug:

-- Check user permissions
SELECT userid, searchinonesave, saveid FROM user WHERE userid = [USER_ID];

-- Check transaction dates
SELECT COUNT(*), MIN(savedailydate), MAX(savedailydate) 
FROM savedaily WHERE saveid = [SAVE_ID];

3. Incorrect Balance Calculations

Issue: Totals don't match expected values

Cause: Transaction type logic or sign handling

Debug:

-- Verify transaction types and amounts
SELECT tablename, savedailychangetype, SUM(savedailychangeamount)
FROM savedaily 
WHERE saveid = [SAVE_ID] AND savedailydate BETWEEN '[START]' AND '[END]'
GROUP BY tablename, savedailychangetype;

4. Performance Issues

Issue: Report takes long time to load

Cause: Large date ranges or missing indexes

Solutions:

---

๐Ÿงช Testing Scenarios

Test Case 1: Daily Report Accuracy

1. Record test transactions in different safes
2. Access controller without parameters
3. Verify correct day's data is shown
4. Check time zone handling
5. Confirm permission filtering works

Test Case 2: Custom Date Range

1. Select specific safe and date range
2. Verify all transactions in range appear
3. Check transaction categorization
4. Confirm totals are accurate
5. Test bank account reporting

Test Case 3: Permission Restrictions

1. Login as restricted user (searchinonesave = 1)
2. Verify only assigned safe appears
3. Test with unrestricted user
4. Confirm all accessible safes show

Test Case 4: Transaction Type Handling

1. Create transactions of each type
2. Verify proper categorization (in/out)
3. Check entity name resolution
4. Confirm aggregation accuracy

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur