Expensesajex Documentation

Expenses Controller Ajax Documentation

File: /controllers/expensesControllerajex.php

Purpose: Ajax-based expense management with accounting integration, cost center allocation, and third-party API integration

Last Updated: December 20, 2024

Total Functions: 20+

Lines of Code: ~794

---

๐Ÿ“‹ Overview

The Expenses Controller Ajax provides comprehensive expense management functionality with real-time Ajax capabilities. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Core Expense Tables

Table NamePurposeKey Columns
**expensestype**Expense category definitionsexpensestypeid, expensestypename, saveid, withinsupervision_ratio
**expenses**Expense transactionsexpensesid, expensesname, expensesValue, expensestypeid, dailyentryid
**save**Cash registers/safessaveid, savename, savecurrentvalue, treeId
**savedaily**Cash register transaction logsavedailyid, saveid, savedailychangeamount, savedailychangetype
### Accounting Integration Tables

Table NamePurposeKey Columns
**dailyentry**Journal entry headersid, totalcreditor, totaldebtor, entryComment, operationId
**dailyentrycreditor**Credit side entriesdailyentryid, accountstreeid, value, dComment
**dailyentrydebtor**Debit side entriesdailyentryid, accountstreeid, value, dComment
**accountstree**Chart of accountsid, name, customName, treeId
### Cost Center & Allocation Tables

Table NamePurposeKey Columns
**costcenter**Cost center definitionsid, name, description
**costcenterdetail**Cost allocationscostcenterid, costamount, modelid, tablename, type
**assetscat**Asset categoriesid, name, description
**assets**Asset master dataassetId, assetsName
**employeedoctor**Employee/doctor recordsid, name, thetype
---

๐Ÿ”‘ Key Functions

1. add - Expense Type Creation (Ajax)

Location: Line 182

Purpose: Real-time expense type creation during expense entry

Process Flow:

1. Validate expense type name and details

2. Create new expensestype record

3. Link to accounts tree for accounting integration

4. Return updated expense type list for dropdown

2. update - Comprehensive Expense Update

Location: Line 427

Purpose: Complex expense modification with accounting reversal and recreation

Function Logic:

function update() {
    global $ExpenseDAO, $dailyEntry, $CostcenterdetailEX;
    
    // Get expense data
    $expenseid = $_POST['expenseid'];
    $expensevalue = $_POST['expensevalue'];
    $expensetype = $_POST['expensetype'];
    $dailyentryid = $_POST['dailyentryid'];
    
    $oldData = $ExpenseDAO->load($expenseid);
    
    // Handle condition changes (delete/restore)
    if ($tempdele != $conditions) {
        if ($conditions == 0) { // Restore expense
            // Validate cash register balance
            $saveValueBefore = getSaveValue();
            if ($saveValueBefore >= $expensevalue) {
                // Update cash register
                updateSave($saveId, $saveValuebefore - $expensevalue);
                // Create journal entries
                createExpenseJournalEntry($expensevalue, $expensetype);
            } else {
                return "0"; // Insufficient funds
            }
        } elseif ($conditions == 1) { // Delete expense
            // Reverse cash register transaction
            updateSave($saveId, $saveValuebefore + $expensevalue);
            // Update cost center details
            $CostcenterdetailEX->updatedellbytypeandmodelid('6', $expenseid, 1);
        }
    }
    
    // Reverse old journal entry
    $x = reverseEntryWithItsID($dailyentryid);
    
    // Create new journal entry with updated values
    $returnedData = insertEntery($dailyEntry, $dailyEntryDebtorArray, $dailyEntryCreditorArray);
    $newDailyEntryId = $returnedData[1];
    
    // Update expense record
    $ExpenseDAO->update($updatedExpense);
    
    return "1"; // Success
}

3. expensetypesave - Ajax Expense Type Search

Location: Line 253

Purpose: Real-time search for expense types with cash register filtering

Function Logic:

function expensetypesave() {
    global $ExpensetypeEX;
    
    $searchTerm = $_POST['searchTerm'];
    $saveid = $_POST['saveid'];
    
    $queryString = " and expensestypename LIKE '%" . $searchTerm . "%' ";
    
    if ($saveid) {
        $queryString .= " and ( saveid = " . $saveid . " or saveid = 0 ) ";
    }
    
    $expensetypes = $ExpensetypeEX->expensetypesave($queryString);
    $return_arr = array();
    
    foreach ($expensetypes as $pro) {
        $row_array = array();
        $row_array['id'] = $pro->expensestypeid;
        $row_array['text'] = $pro->expensestypename;
        array_push($return_arr, $row_array);
    }
    
    echo json_encode($return_arr);
}

4. expensetypesaveuser - User-Restricted Expense Search

Location: Line 269

Purpose: Expense type search with user permission filtering

Permission Logic:

if ($_SESSION['searchinonesave'] == 0 && $_SESSION['saveids'] != 0) {
    $queryString = ' and saveid in (' . $_SESSION['saveids'] . ') or saveid = 0 ';
}

foreach ($expensetypes as $pro) {
    $row_array = array();
    $row_array['id'] = $pro->expensestypeid;
    $row_array['text'] = $pro->expensestypename;
    $row_array['withinsupervisionratio'] = $pro->withinsupervision_ratio;
    array_push($return_arr, $row_array);
}

---

๐ŸŒ Third-Party API Integration

Africano Transportation System Integration

Location: Lines 290-370

Purpose: Integration with external transportation management system

5. triptype - Transportation Type Ajax

elseif ($do == "triptype") {
    $return_arr = array();
    $response = CURL_Request(array(), getenv('africanoUrl') . '/trip-type', 1, 0, getenv('africanoToken'));
    $receivedata = json_decode($response);
    
    foreach ($receivedata->data as $data) {
        $row_array = array();
        $row_array['id'] = $data->id;
        $row_array['text'] = $data->name;
        array_push($return_arr, $row_array);
    }
    echo json_encode($return_arr);
}

6. trips - Trip Management Ajax

elseif ($do == "trips") {
    $response = CURL_Request(array(), getenv('africanoUrl') . '/trip', 1, 0, getenv('africanoToken'));
    // Process trip data for dropdown population
}

7. dateid - Trip Date Filtering

elseif ($do == "dateid") {
    $tripid = (int) $_REQUEST['tripid'];
    $response = CURL_Request(array(), getenv('africanoUrl') . '/trip-date?trip_id=' . $tripid, 1, 0, getenv('africanoToken'));
    
    foreach ($receivedata->data as $data) {
        $row_array = array();
        $row_array['id'] = $data->id;
        $row_array['text'] = $data->trip_name . "/" . $data->day_date;
        $row_array['trip_id'] = $data->trip_id;
        array_push($return_arr, $row_array);
    }
}

API Endpoints Integrated:

---

๐Ÿ”‘ Utility Functions

8. expenseTypeAjax - Dynamic Expense Type Loading

Location: Line 717

Purpose: Load expense types based on user permissions and search criteria

function expenseTypeAjax() {
    global $ExpensetypeEX, $userData;
    
    $name = $_GET['term'];
    $limit = 15;
    
    if ($userData->searchinonesave == 0) {
        $allParents = $ExpensetypeEX->queryAllExtNotParent();
    } else {
        $allParents = $ExpensetypeEX->queryAllWithSaveNotParent($_SESSION['saveid']);
    }
    
    foreach ($allParents as $value) {
        if ($value->parent > 0) {
            $value->expensestypename = "$value->parentexpensestypename / $value->expensestypename";
        }
        
        $row_array['id'] = $value->expensestypeid;
        $row_array['text'] = $value->expensestypename;
        array_push($return_arr, $row_array);
    }
    
    echo json_encode($return_arr);
}

9. Cash Register Management Functions

getSaveValue() - Get Current Cash Balance:

function getSaveValue() {
    global $SaveDAO;
    $saveData = $SaveDAO->load($_SESSION['saveid']);
    return $saveData->savecurrentvalue;
}

updateSave() - Update Cash Register:

function updateSave($saveid, $savevalueafter) {
    global $Save, $SaveExt;
    
    $Save->savecurrentvalue = $savevalueafter;
    $Save->userid = $_SESSION['userid'];
    $Save->saveid = $saveid;
    
    $SaveExt->updateSaveValue($Save);
}

insertSavedaily() - Log Cash Transactions:

function insertSavedaily($savedailysavebefore, $savedailychangeamount, $savedailychangetype, 
                        $saveid, $processname, $savedailymodelid, $savedailysaveafter, $tablename) {
    global $Savedaily, $SavedailyDAO;
    
    $Savedaily->savedailydate = date("Y-m-d H:i:s");
    $Savedaily->userid = $_SESSION['userid'];
    $Savedaily->savedailysavebefore = $savedailysavebefore;
    $Savedaily->savedailychangeamount = $savedailychangeamount;
    $Savedaily->savedailychangetype = $savedailychangetype;
    $Savedaily->saveid = $saveid;
    $Savedaily->processname = $processname;
    $Savedaily->savedailymodelid = $savedailymodelid;
    $Savedaily->savedailysaveafter = $savedailysaveafter;
    $Savedaily->tablename = $tablename;
    
    $SavedailyDAO->insert($Savedaily);
}

---

๐Ÿ”„ Workflows

Workflow 1: Complete Expense Processing with Accounting Integration

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Create New Expense
User selects expense type and enters amount
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Ajax Expense Type Search
- User types in expense type field
- Ajax call to expensetypesaveuser endpoint
- Apply user permission filters:
* Check searchinonesave setting
* Filter by assigned save IDs
* Include supervision ratio data
- Return filtered expense types as JSON
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Cash Register Balance Validation
- Get current cash register balance via getSaveValue()
- Compare available balance vs expense amount
- If insufficient funds:
* Show error message
* Prevent expense creation
- If sufficient funds: proceed to next step
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Accounting Journal Entry Creation
A. Prepare Debit Entry (Expense Account):
- Load expense type to get linked account tree ID
- Create dailyentrydebtor entry:
* accountstreeid = expense type tree ID
* value = expense amount
* dComment = expense description
B. Prepare Credit Entry (Cash Account):
- Get cash register's linked account tree ID
- Create dailyentrycreditor entry:
* accountstreeid = cash account tree ID
* value = expense amount
* dComment = "Payment for " + expense name
C. Create Journal Entry Header:
- totalcreditor = totaldedbtor = expense amount
- entryComment = "Expense: " + expense description
- userid = current user
- thedate = current date
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Execute Complete Transaction
A. Call insertEntery() from dailyentryfun.php:
- Validate debit = credit amounts
- Insert dailyentry header record
- Insert all debit and credit detail records
- Update account balances in accountstree
- Return journal entry ID
B. Update Cash Register:
- Calculate new balance: current - expense amount
- Update save.savecurrentvalue
- Call insertSavedaily() to log transaction:
* savedailychangetype = 1 (decrease)
* processname = "Expense Entry"
* link to expense ID for tracking
C. Handle Cost Center Allocation (if applicable):
- If expense type has cost center assignment
- Call insertCostCenterDetail():
* Link expense amount to specific cost center
* Enable detailed cost tracking and reporting
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Create Expense Master Record
- Insert into expenses table:
* expensesname = user entered description
* expensesValue = amount
* expensestypeid = selected expense type
* dailyentryid = journal entry ID (for reversal)
* expensesdate = current date
* userid = current user
* conditions = 0 (active)
- Link expense to accounting system
- Enable future editing and reversal
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Finalization & User Feedback
- Commit all database transactions
- Update UI with success message
- Refresh expense list
- Update cash register balance display
- Log audit trail for expense creation
ERROR HANDLING:
- Rollback all transactions on any failure
- Restore original cash register balance
- Show specific error message to user
- Log error details for debugging
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Expense Update with Accounting Reversal

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Edit Existing Expense
User modifies expense amount or type
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Original Expense Data
- Load expense record by ID
- Get original: amount, type, journal entry ID
- Check current conditions (active/deleted)
- Load linked journal entry details
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Handle Status Changes (Delete/Restore)
IF conditions changed (delete โ†” restore):
A. Delete Expense (conditions = 1):
- Reverse cash register transaction
- Add expense amount back to cash balance
- Update cost center details (mark deleted)
- Mark expense as deleted
B. Restore Expense (conditions = 0):
- Validate sufficient cash balance
- Subtract expense amount from cash
- Restore cost center allocations
- Recreate accounting entries
IF no status change: proceed to amount/type update
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Reverse Original Accounting Entry
- Call reverseEntryWithItsID(original_dailyentryid)
- This creates a complete reversing entry:
* Original debits โ†’ new credits
* Original credits โ†’ new debits
* Same amounts, opposite effects
* Updates account balances back to pre-expense state
- Mark original entry as reversed
- Original cash and expense account balances restored
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Create New Accounting Entry with Updated Values
A. Prepare Updated Debit Entry:
- Use NEW expense type (may have changed)
- Use NEW expense amount
- Load expense type's chart of accounts link
B. Prepare Updated Credit Entry:
- Same cash register account
- NEW expense amount
C. Create New Journal Entry:
- Call insertEntery() with updated amounts
- Get new journal entry ID
- Update account balances with new amounts
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Update Expense Master Record
- Update expenses table with:
* New expensesname (description)
* New expensesValue (amount)
* New expensestypeid (if changed)
* New dailyentryid (new journal entry)
* Updated userid and timestamp
- Maintain audit trail of changes
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Cash Register Adjustment
IF expense amount changed:
A. Calculate difference: new_amount - old_amount
B. If difference > 0 (increase):
- Validate sufficient cash balance
- Decrease cash balance by difference
C. If difference < 0 (decrease):
- Increase cash balance by absolute difference
D. Log cash register transaction
Update save.savecurrentvalue and log in savedaily
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
7Return Success Status
- Return appropriate status code:
* "1" = Standard update successful
* "2" = Delete/restore successful
* "0" = Insufficient funds error
- UI updates based on return value
- Refresh expense list and cash balance display
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ Ajax API Endpoints

EndpointMethodPurposeParametersResponse
`?do=add`POSTCreate new expense type`expenseName`, `expensecomment`HTML template
`?do=edit`GETLoad expense for editing`id`HTML template
`?do=update`POSTUpdate expense`expenseid`, `expensevalue`, `expensetype`, etc.Status code
`?do=isParent`GETCheck if expense type has children`id`"isParent" or "isNotParent"
`?do=hasExpenses`GETCheck if type has expenses`id`"yes" or "no"
`?do=checkExp`POSTValidate expense name uniqueness`expensesname`-1 or 0
`?do=addCat`POSTAdd expense category`name`, `descripe`, `parent`Redirect
`?do=expenseTypeAjax`GETGet expense types for dropdown`assetorexpense`JSON array
`?do=getemployeeOrDoctorajax`GETGet employee/doctor list`employeeOrDoctor`JSON array
`?do=expensetypesave`POSTSearch expense types`searchTerm`, `saveid`JSON array
`?do=expensetypesaveuser`POSTUser-restricted expense search`searchTerm`, `saveid`JSON array
### Third-Party API Endpoints

EndpointPurposeExternal API
`?do=triptype`Transportation types`/trip-type`
`?do=trips`Available trips`/trip`
`?do=paths`Route definitions`/path`
`?do=dateid`Trip dates`/trip-date`
`?do=referrer`Referral sources`/referrer`
`?do=driver`Driver information`/driver`
`?do=bus`Vehicle information`/bus`
---

๐Ÿ”’ Security & Permissions

User Permission Controls

// Expense type filtering based on user permissions
if ($_SESSION['searchinonesave'] == 0 && $_SESSION['saveids'] != 0) {
    $queryString = ' and saveid in (' . $_SESSION['saveids'] . ') or saveid = 0 ';
}

// User can only see expense types for their assigned cash registers
$userData = $myUserRecord->load($_SESSION['userid']);
if ($userData->searchinonesave == 0) {
    $allParents = $ExpensetypeEX->queryAllExtNotParent();
} else {
    $allParents = $ExpensetypeEX->queryAllWithSaveNotParent($_SESSION['saveid']);
}

Input Validation

// Validate expense amounts
$expensevalue = (float) filter_input(INPUT_POST, 'expensevalue');
if ($expensevalue <= 0) {
    return "0"; // Invalid amount
}

// Validate expense type exists
$expenseTypeData = $ExpensetypeDAO->load($expensetype);
if (empty($expenseTypeData)) {
    return "0"; // Invalid expense type
}

Cash Register Protection

// Prevent negative cash balances
$currentBalance = getSaveValue();
if ($currentBalance < $expenseAmount) {
    return "0"; // Insufficient funds
}

---

๐Ÿ“Š Performance Considerations

Ajax Optimization

1. Efficient Search Queries:

- Use LIKE queries with proper indexing

- Limit results to prevent large response sizes

- Cache frequently accessed expense types

2. Database Indexes Required:

   CREATE INDEX idx_expensestype_name ON expensestype(expensestypename, saveid);
   CREATE INDEX idx_expenses_type ON expenses(expensestypeid, conditions);
   CREATE INDEX idx_savedaily_save ON savedaily(saveid, savedailydate);
   ```

### Third-Party API Performance
php

// Add timeout and error handling for external APIs

$response = CURL_Request(array(), $url, 1, 0, $token, [

'timeout' => 10,

'connecttimeout' => 5,

'retry_count' => 2

]);

if ($response === false) {

// Return empty array or cached data

echo json_encode([]);

exit;

}

---

## ๐Ÿ› Common Issues & Troubleshooting

### 1. **Ajax Search Not Working**
**Issue**: Expense type search returns no results  
**Cause**: Permission filtering or empty search parameters

**Debug**:
php

// Log search parameters

error_log("Search term: " . $_POST['searchTerm']);

error_log("Save ID: " . $_POST['saveid']);

error_log("User save restriction: " . $_SESSION['searchinonesave']);

error_log("User save IDs: " . $_SESSION['saveids']);

### 2. **Insufficient Funds Error**
**Issue**: Cannot create expense despite having cash  
**Cause**: Cash register balance calculation error

**Debug**:
php

$currentBalance = getSaveValue();

$expenseAmount = $_POST['expensevalue'];

error_log("Current balance: $currentBalance");

error_log("Expense amount: $expenseAmount");

error_log("Difference: " . ($currentBalance - $expenseAmount));

### 3. **Journal Entry Imbalance**
**Issue**: Accounting entries don't balance  
**Cause**: Currency conversion or discount calculation errors

**Debug**:
php

$totalDebits = getTotal($dailyEntryDebtorArray);

$totalCredits = getTotal($dailyEntryCreditorArray);

error_log("Debits: $totalDebits, Credits: $totalCredits");

### 4. **Third-Party API Failures**
**Issue**: External API calls timeout or return errors  
**Cause**: Network issues or API key problems

**Debug**:
php

error_log("API URL: " . getenv('africanoUrl'));

error_log("API Token: " . substr(getenv('africanoToken'), 0, 10) . "...");

error_log("API Response: " . $response);

---

## ๐Ÿงช Testing Scenarios

### Test Case 1: Basic Expense Creation

1. Select expense type via Ajax search

2. Enter valid expense amount

3. Verify cash register balance check

4. Submit expense form

5. Verify journal entry creation

6. Check cash register balance update

7. Confirm expense appears in expense list

### Test Case 2: Expense Update with Reversal

1. Edit existing expense

2. Change amount and/or type

3. Verify original journal entry reversal

4. Verify new journal entry creation

5. Check cash register adjustment

6. Confirm updated expense data

### Test Case 3: Permission-Based Search

1. Login as user with restricted save access

2. Search for expense types

3. Verify only permitted types returned

4. Login as admin user

5. Verify all types available

### Test Case 4: Third-Party API Integration

1. Test each Africano API endpoint

2. Verify JSON response structure

3. Test with invalid API credentials

4. Test network timeout handling

5. Verify graceful degradation

```

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When expense processing logic changes