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:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**sellbilldetail**Sales transaction detailssellbilldetailid, sellbillid, sellbilldetailproductid, sellbilldetailquantity, sellbilldetailtotalprice
**returnsellbilldetail**Return transaction detailsreturnsellbilldetailid, returnsellbillid, returnsellbilldetailproductid, returnsellbilldetailquantity
**sellandruternbilldetail**Combined transaction detailssellandruternbilldetailid, sellbillid, sellbilldetailproductid, sellbilldetailquantity, selltype
### Master Tables

Table NamePurposeKey Columns
**sellbill**Sales billssellbillid, sellbillclientid, sellbilldate, conditions
**returnsellbill**Return billsreturnsellbillid, returnsellbillclientid, returnsellbilldate, conditions
**sellbillandrutern**Combined billssellbillid, sellbillclientid, sellbilldate, conditions
**product**Product masterproductId, productName, productCatId, conditions
**client**Customer masterclientid, clientname, conditions
### Reference Tables

Table NamePurposeKey Columns
**productcat**Product categoriesproductCatId, productCatName, productCatParent
**productunit**Product unitsproductunitid, productunitname
**programsettings**System settingsprogramsettingsid, settingkey, settingvalue
**youtubelink**Tutorial linksyoutubelinkid, 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

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Customer-Product Analysis
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Report Interface
- Load customer dropdown data
- Load product selection interface
- Display date range selectors
- Show YouTube tutorial links
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Parameter Selection
- Select customer from dropdown
- Select product (with category hierarchy)
- Choose date range (from/to)
- Submit form
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Validate Parameters
IF all required fields present:
โ”œโ”€ Product ID valid (!= -1, not empty)
โ”œโ”€ Customer ID valid (!= -1)
โ”œโ”€ Start date provided
โ”‚ โ””โ”€ End date provided โ”‚
THEN proceed to analysis
ELSE display form only
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Load Master Data
- Load product details (name, category)
- Load customer details (name)
- Build report header message
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Execute Analysis
CALL loadPricesForClient():
โ”‚
โ†’ Query transaction details
โ”‚ (sellbilldetail, returnsellbilldetail,
โ”‚ sellandruternbilldetail)
โ”‚
โ†’ Process each transaction:
โ”‚ โ”œโ”€ Extract price and quantity
โ”‚ โ”œโ”€ Identify type (sale=0, return=1)
โ”‚ โ”œโ”€ Calculate line totals
โ”‚ โ”‚ โ””โ”€ Accumulate by transaction type โ”‚
โ”‚
โ†’ Calculate summary metrics:
โ”‚ โ”œโ”€ Total sales quantity
โ”‚ โ”œโ”€ Total return quantity
โ”‚ โ”œโ”€ Net quantity (sales - returns)
โ”‚ โ”œโ”€ Total sales price
โ”‚ โ”‚ โ””โ”€ Total return price โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ Assign data to template โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Display Results
- Show customer and product names
- Display date range
- Show detailed transaction list
- Display summary metrics
- Provide quantity and price analysis
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=show` or `do=` (empty)Default actionDisplay customer-product analysis interface
`do=rates`rates actionAlternative interface (duplicate of show)
### Required Parameters for Analysis

Customer-Product Analysis:

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

Input Sanitization

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:

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

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur