Productserailreport Documentation

Product Serial Report Controller Documentation

File: /controllers/productserailreportController.php

Purpose: Manages product serial number tracking, barcode reports, and product expiration reporting

Last Updated: December 20, 2024

Total Functions: 8

Lines of Code: ~398

---

๐Ÿ“‹ Overview

The Product Serial Report Controller is a specialized reporting module that provides comprehensive tracking and reporting for serialized products with barcodes and expiration dates. It handles:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**productserial**Product serial trackingproductserialid, serialnumber, productid, startdate, enddate, del
**soldserialproduct**Sold serial products logsoldserialproductid, productserialid, sellbillid, sellbilldetailid
**product**Product master dataproductid, productname, productcatid, productunit, productprice
**productcat**Product categoriesproductcatid, productcatname, productcatparent
### Reference Tables

Table NamePurposeKey Columns
**programsettings**System configurationprogramsettingsid, settingkey, settingvalue
**youtubelink**Tutorial videosyoutubelinkid, title, url, description
### Extended DAO Operations

DAO MethodPurposeTable(s) Accessed
**queryallEx()**Get all product serials with product infoproductserial JOIN product
**queryallExbyid()**Get product serials by ID with detailsproductserial JOIN product
**queryallExbyidExt()**Get single product serial with full detailsproductserial JOIN product JOIN productcat
**queryallExbydiffExt2()**Get products by expiration conditionproductserial JOIN product with date calculations
**loadProduct()**Load product with category nameproduct JOIN productcat
**getProductCatParents()**Get root product categoriesproductcat WHERE productcatparent = 0
**getCategoryAndParentByCatId()**Get category with parent infoproductcat with recursive lookup
**updatedel()**Mark serial as deletedproductserial UPDATE del field
---

๐Ÿ”‘ Key Functions

1. show() / Default Action - Product Serial Report

Location: Line 279

Purpose: Generate detailed tracking report for a specific product serial number

Function Signature:

// Triggered when: do=show or empty $do
$productserailid = $_REQUEST["productserailid"];
function show($productserailid)

Process Flow:

1. Load product serial data with product information

2. Build product category path using recursive function

3. Calculate remaining days until expiration

4. Format dates and intervals for display

5. Return processed data with expiration calculations

Features:

Date Calculation Logic:

$now = new DateTime(date('Y-m-d H:i:s'));
$endDate = $pro->enddate . ' ' . date('H:i:s');
$endDate = new DateTime($endDate);
$interval = $now->diff($endDate);
$pro->diff = (int) $interval->format('%r%a'); // Remaining days

---

2. showvalidity() - Expiration Validation Report

Location: Line 323

Purpose: Generate reports for products based on expiration conditions

Function Signature:

function showvalidity($condition, $daynumber, $productSearchId)

Process Flow:

1. Build query string with product filter if specified

2. Query products based on expiration conditions

3. Calculate remaining days for each product

4. Apply category path display based on settings

5. Assign processed data to template

Condition Types:

Category Path Logic:

if ($_SESSION['hidecat'] == 1) {
    $parentId = $pro->productCatId;
    $pathArr = getProductPath_recursive($parentId, $categories);
    $pro->productName = $pro->productName . '/' . $pathArr;
} else {
    $pro->productName = $pro->productName;
}

---

3. getallproductserail() - Load All Product Serials

Location: Line 259

Purpose: Retrieve all product serial numbers with product information

Function Signature:

function getallproductserail()

Process Flow:

1. Call extended DAO method to get all serial data

2. Join with product table for complete information

3. Return array of product serial objects

Returns: Array of product serial objects with product names and details

---

4. delserail() - Serial Number Deletion

Location: Line 269

Purpose: Mark product serial numbers as deleted (soft delete)

Function Signature:

function delserail()

Process Flow:

1. Extract serial ID and deletion flag from GET parameters

2. Call extended DAO to update deletion status

3. Maintain data integrity by soft delete approach

Parameters:

---

5. getProductPath_recursive() - Category Path Builder

Location: Line 308

Purpose: Build complete category hierarchy path for products

Function Signature:

function getProductPath_recursive($parentid, $categories)

Process Flow:

1. Get category data for current parent ID

2. Append category name to path string

3. Recursively call for parent category

4. Return complete path string

Recursion Logic:

if (count($catData) > 0) {
    $categories .= $catData->productCatName . '/';
    $newParentId = $catData->productCatParent;
    return getProductPath_recursive($newParentId, $categories);
}

---

6. loadProductCategories() - Product Category Navigation

Location: Line 356

Purpose: Load product categories for navigation and filtering

Function Signature:

function loadProductCategories()

Process Flow:

1. Query all products to get unique categories

2. For each product category, build complete path

3. Assign category data to template variables

4. Prepare navigation iteration counter

Template Variables:

---

7. fetch_recursive() - Alternative Path Builder

Location: Line 381

Purpose: Alternative recursive function for category path building

Function Signature:

function fetch_recursive($parentid, $categories)

Process Flow:

1. Similar to getProductPath_recursive but with different structure

2. Includes parent name handling in recursion

3. Returns formatted category path string

Differences from getProductPath_recursive:

---

8. getProductCatId() - Category ID Retrieval

Location: Line 253

Purpose: Get product category ID for a specific product

Function Signature:

function getProductCatId($productId)

Returns: Category ID for the specified product

---

๐Ÿ”„ Workflows

