# Production Out Controller Documentation

**File**: `/controllers/productionOutController.php`  
**Purpose**: Manages simple production/manufacturing processes for converting raw materials into finished products  
**Last Updated**: December 20, 2024  
**Total Functions**: 15  
**Lines of Code**: ~903

---

## 📋 Overview

The Production Out Controller handles simple manufacturing operations where multiple raw materials are consumed to produce a single finished product. It manages:
- Raw material consumption from inventory
- Finished product creation and inventory updates
- Cost calculation and price updates
- Supplier debt management
- Inventory movement tracking
- Daily accounting entries
- Manufacturing transaction logging

### Primary Functions
- [x] Create simple production orders (1 output, multiple inputs)
- [x] Raw material inventory deduction
- [x] Finished product inventory addition
- [x] Production cost calculation and allocation
- [x] Supplier debt management for manufacturing costs
- [x] Inventory movement reporting
- [x] Daily accounting entry generation
- [x] Size/color variant support
- [x] Unit of measure conversions

### Related Controllers
- [productionOutManyController.php](productionOutManyController.md) - Multiple output production
- [productionEquationController.php](productionEquationController.md) - Production formulas
- [productionRateController.php](productionRateController.md) - Production rates
- [buyBillController.php](#) - Raw material purchasing

---

## 🗄️ Database Tables

### Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **productionout** | Production header records | id, outStore, inStore, supplier, productid, sizeid, colorid, outQuantity, outUnitCost, outAllCost, outAllCostTot, comment, userid, del, sysDate, dailyentryid |
| **productionoutdetails** | Raw material consumption | id, productionOutId, productid, sizeid, colorid, unitid, price, quantity, inTotalCost |

### Inventory Tables (Modified)
| 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 |

### Financial Tables (Modified)
| 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 |

### Reference Tables
| 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 200  
**Purpose**: Display form for creating new simple production orders

**Function Signature**:
```php
// Triggered when: do= (empty)
```

**Process Flow**:
1. Load all active stores for dropdowns
2. Set production number counter
3. Load manufacturing settings
4. Display add form template

**Features**:
- Store selection for input/output
- Production number assignment
- Settings integration
- Custom template flags

---

### 2. **add()** - Create Production Order
**Location**: Line 345  
**Purpose**: Process simple manufacturing operation with raw material consumption

**Function Signature**:
```php
function add()
```

**Process Flow**:
1. Extract and validate production header data
2. Handle size/color variants for output product
3. Create production header record
4. Process input raw materials
5. Update inventory quantities (increase output, decrease inputs)
6. Update product pricing information
7. Update supplier debt
8. Generate daily accounting entry

**Transaction Control**:
```php
$mytransactions = new Transaction();
try {
    // All production operations
    $mytransactions->commit();
    doInventoryDailyEntry($productionOut);
} catch (Exception $e) {
    $mytransactions->rollback();
}
```

**Size/Color Handling**:
```php
if (strpos($productId, "hasSizeColor") !== false) {
    $productIdComplex = explode('-', str_replace("hasSizeColor", "", $productId));
    $productId = $outProductId = $productIdComplex[0];
    $sizeId = $productIdComplex[1];
    $colorId = $productIdComplex[2];
}
```

**Raw Material Processing**:
```php
for ($i = 1; $i <= $productItr; $i++) {
    if (filter_input(INPUT_POST, 'product' . $i)) {
        // Extract product and unit information
        $productunitData = $myProductunitEx->queryWithProductIdAndUnitId($productId, $unitId);
        $finalquantity = $quantity * $productunitData->productnumber;
        
        // Decrease inventory
        decrease($productId, $sizeId, $colorId, $finalquantity, $id, $inStore);
        $totalInProductsCost += $inTotalCost;
    }
}
```

---

### 3. **edit()** - Edit Production Order
**Location**: Line 220  
**Purpose**: Load existing production order for modification

**Process Flow**:
1. Load production header by ID
2. Load all raw material details
3. Build display names with product/category/variant info
4. Assign data to edit template

**Product Name Building**:
```php
$productionOut->productName = $productionOut->productName . '/ ' . $productionOut->productCatName;
if (!empty($productionOut->sizeid) && !empty($productionOut->colorid)) {
    $productionOut->productid = "hasSizeColor" . $productionOut->productid . "-" . $productionOut->sizeid . "-" . $productionOut->colorid;
    $productionOut->productName .= '/ ' . $productionOut->sizeName . '/ ' . $productionOut->colorName;
}
```

---

### 4. **update()** - Update Production Order
**Location**: Line 256  
**Purpose**: Modify existing production orders using delete-and-recreate pattern

**Function Signature**:
```php
function update()
```

**Process Flow**:
1. Delete existing production order (reverses all effects)
2. Create new production order 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.

---

### 5. **show()** - List Production Orders
**Location**: Line 265  
**Purpose**: Display filtered list of production orders with search capabilities

**Process Flow**:
1. Extract filter parameters
2. Build dynamic query string
3. Apply default date filter if no filters specified
4. Load and display production orders
5. Include YouTube tutorials

**Filter Options**:
- Output store selection
- Input store selection
- Supplier selection
- Specific product selection
- Date range filtering
- Production order ID

**Default Filter Logic**:
```php
if ($query == " and productionout.del=0 ") {
    $from = $to = date('Y-m-d');
    $query .= " and date(productionout.sysDate) >= '$from' and date(productionout.sysDate) <= '$to' ";
}
```

---

### 6. **delete()** - Delete Production Order
**Location**: Line 473  
**Purpose**: Reverse all effects of a production order and remove from system

**Function Signature**:
```php
function delete()
```

**Process Flow**:
1. Load production order data
2. Reverse finished product inventory increase
3. Reverse raw material inventory decreases
4. Reverse supplier debt changes
5. Delete production detail records
6. Delete production header record
7. Reverse daily accounting entry

**Reversal Logic**:
```php
// Reverse output product increase
decrease($productionOut->productid, $productionOut->sizeid, $productionOut->colorid, $productionOut->outQuantity, $id, $productionOut->outStore);

// Reverse raw material decreases
foreach ($allProductionOutDetail as $p) {
    $productunitData = $myProductunitEx->queryWithProductIdAndUnitId($p->productid, $p->unitid);
    $finalquantity = $p->quantity * $productunitData->productnumber;
    increase($p->productid, $p->sizeid, $p->colorid, $finalquantity, $id, $productionOut->inStore);
}
```

---

### 7. **decrease()** - Reduce Inventory
**Location**: Line 519  
**Purpose**: Decrease product quantities in inventory (for raw material consumption)

**Function Signature**:
```php
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
5. Handle negative inventory scenarios

**Inventory Update Logic**:
```php
if (count($allStoredetailData) > 0) {
    // Update existing inventory record
    $productquantityAfter = decreaseProductQuantity($storedetailId, $productquantityBefore, $finalquantity);
    insertStorereportupdate($productId, $sizeId, $colorId, $sellbillstoreId, $finalquantity, $productquantityBefore, $productquantityAfter, 1, $sellbillId, "تصنيع مبسط للمنتج" . $type, "productionExecutionController.php", date("Y-m-d H:i:s"));
} else {
    // Create new inventory record with negative quantity
    $specialQuantityAfter = $finalquantity * -1;
    insertStoredetailupdate($sellbillstoreId, $productId, $specialQuantityAfter, date("Y-m-d H:i:s"));
}
```

---

### 8. **increase()** - Add to Inventory
**Location**: Line 570  
**Purpose**: Increase product quantities in inventory (for finished goods)

**Function Signature**:
```php
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

**Key Difference**: Creates new positive inventory records if product doesn't exist in store.

---

### 9. **getBuyPriceFromAndHandleBuyPricesHistoryBook()** - FIFO Cost Calculation
**Location**: Line 727  
**Purpose**: Calculate raw material costs using FIFO methodology

**Function Signature**:
```php
function getBuyPriceFromAndHandleBuyPricesHistoryBook($storeId, $productid, $sizeid, $colorid, $productBuyPrice, $soldQuantity, $type = 0)
```

**Process Flow**:
1. Find earliest available inventory batches
2. Consume quantities in FIFO order
3. Calculate weighted average cost
4. Update sell quantities in price history
5. Return actual cost per unit

**FIFO Logic**:
```php
do {
    $buyPriceFromHistoryBook = $buyPricesHistoryBookEX->getBuyPriceOfFirstAvailableSellQuantity($storeId, $productid, $sizeid, $colorid);
    if (isset($buyPriceFromHistoryBook->id) && $buyPriceFromHistoryBook->id > 0 && $remainQuantity > 0) {
        $availableBuyQuantity = $buyPriceFromHistoryBook->buyQuantity - $buyPriceFromHistoryBook->sellQuantity;
        // Process available quantity
    }
} while (isset($buyPriceFromHistoryBook->id) && $buyPriceFromHistoryBook->id > 0 && $remainQuantity > 0);
```

---

### 10. **increaseBuyPricesHistoryBookBuyQuantity()** - Price History Update
**Location**: Line 792  
**Purpose**: Record new inventory purchases in price history

**Function Signature**:
```php
function increaseBuyPricesHistoryBookBuyQuantity($theDate, $storeId, $productid, $sizeid, $colorid, $buyprice, $buyQuantity)
```

**Features**:
- Records purchase date and price
- Supports size/color variants
- Enables FIFO cost calculation
- Tracks available quantities for sale

---

### 11. **updateSupplierDebt()** - Supplier Debt Management
**Location**: Line 830  
**Purpose**: Update supplier debt balances

**Function Signature**:
```php
function updateSupplierDebt($supplierId, $supplierDebtAfter)
```

**Updates**: Current debt balance and last update date.

---

### 12. **insertSupplierDebtChange()** - Debt Change Logging
**Location**: Line 846  
**Purpose**: Log all supplier debt changes for audit trail

**Function Signature**:
```php
function insertSupplierDebtChange($supplierId, $supplierDebtChangeBefore, $supplierDebtChangeAmount, $supplierDebtChangeType, $processname, $supplierDebtChangeModelId, $supplierDebtChangeAfter, $tablename, $comment)
```

**Tracks**: Before/after balances, change amount, change type, and linking information.

---

### 13. **doInventoryDailyEntry()** - Accounting Integration
**Location**: Line 867  
**Purpose**: Generate daily accounting entries for production transactions

**Function Signature**:
```php
function doInventoryDailyEntry($productionOut)
```

**Process Flow**:
1. Calculate raw material cost totals
2. Get store and supplier account tree IDs
3. Create debit entries (finished goods inventory, supplier debt)
4. Create credit entry (raw materials inventory)
5. Link to production order for reference

**Accounting Logic**:
```php
$dailyEntryDebtorArray = array();
// Debit: Finished goods inventory
$dailyEntryDebtor->accountstreeid = $treeIdOutStore;
$dailyEntryDebtor->value = $rawMaterialCost;

// Debit: Supplier debt
$dailyEntryDebtor->accountstreeid = $suppData['treeId'];
$dailyEntryDebtor->value = $productionOut->outAllCost;

$dailyEntryCreditorArray = array();
// Credit: Raw materials inventory
$dailyEntryCreditor->value = $rawMaterialCost + $productionOut->outAllCost;
$dailyEntryCreditor->accountstreeid = $treeIdInStore;
```

---

## 🔄 Workflows

### Workflow 1: Simple Production Process
```
┌─────────────────────────────────────────────────────────────┐
│              START: Simple Production Order                │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Define Production Parameters                            │
│     - Select output product (with variants)                │
│     - Set output quantity and unit cost                    │
│     - Choose output store                                   │
│     - Select supplier                                       │
│     - Choose input store                                    │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Define Raw Material Requirements                       │
│     FOR EACH raw material:                                 │
│       │                                                     │
│       ├─→ Select product (with variants)                   │
│       ├─→ Choose unit of measure                           │
│       ├─→ Set quantity required                            │
│       └─→ Set unit price                                   │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Process Production Order                               │
│     - Create production header record                       │
│     - Calculate total costs                                 │
│     - Validate inventory availability                       │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Update Inventory Levels                                │
│     - Decrease raw material quantities                     │
│     - Increase finished product quantity                   │
│     - Handle size/color variant tracking                   │
│     - Create inventory movement reports                     │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  5. Update Financial Records                               │
│     - Update finished product pricing                      │
│     - Record purchase price history                        │
│     - Update supplier debt balance                         │
│     - Log debt change transaction                          │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  6. Generate Accounting Entry                              │
│     - Debit: Finished goods inventory                      │
│     - Debit: Supplier debt                                 │
│     - Credit: Raw materials inventory                      │
│     - Link to production order                             │
└─────────────────────────────────────────────────────────────┘
```

---

## 🌐 URL Routes & Actions

| URL Parameter | Function Called | Description |
|---------------|-----------------|-------------|
| `do=` (empty) | Default action | Display add production form |
| `do=add` | `add()` | Create new production order |
| `do=edit&id={id}` | Edit display | Load production order for editing |
| `do=update` | `update()` | Update existing production order |
| `do=show` | `show()` | List production orders with filters |
| `do=delete&id={id}` | `delete()` | Delete production order |

### Required Parameters by Action

**Add Production** (`do=add`):
- `outStore` - Output store ID
- `inStore` - Input store ID  
- `supplier` - Supplier ID
- `productOut` - Output product (may include hasSizeColor encoding)
- `outQuantity` - Output quantity
- `outUnitCost` - Unit cost
- `outAllCostTot_h` - Total cost
- `inProItr` - Number of input products
- `product{i}` - Input product IDs
- `unitId{i}` - Unit IDs for inputs
- `price{i}` - Unit prices for inputs
- `quantity{i}` - Quantities for inputs

**Show/Filter** (`do=show`):
- `outStore` - Output store filter (optional)
- `inStore` - Input store filter (optional)
- `supplier` - Supplier filter (optional)
- `productOut` - Product filter (optional)
- `from` - Date from filter (optional)
- `to` - Date to filter (optional)
- `outId` - Production ID filter (optional)

---

## 🧮 Calculation Methods

### Production Cost Calculation
```php
// Raw material total cost
$totalInProductsCost = 0;
for ($i = 1; $i <= $productItr; $i++) {
    $price = (float) filter_input(INPUT_POST, 'price' . $i);
    $quantity = (float) filter_input(INPUT_POST, 'quantity' . $i);
    $inTotalCost = $price * $quantity;
    $totalInProductsCost += $inTotalCost;
}

// Output product cost allocation
$outProductPrice = $outAllCostTot; // Total allocated cost
$outQuantity = (float) filter_input(INPUT_POST, 'outQuantity');
$unitCost = $outAllCostTot / $outQuantity;
```

### Unit Conversion Calculation
```php
$productunitData = $myProductunitEx->queryWithProductIdAndUnitId($productId, $unitId);
$finalquantity = $quantity * $productunitData->productnumber;
```

### FIFO Cost Calculation
```php
$totalPrice = 0;
$remainQuantity = $soldQuantity;

do {
    $buyPriceFromHistoryBook = $buyPricesHistoryBookEX->getBuyPriceOfFirstAvailableSellQuantity($storeId, $productid, $sizeid, $colorid);
    $availableBuyQuantity = $buyPriceFromHistoryBook->buyQuantity - $buyPriceFromHistoryBook->sellQuantity;
    
    if ($availableBuyQuantity >= $remainQuantity) {
        $totalPrice += $remainQuantity * $buyPriceFromHistoryBook->buyprice;
        $remainQuantity = 0;
    } else {
        $totalPrice += $availableBuyQuantity * $buyPriceFromHistoryBook->buyprice;
        $remainQuantity -= $availableBuyQuantity;
    }
} while ($remainQuantity > 0 && isset($buyPriceFromHistoryBook->id));

$averageCost = $totalPrice / $soldQuantity;
```

---

## 🔒 Security & Permissions

### Authentication Requirements
```php
include_once("../public/authentication.php");
```

### Input Validation
- All numeric inputs cast to appropriate types
- Product and unit IDs validated against database
- Date parameters validated for proper format
- Transaction control prevents partial updates

### Data Integrity
- Transaction rollback on any failure
- Inventory movement logging for audit trail
- Supplier debt change tracking
- Daily accounting entry generation
- Cascading deletion logic

---

## 📊 Performance Considerations

### Database Optimization Tips
1. **Critical Indexes**:
   - `productionout(outStore, inStore, sysDate)`
   - `productionoutdetails(productionOutId)`
   - `storedetail(storeid, productid)`
   - `buypriceshistorybook(storeId, productid, sizeid, colorid, theDate)`

2. **Query Optimization**:
   - Batch inventory updates within transactions
   - Efficient FIFO price calculation
   - Minimize N+1 query patterns

3. **Memory Management**:
   - Process raw materials incrementally
   - Clean up temporary variables
   - Proper transaction scope

---

## 🧪 Testing Scenarios

### Test Case 1: Basic Production Order
```
1. Create production order: 1 chair from 4 legs + 1 seat
2. Set costs: legs $5 each, seat $20, total chair cost $50
3. Verify inventory changes:
   - Chair quantity +1
   - Leg quantity -4
   - Seat quantity -1
4. Check cost updates:
   - Chair buy price updated to $50
   - Price history recorded
5. Verify supplier debt increased by $50
6. Check daily accounting entry created
```

### Test Case 2: Size/Color Variant Production
```
1. Create red large chair from materials
2. Verify hasSizeColor encoding works
3. Check variant-specific inventory updates
4. Confirm size/color inventory tracking
```

### Test Case 3: Edit and Delete Operations
```
1. Create production order
2. Edit with different materials/quantities
3. Verify old data reversed and new applied
4. Delete order
5. Confirm all effects reversed:
   - Inventory restored
   - Supplier debt reversed
   - Accounting entry reversed
```

---

## 📚 Related Documentation

- [CLAUDE.md](/Applications/AMPPS/www/erp19/CLAUDE.md) - PHP 8.2 migration guide
- [productionOutManyController.md](productionOutManyController.md) - Multiple output production
- [productionEquationController.md](productionEquationController.md) - Production formulas
- [buyBillController.md](#) - Raw material purchasing

---

**Documented By**: AI Assistant  
**Review Status**: ✅ Complete  
**Next Review**: When major changes occur