๐Ÿ“š ERP Documentation Viewer

Beautiful, colorful documentation for your ERP system

Product Limit Report Controller Documentation

File: /controllers/productlimitreportController.php

Purpose: Generates inventory limit reports showing products below minimum stock thresholds across stores

Last Updated: December 20, 2024

Total Functions: 3

Lines of Code: ~341

---

๐Ÿ“‹ Overview

The Product Limit Report Controller is a specialized reporting module that monitors inventory levels and alerts when products fall below minimum stock thresholds. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**storedetail**Product inventory by storestoredetailid, storeid, productid, productquantity
**product**Product master dataproductid, productname, productcatid, productlimit, isService
**productstore**Product store-specific limitsproductstoreid, productid, storeid, productlimit
**store**Store/warehouse masterstoreid, storename, storeaddress
**productcat**Product category hierarchyproductcatid, productcatname, productcatparent
### System Tables

Table NamePurposeKey Columns
**youtubelink**Tutorial video linksyoutubelinkid, title, url
**breadcrumb**Navigation breadcrumbslevel, title, url
### Session-Based Access Control

Session VariablePurposeUsage
**$_SESSION['searchinonestore']**Store access mode0=multiple stores, 1=single store
**$_SESSION['storeid']**Default store IDPrimary store for user
**$_SESSION['storeids']**Accessible store listComma-separated store IDs
**$_SESSION['hidecat']**Category display setting0=show categories, 1=hide categories
---

๐Ÿ”‘ Key Functions

1. show() / Default Action - Main Inventory Limit Report

Location: Line 103 (do=show or empty)

Purpose: Generate comprehensive inventory limit report with store and category filtering

Process Flow:

1. Load authentication and YouTube tutorial links

2. Get category hierarchy data for filtering dropdown

3. Determine user store access permissions:

- Single store mode: Use assigned store only

- Multiple store mode: Use accessible stores list

4. Process filter parameters:

- Store ID selection

- Category hierarchy level selection

- Product ID specific filtering

- Search type (individual products vs category summaries)

5. Call showBystoreName() for data processing

6. Build breadcrumb navigation

7. Display via productlimitreportview/show.html

Features:

User Permission Logic:

if ($_SESSION['searchinonestore'] == 0) {
    // Multiple store access
    if ($_SESSION['storeids'] == 0) {
        $stores = $StoreEX->queryByConditions(); // All stores
    } else {
        $stores = $StoreEX->queryByConditions(' and store.storeId in (' . $_SESSION['storeids'] . ')');
    }
} else {
    // Single store mode - use assigned store only
    $storedef = $StoreEX->queryByConditionsOne(' and store.storeId = ' . $_SESSION['storeid'] . ' ');
}

---

2. showBystoreName() - Core Inventory Analysis Logic

Location: Line 195

Purpose: Process inventory data and identify products below minimum thresholds

Function Signature:

function showBystoreName()

Process Flow:

1. Parse Filter Parameters:

- Store ID selection

- Sort order preference

- Limit type (product vs productstore limits)

- Category hierarchy level selection

- Search type (individual vs category summary)

2. Build Base Query Conditions:

- Store filtering based on user permissions

- Exclude service products (product.isService = 0)

- Category-based product filtering

3. Handle Search Types:

- Type 0 (Individual Products): Process each product separately

- Type 1 (Category Summary): Group by last-level categories

4. Execute Inventory Queries:

- Product Limit Mode: Use limits from product table

- ProductStore Limit Mode: Use store-specific limits from productstore table

5. Process Results:

- Compare current quantities against thresholds

- Filter to show only products below limits

- Build category summary objects for type 1 search

Search Type Processing:

if ($searchtype == 0) {
    // Individual product analysis
    if ($searchStoreLimitType == 'product') {
        $storedetailData = $myStoredetailEx->queryWithStoreIdAndProductandorderLimit_f($order, $queryString);
    } else if ($searchStoreLimitType == 'productstore') {
        $storedetailData = $myStoredetailEx->queryWithStoreIdAndProductandorderLimit_f2($order, $queryString);
    }
} elseif ($searchtype == 1) {
    // Category summary analysis
    foreach ($lastLevelCatIDS as $mycatId) {
        // Process each category individually
        // Aggregate results by category
        // Create summary objects
    }
}

Key Variables:

---

3. getAllSubCat() - Recursive Category Processor

Location: Line 302

Purpose: Recursively process product category hierarchies for filtering

Function Signature:

function getAllSubCat($catid, $mode)

Modes:

Process Flow:

1. Query immediate child categories for given category

2. Mode 1 (All Subcategories):

- Add each subcategory to global list

- Recursively process each subcategory

- Build comprehensive category ID list

3. Mode 2 (Last Level Only):

- Check if category has children

- If no children: Add to last level list

- If has children: Recursively check children

- Build list of leaf categories only

Recursive Logic:

$result = $productCatExt->queryByParentExt($catid);
if (count($result) > 0) {
    foreach ($result as $data) {
        if ($mode == 1) {
            $catsIDS .= "," . $data->productCatId;
            getAllSubCat($data->productCatId, $mode); // Recurse for all
        } elseif ($mode == 2) {
            $childData = $productCatExt->queryByParentExt($data->productCatId);
            if (count($childData) > 0) {
                getAllSubCat($data->productCatId, $mode); // Has children, recurse
            } else {
                array_push($lastLevelCatIDS, $data->productCatId); // Leaf node
            }
        }
    }
}

Global Variables Used:

---

๐Ÿ”„ Workflows

Workflow 1: Store Inventory Limit Analysis

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Select Store & Filters
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Validate User Permissions
- Check store access mode (single/multiple)
- Load accessible stores list
- Set default store if single mode
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Parse Filter Parameters
- Store ID selection
- Category hierarchy level
- Product ID specific filter
- Search type (individual vs category)
- Limit type (product vs productstore)
- Sort order preference
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Build Query Conditions
- Store filter: IN (accessible_store_ids)
- Service filter: isService = 0
- Category filter: productid IN (category_products)
- Apply sort order specification
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Process Category Hierarchy (if selected)
IF category selected:
โ†’ getAllSubCat(categoryId, 1) // Get all children
โ†’ Query products in category tree
โ”‚ โ””โ”€โ†’ Add product IDs to filter โ”‚
IF search type = 1 (category summary):
โ†’ getAllSubCat(categoryId, 2) // Get leaf cats
โ”‚ โ””โ”€โ†’ Process each leaf category separately โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Execute Inventory Analysis
IF limit type = 'product':
โ†’ Query storedetail JOIN product
โ†’ Compare quantity vs product.productlimit
โ”‚ โ””โ”€โ†’ Filter: quantity < limit โ”‚
IF limit type = 'productstore':
โ†’ Query storedetail JOIN productstore
โ†’ Compare quantity vs productstore.productlimit
โ”‚ โ””โ”€โ†’ Filter: quantity < store_specific_limit โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
6Process Results by Search Type
IF search type = 0 (individual products):
โ†’ Return filtered product list
โ”‚ โ””โ”€โ†’ Each product below its limit โ”‚
IF search type = 1 (category summary):
โ†’ Group results by category
โ†’ Sum quantities per category
โ†’ Create category summary objects
โ”‚ โ””โ”€โ†’ Return category aggregations โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
7Generate Report Output
- Assign data to template variables
- Include store and category information
- Add breadcrumb navigation
- Display via productlimitreportview/show.html
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Category Hierarchy Processing

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: getAllSubCat(catid, mode)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Query Immediate Children
- Get direct subcategories of catid
- Check if any children exist
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Process Based on Mode
IF mode = 1 (Get all subcategories):
โ†’ Add each child to global catsIDS list
โ†’ Recursively call getAllSubCat() for each child
โ”‚ โ””โ”€โ†’ Build comprehensive ID list โ”‚
IF mode = 2 (Get leaf categories only):
โ†’ Check if child has its own children
โ†’ If no grandchildren: Add to lastLevelCatIDS
โ†’ If has grandchildren: Recursively process
โ”‚ โ””โ”€โ†’ Build leaf node list only โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Update Global Variables
MODE 1 results:
โ”‚ โ””โ”€โ†’ $catsIDS = "1,5,12,18,25,..." (all descendants) โ”‚
MODE 2 results:
โ”‚ โ””โ”€โ†’ $lastLevelCatIDS = [15, 22, 31] (leaf nodes) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Return to Calling Function
- Global variables updated with category lists
- Ready for product filtering queries
- Category tree fully processed
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty) or `do=show``showBystoreName()`Main inventory limit report
`do=sucess`Display templateSuccess message page
`do=error`Display templateError message page
### Required Parameters by Action

Inventory Limit Report (do=show):

Session-Based Parameters

---

๐Ÿงฎ Calculation Methods

Store Access Control

// Determine user store access
if ($_SESSION['searchinonestore'] == 0) {
    // Multiple store mode
    if ($_SESSION['storeids'] != 0) {
        $queryString .= 'and storedetail.storeid in (' . $_SESSION['storeids'] . ') ';
    }
} else {
    // Single store mode
    $queryString .= 'and storedetail.storeid = ' . $_SESSION['storeid'] . ' ';
    $storeId = $_SESSION['storeid'];
}

Product Filtering

// Service product exclusion
$queryString .= ' and product.isService = 0 ';

// Category-based filtering
if (isset($productCatId) && $productCatId != -1) {
    $catsIDS = '' . $productCatId;
    getAllSubCat($productCatId, 1); // Get all subcategories
    $productsOfCat = $ProductEX->queryByProductCatIdIn($catsIDS);
    
    $IDS = '0,' . $productCatId;
    foreach ($productsOfCat as $value) {
        $IDS .= ',' . $value->productId;
    }
    $queryString .= 'and storedetail.productid in (' . $IDS . ') ';
}

Category Summary Aggregation

// Category summary mode processing
if ($searchtype == 1) {
    $lastLevelCatIDS = array();
    array_push($lastLevelCatIDS, $productCatId);
    getAllSubCat($productCatId, 2); // Get leaf categories
    
    foreach ($lastLevelCatIDS as $mycatId) {
        // Process each leaf category
        $catsIDS = '' . $mycatId;
        getAllSubCat($mycatId, 1); // Get all products in category
        
        $myObj = new Storedetail();
        $myObj->productName = $categoryName;
        foreach ($storedetailData as $value) {
            $myObj->productquantity += $value->productquantity; // Sum quantities
        }
        array_push($allDataArr, $myObj);
    }
}

---

๐Ÿ”’ Security & Permissions

User Authentication

// Required authentication
include_once("../public/authentication.php");

Store Access Control

Input Sanitization

// Filter input parameters
$level = filter_input(INPUT_POST, 'level');
$productCatId = filter_input(INPUT_POST, 'productCatId' . $level);
$productId = filter_input(INPUT_POST, 'productId');
$searchtype = filter_input(INPUT_POST, 'searchtype');

Security Measures:

---

๐Ÿ“Š Performance Considerations

Database Optimization

1. Required Indexes:

- storedetail(storeid, productid)

- product(productcatid, isService)

- productstore(productid, storeid)

- productcat(productcatparent)

2. Query Optimization:

- Store filtering reduces dataset size

- Service product exclusion early in query

- Category filtering with IN clauses

- Limit comparison at database level

3. Memory Management:

- Recursive category processing has depth limits

- Large store inventories may need pagination

- Category summary mode reduces memory usage vs individual products

Performance Tips

-- Optimize limit queries with proper indexing
CREATE INDEX idx_storedetail_limit ON storedetail(storeid, productid, productquantity);
CREATE INDEX idx_product_service ON product(isService, productcatid);

-- Consider materialized views for complex category hierarchies
CREATE VIEW product_category_tree AS 
WITH RECURSIVE cat_tree AS (...)

---

๐Ÿ› Common Issues & Troubleshooting

1. No Products Below Limit

Issue: Report shows no results despite low inventory

Cause: Limits not properly configured or wrong limit type selected

Debug:

-- Check product limits configuration
SELECT productname, productlimit, isService 
FROM product 
WHERE productcatid = [CATEGORY_ID];

-- Check productstore limits
SELECT ps.productlimit, p.productname, s.storename
FROM productstore ps
JOIN product p ON ps.productid = p.productid  
JOIN store s ON ps.storeid = s.storeid;

2. Store Access Issues

Issue: User cannot see expected stores

Cause: Session permissions not properly configured

Debug:

echo "Search Mode: " . $_SESSION['searchinonestore'] . "<br>";
echo "Store ID: " . $_SESSION['storeid'] . "<br>";
echo "Store IDs: " . $_SESSION['storeids'] . "<br>";

3. Category Recursion Problems

Issue: Category filtering returns too many/few products

Cause: Infinite recursion or incorrect hierarchy

Fix:

-- Check for circular references
SELECT * FROM productcat WHERE productcatid = productcatparent;

-- Verify category tree depth
WITH RECURSIVE depth_check AS (
  SELECT productcatid, productcatparent, 1 as level
  FROM productcat WHERE productcatparent = 0
  UNION ALL
  SELECT c.productcatid, c.productcatparent, d.level + 1
  FROM productcat c
  JOIN depth_check d ON c.productcatparent = d.productcatid
  WHERE d.level < 20
)
SELECT MAX(level) FROM depth_check;

---

๐Ÿงช Testing Scenarios

Test Case 1: Basic Limit Report

1. Set product limits in product table
2. Ensure inventory quantities below limits
3. Run report for specific store
4. Verify only below-limit products appear
5. Check quantity accuracy against database

Test Case 2: Category Hierarchy Filtering

1. Create nested category structure (3+ levels)
2. Add products to various category levels
3. Set some products below limits
4. Test category filtering at different levels
5. Verify subcategory inclusion works correctly

Test Case 3: Store Permission Enforcement

1. Configure user with limited store access
2. Set session variables appropriately  
3. Run report and verify only accessible stores appear
4. Test both single and multiple store modes

Test Case 4: ProductStore vs Product Limits

1. Set up products with both limit types
2. Configure different limits in product vs productstore
3. Test both limit type options
4. Verify correct limits are applied

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur

โ†‘