Buy Report Controller Documentation
File: /controllers/buyreport.php
Purpose: Comprehensive purchase transaction reporting with supplier analysis and financial tracking
Last Updated: December 20, 2024
Total Functions: 8
Lines of Code: ~1,000+
---
๐ Overview
The Buy Report Controller is a comprehensive reporting module that provides detailed analysis of purchase transactions, supplier relationships, and financial tracking. It handles:
- โข Multi-bill type purchase reporting (standard, returns, combined)
- โข Supplier-specific transaction analysis
- โข Date range filtering with timezone support
- โข Category-based product grouping
- โข Financial debt tracking and supplier payments
- โข Comprehensive data aggregation and sorting
- โข YouTube tutorial integration
- โข Advanced search and filtering capabilities
Primary Functions
- โ Multi-bill type purchase reporting
- โ Supplier transaction analysis
- โ Date range filtering with timezone support
- โ Product category grouping and analysis
- โ Supplier debt tracking and payment history
- โ Financial totals and aggregation
- โ Data sorting and organization
- โ Export and display capabilities
Related Controllers
- โข buyBillController.php - Purchase bill operations
- โข returnBuyBillController.php - Purchase returns
- โข buyandruternBillController.php - Combined bills
- โข supplierController.php - Supplier management
---
๐๏ธ Database Tables
Primary Purchase Tables
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **buybill** | Purchase bills | buybillid, buybillsupplierid, buybilldate, buybillfinalbill | |
| **buybilldetail** | Purchase bill items | buybilldetailid, buybillid, buybilldetailproductid, buybilldetailquantity | |
| **returnbuybill** | Purchase returns | returnbuybillid, returnbuybillsupplierid, returnbuybilldate | |
| **returnbuybilldetail** | Return bill items | returnbuybilldetailid, returnbuybillid, returnbuybilldetailproductid | |
| **buyandruternbill** | Combined bills | buybillid, buybillsupplierid, buybilldate | |
| **buyandruternbilldetail** | Combined bill items | buybilldetailid, buybillid, buybilldetailproductid |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **billsbuy** | Service purchase bills | billsbuyid, clientid, billdate, finalnetbillvalue | |
| **billsproductsbuy** | Service bill items | billsproductsbuyid, billsbuyid, productid, quantity |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **supplier** | Supplier master data | supplierid, suppliername, suppliercurrentDebt | |
| **supplierdebtchange** | Supplier debt history | supplierdebtchangeid, supplierid, supplierdebtchangeamount | |
| **product** | Product catalog | productid, productname, productCatId | |
| **productcat** | Product categories | productCatId, productCatName, parentExt | |
| **productunit** | Product units | productunitid, productid, unitid | |
| **storedetail** | Inventory levels | storedetailid, productid, storeid, productquantity |
๐ Key Functions
1. Default Action (empty $do) - Main Report Display
Location: Line 188
Purpose: Generate comprehensive purchase report with filtering capabilities
Search Parameters:
$datefrom = filter_input(INPUT_POST, 'datefrom');
$dateto = filter_input(INPUT_POST, 'dateto');
$supplierid = filter_input(INPUT_POST, 'supplierid');
$clientid = filter_input(INPUT_POST, 'clientid');
$order = filter_input(INPUT_POST, 'order');
Query Building Logic:
$queryString = " where 1 "; // Service bills
$queryString1 = " where 1 "; // Purchase bills
$queryString1R = " where 1 "; // Return bills
$queryString1SR = " where 1 "; // Combined bills
// Supplier filtering
if (isset($supplierid) && !empty($supplierid) && $supplierid != -1) {
$queryString .= 'and billsbuy.clientid = ' . $supplierid . ' ';
$queryString1 .= 'and buybill.buybillsupplierid = ' . $supplierid . ' ';
$queryString1R .= 'and returnbuybill.returnbuybillsupplierid = ' . $supplierid . ' ';
$queryString1SR .= 'and buyandruternbill.buybillsupplierid = ' . $supplierid . ' ';
}
Date Processing with Timezone Support:
if (isset($Programsetting->reportsPlusHours) && !empty($Programsetting->reportsPlusHours)) {
$reportsPlusHours = $Programsetting->reportsPlusHours + 24;
$datefrom = date('Y-m-d H:i:s', strtotime('+' . $Programsetting->reportsPlusHours . ' hour +0 minutes', strtotime($datefrom)));
} else {
$datefrom = $datefrom . " 00:00:00";
}
---
2. getDataNew() - Enhanced Data Aggregation
Purpose: Aggregate data from multiple bill types with advanced processing
Function Signature:
function getDataNew($queryString, $queryString1, $queryString1R, $queryString1SR, $order)
Multi-Source Data Collection:
1. Service bills (billsbuy)
2. Standard purchase bills (buybill)
3. Purchase return bills (returnbuybill)
4. Combined bills (buyandruternbill)
Data Processing Flow:
- โข Aggregate quantities and totals by product
- โข Handle multiple bill types for same products
- โข Apply sorting and organization logic
- โข Calculate financial summaries
---
3. getData() - Standard Data Aggregation
Purpose: Basic data aggregation without enhanced features
Differences from getDataNew():
- โข Simplified processing logic
- โข Basic aggregation only
- โข Legacy support functionality
---
4. sortByTotal() - Data Sorting Algorithm
Purpose: Sort aggregated data by various criteria
Function Signature:
function sortByTotal($type, $allDataArrTemp, $productTotalArrTemp)
Sorting Options:
- โข By total amount
- โข By quantity
- โข By supplier
- โข By date range
- โข Custom sorting logic
---
5. getAllSubCat() - Category Hierarchy Navigation
Purpose: Recursively traverse product category hierarchy
Function Signature:
function getAllSubCat($catid, $mode)
Mode Options:
- โข
1- Get all sub-categories - โข
2- Get last level categories only
Category Processing:
$result = $productCatExt->queryByParentExt($catid);
if (count($result) > 0) {
foreach ($result as $data) {
if ($mode == 1) {
$catsIDS .= "," . $data->productCatId;
getAllSubCat($data->productCatId, $mode);
} elseif ($mode == 2) {
$childData = $productCatExt->queryByParentExt($data->productCatId);
if (count($childData) == 0) {
array_push($lastLevelCatIDS, $data->productCatId);
}
}
}
}
---
6. getSupplierDept() - Supplier Debt Calculation
Purpose: Calculate current supplier debt balance
Function Signature:
function getSupplierDept($supplierId)
Debt Calculation Logic:
- โข Load current supplier debt
- โข Account for currency differences
- โข Include pending transactions
- โข Return formatted debt amount
---
7. getCLientPayedDeptData() - Payment History Analysis
Purpose: Analyze supplier payment history within date range
Function Signature:
function getCLientPayedDeptData($supplierid, $datefrom, $dateto)
Payment Analysis:
- โข Payment amounts by date
- โข Payment method tracking
- โข Currency conversion handling
- โข Payment trend analysis
---
8. getDataNewWithClient() - Client-Integrated Reporting
Purpose: Enhanced reporting with client relationship data
Function Signature:
function getDataNewWithClient($queryString, $queryString1, $queryString1R, $queryString1SR, $order, $queryStringClient, $queryStringClient1R, $queryStringClient1SR)
Client Integration Features:
- โข Cross-reference supplier and client data
- โข B2B transaction analysis
- โข Reseller relationship tracking
- โข Commission and markup analysis
---
๐ Workflows
Workflow 1: Comprehensive Purchase Report Generation
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description |
|---|---|---|
| `do=` (empty) | Default action | Main purchase report with full filtering |
Date Filtering:
- โข
datefrom- Start date for report (YYYY-MM-DD) - โข
dateto- End date for report (YYYY-MM-DD) - โข Timezone adjustment via
programsettings.reportsPlusHours
Entity Filtering:
- โข
supplierid- Filter by specific supplier (-1 for all) - โข
clientid- Client filter for cross-reference - โข
order- Sort order (asc/desc/no)
Category Filtering (via global variables):
- โข
$catsIDS- Comma-separated category ID list - โข
$lastLevelCatIDS- Array of leaf category IDs
---
๐งฎ Calculation Methods
Date Range Processing with Timezone
// Timezone adjustment calculation
if (isset($Programsetting->reportsPlusHours) && !empty($Programsetting->reportsPlusHours)) {
$reportsPlusHours = $Programsetting->reportsPlusHours + 24; // +24 for end of day
$adjustedDate = date('Y-m-d H:i:s', strtotime('+' . $Programsetting->reportsPlusHours . ' hour +0 minutes', strtotime($inputDate)));
}
Multi-Bill Type Aggregation
// Data aggregation across bill types
$totalQuantity = 0;
$totalAmount = 0;
// Service bills
foreach ($serviceBillData as $bill) {
$totalQuantity += $bill->quantity;
$totalAmount += $bill->finalnetbillvalue;
}
// Purchase bills
foreach ($purchaseBillData as $bill) {
$totalQuantity += $bill->buybilldetailquantity;
$totalAmount += $bill->buybillfinalbill;
}
// Return bills (subtract)
foreach ($returnBillData as $bill) {
$totalQuantity -= $bill->returnbuybilldetailquantity;
$totalAmount -= $bill->returnbuybillfinalbill;
}
Supplier Debt Calculation
function getSupplierDept($supplierId) {
global $supplierDAO;
if ($supplierId > 0) {
$supplierData = $supplierDAO->load($supplierId);
return $supplierData->suppliercurrentDebt;
}
return 0;
}
---
๐ Security & Permissions
User Authentication
include_once("../public/authentication.php");
User Group Permissions
$userGroupId = $_SESSION['usergroupid'];
$loadUserGroupData = $myUserGroupRecord->load($userGroupId);
$smarty->assign("loadUserGroupData", $loadUserGroupData);
Input Validation
// Secure input filtering
$datefrom = filter_input(INPUT_POST, 'datefrom');
$dateto = filter_input(INPUT_POST, 'dateto');
$supplierid = filter_input(INPUT_POST, 'supplierid');
// Order validation
if ($order != "asc" && $order != "desc") {
$order = "no";
}
---
๐ Performance Considerations
Database Optimization
1. Required Indexes:
CREATE INDEX idx_buybill_supplier_date ON buybill(buybillsupplierid, buybilldate);
CREATE INDEX idx_returnbuybill_supplier_date ON returnbuybill(returnbuybillsupplierid, returnbuybilldate);
CREATE INDEX idx_billsbuy_client_date ON billsbuy(clientid, billdate);
```
2. **Query Optimization**:
- Use appropriate date range queries
- Limit result sets with proper WHERE clauses
- Efficient JOIN operations for detail data
3. **Memory Management**:
- Large date ranges may consume significant memory
- Consider pagination for very large datasets
- Optimize data aggregation algorithms
### Performance Monitoring
php
// Add performance tracking
$startTime = microtime(true);
// Report generation code...
$endTime = microtime(true);
$executionTime = ($endTime - $startTime);
error_log("Report generation time: " . $executionTime . " seconds");
---
## ๐ Common Issues & Troubleshooting
### 1. **Incorrect Date Range Results**
**Issue**: Reports show wrong data for date ranges
**Cause**: Timezone adjustment errors or date format issues
**Debug**:
php
echo "Original date: " . $datefrom . "
";
echo "Adjusted date: " . $adjustedDate . "
";
echo "Timezone hours: " . $Programsetting->reportsPlusHours . "
";
### 2. **Supplier Debt Calculation Errors**
**Issue**: Debt amounts don't match expected values
**Cause**: Currency conversion or debt change tracking issues
**Debug**:
php
function debugSupplierDebt($supplierId) {
global $supplierDAO, $supplierDeptChangeExt;
$supplier = $supplierDAO->load($supplierId);
$debtChanges = $supplierDeptChangeExt->queryBySupplierId($supplierId);
echo "Current debt: " . $supplier->suppliercurrentDebt . "
";
echo "Debt changes count: " . count($debtChanges) . "
";
foreach ($debtChanges as $change) {
echo "Change: " . $change->supplierdebtchangeamount . " Type: " . $change->supplierdebtchangetype . "
";
}
}
### 3. **Data Aggregation Inconsistencies**
**Issue**: Totals don't match when filtering by different criteria
**Cause**: Logic errors in data collection or aggregation
**Debug**:
php
// Log aggregation steps
foreach ($billTypes as $type => $data) {
echo "$type bills count: " . count($data) . "
";
$typeTotal = array_sum(array_column($data, 'amount'));
echo "$type total: $typeTotal
";
}
---
## ๐งช Testing Scenarios
### Test Case 1: Basic Purchase Report
1. Select date range (last 30 days)
2. Select specific supplier
3. Generate report
4. Verify all bill types included
5. Check financial totals accuracy
### Test Case 2: Multi-Supplier Analysis
1. Run report for all suppliers
2. Verify supplier-specific data separation
3. Check debt calculations per supplier
4. Validate payment history accuracy
### Test Case 3: Date Range with Timezone
1. Set specific timezone in program settings
2. Run report with date range
3. Verify timezone adjustments applied
4. Check edge cases (date boundaries)
```
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข buyBillController.md - Purchase operations
- โข supplierController.md - Supplier management
- โข Reporting Framework Documentation - Complete reporting system
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When purchase reporting requirements change