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:
- โข Individual supplier debt reports with advanced filtering
- โข Supplier transaction history with detailed analysis
- โข Purchase bill tracking (buy, return, combined) with product details
- โข Ajax-powered data tables for large datasets
- โข Check withdrawal tracking and management
- โข Advanced currency support and conversion
- โข Cash register/safe integration
- โข Multi-user permission levels
- โข Transaction deletion and reversal capabilities
- โข Real-time data processing with AJAX
- โข Export capabilities and print views
Primary Functions
- โ Generate comprehensive supplier debt reports
- โ Track supplier payment history with detailed analysis
- โ Purchase transaction analysis with product breakdowns
- โ Advanced date range filtering with timezone support
- โ Debt balance calculations with currency conversion
- โ Transaction linking to source documents
- โ Purchase bill detail analysis with discount calculations
- โ Net view calculations for cleaner reports
- โ Ajax-powered data tables for performance
- โ Check withdrawal management
- โ Transaction deletion and reversal
- โ Multi-currency support
- โ User permission management
- โ Cash register/safe integration
Related Controllers
- โข buyBillController.php - Purchase operations
- โข supplierController.php - Supplier management
- โข returnBuyBillController.php - Purchase returns
- โข supplierPayedDeptController.php - Payment processing
- โข checkwithdrawalController.php - Check withdrawals
- โข kempialaController.php - Promissory notes
- โข dailyentry.php - Journal entries
- โข saveController.php - Cash register management
- โข currencyController.php - Currency management
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **supplierdebtchange** | Supplier debt transaction log | supplierdebtchangeid, supplierid, supplierdebtchangeamount, supplierdebtchangetype, supplierdebtchangedate, tablename, currencyId, conversionFactor | |
| **supplier** | Supplier master data | supplierid, suppliername, suppliercurrentDebt, suppliercurrentDebtInCurrency, inUse |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **buybill** | Purchase bills | buybillid, buybillsupplierid, buybilltotalbill, buybillaftertotalbill, buybilltotalpayed, buybilldiscounttype, buybilldiscount | |
| **buybilldetail** | Purchase bill line items | buybilldetailid, buybillid, buybilldetailproductid, buybilldetailquantity, buybilldetailtotalprice | |
| **returnbuybill** | Purchase return bills | returnbuybillid, returnbuybillsupplierid, returnbuybilltotalbill, returnbuybillaftertotalbill | |
| **returnbuybilldetail** | Return bill details | returnbuybilldetailid, returnbuybillid, returnbuybilldetailproductid, returnbuybilldetailquantity | |
| **buyandruternbill** | Combined buy & return | buybillid, buybillsupplierid, buybillprice, returnbuybillprice, buybilldate | |
| **buyandruternbilldetail** | Combined bill details | buyandruternbilldetailid, buybillid, buybilldetailproductid, buybilldetailquantity, buytype |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **checkwithdrawal** | Check withdrawals | checkwithdrawalid, bankaccountid, supplierid, checkwithdrawalamount, checkwithdrawaldate | |
| **save** | Cash registers/safes | saveid, savename, savecurrentvalue, conversionFactor | |
| **savedaily** | Daily cash movements | savedailyid, saveid, savedailychangeamount, savedailychangetype, savedailymodelid, tablename | |
| **currency** | Currency definitions | currencyid, currencyname, conversionfactor |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **user** | System users | userid, username, viewbills, searchinonesave, usergroupid | |
| **youtubelink** | Tutorial links | youtubelinkid, title, url | |
| **programsettings** | System configuration | programsettingsid, reportsPlusHours | |
| **associatedtags** | Tag system | id, tagname | |
| **product** | Product information | productid, productName | |
| **productcat** | Product categories | productCatId, productCatName | |
| **unit** | Measurement units | unitid, 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:
- โข Server-side pagination for large datasets
- โข Advanced filtering (supplier, save, date, serial number)
- โข User permission enforcement
- โข Real-time totals calculation
- โข Search functionality across multiple columns
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:
- โข
order = 1- Date descending - โข
order = 2- ID ascending (default)
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
---
Workflow 2: Transaction Deletion Process
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | |
|---|---|---|---|
| `do=` (empty) or `do=show` | Default action | Main 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 form | Edit transaction | |
| `do=update` | Database update | Update transaction | |
| `do=editprint` | Print view | Print transaction |
Main Report Interface (do=show):
- โข
from- Start date (optional) - โข
to- End date (optional) - โข
supplierId- Supplier filter (optional) - โข
saveId- Save filter (optional)
Individual Supplier Report (do=oneSupplier):
- โข
supplierid- Supplier ID (required) - โข
from- Start date - โข
to- End date - โข
order- Sort order (1=date desc, 2=ID desc)
Ajax Requests:
- โข Standard DataTables parameters (start, length, order, search)
- โข Custom filters (supplierId, saveId, from, to)
---
๐งฎ 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
- โข All POST/GET parameters filtered and validated
- โข Numeric IDs cast to integers:
(int) $_REQUEST['supplierId'] - โข Date validation and proper formatting
- โข SQL injection prevented by DAO layer parameterized queries
- โข CSRF protection via session validation
Access Control
- โข Requires authentication via
../public/authentication.php - โข Permission checks for data visibility
- โข Transaction modification restrictions
- โข Audit trail for all changes
---
๐ 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:
- โข Server-side pagination prevents memory issues
- โข Efficient JOIN structures in Ajax queries
- โข Date range filtering with proper time zone handling
- โข Query result caching where appropriate
Memory Management:
- โข Ajax loading prevents large dataset memory issues
- โข Pagination limits result sets
- โข Efficient data structures in processing loops
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:
- โข Add required database indexes
- โข Optimize JOIN queries
- โข Reduce date range for large suppliers
- โข Check
reportsPlusHourssetting for timezone issues
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:
- โข Verify currency conversion factors are set
- โข Check save conversion factors
- โข Ensure proper rounding (4 decimal places)
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:
- โข Check all related table dependencies
- โข Verify journal entry reversal
- โข Ensure save balance updates are correct
---
๐งช 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
- โข CLAUDE.md - PHP 8.2 migration guide
- โข buyBillController.md - Purchase operations
- โข supplierController.php - Supplier management
- โข saveController.php - Cash register management
- โข currencyController.php - Currency management
- โข Database Schema Documentation - Table relationships
---
๐ Summary
Controller Purpose: Comprehensive supplier debt tracking with advanced features
Function Count: 17+
Table Count: 15+ (direct and referenced)
Notable Findings:
- โข Advanced Ajax data table implementation for performance
- โข Complex multi-currency support with conversion tracking
- โข Sophisticated user permission system
- โข Transaction reversal with full audit trail
- โข Real-time supplier locking mechanism
- โข Comprehensive financial integration (saves, checks, journal entries)
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur