Customersproducts Documentation

Customers Products Controller Documentation

File: /controllers/customersproductsController.php

Purpose: Generates comprehensive customer-product sales analysis reports with detailed transaction tracking and category hierarchy support

Last Updated: December 20, 2024

Total Functions: 22

Lines of Code: ~506

---

๐Ÿ“‹ Overview

The Customers Products Controller is a comprehensive analytics module that provides detailed customer-product sales analysis with support for complex product category hierarchies. This controller extends beyond simple reporting to include sophisticated product categorization, detailed transaction analysis, and comprehensive customer purchasing behavior insights. The system features:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Transaction Analysis)

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

Table NamePurposeKey Columns
**sellbill**Sales bill headerssellbillid, sellbillclientid, sellbilldate, conditions
**returnsellbill**Return bill headersreturnsellbillid, returnsellbillclientid, returnsellbilldate, conditions
**sellbillandrutern**Combined bill headerssellbillid, sellbillclientid, sellbilldate, conditions
**product**Product master dataproductId, productName, productCatId, conditions
**client**Customer master dataclientid, clientname, conditions
### Category Hierarchy Tables

Table NamePurposeKey Columns
**productcat**Product categoriesproductCatId, productCatName, productCatParent
**productunit**Product unitsproductunitid, productunitname
---

๐Ÿ”‘ Key Functions

1. Default Action - Analysis Interface Display

Location: Line 124-155

Purpose: Display customer-product analysis form with data loading

Process Flow:

1. Load product category hierarchy

2. Load customer data for dropdown

3. Set breadcrumb navigation

4. Enable product selection interface

5. Display analysis form

if (empty($do)) {
    include_once("../public/authentication.php");
    
    // Load product categories with hierarchy
    $productCatData = loadProductCat();
    $smarty->assign("productCatData", $productCatData);
    
    // Load all customers
    $allclient = getallclient();
    $smarty->assign("allclient", $allclient);
    
    // Load product/customer data if already selected
    $myclientdata = $ClientDAO->load($clientid);
    $myproductdata = $myProductRecord->load($productId);
    
    // Breadcrumb navigation
    $breadcrumbObject->add('ุงู„ุงุฏุงุฑุฉ><a href="productsellsreportController.php">ุงู„ุชู‚ุงุฑูŠุฑ</a> >ุชู‚ุฑูŠุฑ ู…ุจูŠุนุงุช ู…ู†ุชุฌ', 'productsellsreportController.php', 0);
    
    $smarty->assign("settlementstoreshow", 1);
    $smarty->display("customersproductsview/show.html");
}

---

2. show Action - Analysis Report Generation

Location: Line 156-228

Purpose: Process analysis parameters and generate detailed customer-product report

Function Signature:

// URL Parameters
$startDate = $_REQUEST['from'];
$endDate = $_REQUEST['to'];
$productId = $_REQUEST['productId'];
$clientid = $_REQUEST['clientid'];

Process Flow:

elseif ($do == "show") {
    include_once("../public/authentication.php");
    
    // Load supporting data
    $productCatData = loadProductCat();
    $smarty->assign("productCatData", $productCatData);
    
    $allclient = getallclient();
    $smarty->assign("allclient", $allclient);
    
    // Validate required parameters
    if (isset($startDate) && isset($endDate) && isset($clientid) &&
        isset($productId) && $startDate != "" && $endDate != "" && 
        $clientid != -1 && $productId != '-1') {
        
        // Load master data for report header
        $myclientdata = $ClientDAO->load($clientid);
        $myproductdata = $myProductRecord->load($productId);
        
        // Generate report message
        $message = "ุชู‚ุฑูŠุฑ ู…ุดุชุฑูŠุงุช  ุงู„ุนู…ูŠู„ :" . $myclientdata->clientname . 
                   " ู…ู† ุงู„ู…ู†ุชุฌ :" . $myproductdata->productName . 
                   "<br> ู…ู† ุชุงุฑูŠุฎ:" . $startDate . " ุงู„ู‰ ุชุงุฑูŠุฎ" . $endDate;
        $smarty->assign('message', $message);
        
        // Execute analysis
        $allmydata = loadProductByProductclientAndDate($productId, $startDate, $endDate, $clientid);
        $smarty->assign("allmydata", $allmydata);
    }
    
    // Display results
    $smarty->display("customersproductsview/show.html");
    $smarty->assign("settlementstoreshow", 1);
}

---

3. loadProductByProductclientAndDate() - Core Analysis Engine

Location: Line 368-379

Purpose: Retrieve detailed transaction data for customer-product combination

Function Signature:

function loadProductByProductclientAndDate($productid, $startDate, $endDate, $clientid)

Implementation:

function loadProductByProductclientAndDate($productid, $startDate, $endDate, $clientid) {
    global $myProductEx;
    global $mySellbilldetailEx;
    global $smarty;
    
    // Get all product transactions for customer in date range
    $productData = $mySellbilldetailEx->getallproductbyclientanddate($startDate, $endDate, $productid, $clientid);
    
    return $productData;
}

---

4. Product Analysis Functions - Quantity Aggregation

4a. showSellByProduct() - Sales Quantity Analysis

Location: Line 243-251

function showSellByProduct($productId) {
    global $mySellbilldetailEx;
    $sumQuantity = $mySellbilldetailEx->queryQuantityWithProduct($productId);
    return $sumQuantity;
}

4b. showAditionalSellByProduct() - Additional Sales Analysis

Location: Line 254-263

function showAditionalSellByProduct($productId) {
    global $mySellandruternbilldetailEx;
    $sumQuantity = $mySellandruternbilldetailEx->queryQuantityWithProductAndSellType($productId, 0);
    return $sumQuantity;
}

4c. showReturnSellByProduct() - Return Quantity Analysis

Location: Line 265-274

function showReturnSellByProduct($productId) {
    global $myReturnsellbilldetailEx;
    $sumQuantity = $myReturnsellbilldetailEx->queryQuantityWithProduct($productId);
    return $sumQuantity;
}

4d. showAditionalReturnSellByProduct() - Additional Returns Analysis

Location: Line 276-285

function showAditionalReturnSellByProduct($productId) {
    global $mySellandruternbilldetailEx;
    $sumQuantity = $mySellandruternbilldetailEx->queryQuantityWithProductAndSellType($productId, 1);
    return $sumQuantity;
}

---

5. Date-Filtered Analysis Functions

5a. showSellByProductAndDate() - Date-Filtered Sales

Location: Line 323-331

function showSellByProductAndDate($productId, $startDate, $endDate) {
    global $mySellbilldetailEx;
    $sumQuantity = $mySellbilldetailEx->queryQuantityWithProductAndDate($productId, $startDate, $endDate);
    return $sumQuantity;
}

5b. showAditionalSellByProductAndDate() - Date-Filtered Additional Sales

Location: Line 334-342

function showAditionalSellByProductAndDate($productId, $startDate, $endDate) {
    global $mySellandruternbilldetailEx;
    $sumQuantity = $mySellandruternbilldetailEx->queryQuantityWithProductAndSellTypeAndDate($productId, 0, $startDate, $endDate);
    return $sumQuantity;
}

5c. showReturnSellByProductAndDate() - Date-Filtered Returns

Location: Line 345-353

function showReturnSellByProductAndDate($productId, $startDate, $endDate) {
    global $myReturnsellbilldetailEx;
    $sumQuantity = $myReturnsellbilldetailEx->queryQuantityWithProductAndDate($productId, $startDate, $endDate);
    return $sumQuantity;
}

---

6. Category Hierarchy Functions

6a. loadProductCat() - Category Tree Builder

Location: Line 453-467

Purpose: Build complete product category hierarchy for display

function loadProductCat() {
    global $myProductcatEx;
    
    // Get categories that have products
    $productcatData = $myProductcatEx->queryProductcatInProduct();
    
    // Build full hierarchy path for each category
    foreach ($productcatData as $productcat) {
        $productcatName;
        $productcat->productCatName = loadProductCatNameById($productcat->productCatId, $productcatName, 1);
    }
    
    return $productcatData;
}

6b. loadProductCatNameById() - Recursive Category Name Builder

Location: Line 470-494

Purpose: Build full category path with parent hierarchy

function loadProductCatNameById($productCatId, $productcatName, $itr) {
    global $myProductcatRecord;
    
    $productcatNamex = $productcatName;
    $productcatData = $myProductcatRecord->load($productCatId);
    
    if (count($productcatData) > 0) {
        if ($itr == 1) {
            // First iteration - current category name
            $productcatNamex = $productcatData->productCatName;
        } elseif ($itr == 2) {
            // Subsequent iterations - prepend parent name
            $productcatNamex = $productcatData->productCatName . "/" . $productcatNamex;
        }
        
        // Recurse to parent if exists
        if ($productcatData->productCatParent != 0) {
            return loadProductCatNameById($productcatData->productCatParent, $productcatNamex, 2);
        }
    }
    
    return $productcatNamex;
}

---

7. Category Analysis Functions

7a. loadProductByProductcatId() - Category-Based Analysis

Location: Line 288-320

Purpose: Analyze all products within a category

function loadProductByProductcatId($productcatId) {
    global $myProductEx;
    global $myProductRecord;
    global $smarty;
    
    // Load all products in category
    $productData = $myProductRecord->queryByProductCatId($productcatId);
    $smarty->assign("productData", $productData);
    
    $h = 1;
    foreach ($productData as $product) {
        $productId = $product->productId;
        
        // Calculate sales quantities
        $sellsQuantity = showSellByProduct($productId);
        $aditionalSellsQuantity = showAditionalSellByProduct($productId);
        $totalSellsQuantity = $sellsQuantity + $aditionalSellsQuantity;
        
        // Calculate return quantities
        $returnSellQuantity = showReturnSellByProduct($productId);
        $aditionalReturnSellsQuantity = showAditionalReturnSellByProduct($productId);
        $totalReturnSellsQuantity = $returnSellQuantity + $aditionalReturnSellsQuantity;
        
        // Calculate net quantity
        $remainQuantity = $totalSellsQuantity - $totalReturnSellsQuantity;
        
        // Assign to template with indexed variables
        $smarty->assign("totalSellsQuantity" . $h . "", $totalSellsQuantity);
        $smarty->assign("totalReturnSellsQuantity" . $h . "", $totalReturnSellsQuantity);
        $smarty->assign("remainQuantity" . $h . "", $remainQuantity);
        
        $h++;
    }
}

---

8. Supporting Functions

8a. getallclient() - Customer Data Loader

Location: Line 496-504

function getallclient() {
    global $Client;
    global $ClientDAO;
    global $ClientEX;
    
    $allclientdata = $ClientDAO->queryAll();
    return $allclientdata;
}

---

๐Ÿ”„ Workflows

Workflow 1: Customer-Product Analysis

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Customer-Product Analysis
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Analysis Interface
- Load product category hierarchy
- Build category dropdown with full paths
- Load customer dropdown data
- Display product selection interface
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Parameter Selection
- Select customer from dropdown
- Choose product (with category context)
- Set date range for analysis
- Submit analysis form
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Parameter Validation
Validate all required parameters:
โ”œโ”€ Customer ID (!= -1)
โ”œโ”€ Product ID (!= -1, not empty)
โ”œโ”€ Start date (not empty)
โ”‚ โ””โ”€ End date (not empty) โ”‚
IF validation passes:
โ”‚ โ””โ”€โ†’ Proceed to analysis โ”‚
ELSE:
โ”‚ โ””โ”€โ†’ Display form only โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Load Master Data
- Load customer details for report header
- Load product details for report header
- Build descriptive report title
- Set template variables
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Execute Transaction Analysis
CALL loadProductByProductclientAndDate():
โ”‚
โ”‚ โ””โ”€โ†’ Execute mySellbilldetailEx->getallproductby... โ”‚
โ”œโ”€ Query sellbilldetail transactions
โ”œโ”€ Query returnsellbilldetail transactions
โ”œโ”€ Query sellandruternbilldetail transactions
โ”œโ”€ Filter by customer, product, and date range
โ”œโ”€ Include transaction type information
โ”‚ โ””โ”€ Return aggregated transaction data โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Display Analysis Results
- Show customer and product names
- Display date range for analysis
- Present detailed transaction list
- Show transaction types (sale/return)
- Display quantities and amounts
- Provide analysis summary
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Product Category Hierarchy Building

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Category Hierarchy Building
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Load Categories with Products
CALL loadProductCat():
โ”‚
โ”‚ โ””โ”€โ†’ Query categories that have products โ”‚
(myProductcatEx->queryProductcatInProduct)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Build Category Names
FOR EACH category:
โ”‚
โ”‚ โ””โ”€โ†’ CALL loadProductCatNameById(catId, "", 1): โ”‚
โ”‚
โ†’ Load category record
โ†’ Start with category name
โ†’ Check for parent category
โ”‚
โ”‚ โ””โ”€โ†’ IF parent exists: โ”‚
โ”‚ โ””โ”€โ†’ Recursively call with parent ID โ”‚
โ”œโ”€ Build: "Parent/Child" format
โ”œโ”€ Continue up hierarchy
โ”‚ โ””โ”€ Return full path โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Category Path Example
Original category structure:
Electronics (ID: 1, Parent: 0)
โ”‚ โ””โ”€ Mobile Phones (ID: 5, Parent: 1) โ”‚
โ”‚ โ””โ”€ Smartphones (ID: 10, Parent: 5) โ”‚
Resulting display name:
"Electronics/Mobile Phones/Smartphones"
This provides full context in dropdown
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Return Structured Data
- Array of category objects
- Each with full hierarchical path
- Ready for dropdown display
- Supports nested product selection
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty)Default actionDisplay customer-product analysis interface
`do=show`Show actionProcess and display customer-product analysis
### Required Parameters for Analysis

Customer-Product Analysis:

Example URL:

customersproductsController.php?do=show&clientid=123&productId=456&from=2024-01-01&to=2024-12-31

---

๐Ÿงฎ Calculation Methods

Quantity Aggregation (Category Analysis)

// Sales quantities
$sellsQuantity = showSellByProduct($productId);
$aditionalSellsQuantity = showAditionalSellByProduct($productId);
$totalSellsQuantity = $sellsQuantity + $aditionalSellsQuantity;

// Return quantities
$returnSellQuantity = showReturnSellByProduct($productId);
$aditionalReturnSellsQuantity = showAditionalReturnSellByProduct($productId);
$totalReturnSellsQuantity = $returnSellQuantity + $aditionalReturnSellsQuantity;

// Net quantity
$remainQuantity = $totalSellsQuantity - $totalReturnSellsQuantity;

Category Hierarchy Path Building

// Recursive category path construction
function loadProductCatNameById($productCatId, $productcatName, $itr) {
    // $itr = 1: First call, use current name
    // $itr = 2: Recursive calls, prepend parent
    
    if ($itr == 1) {
        $productcatNamex = $productcatData->productCatName; // "Smartphones"
    } elseif ($itr == 2) {
        $productcatNamex = $productcatData->productCatName . "/" . $productcatNamex; // "Mobile Phones/Smartphones"
    }
    
    // Continue recursion if parent exists
    if ($productcatData->productCatParent != 0) {
        return loadProductCatNameById($productcatData->productCatParent, $productcatNamex, 2);
    }
    
    // Final result: "Electronics/Mobile Phones/Smartphones"
}

---

๐Ÿ”’ Security & Permissions

Access Control

// Authentication required for all actions
include_once("../public/authentication.php");

Input Sanitization

Security Risk Example:

// Current (unsafe)
$productId = $_REQUEST['productId'];
$clientid = $_REQUEST['clientid'];

// Should be (safe)
$productId = filter_input(INPUT_REQUEST, 'productId', FILTER_VALIDATE_INT);
$clientid = filter_input(INPUT_REQUEST, 'clientid', FILTER_VALIDATE_INT);

SQL Injection Prevention

---

๐Ÿ“Š Performance Considerations

Database Optimization Tips

1. Indexes Required:

- sellbilldetail(sellbilldetailproductid, sellbillid)

- returnsellbilldetail(returnsellbilldetailproductid, returnsellbillid)

- sellandruternbilldetail(sellbilldetailproductid, sellbillid, selltype)

- sellbill(sellbillclientid, sellbilldate, conditions)

- productcat(productCatParent, productCatId)

- product(productCatId, conditions)

2. Query Optimization:

- Category hierarchy loaded once and cached

- Separate queries for different transaction types

- Date filtering applied at database level

3. Category Performance:

- Recursive category path building can be expensive

- Consider caching category paths

- Limit hierarchy depth if needed

Performance Risks

// Recursive category loading could be slow with deep hierarchies
function loadProductCatNameById($productCatId, $productcatName, $itr) {
    // Each recursion = one database query
    // Deep hierarchies = many queries
}

Improvement Suggestion:

// Cache category paths or use single query with CTE
$categoryPaths = loadAllCategoryPaths(); // Single query
foreach ($categories as $category) {
    $category->fullPath = $categoryPaths[$category->productCatId];
}

---

๐Ÿ› Common Issues & Troubleshooting

1. Category Hierarchy Display Issues

Issue: Category names showing incorrectly or incompletely

Cause: Recursive function errors or missing parent categories

Debug:

// Test category hierarchy
$testCatId = 10;
echo "Testing category ID: " . $testCatId . "<br>";
$fullName = loadProductCatNameById($testCatId, "", 1);
echo "Full path: " . $fullName . "<br>";

// Check for orphaned categories
SELECT c1.productCatId, c1.productCatName, c1.productCatParent
FROM productcat c1
LEFT JOIN productcat c2 ON c1.productCatParent = c2.productCatId
WHERE c1.productCatParent != 0 AND c2.productCatId IS NULL;

2. Product Selection Issues

Issue: Products not appearing in analysis despite existing transactions

Cause: Parameter validation or product status filtering

Debug:

// Check parameter validation
if (isset($productId) && $productId != "-1" && $productId != "") {
    echo "Product ID is valid: " . $productId . "<br>";
} else {
    echo "Product ID validation failed<br>";
    echo "Product ID value: '" . $productId . "'<br>";
}

// Check product exists and is active
SELECT productId, productName, conditions FROM product WHERE productId = [ID];

3. Date Range Analysis Issues

Issue: Analysis returns no data for valid date ranges

Cause: Date format issues or timezone problems

Debug:

echo "Date range: " . $startDate . " to " . $endDate . "<br>";

// Test date format
if (DateTime::createFromFormat('Y-m-d', $startDate)) {
    echo "Start date format valid<br>";
} else {
    echo "Start date format invalid<br>";
}

// Check for transactions in date range
SELECT COUNT(*) FROM sellbilldetail sbd
JOIN sellbill sb ON sbd.sellbillid = sb.sellbillid
WHERE sb.sellbillclientid = [CLIENT_ID]
AND sbd.sellbilldetailproductid = [PRODUCT_ID]
AND sb.sellbilldate BETWEEN 'startdate' AND 'enddate';

4. Template Variable Indexing Issues

Issue: Category analysis results not displaying correctly

Cause: Dynamic template variable assignment in loadProductByProductcatId()

Debug:

// Check template variable assignment
foreach ($productData as $key => $product) {
    $h = $key + 1; // Ensure consistent indexing
    echo "Assigning variables for product " . $h . ": " . $product->productName . "<br>";
    $smarty->assign("totalSellsQuantity" . $h, $totalSellsQuantity);
    // ... other assignments
}

// Verify variables in template
// In template: {if isset($totalSellsQuantity1)}{$totalSellsQuantity1}{/if}

---

๐Ÿงช Testing Scenarios

Test Case 1: Customer-Product Analysis

1. Create customer with product transactions
2. Create sales, returns, and combined transactions
3. Set date range covering all transactions
4. Run analysis
5. Verify all transaction types appear
6. Check quantity calculations are correct

Test Case 2: Category Hierarchy Display

1. Create multi-level category hierarchy:
   - Electronics (parent: none)
   - Mobile Phones (parent: Electronics)  
   - Smartphones (parent: Mobile Phones)
2. Add products to deepest category
3. Load category interface
4. Verify full path displays as "Electronics/Mobile Phones/Smartphones"

Test Case 3: Date Range Filtering

1. Create transactions on different dates
2. Test various date ranges:
   - Single day
   - Week range
   - Month range
   - Cross-month range
3. Verify filtering works correctly
4. Test edge cases (transaction on boundary dates)

Test Case 4: Parameter Validation

1. Test with missing parameters:
   - No customer ID (-1)
   - No product ID (-1 or empty)
   - No dates (empty strings)
2. Test with invalid parameters:
   - Non-existent customer ID
   - Non-existent product ID
   - Invalid date formats
3. Verify form displays without analysis when validation fails

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur