# Bill Template Controller Documentation

**File**: `/controllers/billTemplateController.php`  
**Purpose**: Manages predefined bill templates for quick product selection and standardized billing  
**Last Updated**: December 20, 2024  
**Total Functions**: 5  
**Lines of Code**: ~324

---

## 📋 Overview

The Bill Template Controller provides functionality for creating, managing, and using predefined bill templates. These templates allow users to create standardized product combinations for both sales and returns, streamlining the billing process by pre-defining commonly sold product groups with quantities and specifications.

### Primary Functions
- [x] Create bill templates with product combinations
- [x] Support both sale and return product templates
- [x] Handle products with size and color variations
- [x] Display template listings with edit/delete capabilities
- [x] Edit existing templates with full product details
- [x] Delete templates and associated details
- [x] Support product unit variations
- [x] Transaction-based operations for data consistency

### Related Controllers
- [sellbillController.php](sellbillController.md) - Uses templates for quick bill creation
- [buyBillController.php](buyBillController.md) - Purchase operations
- [productController.php](#) - Product management
- [returnsellbillController.php](#) - Return operations

---

## 🗄️ Database Tables

### Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **billtemplate** | Template master data | id, name, userid, sysdate, del |
| **billtemplatedetail** | Template product details | id, billTemplateId, type, parcode, productid, sizeid, colorid, unitid, quantity |

### Product Reference Tables
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **product** | Product master data | productid, productname, productnumber, productprice, productCatId |
| **productcat** | Product categories | id, productCatName, productCatParent |
| **productunit** | Product units | productunitid, productunitname, productid |
| **size** | Product sizes | sizeid, sizename |
| **color** | Product colors | colorid, colorname |

### System Tables
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **programsettings** | System configuration | programsettingsid, settingkey, settingvalue |

---

## 🔑 Key Functions

### 1. **Default Action** - Display Template Form
**Location**: Line 63-66  
**Purpose**: Show bill template creation form

**Process Flow**:
1. Display header template
2. Show `billTemplateview/bill.html` form
3. Load product selection interface
4. Enable custom validation

---

### 2. **add()** - Create/Update Template
**Location**: Line 123-226  
**Purpose**: Create new template or update existing template with product details

**Function Signature**:
```php
function add()
// Returns: template ID
```

**Transaction Handling**:
```php
$mytransactions = new Transaction();
try {
    // Template operations
    $mytransactions->commit();
} catch (Exception $ex) {
    $mytransactions->rollback();
}
```

**Process Flow**:
1. **Create/Update Template Master**:
   ```php
   $billTemplate->name = $name ?: "نموذج " . $id;
   $billTemplate->userid = $_SESSION['userid'];
   $billTemplate->sysdate = date('Y-m-d H:i:s');
   $billTemplate->del = 0;
   
   if ($id > 0) {
       $billTemplateEX->insertWithId($billTemplate, $id);
   } else {
       $id = $billTemplateDAO->insert($billTemplate);
   }
   ```

2. **Process Sale Products** (type = 0):
   ```php
   for ($i = 1; $i <= $itr; $i++) {
       $product = filter_input(INPUT_POST, "product$i");
       $pronum = (float) filter_input(INPUT_POST, "pronum$i");
       
       // Handle size/color combinations
       if (strpos($product, "hasSizeColor") !== false) {
           $productIdComplex = explode('-', str_replace("hasSizeColor", "", $product));
           $product = $productIdComplex[0];
           $sizeId = $productIdComplex[1];
           $colorId = $productIdComplex[2];
       }
       
       $billTemplateDetail->type = 0; // Sale
       $billTemplateDetail->productid = $product;
       $billTemplateDetail->quantity = $pronum;
   }
   ```

3. **Process Return Products** (type = 1):
   ```php
   for ($i = 1; $i <= $itr; $i++) {
       $product = filter_input(INPUT_POST, "returnproduct$i");
       $billTemplateDetail->type = 1; // Return
       $billTemplateDetail->productid = $product;
   }
   ```

**Size/Color Processing**:
```php
if (strpos($product, "hasSizeColor") !== false) {
    // Format: "productid-hasSizeColor-sizeid-colorid"
    $productIdComplex = explode('-', str_replace("hasSizeColor", "", $product));
    $product = $productIdComplex[0];
    $sizeId = $productIdComplex[1]; 
    $colorId = $productIdComplex[2];
}
```

---

### 3. **show()** - Display Templates
**Location**: Line 73-77  
**Purpose**: List all available bill templates

**Process Flow**:
1. Query all templates: `$billTemplateDAO->queryAll()`
2. Assign to Smarty: `$smarty->assign("allTemplates", $allTemplates)`
3. Display: `billTemplateview/show.html`

---

### 4. **edit()** - Load Template for Editing
**Location**: Line 248-307  
**Purpose**: Load template data with full product details for editing

**Function Signature**:
```php
function edit($id)
```

**Process Flow**:
1. **Load Template Master**:
   ```php
   $billTemplate = $billTemplateDAO->load($id);
   $smarty->assign("billTemplate", $billTemplate);
   ```

2. **Load Sale Products** (type = 0):
   ```php
   $billTemplateDetails = $billTemplateDetailEX->queryByBillTemplateIdEXAndType($id, 0);
   
   foreach ($billTemplateDetails as $mydetales) {
       // Build product path from categories
       $parentId = $mydetales->productCatId;
       $pathArr = getProductPath_recursive($parentId, $categories);
       $mydetales->productName = $mydetales->productName . '/' . $pathArr;
       
       // Add size/color information
       if ($mydetales->sizeName != '')
           $mydetales->productName .= "/ " . $mydetales->sizeName;
       if ($mydetales->colorName != '')
           $mydetales->productName .= "/ " . $mydetales->colorName;
           
       // Load available units for product
       $myunitdata = $myProductunitEx->queryWithProductIdAndCondition($mydetales->productid);
       $smarty->assign("myunitdata" . $i, $myunitdata);
   }
   ```

3. **Load Return Products** (type = 1):
   ```php
   $billTemplateDetails = $billTemplateDetailEX->queryByBillTemplateIdEXAndType($id, 1);
   // Similar processing for return products
   ```

**Product Path Building**:
```php
function getProductPath_recursive($parentid, $categories) {
    $catData = $productCatExt->getCategoryAndParentByCatId($parentid);
    if (count($catData) > 0) {
        $categories .= $catData->productCatName . '/';
        return getProductPath_recursive($catData->productCatParent, $categories);
    }
    return substr($categories, 0, strlen($categories) - 1);
}
```

---

### 5. **delete()** - Delete Template
**Location**: Line 228-246  
**Purpose**: Remove template and all associated details

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

**Transaction Process**:
```php
$mytransactions = new Transaction();
try {
    $billTemplateDAO->delete($id);
    $billTemplateDetailDAO->deleteByBillTemplateId($id);
    $mytransactions->commit();
} catch (Exception $ex) {
    $mytransactions->rollback();
}
```

**Cleanup Operations**:
1. Delete template master record
2. Delete all template detail records
3. Maintain referential integrity

---

## 🔄 Workflows

### Workflow 1: Create Bill Template
```
┌─────────────────────────────────────────────────────────────┐
│                START: Create Template                      │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Access Template Form                                    │
│     - Load product categories and units                     │
│     - Initialize template form interface                    │
│     - Display sale and return sections                      │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Configure Template Details                             │
│     - Enter template name                                   │
│     - Add sale products with quantities                     │
│     - Add return products (if needed)                       │
│     - Specify units, sizes, colors                          │
│     - Set product codes (parcode)                          │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Process Sale Products                                   │
│     FOR EACH sale product:                                  │
│       │                                                     │
│       ├─→ Validate product selection                       │
│       ├─→ Parse size/color combinations                     │
│       ├─→ Set quantity and unit                             │
│       ├─→ Create template detail record                     │
│       │   ├─ type = 0 (sale)                               │
│       │   ├─ productid, sizeid, colorid                    │
│       │   └─ quantity, unitid, parcode                     │
│       │                                                     │
│       └─→ Insert detail record                              │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Process Return Products                                 │
│     FOR EACH return product:                                │
│       │                                                     │
│       ├─→ Validate product selection                       │
│       ├─→ Parse size/color combinations                     │
│       ├─→ Set quantity and unit                             │
│       ├─→ Create template detail record                     │
│       │   ├─ type = 1 (return)                             │
│       │   ├─ productid, sizeid, colorid                    │
│       │   └─ quantity, unitid, parcode                     │
│       │                                                     │
│       └─→ Insert detail record                              │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  5. Finalize Template                                       │
│     - Commit transaction                                    │
│     - Return template ID                                    │
│     - Redirect to success page                             │
└─────────────────────────────────────────────────────────────┘
```

### Workflow 2: Edit Template
```
┌─────────────────────────────────────────────────────────────┐
│                START: Edit Template                        │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Load Template Data                                      │
│     - Get template master information                       │
│     - Load sale products (type = 0)                         │
│     - Load return products (type = 1)                       │
│     - Build product category paths                          │
│     - Load available units for each product                 │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Display Edit Form                                       │
│     - Pre-populate template name                            │
│     - Show existing sale products with:                     │
│       ├─ Full product path (category/product/size/color)   │
│       ├─ Current quantity                                   │
│       ├─ Selected unit                                      │
│       └─ Product code                                       │
│     - Show existing return products                         │
│     - Allow additions and modifications                     │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Process Update (do=update)                             │
│     - Delete existing template and details                  │
│     - Recreate template with new data                       │
│     - Use same add() function logic                         │
│     - Maintain template ID if specified                     │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Success Response                                        │
│     - Redirect to success page                             │
│     - Template ready for use                               │
└─────────────────────────────────────────────────────────────┘
```

---

## 🌐 URL Routes & Actions

| URL Parameter | Function Called | Description |
|---------------|----------------|-------------|
| `do=` (empty) | Default | Display template creation form |
| `do=add` | `add()` | Create new template |
| `do=show` | Display | Show all templates list |
| `do=edit` | `edit($id)` | Load template for editing |
| `do=showdetail` | `edit($id)` | Show template details (view-only) |
| `do=update` | `delete($id)` + `add()` | Update existing template |
| `do=delete` | `delete($id)` | Remove template |
| `do=sucess` | Template | Success page |
| `do=error` | Template | Error page |

### Required Parameters by Action

**Create Template** (`do=add`):
- `name` - Template name (optional, auto-generated if empty)
- `hidden_itr` - Number of sale products
- `returnhidden_itr` - Number of return products
- Dynamic arrays: `product{N}`, `pronum{N}`, `productunit{N}`, `parcode{N}`
- Return arrays: `returnproduct{N}`, `returnpronum{N}`, etc.

**Edit Template** (`do=edit`):
- `id` - Template ID to edit

**Update Template** (`do=update`):
- `id` - Template ID to update
- Same product arrays as create

**Delete Template** (`do=delete`):
- `id` - Template ID to delete

---

## 🧮 Business Logic

### Product Type Classification
- **type = 0**: Sale products (normal sales items)
- **type = 1**: Return products (items to be returned)

### Size/Color Handling
```php
// Input format: "productid-hasSizeColor-sizeid-colorid"
if (strpos($product, "hasSizeColor") !== false) {
    $productIdComplex = explode('-', str_replace("hasSizeColor", "", $product));
    $product = $productIdComplex[0];     // Main product ID
    $sizeId = $productIdComplex[1];      // Size variant
    $colorId = $productIdComplex[2];     // Color variant
}
```

### Template Naming
```php
// Auto-generate name if not provided
if (empty($name)) {
    $billTemplate->name = "نموذج " . $id; // "Template " + ID
}
```

### Product Path Display
```php
// Build full product hierarchy: Category/Subcategory/Product/Size/Color
$mydetales->productName = $mydetales->productName . '/' . $pathArr;
if ($mydetales->sizeName != '') $mydetales->productName .= "/ " . $mydetales->sizeName;
if ($mydetales->colorName != '') $mydetales->productName .= "/ " . $mydetales->colorName;
```

---

## 🔒 Security & Permissions

### Input Filtering
```php
$id = (int) filter_input(INPUT_POST, "id");
$name = filter_input(INPUT_POST, "name");
$parcode = filter_input(INPUT_POST, "parcode$i");
$product = filter_input(INPUT_POST, "product$i");
$pronum = (float) filter_input(INPUT_POST, "pronum$i");
```

### Authentication
- ✅ User session tracking: `$_SESSION['userid']`
- ✅ Database user association
- ❌ No explicit permission checks
- ❌ No role-based access control

### Input Validation
- ✅ Type casting for numeric values
- ✅ Basic input filtering
- ✅ Empty value checks
- ❌ No SQL injection protection beyond filtering
- ❌ No CSRF token validation

---

## 📊 Performance Considerations

### Transaction Management
```php
$mytransactions = new Transaction();
try {
    // Multiple database operations
    $mytransactions->commit();
} catch (Exception $ex) {
    $mytransactions->rollback();
}
```

### Optimization Opportunities
1. **Batch Insert Operations**:
   - Multiple detail inserts could be batched
   - Reduce database round trips

2. **Caching**:
   - Product category paths could be cached
   - Unit data caching for frequently used products

3. **Query Optimization**:
   - Index on `billTemplateId` and `type`
   - Composite index for product searches

### Database Load
- **Light Operations**: Template management is relatively low-volume
- **Complex Queries**: Product path building uses recursive queries
- **Transaction Safety**: Proper rollback on failures

---

## 🐛 Common Issues & Troubleshooting

### 1. **Size/Color Parsing Errors**
**Issue**: Complex product format parsing fails  
**Debug**: Check product input format: `productid-hasSizeColor-sizeid-colorid`

### 2. **Missing Product Units**
**Issue**: Product units not loading in edit form  
**Debug**: 
```sql
SELECT * FROM productunit WHERE productid = ?;
```

### 3. **Template Update Issues**
**Issue**: Update operation fails  
**Cause**: Delete-then-add approach may leave orphaned records
**Solution**: Ensure transaction rollback on failure

### 4. **Product Path Building Infinite Loop**
**Issue**: Circular category references cause recursion  
**Debug**: Check category parent relationships

---

## 🧪 Testing Scenarios

### Test Case 1: Basic Template Creation
```
1. Create template with simple products
2. Verify template master record
3. Check detail records for sale products
4. Validate return products if added
5. Confirm template appears in listing
```

### Test Case 2: Size/Color Combinations
```
1. Add products with size/color variants
2. Verify correct parsing of complex IDs
3. Check detail records have proper size/color IDs
4. Validate display in edit form
```

### Test Case 3: Template Update
```
1. Create initial template
2. Edit and add/remove products
3. Verify old records are properly deleted
4. Check new records are inserted correctly
5. Confirm no orphaned detail records
```

### Test Case 4: Error Handling
```
1. Submit invalid product combinations
2. Test transaction rollback scenarios
3. Verify error page display
4. Check database consistency after errors
```

---

## 📚 Related Documentation

- [CLAUDE.md](/Applications/AMPPS/www/erp19/CLAUDE.md) - PHP 8.2 migration guide
- [sellbillController.md](sellbillController.md) - Sales operations using templates
- [productController.php](#) - Product management
- [Database Schema Documentation](#) - Table relationships

---

**Documented By**: AI Assistant  
**Review Status**: ✅ Complete  
**Next Review**: When template usage analytics are added