Workflow 1: Product Serial Report Generation

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Select Product Serial
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Validate Input Parameters
- Check productserailid
- Verify serial exists in database
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Load Product Serial Data
- Query productserial with product details
- Get product name and category information
- Load start date and end date
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Build Category Path
- Get product category ID
- Recursively build category hierarchy
- Create complete product path string
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Calculate Expiration Information
- Get current date and time
- Calculate interval to expiration date
- Convert to remaining days
- Format for display
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
5Generate Report Output
- Assign data to template variables
- Include product path and expiration
- Display via show.html template
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Expiration Validity Report

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Set Expiration Criteria
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Parse Filter Parameters
- Get condition type (before/after/within)
- Get day number threshold
- Get product filter (optional)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Build Database Query
- Add product filter if specified
- Apply expiration date conditions
- Include product and category joins
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Process Each Product
FOR EACH product in results:
โ”‚
โ†’ Calculate remaining days
โ”‚
โ†’ Build category path (if enabled)
โ”‚
โ”‚ โ””โ”€โ†’ Format for report display โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Generate Validity Report
- Sort by expiration date
- Assign to template variables
- Display via showvalidity.html
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty) or `do=show``show()`Product serial report
`do=showvalidity``showvalidity()`Expiration validation report
`do=tempdelete``delserail()`Delete/deactivate serial number
`do=sucess`Display templateSuccess message page
`do=error`Display templateError message page
### Required Parameters by Action

Product Serial Report (do=show):

Validity Report (do=showvalidity):

Serial Deletion (do=tempdelete):

---

๐Ÿงฎ Calculation Methods

Expiration Days Calculation

$now = new DateTime(date('Y-m-d H:i:s'));
$endDate = $pro->enddate . ' ' . date('H:i:s');
$endDate = new DateTime($endDate);
$interval = $now->diff($endDate);
$pro->diff = (int) $interval->format('%r%a');
// %r = sign ("-" if negative), %a = total days

Category Path Building

function getProductPath_recursive($parentid, $categories) {
    $catData = $productCatExt->getCategoryAndParentByCatId($parentid);
    
    if (count($catData) > 0) {
        $categories .= $catData->productCatName . '/';
        $newParentId = $catData->productCatParent;
        return getProductPath_recursive($newParentId, $categories);
    }
    
    // Remove trailing slash
    $categories = substr($categories, 0, strlen($categories) - 1);
    return $categories;
}

Product Path Formatting

// Build complete product name with category path
$pro->productName = $pro->productName . '/' . $pathArr;

// Example output: "iPhone 13/Electronics/Mobile Phones/Smartphones"

---

๐Ÿ”’ Security & Permissions

Authentication Requirements

// All modification actions require authentication
include_once("../public/authentication.php");

Input Sanitization

Session Management

---

๐Ÿ“Š Performance Considerations

Database Optimization Tips

1. Indexes Required:

- productserial(productid, enddate)

- productserial(serialnumber)

- product(productcatid)

- productcat(productcatparent)

2. Query Optimization:

- Extended DAO methods use JOINs efficiently

- Recursive category functions cache results

- Date calculations done in PHP vs database

3. Memory Management:

- Recursive functions have depth limits

- Large product catalogs may need pagination

- Category path building cached per session

Known Performance Issues

-- Recursive category queries can be slow for deep hierarchies
-- Solution: Consider materialized path or closure table approaches

-- Date calculations on large datasets
-- Solution: Add computed columns for common date ranges

---

๐Ÿ› Common Issues & Troubleshooting

1. Missing Product Names in Reports

Issue: Product serials show without product information

Cause: Extended DAO queries failing to join properly

Debug:

SELECT ps.*, p.productname 
FROM productserial ps 
LEFT JOIN product p ON ps.productid = p.productid 
WHERE ps.productserialid = [ID];

2. Incorrect Expiration Calculations

Issue: Wrong remaining days displayed

Cause: Date format inconsistencies or timezone issues

Fix:

// Ensure consistent date format
$endDate = $pro->enddate . ' ' . date('H:i:s');
$endDate = new DateTime($endDate);

3. Category Path Building Errors

Issue: Infinite recursion or missing category names

Cause: Circular references in category hierarchy

Debug:

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

-- Verify hierarchy integrity
SELECT pc1.productcatname, pc2.productcatname as parent
FROM productcat pc1
LEFT JOIN productcat pc2 ON pc1.productcatparent = pc2.productcatid;

4. Serial Deletion Not Working

Issue: Products still appear after deletion

Cause: Soft delete flag not properly set

Fix:

// Verify deletion flag in queries
WHERE del = 0  // Only show active serials
WHERE del = 1  // Only show deleted serials

---

๐Ÿงช Testing Scenarios

Test Case 1: Basic Serial Report

1. Create product with serial number
2. Set expiration date in future
3. Generate serial report
4. Verify product name, category path, and days calculation
5. Check barcode display and serial number formatting

Test Case 2: Expiration Validation

1. Create products with various expiration dates
2. Test "within X days" condition
3. Test "expired" condition
4. Verify day calculations are accurate
5. Check product filtering works correctly

Test Case 3: Category Path Building

1. Create nested product categories (3+ levels deep)
2. Assign products to different category levels
3. Generate reports and verify complete paths
4. Test with hidecat session setting enabled/disabled

Test Case 4: Serial Deletion

1. Create product serial record
2. Mark as deleted via tempdelete action
3. Verify serial doesn't appear in active reports
4. Check data integrity maintained

Debug Mode Enable

// Add at top of controller for debugging
error_reporting(E_ALL);
ini_set('display_errors', 1);

// Debug category recursion
echo "Building path for category: " . $parentId . "<br>";

// Debug date calculations
echo "End date: " . $endDate->format('Y-m-d H:i:s') . "<br>";
echo "Interval: " . $interval->format('%r%a') . " days<br>";

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur