Assistantledger Documentation

Assistant Ledger Controller Documentation

File: /controllers/assistantledger.php

Purpose: Generate detailed account ledger reports with transaction analysis and T-shape formatting

Last Updated: December 20, 2024

Total Functions: 6+

Lines of Code: ~559

---

๐Ÿ“‹ Overview

The Assistant Ledger Controller provides comprehensive accounting ledger functionality with advanced transaction analysis capabilities. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Core Accounting Tables

Table NamePurposeKey Columns
**accountstree**Chart of accountsid, parent, customName, theValue, itemtype2
**dailyentry**Journal entry headersid, thedate, entryComment, related
**dailyentrydebtor**Debit entriesid, dailyentryid, accountstreeid, value, dComment
**dailyentrycreditor**Credit entriesid, dailyentryid, accountstreeid, value, dComment
### Support Tables

Table NamePurposeKey Columns
**youtubelink**Tutorial videosyoutubelinkid, title, url
---

๐Ÿ”‘ Key Functions

1. Default Action - Ledger Interface

Location: Line 76

Purpose: Display ledger interface with parameter handling

Process Flow:

1. Parse input parameters from POST data

2. Set default date range if not provided

3. Load YouTube tutorial links

4. Check account type for child account handling

5. Call appropriate ledger generation function

6. Display results via Smarty template

Parameter Handling:

$accountsTreeId = filter_input(INPUT_POST, "assistantledgerid");
$datefrom = filter_input(INPUT_POST, "datefrom");
$dateto = filter_input(INPUT_POST, "dateto");
$shape = filter_input(INPUT_POST, "shape");

Default Values:

if (empty($accountsTreeId)) {
    $accountsTreeId = -1;
}

if (empty($shape) || !isset($shape)) {
    $shape = 0; // Standard format
}

if (empty($datefrom) && empty($dateto)) {
    $datefrom = date('Y-m-d');
    $dateto = date('Y-m-d');
}

---

2. DrawTableByAccountNew() - Advanced Ledger Generation

Location: Line 130

Purpose: Generate comprehensive account ledger with transaction matching

Function Signature:

function DrawTableByAccountNew($id, $startDate, $endDate, $shape)

Process Flow:

1. Build date filter SQL clauses

2. Query for related daily entries (both debtor and creditor)

3. Process transactions to find matching relationships

4. Handle single vs. multiple transaction scenarios

5. Apply T-shape formatting if requested

6. Sort and assign data to template

Complex SQL Generation:

$queryStringDebtor = ' where dailyentrydebtor.accountstreeid in( ' . $id . ') ' . $queryString_date . ' ';
$queryStringCreditor = ' where dailyentrycreditor.accountstreeid in( ' . $id . ') ' . $queryString_date . ' ';

// Union query to get all related entry IDs
$dailyEntryIds = R::getAll('(   SELECT dailyentry.id
                                FROM dailyentry
                                join dailyentrydebtor on dailyentrydebtor.dailyentryid = dailyentry.id
                               ' . $queryStringDebtor . '
                            )union(
                                SELECT dailyentry.id
                                FROM dailyentry
                                join dailyentrycreditor on dailyentrycreditor.dailyentryid = dailyentry.id
                                ' . $queryStringCreditor . ')');

Transaction Relationship Logic:

foreach ($mainItem as $myItem) {
    // Get count of sibling transactions
    $itemBroCount = count($itemBro[$myItem['id']]) + 1;
    
    // Get opposing side transactions
    $result = $resultDataArr[$myItem['id']];
    $resultCount = count($result);
    
    if ($itemBroCount == 1 && $resultCount >= 1) {
        // Simple one-to-one or one-to-many
        foreach ($result as $value) {
            array_push($allDailyEntery, $value);
        }
    } elseif ($itemBroCount > 1 && $resultCount == 1) {
        // Many-to-one relationship
        $result[0]->value = $myItem['value'];
        array_push($allDailyEntery, $result[0]);
    } elseif ($itemBroCount > 1 && $resultCount > 1) {
        // Complex many-to-many relationship
        $result[0]->accountstreeName = "ู…ุฐูƒูˆุฑูŠู†"; // Multiple accounts
        $result[0]->value = $myItem['value'];
        array_push($allDailyEntery, $result[0]);
    }
}

---

3. T-Shape Formatting Logic

Location: Line 319-353

Purpose: Format ledger data in traditional T-account layout

Process Flow:

1. Separate debtor and creditor transactions

2. Calculate total count for proper alignment

3. Alternate between debit and credit columns

4. Fill empty cells with blank entries

5. Track actual vs. total record count

T-Shape Implementation:

$debtorItr = 0;
$creditorItr = 0;
$realCount = 0;
$totalCount = count($TShapeArrDebtor) + count($TShapeArrCerditor);

for ($i = 0; $i < ($totalCount * 2); $i++) {
    if (empty($TShapeArrDebtor[$debtorItr]) && empty($TShapeArrCerditor[$creditorItr])) {
        // No more data to process
    } else {
        $realCount++;
        if ($i % 2 == 0) { // Even positions for debtors
            if (empty($TShapeArrDebtor[$debtorItr])) {
                array_push($allDailyEntery, $dailyEntry);
            } else {
                array_push($allDailyEntery, $TShapeArrDebtor[$debtorItr]);
                $debtorItr++;
            }
        } else { // Odd positions for creditors
            if (empty($TShapeArrCerditor[$creditorItr])) {
                array_push($allDailyEntery, $dailyEntry);
            } else {
                array_push($allDailyEntery, $TShapeArrCerditor[$creditorItr]);
                $creditorItr++;
            }
        }
    }
}

---

4. Advanced Account Name Generation

Location: Lines 186-192, 256-262

Purpose: Create hierarchical account names with parent/child relationships

Implementation:

// Generate account path: Parent/Child format
concat(dailyentrycreditor.accountstreeid,"-",parent.customName,"/",accountstree.customName) as accountstreeName

// Join with parent accounts
join accountstree on accountstree.id = dailyentrycreditor.accountstreeid
join accountstree parent on parent.id = accountstree.parent

---

5. sortById() - Custom Sorting Algorithm

Location: Line 520

Purpose: Sort transactions by ID with custom bubble sort implementation

Function Signature:

function sortById($type)

Implementation:

$membresCount = count($allDailyEntery) - 1;
foreach ($allDailyEntery as $myalloutRole) {
    for ($i = 0; $i < $membresCount; $i++) {
        if ($type == "desc") {
            if ($allDailyEntery[$i]->id < $allDailyEntery[$i + 1]->id) {
                $tempMember = $allDailyEntery[$i];
                $allDailyEntery[$i] = $allDailyEntery[$i + 1];
                $allDailyEntery[$i + 1] = $tempMember;
            }
        } elseif ($type == "asc") {
            if ($allDailyEntery[$i]->id > $allDailyEntery[$i + 1]->id) {
                $tempMember = $allDailyEntery[$i + 1];
                $allDailyEntery[$i + 1] = $allDailyEntery[$i];
                $allDailyEntery[$i] = $tempMember;
            }
        }
    }
}

---

6. getChilds() - Recursive Account Hierarchy

Location: Line 545

Purpose: Recursively retrieve child accounts for hierarchical processing

Function Signature:

function getChilds($parent)

Implementation:

function getChilds($parent) {
    global $accountsTreeEX;
    global $cildrenIds;
    
    $result = $accountsTreeEX->queryByParentExt($parent);
    if (count($result) > 0) {
        foreach ($result as $type) {
            $cildrenIds .= $type->id . ',';
            getChilds($type->id); // Recursive call
        }
    }
    return $cildrenIds;
}

---

๐Ÿ”„ Workflows

Workflow 1: Standard Ledger Generation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Select Account & Date Range
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Validate Input Parameters
- Account ID (-1 for all)
- Date range (default to today)
- Display shape (0=standard, 1=T-shape)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Check Account Type
IF account has children AND itemtype2 == 0:
โ”‚ โ””โ”€โ†’ Skip processing (parent account) โ”‚
ELSE:
โ”‚ โ””โ”€โ†’ Proceed with ledger generation โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Build Date Filter SQL
- Add start date condition if specified
- Add end date condition if specified
- Combine with account filter
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Query Related Daily Entries
- UNION query for debtor and creditor sides
- Get all daily entry IDs that involve this account
- Build consolidated ID list
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Process Debtor Transactions
FOR EACH debtor transaction:
โ”‚
โ†’ Get main transaction details
โ†’ Count sibling transactions
โ†’ Get opposing creditor transactions
โ†’ Determine relationship type
โ”‚ โ””โ”€โ†’ Format account names appropriately โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Process Creditor Transactions
FOR EACH creditor transaction:
โ”‚
โ†’ Get main transaction details
โ†’ Count sibling transactions
โ†’ Get opposing debtor transactions
โ†’ Determine relationship type
โ”‚ โ””โ”€โ†’ Format account names appropriately โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
7Apply Display Formatting
IF shape == 0 (Standard):
โ”‚ โ””โ”€โ†’ Sort by ID ascending โ”‚
ELSE IF shape == 1 (T-Shape):
โ†’ Separate debtor and creditor arrays
โ†’ Alternate between debit/credit columns
โ”‚ โ””โ”€โ†’ Fill empty positions with blank entries โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
8Generate Report Output
- Assign data to Smarty template
- Include account details and totals
- Display via assistantledgerview/add.html
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: T-Shape Ledger Formatting

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: T-Shape Format Request
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Separate Transaction Types
- TShapeArrDebtor: All debit transactions
- TShapeArrCreditor: All credit transactions
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Calculate Layout Requirements
- Total count = debtors + creditors
- Real count = actual populated cells
- Initialize iterators for each side
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Generate T-Shape Layout
FOR i = 0 to (totalCount * 2):
โ”‚
โ”œโ”€โ†’ IF i is even: Place debtor transaction
โ”‚ โ”‚ โ””โ”€โ†’ Use blank entry if no more debtors โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ IF i is odd: Place creditor transaction โ”‚
โ”‚ โ””โ”€โ†’ Use blank entry if no more creditors โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Assign to Template
- Set realCount for template logic
- Pass formatted array to Smarty
- Display with T-shape CSS styling
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default actionGenerate ledger report
`do=sucess`Show templateDisplay success message
`do=error`Show templateDisplay error message
### Required Parameters

Ledger Generation:

---

๐Ÿงฎ Advanced SQL Analysis

Transaction Relationship Detection

-- Get main item transactions (account as debtor)
SELECT dailyentry.id, dailyentrydebtor.value, 0 as type
FROM dailyentry
JOIN dailyentrydebtor ON dailyentrydebtor.dailyentryid = dailyentry.id
WHERE dailyentry.id IN (entry_ids) 
  AND accountstreeid IN (account_id)
ORDER BY dailyentry.related, dailyentry.id, dailyentrydebtor.id

-- Get brother transactions (other accounts in same entry)
SELECT dailyentryid
FROM dailyentrydebtor
WHERE dailyentrydebtor.accountstreeid NOT IN (account_id) 
  AND dailyentryid IN (entry_ids)

-- Get opposing transactions (credits in same entries)
SELECT dailyentry.*, 
       dailyentrycreditor.value,
       CONCAT(parent.customName, "/", accountstree.customName) as accountstreeName
FROM dailyentry
JOIN dailyentrycreditor ON dailyentrycreditor.dailyentryid = dailyentry.id
JOIN accountstree ON accountstree.id = dailyentrycreditor.accountstreeid
JOIN accountstree parent ON parent.id = accountstree.parent
WHERE accountstree.id NOT IN (account_id) 
  AND dailyentry.id IN (entry_ids)

Custom Array Indexing

// Group results by daily entry ID for relationship analysis
$resultDataArr = customArrayIndexMany($resultDataArr, 'id');

// Convert to objects for template processing
foreach ($resultDataArr as $key => $value) {
    $rowArr = array();
    foreach ($value as $data) {
        $obj = new stdClass();
        foreach ($data as $key1 => $value1) {
            $obj->$key1 = $value1;
        }
        $rowArr[] = $obj;
    }
    $tempArr[$key] = $rowArr;
}

---

๐Ÿ“Š Performance Considerations

Query Optimization

1. Union Queries: Combine debtor and creditor lookups efficiently

2. Index Usage: Leverage indexes on accountstreeid and dailyentryid

3. Date Filtering: Apply date filters early in query processing

4. Result Limiting: Process only relevant entries

Memory Management

---

๐Ÿ”’ Security & Validation

Input Sanitization

$accountsTreeId = filter_input(INPUT_POST, "assistantledgerid");
$datefrom = filter_input(INPUT_POST, "datefrom");
$dateto = filter_input(INPUT_POST, "dateto");
$shape = filter_input(INPUT_POST, "shape");

Access Control

---

๐Ÿ› Common Issues & Troubleshooting

1. Missing Account Relationships

Issue: Transactions show incomplete account names

Cause: Missing parent account join

Fix: Ensure parent account table is properly joined

2. T-Shape Layout Issues

Issue: Unbalanced T-shape display

Cause: Incorrect iterator management

Debug: Check realCount vs totalCount values

3. Date Filter Problems

Issue: Transactions outside date range appear

Cause: Improper date format in SQL

Solution: Ensure proper date format (YYYY-MM-DD)

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur