# Project Material Operations Controller Documentation

**File**: `/controllers/projectoperationController.php`  
**Purpose**: Manage material issuance to projects with inventory tracking and accounting integration  
**Last Updated**: 2024-12-20

---

## 📋 Overview

### Primary Functions
- [x] Material issuance to projects
- [x] Inventory quantity management
- [x] Accounting integration for materials
- [x] Supplier relationship tracking
- [x] Service vs physical product handling
- [x] Store reporting and audit trail

### Related Controllers
- [projectController.php](projectController.md) - Project master data
- [projectoperationControllerreturn.php](projectoperationControllerreturn.md) - Material returns
- [storedetailController.php](#) - Inventory management

---

## 🗄️ Database Tables

### Primary Tables
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| projectexchmaterial | Material issue header | id, serilno, projectid, storeid, totalbuyprice, supplierid |
| projectexchmaterialdetail | Material issue lines | projectexchid, productid, pronumber, probuyprice, expensestypeid |
| storedetail | Inventory quantities | storedetailid, productid, storeid, productquantity |
| storereport | Inventory movement log | productid, storeid, processname, productbefore, productafter |

### Secondary Tables (Referenced)
| Table Name | Purpose | Relationship |
|------------|---------|--------------|
| project | Project master | Foreign Key: projectexchmaterial.projectid |
| store | Warehouse/location | Foreign Key: projectexchmaterial.storeid |
| product | Product master | Foreign Key: projectexchmaterialdetail.productid |
| supplier | Supplier master | Foreign Key: projectexchmaterial.supplierid |
| expensestype | Expense categories | Foreign Key: projectexchmaterialdetail.expensestypeid |
| accountstree | Accounting structure | For financial entries |

---

## 🔧 Key Functions

### 1. add($id)
**Purpose**: Issue materials to project with inventory and accounting updates  
**Called By**: POST action to `?do=add`  
**Parameters**:
- `$serialno` (string) - Transaction serial number
- `$projectid` (int) - Target project
- `$storeid` (int) - Source warehouse
- `$finaltotalprice` (float) - Total material value
- `$offerhidden_itr` (int) - Number of material lines

**Returns**: Creates material issue transaction

**Database Operations**:
- INSERT into `projectexchmaterial` - Transaction header
- INSERT into `projectexchmaterialdetail` - Material lines
- UPDATE `storedetail` - Decrease inventory quantities
- INSERT into `storereport` - Audit trail
- INSERT into `dailyentry` - Accounting entries

**Business Logic**:
1. **Accounting Tree Setup**:
   ```php
   $treeData = $accountsTreeDAO->queryByName($projectName);
   if (count($treeData) == 0) {
       $treeid = addTreeElement($projectName, 23, 3, 0, 1, '', 0, $finaltotalprice);
       $treeproid = addTreeElement('بضاعة تحت التسوية (' . $txtName . ')', 39, 1, 0, 1, '', 0, $finaltotalprice);
   }
   ```

2. **Inventory Processing**:
   ```php
   for ($i = 1; $i <= $offerhidden_itr; $i++) {
       $productid = filter_input(INPUT_POST, 'projectproudctid' . $i);
       $productnumber = filter_input(INPUT_POST, 'productnumber' . $i);
       
       if (isset($productid) && $productid != '-1') {
           $product = $productDAO->load($productid);
           if ($product->isService != 1) {
               $storedetailFromData = getStoredetailData($storeid, $productid);
               $productquantityFromAfter = decreaseProductQuantity($storedetailFromId, $productquantityFromBefore, $productnumber);
               insertStorereport($productid, $storeid, $productnumber, $productquantityFromBefore, $productquantityFromAfter, 1, $projmaterialid, "صرف مواد للمشروع " . $projectName, "projectoperationController.php");
           }
       }
   }
   ```

3. **Accounting Entry**:
   ```php
   function entryinsert_data($projectname, $value, $clientid, $projectid) {
       $dailyEntry->entryComment = 'تم صرف مواد للمشروع';
       
       // Credit: Goods Under Settlement
       $dailyEntryCreditor->value = $value;
       $dailyEntryCreditor->accountstreeid = $projectid;
       
       // Debit: Project Account
       $dailyEntryDebtor->value = $value;
       $dailyEntryDebtor->accountstreeid = $clientid;
       
       return insertEntery($dailyEntry, $dailyEntryDebtorArray, $dailyEntryCreditorArray);
   }
   ```

### 2. update()
**Purpose**: Update material issue by delete and re-add  
**Called By**: POST action to `?do=update`  
**Parameters**: Same as add() plus `$editid`

**Business Logic**:
```php
function update() {
    $editid = filter_input(INPUT_POST, 'editid', FILTER_DEFAULT);
    delete($editid);  // Remove existing transaction
    add($editid);     // Recreate with new data
}
```

### 3. delete($id)
**Purpose**: Reverse material issue and restore inventory  
**Called By**: GET action to `?do=delete&id=$id`  
**Parameters**:
- `$id` (int) - Transaction ID to delete

**Database Operations**:
- SELECT transaction details
- UPDATE `storedetail` - Restore inventory quantities
- INSERT into `storereport` - Log restoration
- DELETE transaction records
- Reverse accounting entries

**Business Logic**:
1. **Inventory Restoration**:
   ```php
   foreach ($details as $value) {
       if (isset($value->productid) && $value->productid != '-1') {
           $product = $productDAO->load($productid);
           if ($product->isService != 1) {
               $storedetailFromData = getStoredetailData($storeid, $productid);
               $productquantityFromAfter = increaseProductQuantity($storedetailFromId, $productquantityFromBefore, $productnumber);
               insertStorereport($productid, $storeid, $productnumber, $productquantityFromBefore, $productquantityFromAfter, 0, $id, "حذف صرف مواد للمشروع " . $projectName, "projectoperationController.php");
           }
       }
   }
   ```

### 4. getserails()
**Purpose**: Generate unique serial numbers  
**Returns**: Year + 4 random digits

**Business Logic**:
```php
function generateRandomString($length = 4) {
    $newnum = substr(str_shuffle("0123456789"), 0, $length);
    return date("Y") . '' . $newnum;
}

$number = generateRandomString();
$checkifthere = $ProjectexchmaterialEx->queryAllbyserialno($number);
if (count($checkifthere) > 0) {
    $number = generateRandomString(); // Regenerate if duplicate
}
```

### 5. Inventory Management Functions

**getStoredetailData($storeid, $productid)**:
```php
function getStoredetailData($storeid, $productid) {
    $storedetailData = $myStoredetailEx->queryWithStoreAndProduct($productid, $storeid);
    $storedetailId = $storedetailData->storedetailid;
    $productquantityBefore = $storedetailData->productquantity;
    return array($storedetailData, $storedetailId, $productquantityBefore);
}
```

**decreaseProductQuantity($storedetailId, $productquantityBefore, $productChangeAmount)**:
```php
function decreaseProductQuantity($storedetailId, $productquantityBefore, $productChangeAmount) {
    $productquantityAfter = $productquantityBefore - $productChangeAmount;
    $myStoredetail->storedetailid = $storedetailId;
    $myStoredetail->productquantity = $productquantityAfter;
    $myStoredetailEx->updateProductquantity($myStoredetail);
    return $productquantityAfter;
}
```

---

## 📊 Main Workflows

### Workflow 1: Material Issuance
```
1. Select Project & Store
   ↓
2. Add Material Lines
   ├── Product Selection
   ├── Quantity Entry  
   ├── Price Entry
   └── Expense Type
   ↓
3. Calculate Totals
   ↓
4. Submit Transaction
   ↓
5. Create Accounting Trees (if needed)
   ↓
6. Create Accounting Entry
   ↓
7. Update Inventory Quantities
   ↓
8. Create Audit Trail
   ↓
9. Success Response
```

**Files Involved**:
- View: `/views/default/projectoperationview/add.html`
- Model: `/models/dto/Projectexchmaterial.class.php`
- DAO: `/models/mysql/ProjectexchmaterialMySqlDAO.class.php`

### Workflow 2: Inventory Impact
```
For Each Material Line:
1. Check if Product is Service
   ├── If Service: Skip inventory
   └── If Physical: Continue
   ↓
2. Get Current Store Quantity
   ↓
3. Validate Sufficient Quantity
   ↓
4. Decrease Store Quantity
   ↓
5. Create Store Movement Report
   ↓
6. Update Audit Trail
```

### Workflow 3: Accounting Integration
```
1. Locate/Create Project Tree Accounts
   ├── Project Account (Debit Side)
   └── Goods Under Settlement (Credit Side)
   ↓
2. Create Double Entry:
   ├── DR: Project Account
   └── CR: Goods Under Settlement
   ↓
3. Link to Transaction
   ↓
4. Update Account Balances
```

---

## 🔗 File Dependencies

### Includes
```php
include("../public/impOpreation.php");
include_once("../public/config.php");
include("../public/include_dao.php");
include_once("dailyentryfun.php");
```

### Required Models
- Project, Client, Supplier, Costcenter, Accountstree
- Store, Expensestype, Product, Programsettings  
- Projectexchmaterial, Projectexchmaterialdetail
- Dailyentry, Dailyentrycreditor, Dailyentrydebtor
- Storedetail, Storereport

### Related Views
- `/views/default/projectoperationview/add.html` - Material issue form
- `/views/default/projectoperationview/show.html` - Transaction listing
- `/views/default/projectoperationview/edit.html` - Transaction editing

---

## 🎯 URL Routes & Actions

| Action (`?do=`) | Method | Description | View Template |
|-----------------|--------|-------------|---------------|
| (empty) | GET | Display issue form | add.html |
| show | GET/POST | List transactions with filters | show.html |
| add | POST | Create material issue | - |
| edit | GET | Display edit form | edit.html |
| update | POST | Update existing transaction | - |
| delete | GET | Reverse transaction | - |
| sucess | GET | Success message | succes.html |
| error | GET | Error message | error.html |

---

## ⚠️ Known Issues & Fixes

### Issue 1: Undefined Variable in Tree Creation (Line 433)
**Problem**: `$txtName` used instead of `$projectName`  
**Cause**: Copy-paste error  
**Fix**: Replace with `$projectName`  
**File**: Line 433

### Issue 2: Missing Product Validation (Line 717)
**Problem**: `$productid` used but `$value->productid` should be used  
**Cause**: Variable scope error  
**Fix**: Use `$value->productid` consistently  
**File**: Line 717

### Issue 3: Incomplete Store Assignment (Line 436)
**Problem**: `$treeproid = $store['treeId']` may be null  
**Cause**: Store may not have tree ID  
**Fix**: Add null check and default handling  
**File**: Line 436

### Issue 4: Large Function Complexity
**Problem**: `add()` function is very large (200+ lines)  
**Cause**: Multiple responsibilities in single function  
**Fix**: Break into smaller, focused functions  
**File**: Lines 388-559

---

## 🔐 Permissions & Security

### Required Permissions
- Project material management
- Store inventory access
- Accounting entry creation

### Security Checks
```php
include_once("../public/authentication.php");
```

### Business Rules
- Cannot issue more than available inventory
- Services don't affect inventory quantities
- All transactions create accounting entries
- Serial numbers must be unique

### Session Filtering
```php
if( $_SESSION['projectids'] != 0){
    $queryString .= ' AND projectexchmaterial.projectid in (' . $_SESSION['projectids'] . ')';
}
```

---

## 🔢 Accounting Integration

### Chart of Accounts Structure
```
23 = Project Accounts (Debit/Asset)
39 = Goods Under Settlement (Credit/Liability)
28 = Alternative goods account
```

### Double Entry Logic
```
Material Issue Transaction:
DR: Project Account (Asset)          $amount
    CR: Goods Under Settlement            $amount

Comment: "تم صرف مواد للمشروع {project_name}"
```

### Reversal Logic
```
Material Issue Deletion:
DR: Goods Under Settlement (Asset)   $amount  
    CR: Project Account                   $amount

Comment: "الغاء صرف مواد للمشروع {project_name}"
```

---

## 📝 Notes

### Important Considerations
- Services (isService = 1) don't affect inventory
- All inventory changes are logged in storereport
- Accounting trees are created automatically for new projects
- Serial numbers prevent duplicate transactions
- Update operation uses delete/re-add pattern

### Performance Considerations
- Large transactions may timeout
- Consider batch processing for many lines
- Inventory calculations are transaction-based

### Future Improvements
- [ ] Add material approval workflow
- [ ] Implement batch operations
- [ ] Add barcode scanning
- [ ] Create mobile material issue
- [ ] Add cost center validation
- [ ] Implement material reservations

---

## 📚 Related Documentation
- [Project Master](projectController.md)
- [Material Returns](projectoperationControllerreturn.md)
- [Inventory Management](../inventory/storedetailController.md)
- [Accounting Integration](../accounting/dailyentryfun.md)