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:
- โข Physical inventory counting by category, store, or product
- โข Inventory adjustments and reconciliation
- โข Automatic daily entries for inventory changes
- โข Support for size/color variations
- โข Store reporting and tracking
- โข Multi-store inventory management
- โข Real-time quantity updates
Primary Functions
- โ Physical inventory counting interface
- โ Quantity adjustments and updates
- โ Size/color variant inventory management
- โ Daily entry generation for inventory changes
- โ Store report generation
- โ Category-based inventory filtering
- โ Auto-save functionality
- โ Inventory history tracking
- โ Store quantity synchronization
Related Controllers
- โข inventorybybarcodeController.php - Barcode-based inventory
- โข inventoryexpirationController.php - Product expiration tracking
- โข storedetailController.php - Store quantity management
- โข storereportController.php - Store reports
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **storedetail** | Store inventory quantities | storedetailid, productid, storeid, productquantity, userid, storedetaildate | |
| **storereport** | Inventory movement history | storereportid, productid, storeid, productbefore, productafter, productquantity, storereporttype, tablename, userid, storereportdate | |
| **sizecolorstoredetail** | Size/color variant quantities | sizecolorstoredetailid, productid, storeid, sizeid, colorid, quantity, userid, sysdate |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **product** | Product master data | productId, productName, productCatId, productBuyPrice, meanbuyprice, lastbuyprice | |
| **productcat** | Product categories | productCatId, productCatName, productCatParent | |
| **store** | Store locations | storeId, storeName, conditions, treeId |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **unit** | Units of measure | unitId, unitName | |
| **productunit** | Product unit conversions | productunitid, productid, unitid, productnumber | |
| **programsettings** | System configuration | programsettingsid, dailyEntryCostprice, Inventoryevaluation | |
| **youtubelink** | Tutorial links | youtubelinkid, title, url | |
| **user** | System users | userid, 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:
- โข
catData- Category hierarchy - โข
storesData- Available stores - โข
programsettingsdata- System settings - โข
youtubes- Tutorial links
---
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:
- โข
$newQty- Updated quantity - โข
$oldQty- Previous quantity - โข
$productId- Product identifier - โข
$storeid- Store location - โข
$sizeId, $colorId- Variant identifiers
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:
- โข
first- Original buy price - โข
last- Last purchase price - โข
mean- Average buy price - โข
last_discount- Last price with discount - โข
mean_discount- Average price with discount - โข
tax- Last price with tax - โข
mean_tax- Average price with tax
---
4. autosave() - Single Item Auto-Save
Location: Line 510
Purpose: Save individual inventory adjustments via AJAX
Similar to add() but processes single item:
- โข Handles one product adjustment
- โข Immediate quantity update
- โข Real-time store report generation
- โข Used for progressive inventory entry
---
5. invReport() Action - Inventory Reports
Location: Line 202
Purpose: Generate inventory adjustment reports with filtering
Search Parameters:
- โข
storeId- Filter by store - โข
productCatId- Filter by category - โข
product- Filter by specific product - โข
from/to- Date range filtering
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:
- โข
$catid- Starting category ID - โข
$mode- 1=all subcats, 2=last level only
---
๐ Workflows
Workflow 1: Physical Inventory Count Process
---
Workflow 2: Size/Color Variant Handling
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | |
|---|---|---|---|
| `do=` (empty) or `do=show` | Default action | Display inventory entry interface | |
| `do=add` | `add()` | Process inventory adjustments | |
| `do=autosave` | `autosave()` | Auto-save single item | |
| `do=details` | Details display | Show specific inventory report | |
| `do=invReport` | Report generation | Display inventory adjustment reports |
Inventory Entry (do=add):
- โข
itr- Number of items being processed - โข
newQty{N}- New quantity for item N - โข
productId{N}- Product ID for item N - โข
storeid{N}- Store ID for item N - โข
oldQty{N}- Previous quantity for item N
Auto-save (do=autosave):
- โข Same as add but for single item
Reports (do=invReport):
- โข
storeId- Store filter (optional) - โข
productCatId{level}- Category filter (optional) - โข
product- Product filter (optional) - โข
from/to- Date range (optional)
---
๐งฎ 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
- โข All actions require valid session
- โข User authentication checked via
../public/authentication.php
Session Variables Used
- โข
$_SESSION['userid']- Current user ID for tracking - โข
$_SESSION['storenegative']- Display setting for negative quantities - โข
$_SESSION["serialarray"]- Serial number tracking
Input Validation
- โข Numeric casting for quantities and IDs
- โข Product ID validation for size/color format
- โข Store and product existence 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
- โข Processes items iteratively to avoid large memory usage
- โข Cleans up variables after processing
Potential Bottlenecks
- โข Large inventory counts with many variants
- โข Daily entry generation for high-value items
- โข Category traversal for large hierarchies
---
๐ 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
- โข CLAUDE.md - PHP 8.2 migration guide
- โข inventorybybarcodeController.md - Barcode inventory
- โข inventoryexpirationController.md - Expiration tracking
- โข storedetailController.md - Store management
- โข dailyentry.php - Accounting integration
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur