ClientsAndsellProductsReport Documentation
Clients and Sell Products Report Controller Documentation
File: /controllers/clientsAndsellProductsReportController.php
Purpose: Generates detailed customer-product sales analysis reports with quantity and pricing metrics
Last Updated: December 20, 2024
Total Functions: 4
Lines of Code: ~301
---
๐ Overview
The Clients and Sell Products Report Controller is a specialized analytics module that provides detailed insights into customer purchasing patterns and product performance. It offers granular analysis of sales data by combining customer and product dimensions with date-based filtering. The controller features:
- โข Customer-specific product purchase analysis
- โข Detailed quantity tracking (sold vs returned)
- โข Price analysis and revenue calculations
- โข Multi-transaction type aggregation
- โข Date range filtering capabilities
- โข Product selection with category hierarchy
- โข Rate analysis and pricing trends
Primary Functions
- โ Customer-product sales analysis
- โ Quantity tracking (sales and returns)
- โ Revenue calculation and analysis
- โ Price trend analysis
- โ Date range filtering
- โ Multi-source transaction aggregation
- โ Product category integration
- โ Customer selection and filtering
Related Controllers
- โข sellbillController.php - Sales operations
- โข returnsellbillController.php - Sales returns
- โข productController.php - Product management
- โข clientController.php - Customer management
- โข productReportsController.php - Product analytics
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **sellbilldetail** | Sales transaction details | sellbilldetailid, sellbillid, sellbilldetailproductid, sellbilldetailquantity, sellbilldetailtotalprice | |
| **returnsellbilldetail** | Return transaction details | returnsellbilldetailid, returnsellbillid, returnsellbilldetailproductid, returnsellbilldetailquantity | |
| **sellandruternbilldetail** | Combined transaction details | sellandruternbilldetailid, sellbillid, sellbilldetailproductid, sellbilldetailquantity, selltype |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **sellbill** | Sales bills | sellbillid, sellbillclientid, sellbilldate, conditions | |
| **returnsellbill** | Return bills | returnsellbillid, returnsellbillclientid, returnsellbilldate, conditions | |
| **sellbillandrutern** | Combined bills | sellbillid, sellbillclientid, sellbilldate, conditions | |
| **product** | Product master | productId, productName, productCatId, conditions | |
| **client** | Customer master | clientid, clientname, conditions |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **productcat** | Product categories | productCatId, productCatName, productCatParent | |
| **productunit** | Product units | productunitid, productunitname | |
| **programsettings** | System settings | programsettingsid, settingkey, settingvalue | |
| **youtubelink** | Tutorial links | youtubelinkid, title, url |
๐ Key Functions
1. show/Default Action - Report Generation Interface
Location: Line 157-186
Purpose: Display customer-product analysis form and process report requests
Function Signature:
// URL Parameters
$startDate = $_REQUEST['from'];
$endDate = $_REQUEST['to'];
$productId = $_REQUEST['productId'];
$clientId = $_REQUEST['clientId'];
Process Flow:
1. Load customer data for selection dropdown
2. Parse report parameters from request
3. Validate all required parameters are present
4. Load product and customer names for report header
5. Call loadPricesForClient() to generate analysis
6. Load YouTube tutorials and program settings
7. Display via clientsAndsellProductsReportview/show.html
Parameter Validation:
if (isset($productId) && $productId != "-1" && $productId != "" &&
isset($clientId) && $clientId != "-1" &&
isset($startDate) && isset($endDate) &&
$startDate != "" && $endDate != "") {
// All parameters valid - generate report
$productData = $productDAO->load($productId);
$clientData = $clientDAO->load($clientId);
$message = "ุงูุนู
ูู :" . $clientData->clientname .
"<br> ุงูู
ูุชุฌ: " . $productData->productName .
"<br> ู
ู ุชุงุฑูุฎ: " . $startDate . " ุฅูู ุชุงุฑูุฎ: " . $endDate;
loadPricesForClient($productId, $clientId, $startDate, $endDate);
}
---
2. rates Action - Price Analysis Interface
Location: Line 189-215
Purpose: Duplicate of show action for rate-focused analysis
Note: This appears to be a duplicate of the main show action, possibly for different UI views or future rate-specific analysis features.
---
3. getClients() - Customer Data Loader
Location: Line 223-227
Purpose: Load active customers for selection dropdown
Function Signature:
function getClients()
Implementation:
global $clientDAO;
$clientsData = $clientDAO->queryByCondition(0); // Active customers only
return $clientsData;
---
4. loadPricesForClient() - Core Analysis Engine
Location: Line 229-299
Purpose: Generate comprehensive customer-product sales analysis
Function Signature:
function loadPricesForClient($productId, $clientId, $startDate, $endDate)
Analysis Process:
1. Data Retrieval:
// Get all transactions for this customer-product combination
$mydata = $SellbilldetailEX->getallproductbyclientanddatenor($startDate, $endDate, $productId, $clientId);
2. Transaction Analysis Loop:
$totalquantity = 0;
$sellquantity = 0;
$returnquantity = 0;
$totalsellprice = 0;
$totalreturnprice = 0;
foreach ($mydata as $alldata) {
$price = $alldata->price;
$quantity = $alldata->quantity;
$type = $alldata->type; // 0 = sale, 1 = return
if ($type == 0) { // Sales transaction
$myprice = ($quantity * $price);
$totalsellprice = $totalsellprice + ($price);
$sellquantity = $sellquantity + ($myprice / $price);
$totalquantity = $totalquantity + ($totalsellprice / $price);
} elseif ($type == 1) { // Return transaction
$myprice = ($quantity * $price);
$totalreturnprice = $totalreturnprice + ($price);
$returnquantity = $returnquantity + ($myprice / $price);
$totalquantity = $totalquantity + ($totalreturnprice / $price);
}
}
3. Final Calculations:
$final = $sellquantity - $returnquantity; // Net quantity
// Assign results to template
$smarty->assign("totalsellprice", $totalsellprice);
$smarty->assign("sellquantity", $sellquantity);
$smarty->assign("totalreturnprice", $totalreturnprice);
$smarty->assign("returnquantity", $returnquantity);
$smarty->assign("totalquantity", $totalquantity);
$smarty->assign("final", $final);
$smarty->assign("mydata", $mydata);
---
๐ Workflows
Workflow 1: Customer-Product Analysis
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | |
|---|---|---|---|
| `do=show` or `do=` (empty) | Default action | Display customer-product analysis interface | |
| `do=rates` | rates action | Alternative interface (duplicate of show) |
Customer-Product Analysis:
- โข
productId- Product ID (must not be "-1" or empty) - โข
clientId- Customer ID (must not be "-1") - โข
from- Start date (YYYY-MM-DD format) - โข
to- End date (YYYY-MM-DD format)
Example URL:
clientsAndsellProductsReportController.php?do=show&productId=123&clientId=45&from=2024-01-01&to=2024-12-31
---
๐งฎ Calculation Methods
Quantity Calculations
// For sales transactions (type = 0)
$myprice = ($quantity * $price);
$totalsellprice = $totalsellprice + ($price);
$sellquantity = $sellquantity + ($myprice / $price); // Effectively: + $quantity
$totalquantity = $totalquantity + ($totalsellprice / $price);
// For return transactions (type = 1)
$myprice = ($quantity * $price);
$totalreturnprice = $totalreturnprice + ($price);
$returnquantity = $returnquantity + ($myprice / $price); // Effectively: + $quantity
$totalquantity = $totalquantity + ($totalreturnprice / $price);
// Net quantity calculation
$final = $sellquantity - $returnquantity;
Note: The calculation logic appears to have some redundancy - the division by price after multiplication creates a roundabout way to get the original quantity.
Simplified Logic
// More straightforward approach would be:
if ($type == 0) {
$sellquantity += $quantity;
$totalsellprice += ($quantity * $price);
} elseif ($type == 1) {
$returnquantity += $quantity;
$totalreturnprice += ($quantity * $price);
}
---
๐ Security & Permissions
Access Control
- โข Requires authentication via
../public/authentication.php - โข No specific permission level checks mentioned
- โข Standard session-based authentication
Input Sanitization
- โข Uses
$_REQUESTdirectly (should be improved tofilter_input()) - โข Parameters validated for presence but not sanitized
- โข SQL injection prevented by DAO layer parameterized queries
Security Improvement Needed:
// Current (unsafe)
$productId = $_REQUEST['productId'];
// Should be
$productId = filter_input(INPUT_REQUEST, 'productId', FILTER_VALIDATE_INT);
---
๐ Performance Considerations
Database Optimization Tips
1. Indexes Required:
- sellbilldetail(sellbilldetailproductid, sellbillid)
- returnsellbilldetail(returnsellbilldetailproductid, returnsellbillid)
- sellandruternbilldetail(sellbilldetailproductid, sellbillid, selltype)
- sellbill(sellbillclientid, sellbilldate, conditions)
- returnsellbill(returnsellbillclientid, returnsellbilldate, conditions)
2. Query Optimization:
- Single complex query vs multiple simple queries
- Date filtering at database level
- Product and customer filtering in SQL
3. Memory Management:
- Process transactions in streaming fashion for large datasets
- Consider pagination for high-volume customer-product combinations
Potential Performance Issues
-- This type of query could be slow without proper indexes
SELECT * FROM sellbilldetail
JOIN sellbill ON sellbilldetail.sellbillid = sellbill.sellbillid
WHERE sellbill.sellbillclientid = ?
AND sellbilldetail.sellbilldetailproductid = ?
AND sellbill.sellbilldate BETWEEN ? AND ?
AND sellbill.conditions = 0;
---
๐ Common Issues & Troubleshooting
1. No Data Showing in Report
Issue: Report shows empty results despite existing transactions
Causes:
- โข Parameter validation failing
- โข Date format issues
- โข Product or customer not found
- โข Transaction conditions filtering out data
Debug:
// Add debugging to show action
echo "Product ID: " . $productId . "<br>";
echo "Client ID: " . $clientId . "<br>";
echo "Date range: " . $startDate . " to " . $endDate . "<br>";
// Check if parameters pass validation
if (isset($productId) && $productId != "-1" && $productId != "") {
echo "Product ID valid<br>";
} else {
echo "Product ID invalid<br>";
}
2. Incorrect Quantity Calculations
Issue: Quantity totals don't match expected values
Cause: Complex calculation logic in loadPricesForClient()
Debug:
// Simplify calculation and add debugging
foreach ($mydata as $alldata) {
echo "Type: " . $alldata->type . ", Qty: " . $alldata->quantity .
", Price: " . $alldata->price . "<br>";
if ($alldata->type == 0) {
$sellquantity += $alldata->quantity;
echo "Added to sales: " . $alldata->quantity . "<br>";
}
}
3. Performance Issues with Large Datasets
Issue: Report loads slowly for customers with many transactions
Cause: Inefficient query or lack of indexes
Solutions:
// Add date limits and pagination
if (empty($startDate) || empty($endDate)) {
// Require date range for performance
throw new Exception("Date range required");
}
// Consider adding limits
$mydata = $SellbilldetailEX->getallproductbyclientanddatenor(
$startDate, $endDate, $productId, $clientId, $limit = 1000
);
4. Product Selection Issues
Issue: Product dropdown not working or showing wrong products
Cause: Product category hierarchy or conditions filtering
Debug:
-- Check product status
SELECT productId, productName, conditions FROM product
WHERE productId = [PRODUCT_ID];
-- Check if product is in valid category
SELECT * FROM productcat WHERE productCatId = [CAT_ID];
---
๐งช Testing Scenarios
Test Case 1: Basic Customer-Product Analysis
1. Select customer with known transactions
2. Select product with known sales
3. Set date range covering known transactions
4. Verify quantities match expected values
5. Check price calculations are correct
Test Case 2: Sales vs Returns Analysis
1. Create sales transactions for customer-product
2. Create return transactions for same combination
3. Run report
4. Verify net quantity = sales - returns
5. Check price totals for both sales and returns
Test Case 3: Date Range Filtering
1. Create transactions on different dates
2. Set narrow date range
3. Verify only transactions in range appear
4. Test edge cases (start/end of period)
5. Test with no transactions in range
Test Case 4: Edge Cases
1. Test with invalid product ID (-1, empty)
2. Test with invalid customer ID (-1)
3. Test with missing date parameters
4. Test with future dates (should be empty)
5. Test with deleted/cancelled transactions
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข sellbillController.md - Sales operations
- โข productController.md - Product management
- โข clientController.php - Customer management
- โข Database Schema Documentation - Table relationships
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur