SupplierReports Documentation

Supplier Reports Controller Documentation

File: /controllers/supplierReportsController.php

Purpose: Comprehensive supplier reporting module with advanced features for debt tracking, transaction management, and financial operations

Last Updated: December 20, 2024

Total Functions: 17+

Lines of Code: ~2,100+

---

๐Ÿ“‹ Overview

The Supplier Reports Controller is a comprehensive reporting module that provides advanced supplier account analysis and debt tracking capabilities. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**supplierdebtchange**Supplier debt transaction logsupplierdebtchangeid, supplierid, supplierdebtchangeamount, supplierdebtchangetype, supplierdebtchangedate, tablename, currencyId, conversionFactor
**supplier**Supplier master datasupplierid, suppliername, suppliercurrentDebt, suppliercurrentDebtInCurrency, inUse
### Purchase Tables (Referenced)

Table NamePurposeKey Columns
**buybill**Purchase billsbuybillid, buybillsupplierid, buybilltotalbill, buybillaftertotalbill, buybilltotalpayed, buybilldiscounttype, buybilldiscount
**buybilldetail**Purchase bill line itemsbuybilldetailid, buybillid, buybilldetailproductid, buybilldetailquantity, buybilldetailtotalprice
**returnbuybill**Purchase return billsreturnbuybillid, returnbuybillsupplierid, returnbuybilltotalbill, returnbuybillaftertotalbill
**returnbuybilldetail**Return bill detailsreturnbuybilldetailid, returnbuybillid, returnbuybilldetailproductid, returnbuybilldetailquantity
**buyandruternbill**Combined buy & returnbuybillid, buybillsupplierid, buybillprice, returnbuybillprice, buybilldate
**buyandruternbilldetail**Combined bill detailsbuyandruternbilldetailid, buybillid, buybilldetailproductid, buybilldetailquantity, buytype
### Financial Tables

Table NamePurposeKey Columns
**checkwithdrawal**Check withdrawalscheckwithdrawalid, bankaccountid, supplierid, checkwithdrawalamount, checkwithdrawaldate
**save**Cash registers/safessaveid, savename, savecurrentvalue, conversionFactor
**savedaily**Daily cash movementssavedailyid, saveid, savedailychangeamount, savedailychangetype, savedailymodelid, tablename
**currency**Currency definitionscurrencyid, currencyname, conversionfactor
### Reference Tables

Table NamePurposeKey Columns
**user**System usersuserid, username, viewbills, searchinonesave, usergroupid
**youtubelink**Tutorial linksyoutubelinkid, title, url
**programsettings**System configurationprogramsettingsid, reportsPlusHours
**associatedtags**Tag systemid, tagname
**product**Product informationproductid, productName
**productcat**Product categoriesproductCatId, productCatName
**unit**Measurement unitsunitid, unitName
---

๐Ÿ”‘ Key Functions

1. show() / Default Action - Main Report Interface

Location: Line 172

Purpose: Display main supplier reporting interface with filtering options

Function Signature:

// Triggered when: do is empty or do=show
$startDate = $_REQUEST['from'];
$endDate = $_REQUEST['to'];
$supplierId = $_POST['supplierId'];
$saveId = filter_input(INPUT_POST, 'saveId');

Process Flow:

1. Load supplier and save dropdown data

2. Handle project and cost center filtering

3. Display main report interface

4. Integrate with Ajax data tables

---

2. showallajax() - Ajax Data Table Handler

Location: Line 652

Purpose: Handle Ajax requests for supplier payment data tables

Function Signature:

function showallajax()

Process Flow:

1. Parse DataTables Ajax parameters (pagination, sorting, searching)

2. Build complex SQL query with multiple filters

3. Apply user permission restrictions

4. Handle date range filtering with timezone support

5. Execute query and format results for DataTables

6. Return JSON response with pagination metadata

Key Features:

SQL Query Structure:

SELECT supplierdebtchange.*, supplier.suppliername, user.employeename, save.savename
FROM supplierdebtchange
JOIN supplier ON supplier.supplierid = supplierdebtchange.supplierid
JOIN user ON user.userid = supplierdebtchange.userid
JOIN savedaily ON savedaily.savedailymodelid = supplierdebtchange.supplierdebtchangeid
JOIN save ON savedaily.saveid = save.saveid
WHERE supplierdebtchange.tablename = 'supplierPayedDeptController.php'

---

3. showallajaxCheques() - Check Withdrawal Ajax Handler

Location: Line 952

Purpose: Handle Ajax requests for check withdrawal data tables

Function Signature:

function showallajaxCheques()

Process Flow:

1. Query check withdrawal data with bank and supplier information

2. Apply filtering by supplier and date range

3. Format data for DataTables display

4. Handle check status (active/deleted)

5. Return formatted JSON response

SQL Query:

SELECT checkwithdrawalnumber, bankname, accountname, suppliername, 
       checkwithdrawaldate, checkwithdrawalamount, conditions, dailyentryid
FROM checkwithdrawal c
JOIN bankaccount a ON a.accountid = c.bankaccountid
JOIN bank b ON b.bankid = a.bankid
LEFT JOIN supplier s ON s.supplierid = c.supplierid

---

4. supplierShow() - Detailed Supplier Report

Location: Line 1351

Purpose: Generate comprehensive supplier account statement

Function Signature:

function supplierShow($supplierid, $startDate, $endDate, $order)

Process Flow:

1. Build dynamic SQL query with supplier and date filters

2. Apply user permission restrictions

3. Query supplier debt change history

4. Link each transaction to source documents

5. Handle net view processing for cleaner display

6. Calculate running balances

7. Load additional data (bank info, bill details)

Order Options:

Transaction Processing Logic:

foreach ($shownData as $data) {
    if ($data->tablename == "buyBillController.php") {
        $buybillid = $buyBillDAO->load($data->supplierdebtchangemodelid);
        $data->totalbillvalue = $buybillid->buybillaftertotalbill;
        $data->buybillpaid = $buybillid->buybilltotalpayed;
        $data->link = "buyBillController.php?do=details&id=" . $data->supplierdebtchangemodelid;
    }
    // ... handle other transaction types
}

---

5. showAllOperations() - Comprehensive Operations Report

Location: Line 1249

Purpose: Display all supplier operations (bills, returns, payments) in unified view

Function Signature:

function showAllOperations($supplierid, $startDate, $endDate)

Process Flow:

1. Call showBuyBillsBySupplierAndDate() for purchase data

2. Call showReturnBuyBillsBySupplierAndDate() for return data

3. Query supplierdebtchange for other operations

4. Cross-reference and eliminate double-counting

5. Calculate net payment totals

6. Load additional metadata (bank info for checks)

Data Integration:

// Purchase bills from multiple sources
$buybillData = showBuyBillsBySupplierAndDate($supplierid, $startDate, $endDate);
$returnbuybillData = showReturnBuyBillsBySupplierAndDate($supplierid, $startDate, $endDate);

// Payment operations
$SupplierShowData = $supplierDeptChangeExt->queryBySupplierIdAndDateNew_f($queryString);

// Eliminate double-counting
foreach ($buybillData as $data) {
    if ($data->buybilltotalpayed != 0) {
        $totalPrice += $data->buybilltotalpayed;
    }
}

---

6. supplierShowforbuyonly() - Purchase-Only Analysis

Location: Line 1893

Purpose: Focus on purchase transactions with detailed product analysis

Function Signature:

function supplierShowforbuyonly($supplierid, $startDate, $endDate)

Process Flow:

1. Apply user permission filtering based on viewbills setting

2. Query supplier debt changes for purchase-related transactions

3. Load detailed product information for each bill

4. Calculate totals with tax and discount processing

5. Generate product-level analysis

User Permission Logic:

$userData = $myUserRecord->load($_SESSION['userid']);
if ($userData->viewbills == 0) {
    $queryString .= ' user.userid =' . $_SESSION['userid'] . ' AND';
} else if ($userData->viewbills == 2) {
    $queryString .= ' user.usergroupid =' . $_SESSION['usergroupid'] . ' AND';
}

Product Detail Loading:

$myselldata = R::getAll('select buybilldetail.*, product.productName, productcat.productCatName, unit.unitName
    from buybilldetail
    JOIN product ON buybilldetail.buybilldetailproductid = product.productId
    JOIN productunit ON buybilldetail.productunitid = productunit.productunitid
    JOIN unit ON unit.unitId = productunit.unitid
    JOIN productcat ON productcat.productCatId = product.productCatId
    where buybillid=' . $data->supplierdebtchangemodelid);

---

7. delete() - Transaction Deletion and Reversal

Location: Line 393

Purpose: Delete supplier debt transactions with full reversal logic

Function Signature:

function delete()

Process Flow:

1. Load transaction details and supplier information

2. Use supplier locking mechanism to prevent conflicts

3. Calculate reversal amounts and update supplier debt

4. Create offsetting entries in supplierdebtchange

5. Update cash register/save balances

6. Reverse journal entries in daily entry system

7. Commit transaction or rollback on error

Supplier Locking:

$supplierdata = getSupplierDataFromSupplierInUseSP($supplierId);
// Uses stored procedure to lock supplier during transaction processing

Reversal Logic:

if ($oldchangeType == 0) { // It was get money
    $supplierDebtAfterTotal = $supplierDebtAfter - $payedDebt;
    $newChangeType = 1;
    $processname = "ุงู„ุบุงุก ุชุญุตูŠู„ ู…ู† ู…ูˆุฑุฏ";
} else { // It was payed debt
    $supplierDebtAfterTotal = $supplierDebtAfter + $payedDebt;
    $processname = "ุงู„ุบุงุก ุณุฏุงุฏ ุฏูŠูˆู† ู…ูˆุฑุฏ";
}

---

8. showBuyBillsBySupplierAndDate() - Purchase Bills Analysis

Location: Line 1601

Purpose: Comprehensive purchase bill analysis with discount processing

Function Signature:

function showBuyBillsBySupplierAndDate($supplierid, $startDate, $endDate)

Process Flow:

1. Build dynamic queries for both buybill and buyandruternbill tables

2. Apply supplier and date filters

3. Process discount calculations for each bill

4. Count product quantities via detail tables

5. Merge datasets from multiple sources

6. Calculate totals for template display

Dynamic Query Building:

$queryString = '';
if (!empty($supplierid)) {
    $queryString .= ' AND buybill.buybillsupplierid = ' . $supplierid;
}
if (!empty($startDate)) {
    $queryString .= ' AND buybill.buybilldate >= "' . $startDate . '"';
}
if (!empty($endDate)) {
    $queryString .= ' AND buybill.buybilldate <= "' . $endDate . '"';
}

---

9. Currency and Save Management Functions

getSaveValueAndMinus() / getSaveValueAndPlus() - Lines 519/539

Handle cash register/save balance calculations with currency conversion:

function getSaveValueAndPlus($savevaluechanged, $saveid, $saveConversionFactor = 0) {
    $saveData = $SaveExt->loadForUpdateEx($saveid);
    $saveValuebefore = $saveData->savecurrentvalue;
    
    if ($saveConversionFactor == 0) {
        $saveConversionFactor = $saveData->conversionFactor;
    }
    
    $savevaluechanged = round(($savevaluechanged * $saveConversionFactor), 4);
    $saveValueafter = $saveValuebefore + $savevaluechanged;
    
    return array($saveId, $saveValuebefore, $saveValueafter, $savevaluechanged, $saveConversionFactor);
}

---

10. Supplier Locking Management

getSupplierDataFromSupplierInUseSP() - Line 1854

markSupplierAsNOTInUse() - Line 1876

Handle supplier locking to prevent concurrent modifications:

function getSupplierDataFromSupplierInUseSP($supplier) {
    $supplier_data = $supplierExt->callSupplierInUseSP($supplier);
    while ($supplier_data->suppliercurrentDebt == 'in_use') {
        sleep(1);
        $noOfTries++;
        if ($noOfTries > 15) { // 15 second timeout
            R::exec('UPDATE supplier SET inUse = 0 where supplierid = ' . $supplier);
        }
        $supplier_data = $supplierExt->callSupplierInUseSP($supplier);
    }
    return $supplier_data;
}

---

๐Ÿ”„ Workflows

Workflow 1: Ajax Data Loading Process

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Ajax Request from DataTable
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Parse DataTables Parameters
- Pagination (start, length)
- Ordering (column, direction)
- Search filters
- Custom filters (supplier, save, date)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Apply User Permissions
- Check viewbills setting
- Apply user/group restrictions
- Check save restrictions
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Build Dynamic SQL Query
- Base JOIN structure
- Add WHERE clauses for filters
- Add date range with timezone handling
- Add ORDER BY and LIMIT clauses
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Execute Queries
- Main data query
- Count query for pagination
- Totals query for summary
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Format Data for DataTables
- Process each row
- Add action buttons (edit, delete, print)
- Calculate running totals
- Apply row styling based on status
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Return JSON Response
- Data array
- Pagination metadata
- Totals summary
- Draw counter for DataTables
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Transaction Deletion Process

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Delete Transaction Request
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Transaction Details
- Get supplier debt change record
- Load supplier information
- Identify related records (save, daily entry)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Lock Supplier Record
- Use stored procedure to lock supplier
- Wait for lock or timeout after 15 seconds
- Force unlock if needed
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Calculate Reversal Amounts
- Determine new supplier debt balance
- Calculate currency conversions
- Determine save balance changes
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Create Reversal Entries
- Update supplier debt
- Insert offsetting debt change entry
- Update save balance
- Insert save daily entry
- Reverse journal entry
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Commit or Rollback
- Commit transaction if successful
- Rollback and release lock on error
- Log any issues
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty) or `do=show`Default actionMain report interface
`do=showallajax``showallajax()`Ajax payment data
`do=showallajaxCheques``showallajaxCheques()`Ajax check data
`do=oneSupplier``supplierShow()`Individual supplier report
`do=supplierShowforbuyonly``supplierShowforbuyonly()`Purchase-only analysis
`do=all``showAllOperations()`Comprehensive operations
`do=remove``delete()`Delete transaction
`do=edit`Default + edit formEdit transaction
`do=update`Database updateUpdate transaction
`do=editprint`Print viewPrint transaction
### Required Parameters by Action

