ProductionOutMany Documentation
Production Out Many Controller Documentation
File: /controllers/productionOutManyController.php
Purpose: Manages complex production/manufacturing processes with multiple output products and external manufacturing costs
Last Updated: December 20, 2024
Total Functions: 17
Lines of Code: ~1,019
---
๐ Overview
The Production Out Many Controller handles advanced manufacturing operations where multiple raw materials are converted into multiple finished products, typically involving external manufacturing services. It manages:
- โข Multiple raw material input consumption
- โข Multiple finished product output creation
- โข External supplier manufacturing costs
- โข Complex cost allocation across outputs
- โข Inventory management for multi-product manufacturing
- โข Daily accounting entries for complex transactions
- โข Manufacturing batch tracking with production numbers
Primary Functions
- โ Create complex production orders (multiple inputs, multiple outputs)
- โ External manufacturing cost management
- โ Multi-product cost allocation
- โ Raw material and finished goods inventory updates
- โ Supplier debt management for manufacturing services
- โ Production batch numbering and tracking
- โ Daily accounting entry generation
- โ Size/color variant support for all products
- โ Unit of measure conversions for inputs and outputs
Related Controllers
- โข productionOutController.php - Simple production (single output)
- โข productionEquationController.php - Production formulas
- โข productionRateController.php - Production rates
- โข buyBillController.php - Raw material purchasing
---
๐๏ธ Database Tables
Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **productionoutmany** | Production batch headers | id, title, inStore, outStore, supplier, productionoutmanynum, comment, userid, sysDate, del, dailyentryid | |
| **productionoutmanyinproducts** | Raw material inputs | id, productionoutmanyid, productid, sizeid, colorid, prounitid, quantity, unitpriceraw, unitManufPrice, inTotalCostUnit, inTotalCost | |
| **productionoutmanyoutproducts** | Finished product outputs | id, productionoutmanyid, productid, sizeid, colorid, prounitid, quantity, unitprice, cost |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **storedetail** | Main inventory quantities | storedetailid, storeid, productid, productquantity, userid, storedetaildate | |
| **sizecolorstoredetail** | Size/color variant inventory | id, storeid, productid, sizeid, colorid, quantity, userid, sysdate | |
| **storereport** | Inventory movement log | storereportid, productid, sizeid, colorid, storeid, productquantity, productbefore, productafter, storereporttype, storereportmodelid, processname, tablename, storereportdate, userid |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **buypriceshistorybook** | Purchase price history | id, theDate, storeId, productid, sizeid, colorid, buyprice, buyQuantity, sellQuantity, del, userid, sysDate | |
| **supplier** | Supplier master data | supplierid, suppliername, suppliercurrentDebt, supplierdate, userid | |
| **supplierdebtchange** | Supplier debt change log | supplierdebtchangeid, supplierid, supplierdebtchangebefore, supplierdebtchangeamount, supplierdebtchangeafter, supplierdebtchangetype, processname, supplierdebtchangemodelid, tablename, comment, supplierdebtchangedate, userid, dailyentryid |
| Table Name | Purpose | Key Columns | |
|---|---|---|---|
| **product** | Product master data | productId, productName, productCatId, productBuyPrice, lastbuyprice, meanbuyprice | |
| **productcat** | Product categories | productCatId, productCatName | |
| **productunit** | Unit conversions | productunitid, productid, unitname, productnumber, proUnitBuyPrice | |
| **store** | Store/warehouse definitions | storeId, storeName, conditions, treeId | |
| **programsettings** | System configuration | programsettingsid, settingkey, settingvalue |
๐ Key Functions
1. Default Action - Add Production Form
Location: Line 211
Purpose: Display form for creating new complex production batches
Function Signature:
// Triggered when: do= (empty)
Process Flow:
1. Load all active stores for dropdowns
2. Generate next production batch number
3. Load manufacturing settings
4. Set form permissions and flags
5. Display add form template
Production Number Generation:
$productionoutmanynum = 0;
$allExecution = $productionOutManyEX->getLastRow();
$productionoutmanynum = (int) $allExecution->id + 1;
$smarty->assign('productionoutmanynum', $productionoutmanynum);
---
2. add() - Create Complex Production Batch
Location: Line 414
Purpose: Process complex manufacturing operation with multiple inputs and outputs
Function Signature:
function add()
Process Flow:
1. Create production batch header with unique number
2. Process multiple output products
3. Process multiple input raw materials
4. Calculate total costs and allocations
5. Update inventory levels for all products
6. Update supplier debt for manufacturing costs
7. Generate daily accounting entry
Transaction Control:
$mytransactions = new Transaction();
try {
// All production operations
$mytransactions->commit();
doInventoryDailyEntry($productionOutMany);
} catch (Exception $e) {
$mytransactions->rollback();
}
Production Number Logic:
if (empty($id)) {
$count = $productionOutManyEX->countProductionoutmanynumValue($productionOutMany->productionoutmanynum);
if ($count > 0) {
$productionOutMany->productionoutmanynum = (int) $productionOutManyEX->getMaxValOfProductionoutmanynum() + 1;
}
$id = $productionoutmanyid = $productionOutManyDAO->insert($productionOutMany);
}
Output Product Processing:
for ($i = 1; $i <= $rowitr; $i++) {
$productId = filter_input(INPUT_POST, 'pro' . $i);
$quantity = (float) filter_input(INPUT_POST, 'actual' . $i);
$actualCost = (float) filter_input(INPUT_POST, 'actualCost' . $i);
$unitPrice = $actualCost / $quantity;
if ($productId > 0 && $unitId > 0 && $quantity > 0) {
// Insert output product record
// Decrease inventory (removing from output store)
decrease($productId, $sizeId, $colorId, $finalquantity, $id, $productionOutMany->outStore);
}
}
Input Product Processing:
for ($i = 1; $i <= $inProItr; $i++) {
$unitManufPrice = (float) filter_input(INPUT_POST, 'unitManufPrice' . $i);
$inTotalCost = $quantity * $inTotalCostUnit;
if ($productId > 0 && $unitId > 0 && $quantity > 0) {
$allCost += $inTotalCost;
$allUnitManufPrice += $quantity * $unitManufPrice;
// Insert input product record
// Increase inventory (adding to input store)
increase($productId, $sizeId, $colorId, $finalquantity, $id, $productionOutMany->inStore);
// Update product pricing
increaseBuyPricesHistoryBookBuyQuantity(date('Y-m-d'), $productionOutMany->inStore, $productId, $sizeId, $colorId, $inTotalCostUnit, $finalquantity);
}
}
---
3. details() - View Production Details
Location: Line 239
Purpose: Display read-only view of production batch with all inputs and outputs
Process Flow:
1. Load production batch header
2. Load all output products with display names
3. Load all input products with display names
4. Build product names with category/variant info
5. Display details template
Product Name Building:
foreach ($outProducts as $value) {
$value->productName = $value->productName . '/ ' . $value->productCatName;
if (!empty($value->sizeid) && !empty($value->colorid)) {
$value->productid = "hasSizeColor" . $value->productid . "-" . $value->sizeid . "-" . $value->colorid;
$value->productName .= '/ ' . $value->sizeName . '/ ' . $value->colorName;
}
}
---
4. edit() - Edit Production Batch
Location: Line 280
Purpose: Load existing production batch for modification
Process Flow:
1. Load production batch header
2. Load all output products for editing
3. Load all input products for editing
4. Build product display names
5. Assign data to edit template
Similar to details but with edit capabilities and form pre-population.
---
5. update() - Update Production Batch
Location: Line 322
Purpose: Modify existing production batches using delete-and-recreate pattern
Function Signature:
function update()
Process Flow:
1. Delete existing production batch (reverses all effects)
2. Create new production batch with updated data
3. Maintains data integrity through transaction control
Note: This approach ensures all inventory movements, costs, and supplier debts are properly reversed and re-applied for complex multi-product scenarios.
---
6. show() - List Production Batches
Location: Line 331
Purpose: Display filtered list of production batches with search capabilities
Filter Options:
- โข Output store selection
- โข Input store selection
- โข Supplier selection
- โข Production batch number
- โข Date range filtering
- โข Batch ID
Default Filter Logic:
if ($query == " and productionoutmany.del=0 ") {
$from = $to = date('Y-m-d');
$query .= " and date(productionoutmany.sysDate) >= '$from' and date(productionoutmany.sysDate) <= '$to' ";
}
---
7. delete() - Delete Production Batch
Location: Line 571
Purpose: Reverse all effects of a complex production batch and remove from system
Function Signature:
function delete()
Process Flow:
1. Load production batch data
2. Reverse all output product inventory decreases
3. Reverse all input product inventory increases
4. Reverse supplier debt changes
5. Delete all detail records (input and output)
6. Delete batch header record
7. Reverse daily accounting entry
Output Products Reversal:
$outProducts = $productionOutManyOutProductDAO->queryByProductionoutmanyid($id);
foreach ($outProducts as $value) {
$productunitData = $myProductunitEx->queryWithProductIdAndUnitId($value->productid, $value->prounitid);
$finalquantity = $value->quantity * $productunitData->productnumber;
// Increase back to output store (reverse the decrease)
increase($value->productid, $value->sizeid, $value->colorid, $finalquantity, $id, $productionOutMany->outStore);
}
Input Products Reversal:
$inProducts = $productionOutManyInProductDAO->queryByProductionoutmanyid($id);
foreach ($inProducts as $value) {
$productunitData = $myProductunitEx->queryWithProductIdAndUnitId($value->productid, $value->prounitid);
$finalquantity = $value->quantity * $productunitData->productnumber;
// Decrease from input store (reverse the increase)
decrease($value->productid, $value->sizeid, $value->colorid, $finalquantity, $id, $productionOutMany->inStore);
}
---
8. decrease() - Reduce Inventory
Location: Line 633
Purpose: Decrease product quantities in inventory (for output products taken from store)
Function Signature:
function decrease($productId, $sizeId, $colorId, $finalquantity, $sellbillId, $sellbillstoreId = 0, $type = "")
Process Flow:
1. Get current inventory levels
2. Decrease main inventory quantity
3. Update size/color specific inventory if applicable
4. Create inventory movement report with "external manufacturing" label
Inventory Report Label: "ุชุตููุน ุฎุงุฑุฌู ููู ูุชุฌ" (External manufacturing for product)
---
9. increase() - Add to Inventory
Location: Line 684
Purpose: Increase product quantities in inventory (for input products added to store)
Function Signature:
function increase($productId, $sizeId, $colorId, $finalquantity, $sellbillId, $sellbillstoreId = 0, $type = "")
Process Flow:
1. Get current inventory levels
2. Increase main inventory quantity
3. Update size/color specific inventory if applicable
4. Create inventory movement report with "external manufacturing" label
---
10. increaseBuyPricesHistoryBookBuyQuantity() - Price History Update
Location: Line 906
Purpose: Record new inventory purchases in price history for input products
Function Signature:
function increaseBuyPricesHistoryBookBuyQuantity($theDate, $storeId, $productid, $sizeid, $colorid, $buyprice, $buyQuantity)
Features:
- โข Records purchase date and allocated cost
- โข Supports size/color variants
- โข Enables FIFO cost calculation
- โข Tracks available quantities for future consumption
---
11. doInventoryDailyEntry() - Complex Accounting Integration
Location: Line 981
Purpose: Generate daily accounting entries for complex production transactions
Function Signature:
function doInventoryDailyEntry($productionOutMany)
Process Flow:
1. Calculate total raw material costs (output products)
2. Calculate total manufacturing costs (supplier charges)
3. Get store and supplier account tree IDs
4. Create debit entry for input store (finished products)
5. Create credit entries for output store and supplier
6. Link to production batch for reference
Accounting Logic:
$rawMaterialCost = R::getCell('select sum(cost) from productionoutmanyoutproducts where productionoutmanyid=' . $productionOutMany->id);
$suppCost = R::getCell('select sum(unitManufPrice*quantity) from productionoutmanyinproducts where productionoutmanyid=' . $productionOutMany->id);
$dailyEntryDebtorArray = array();
// Debit: Input store (finished products received)
$dailyEntryDebtor->value = $rawMaterialCost + $suppCost;
$dailyEntryDebtor->accountstreeid = $treeIdInStore;
$dailyEntryCreditorArray = array();
// Credit: Output store (raw materials sent)
$dailyEntryCreditor->accountstreeid = $treeIdOutStore;
$dailyEntryCreditor->value = $rawMaterialCost;
// Credit: Supplier (manufacturing services)
$dailyEntryCreditor->accountstreeid = $suppData['treeId'];
$dailyEntryCreditor->value = $suppCost;
---
๐ Workflows
Workflow 1: Complex Production Batch Process
---
๐ URL Routes & Actions
| URL Parameter | Function Called | Description | |
|---|---|---|---|
| `do=` (empty) | Default action | Display add production batch form | |
| `do=add` | `add()` | Create new production batch | |
| `do=details&id={id}` | Details display | View production batch details | |
| `do=edit&id={id}` | Edit display | Load production batch for editing | |
| `do=update` | `update()` | Update existing production batch | |
| `do=show` | `show()` | List production batches with filters | |
| `do=delete&id={id}` | `delete()` | Delete production batch |
Add Production Batch (do=add):
- โข
title- Batch title/description - โข
inStore- Input store ID (for finished products) - โข
outStore- Output store ID (for raw materials) - โข
supplier- External manufacturer/supplier ID - โข
productionoutmanynum- Batch number - โข
rowitr- Number of output products - โข
pro{i}- Output product IDs (with hasSizeColor encoding) - โข
unit{i}- Output product unit IDs - โข
actual{i}- Output product quantities - โข
actualCost{i}- Output product total costs - โข
inProItr- Number of input products - โข
product{i}- Input product IDs (with hasSizeColor encoding) - โข
unitIdIn{i}- Input product unit IDs - โข
quantity{i}- Input product quantities - โข
price{i}- Input raw material unit costs - โข
unitManufPrice{i}- Input manufacturing unit costs
Show/Filter (do=show):
- โข
outStore- Output store filter (optional) - โข
inStore- Input store filter (optional) - โข
supplier- Supplier filter (optional) - โข
productionoutmanynum- Batch number filter (optional) - โข
from- Date from filter (optional) - โข
to- Date to filter (optional) - โข
outId- Batch ID filter (optional)
---
๐งฎ Calculation Methods
Multi-Product Cost Allocation
// Output products (raw materials sent)
for ($i = 1; $i <= $rowitr; $i++) {
$quantity = (float) filter_input(INPUT_POST, 'actual' . $i);
$actualCost = (float) filter_input(INPUT_POST, 'actualCost' . $i);
$unitPrice = $actualCost / $quantity;
$productionOutManyOutProduct->quantity = $quantity;
$productionOutManyOutProduct->unitprice = $unitPrice;
$productionOutManyOutProduct->cost = $actualCost;
}
Complex Cost Tracking
// Input products (finished goods received)
$allCost = 0;
$allUnitManufPrice = 0;
for ($i = 1; $i <= $inProItr; $i++) {
$unitpriceraw = (float) filter_input(INPUT_POST, 'price' . $i);
$unitManufPrice = (float) filter_input(INPUT_POST, 'unitManufPrice' . $i);
$inTotalCostUnit = (float) filter_input(INPUT_POST, 'inTotalCostUnit_h' . $i);
$inTotalCost = $quantity * $inTotalCostUnit;
$allCost += $inTotalCost;
$allUnitManufPrice += $quantity * $unitManufPrice;
$productionOutManyInProduct->unitpriceraw = $unitpriceraw;
$productionOutManyInProduct->unitManufPrice = $unitManufPrice;
$productionOutManyInProduct->inTotalCostUnit = $inTotalCostUnit;
$productionOutManyInProduct->inTotalCost = $inTotalCost;
}
Supplier Debt Calculation
// Supplier debt increase by manufacturing costs only
$supdata = $supplierDAO->load($productionOutMany->supplier);
$totaldeptbefore = $supdata->suppliercurrentDebt;
$totaldeptafter = $totaldeptbefore + $allUnitManufPrice; // Only manufacturing costs
updateSupplierDebt($productionOutMany->supplier, $totaldeptafter);
---
๐ Security & Permissions
Authentication Requirements
include_once("../public/authentication.php");
Input Validation
- โข All numeric inputs cast to appropriate types
- โข Product and unit IDs validated against database
- โข Production batch number uniqueness enforced
- โข Date parameters validated for proper format
- โข Transaction control prevents partial updates
Data Integrity
- โข Automatic batch number generation if conflict
- โข Transaction rollback on any failure
- โข Complex inventory movement logging
- โข Supplier debt change tracking
- โข Daily accounting entry generation
- โข Cascading deletion logic for multi-table operations
---
๐ Performance Considerations
Database Optimization Tips
1. Critical Indexes:
- productionoutmany(outStore, inStore, sysDate, productionoutmanynum)
- productionoutmanyinproducts(productionoutmanyid)
- productionoutmanyoutproducts(productionoutmanyid)
- storedetail(storeid, productid)
2. Query Optimization:
- Batch operations for multiple products
- Efficient unit conversion calculations
- Minimize database round trips
- Proper transaction scope management
3. Memory Management:
- Process products incrementally
- Clear arrays after processing
- Proper variable cleanup
- Transaction scope optimization
---
๐งช Testing Scenarios
Test Case 1: Basic Multi-Product Manufacturing
1. Create batch: Send 10kg fabric + 5m thread โ Receive 8 shirts + 2 pants
2. Set costs:
- Fabric: $50 ($5/kg)
- Thread: $10 ($2/m)
- Manufacturing: $30 total
3. Verify inventory changes:
- Output store: Fabric -10kg, Thread -5m
- Input store: Shirts +8, Pants +2
4. Check cost allocations and price updates
5. Verify supplier debt increased by $30 (manufacturing only)
6. Check complex accounting entry
Test Case 2: Batch Number Conflict Resolution
1. Create batch with number 100
2. Create another batch with same number
3. Verify system auto-generates unique number
4. Check database consistency
Test Case 3: Size/Color Variant Production
1. Send red large fabric, blue medium fabric
2. Receive red large shirts, blue medium shirts
3. Verify variant-specific inventory tracking
4. Check size/color inventory updates
Test Case 4: Complex Delete Operation
1. Create batch with multiple inputs/outputs
2. Delete batch
3. Verify all effects reversed:
- All input inventory decreased
- All output inventory increased
- Supplier debt reversed
- Accounting entry reversed
- All detail records deleted
---
๐ Related Documentation
- โข CLAUDE.md - PHP 8.2 migration guide
- โข productionOutController.md - Simple production
- โข productionEquationController.md - Production formulas
- โข buyBillController.md - Raw material purchasing
---
Documented By: AI Assistant
Review Status: โ Complete
Next Review: When major changes occur