Inventory Documentation

Inventory Controller Documentation

File: /controllers/inventoryController.php

Purpose: Physical inventory management and stock reconciliation system

Last Updated: December 20, 2024

Total Functions: 15+

Lines of Code: ~634

---

๐Ÿ“‹ Overview

The Inventory Controller handles physical inventory counting, stock reconciliation, and inventory adjustments. It provides tools for:

Primary Functions

Related Controllers

---

๐Ÿ—„๏ธ Database Tables

Primary Tables (Direct Operations)

Table NamePurposeKey Columns
**storedetail**Store inventory quantitiesstoredetailid, productid, storeid, productquantity, userid, storedetaildate
**storereport**Inventory movement historystorereportid, productid, storeid, productbefore, productafter, productquantity, storereporttype, tablename, userid, storereportdate
**sizecolorstoredetail**Size/color variant quantitiessizecolorstoredetailid, productid, storeid, sizeid, colorid, quantity, userid, sysdate
### Product Tables (Referenced)

Table NamePurposeKey Columns
**product**Product master dataproductId, productName, productCatId, productBuyPrice, meanbuyprice, lastbuyprice
**productcat**Product categoriesproductCatId, productCatName, productCatParent
**store**Store locationsstoreId, storeName, conditions, treeId
### Reference Tables

Table NamePurposeKey Columns
**unit**Units of measureunitId, unitName
**productunit**Product unit conversionsproductunitid, productid, unitid, productnumber
**programsettings**System configurationprogramsettingsid, dailyEntryCostprice, Inventoryevaluation
**youtubelink**Tutorial linksyoutubelinkid, title, url
**user**System usersuserid, username, storeid, storeids
---

๐Ÿ”‘ Key Functions

1. show() / Default Action - Inventory Entry Interface

Location: Line 139

Purpose: Display inventory counting interface with category and store filters

Process Flow:

1. Load YouTube tutorial links

2. Load category hierarchy for filtering

3. Load available stores

4. Assign session variables for display

5. Display via inventoryview/add.html template

Template Variables:

---

2. add() - Process Inventory Adjustments

Location: Line 341

Purpose: Process multiple inventory quantity adjustments and generate reports

Function Flow:

1. Loop through submitted inventory items ($_POST['itr'])

2. For each item:

- Extract new quantity, product ID, store ID

- Handle size/color variants if present

- Update store quantities

- Calculate quantity differences

- Generate store reports

- Create daily entries

3. Sync with online store if applicable

Key Variables:

Quantity Change Detection:

if ($oldQty > $newQty) {
    $status = "ุจุงู„ู†ู‚ุต";  // Decrease
    $actualQty = $oldQty - $newQty;
    $type = 1;
} else if ($oldQty < $newQty) {
    $status = "ุจุงู„ุฒูŠุงุฏุฉ";  // Increase
    $actualQty = $newQty - $oldQty;
    $type = 0;
} else {
    $status = "ู„ู… ูŠุชุบูŠุฑ";  // No change
    $type = 0;
}

---

3. doInventoryDailyEntry() - Accounting Entry Generation

Location: Line 440

Purpose: Generate accounting entries for inventory adjustments

Function Signature:

function doInventoryDailyEntry($storeId, $productId, $quantity, $newQty, $type, $storeReport)

Process Flow:

1. Get store and product data

2. Determine cost price based on system settings

3. Calculate total cost impact

4. Create debit/credit entries:

- Increase (type=0): Debit store account, Credit inventory variance

- Decrease (type=1): Debit inventory variance, Credit store account

5. Insert daily entry with linking

Cost Price Options:

---

4. autosave() - Single Item Auto-Save

Location: Line 510

Purpose: Save individual inventory adjustments via AJAX

Similar to add() but processes single item:

---

5. invReport() Action - Inventory Reports

Location: Line 202

Purpose: Generate inventory adjustment reports with filtering

Search Parameters:

Query Building:

$queryString = '';
if ($storeId > 0) {
    $queryString .= " and storereport.storeid=$storeId ";
}
if ($product > 0) {
    $queryString .= " and storereport.productid=$product ";
} else if ($productCatId > 0) {
    // Get all subcategories and products
    getAllSubCat($productCatId, 1);
    $productsOfCat = $ProductEX->queryByProductCatIdIn($catsIDS);
    $IDS = '0';
    foreach ($productsOfCat as $value) {
        $IDS .= ',' . $value->productId;
    }
    $queryString .= " and storereport.productid in ($IDS) ";
}

---

6. getCategoryChilds() - Category Hierarchy

Location: Line 284

Purpose: Load category tree structure for filtering

Returns: Array containing parent object and children array

---

7. getStores() - Store List

Location: Line 334

Purpose: Load active stores for selection

Returns: Array of store objects with conditions = 0

---

8. getAllSubCat() - Recursive Category Traversal

Location: Line 605

Purpose: Recursively get all subcategories for filtering

Parameters:

---

๐Ÿ”„ Workflows

Workflow 1: Physical Inventory Count Process

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
START: Physical Inventory
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Setup Inventory Session
- Select store(s) to count
- Choose category filter (optional)
- Load current quantities
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Physical Count Entry
- Display products with current quantities
- Enter actual counted quantities
- Support auto-save for real-time updates
- Handle size/color variants
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Process Adjustments
FOR EACH product with quantity change:
โ”‚
โ†’ Calculate difference (increase/decrease)
โ”‚
โ†’ Update store quantities
โ”‚ โ”œโ”€ Regular products: storedetail table
โ”‚ โ”‚ โ””โ”€ Size/color variants: sizecolorstoredetail โ”‚
โ”‚
โ†’ Generate store report entry
โ”‚ โ”œโ”€ Record before/after quantities
โ”‚ โ”œโ”€ Set adjustment type and reason
โ”‚ โ”‚ โ””โ”€ Link to inventory controller โ”‚
โ”‚
โ”‚ โ””โ”€โ†’ Create accounting entry โ”‚
โ”œโ”€ Calculate cost impact
โ”œโ”€ Generate debit/credit entries
โ”‚ โ””โ”€ Link to store report โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
4Finalize Inventory
- Sync quantities with online systems
- Generate completion report
- Update inventory completion status
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

Workflow 2: Size/Color Variant Handling

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
Product with Size/Color Variants
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
1Parse Variant Information
- Extract product ID, size ID, color ID
- Format: "hasSizeColor" + productId + "-" + sizeId
+ "-" + colorId
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
2Update Variant Quantity
- Load sizecolorstoredetail record
- Update specific size/color quantity
- Sync online store data
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ–ผ
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
3Update Parent Product Quantity
- Recalculate total product quantity
- Sum all size/color combinations
- Update main storedetail record
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

---

๐ŸŒ URL Routes & Actions

URL ParameterFunction CalledDescription
`do=` (empty) or `do=show`Default actionDisplay inventory entry interface
`do=add``add()`Process inventory adjustments
`do=autosave``autosave()`Auto-save single item
`do=details`Details displayShow specific inventory report
`do=invReport`Report generationDisplay inventory adjustment reports
### Required Parameters

Inventory Entry (do=add):

Auto-save (do=autosave):

Reports (do=invReport):

---

๐Ÿงฎ Calculation Methods

Quantity Difference Calculation

if ($oldQty > $newQty) {
    $actualQty = $oldQty - $newQty;  // Shortage
    $type = 1;  // Decrease
} else if ($oldQty < $newQty) {
    $actualQty = $newQty - $oldQty;  // Overage
    $type = 0;  // Increase
}

Cost Impact Calculation

$productData = R::getRow('select ' . $priceColName . ' as price from product where productId=' . $productId);
$productCost = $productData['price'] * $quantity;

Size/Color Quantity Aggregation

// Update parent product from sum of all variants
$storeDetailExt->updateQuantityWithSumChild(
    $storeDetailData->storedetailid, 
    $_SESSION['userid'], 
    date("Y-m-d"), 
    0, 
    $storeid, 
    $productid
);

---

๐Ÿ”’ Security & Permissions

Authentication Required

Session Variables Used

Input Validation

---

๐Ÿ“Š Performance Considerations

Database Optimization

1. Batch Processing: Processes multiple items in single transaction

2. Indexed Queries: Uses primary keys for quick lookups

3. Minimal Queries: Efficient update patterns

Memory Management

Potential Bottlenecks

---

๐Ÿ› Common Issues & Troubleshooting

1. Size/Color Quantity Sync Issues

Issue: Parent product quantity doesn't match variant totals

Cause: Failed updateQuantityWithSumChild() call

Debug:

SELECT p.productName, 
       sd.productquantity as parent_qty,
       SUM(scsd.quantity) as variant_total
FROM product p
JOIN storedetail sd ON sd.productid = p.productId  
LEFT JOIN sizecolorstoredetail scsd ON scsd.productid = p.productId
WHERE p.productId = [ID]
GROUP BY p.productId;

2. Daily Entry Creation Failures

Issue: Accounting entries not created for inventory adjustments

Cause: Missing store tree ID or invalid cost price setting

Fix:

-- Check store tree mapping
SELECT storeId, storeName, treeId FROM store WHERE storeId = [ID];

-- Verify cost price setting
SELECT dailyEntryCostprice FROM programsettings WHERE programsettingsid = 1;

3. Negative Quantity Issues

Issue: System allows negative quantities

Cause: No validation on quantity entry

Fix: Add client-side and server-side validation for minimum quantities

4. Category Filtering Not Working

Issue: Category filter returns no products

Cause: Recursive category traversal issues

Debug:

-- Check category hierarchy
SELECT productCatId, productCatName, productCatParent 
FROM productcat 
WHERE productCatId = [CATID] OR productCatParent = [CATID];

---

๐Ÿงช Testing Scenarios

Test Case 1: Basic Inventory Adjustment

1. Navigate to inventory controller
2. Select a store and product
3. Enter new quantity different from current
4. Submit inventory adjustment
5. Verify quantity updated in storedetail table
6. Check store report entry created
7. Confirm daily entry generated

Test Case 2: Size/Color Variant Adjustment

1. Select product with size/color variants
2. Adjust quantity for specific variant
3. Verify sizecolorstoredetail updated
4. Check parent product quantity recalculated
5. Confirm variant totals match parent

Test Case 3: Category-Based Inventory

1. Select category filter
2. Verify all products in category displayed
3. Include subcategory products
4. Test recursive category inclusion

Test Case 4: Auto-Save Functionality

1. Enter quantity for single product
2. Trigger auto-save (AJAX)
3. Verify immediate quantity update
4. Check real-time report generation
5. Confirm no page reload required

---

๐Ÿ“š Related Documentation

---

Documented By: AI Assistant

Review Status: โœ… Complete

Next Review: When major changes occur