Main Report Interface (do=show):

Individual Supplier Report (do=oneSupplier):

Ajax Requests:

---

๐Ÿงฎ Calculation Methods

Currency Conversion

// Convert to save currency
$savevaluechanged = round(($savevaluechanged * $saveConversionFactor), 4);

// Track both main currency and supplier currency
$supplierDeptChange->debtchangbeforeInSupplierCurrency = $supplierDebtBeforeInSuppCurr;
$supplierDeptChange->debtchangamountInSupplierCurrency = $payedDebtInSuppCurr;
$supplierDeptChange->debtchangafterInSupplierCurrency = $supplierDebtAfterTotalInSuppCurr;

Discount Processing in Combined Bills

// Fixed amount discount
if ($buybilldiscountrype == 0) {
    $myfialtotal = $mytotal - $buybilldiscount;
} 
// Percentage discount
else {
    $myfialtotal = $mytotal - (($mytotal * $buybilldiscount) / 100);
}

Tax Calculation

$data->tax = ($sellBillData->buybilltotalbill - $discount) * $sellBillData->payedtax / 100;

Net View Balance Calculation

foreach ($shownData as $mov) {
    if ($mov->supplierdebtchangetype == "1") { // Payment
        $mov->supplierdebtchangebefore = $startbefore + $startvalue;
        $startbefore = $startbefore + $startvalue;
    } else { // Purchase/Debt increase
        $mov->supplierdebtchangebefore = $startbefore - $startvalue;
        $startbefore = $startbefore - $startvalue;
    }
}

---

๐Ÿ”’ Security & Permissions

User Permission Levels

// Individual user restriction
if ($userData->viewbills == 0) {
    $queryString .= ' user.userid =' . $_SESSION['userid'] . ' AND';
}
// User group restriction  
else if ($userData->viewbills == 2) {
    $queryString .= ' user.usergroupid =' . $_SESSION['usergroupid'] . ' AND';
}
// Full access (viewbills == 1) - no restrictions

// Save restriction
if ($userdata->searchinonesave == 1) {
    $queryString .= ' supplierdebtchange.saveid = ' . $userdata->saveid . ' AND';
}

Input Sanitization

Access Control

---

๐Ÿ“Š Performance Considerations

Database Optimization

Critical Indexes Required:

-- Core performance indexes
CREATE INDEX idx_supplier_debt_date ON supplierdebtchange(supplierid, supplierdebtchangedate);
CREATE INDEX idx_supplier_debt_table ON supplierdebtchange(tablename, del, supplierdebtchangedate);
CREATE INDEX idx_savedaily_link ON savedaily(savedailymodelid, tablename);
CREATE INDEX idx_buybill_supplier_date ON buybill(buybillsupplierid, buybilldate);
CREATE INDEX idx_checkwithdrawal_supplier ON checkwithdrawal(supplierid, checkwithdrawaldate);

Query Optimization:

Memory Management:

Performance Features

1. Ajax DataTables: Handle large datasets efficiently

2. Server-side Processing: Pagination, sorting, filtering on database side

3. Selective Loading: Only load needed data based on user permissions

4. Query Optimization: Efficient JOINs and WHERE clauses

5. Result Caching: Cache dropdown data and static content

---

๐Ÿ› Common Issues & Troubleshooting

1. Ajax Timeout Issues

Issue: DataTables requests timing out with large datasets

Cause: Complex queries or missing indexes

Solutions:

2. Supplier Lock Conflicts

Issue: "Supplier in use" errors during transaction processing

Cause: Concurrent access or stale locks

Debug:

SELECT supplierid, inUse FROM supplier WHERE inUse = 1;
-- Check for locked suppliers

UPDATE supplier SET inUse = 0 WHERE supplierid = [ID];
-- Force unlock if needed

3. Currency Conversion Errors

Issue: Incorrect balance calculations with multi-currency

Cause: Missing conversion factors or rounding issues

Solutions:

4. Permission Access Issues

Issue: Users seeing unauthorized data

Cause: Permission logic not properly applied

Debug: Check user settings and permission application in queries

5. Transaction Reversal Failures

Issue: Delete operation fails or creates incorrect balances

Cause: Missing related records or calculation errors

Solutions:

---

๐Ÿงช Testing Scenarios

Test Case 1: Ajax Data Loading

1. Load main report page with large dataset
2. Test pagination, sorting, and filtering
3. Verify search functionality across columns
4. Check totals calculation accuracy
5. Test different user permission levels

Test Case 2: Transaction Deletion

1. Create test supplier transaction
2. Verify balance updates correctly
3. Delete the transaction
4. Verify reversal calculations are correct
5. Check all related records are updated

Test Case 3: Multi-Currency Operations

1. Set up supplier with non-default currency
2. Create transactions in supplier currency
3. Verify conversion calculations
4. Test save balance updates with conversion
5. Check reporting accuracy in both currencies

Test Case 4: User Permissions

1. Test with viewbills = 0 (own data only)
2. Test with viewbills = 2 (group data)
3. Test with searchinonesave = 1
4. Verify data visibility restrictions
5. Test transaction modification permissions

---

๐Ÿ“š Related Documentation

---

๐Ÿ“ Summary

Controller Purpose: Comprehensive supplier debt tracking with advanced features

Function Count: 17+

Table Count: 15+ (direct and referenced)

Notable Findings:

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur