# Offer Client Controller Documentation

**File**: `/controllers/offerclient.php`  
**Purpose**: Manages client product offers including creation, viewing, editing, and product detail management  
**Last Updated**: December 20, 2024  
**Total Functions**: 2  
**Lines of Code**: ~234

---

## 📋 Overview

The Offer Client Controller handles the creation and management of product offers for clients. It provides functionality to:
- Create new offers with multiple products
- Display offer listings with client information
- View detailed offer information including products
- Edit existing offers and their products
- Manage offer product quantities and pricing
- Track inventory availability and shortage data

### Primary Functions
- [x] Create client offers with multiple products
- [x] Display offer forms with product selection
- [x] Manage offer product quantities and pricing
- [x] Track store quantities vs. available vs. shortage amounts
- [x] Show offer listings with client details
- [x] Provide detailed offer viewing capabilities
- [x] Enable offer editing and updates

### Related Controllers
- [offerorder.php](offerorder.md) - Order creation from offers
- [clientController.php](#) - Customer management
- [productController.php](#) - Product management
- [sellbillController.php](sellbillController.md) - Sales processing

---

## 🗄️ Database Tables

### Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **offerclient** | Offer master records | id, datenow, userid, del, client, mydate, alltotal, allquantity, allquantstore, pricestore, allquantavailable, priceavailable, allquantmiun, pricemiun, oldoffer |
| **offerproduct** | Offer product line items | clientid (offer id), productid, quantity, storequant, availablequant, miunquant, price, total |

### Reference Tables
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **client** | Customer master data | clientid, clientname, clientphone, clientmobile |
| **product** | Product master data | productId, productName, logo, productprice |

---

## 🔑 Key Functions

### 1. **Default Action (Empty $do)** - Offer Creation Form
**Location**: Lines 75-80  
**Purpose**: Display offer creation form

**Function Signature**:
```php
// Triggered when: empty $do
// Displays: offerclient/add.html template
```

**Process Flow**:
1. Include authentication check
2. Display offer creation form template
3. Allow user to add products and client information

---

### 2. **add()** - Create New Offer
**Location**: Lines 161-230  
**Purpose**: Process offer creation with product details

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

**Process Flow**:
1. Extract form data for offer header
2. Create offer master record with totals
3. Process each product line item
4. Store quantities and pricing information
5. Link to original offer if exists

**Key Variables Processed**:
```php
$oldoffer = filter_input(INPUT_POST, 'oldoffer');
$datenow = date("Y-m-d");
$userid = $_SESSION["userid"];
$del = 0;
$client = filter_input(INPUT_POST, 'client');
$mydate = filter_input(INPUT_POST, 'mydate');
$alltotal = filter_input(INPUT_POST, 'alltotal');
$allquantity = filter_input(INPUT_POST, 'allquantity');
$allquantstore = filter_input(INPUT_POST, 'allquantstore');
$allquantavailable = filter_input(INPUT_POST, 'allquantavailable');
$allquantminus = filter_input(INPUT_POST, 'allquantminus');
```

**Product Processing Logic**:
```php
$itr = filter_input(INPUT_POST, 'itr'); // Number of products
for ($i = 1; $i <= $itr; $i++) {
    if (isset($_POST['product' . $i]) && !empty($_POST['product' . $i])) {
        $product = filter_input(INPUT_POST, 'product' . $i);
        $quantproduct = filter_input(INPUT_POST, 'quantity' . $i);
        $quantstore = filter_input(INPUT_POST, 'prostore' . $i);
        $quantavailable = filter_input(INPUT_POST, 'proavailable' . $i);
        $quantminus = filter_input(INPUT_POST, 'prominus' . $i);
        $price = filter_input(INPUT_POST, 'price' . $i);
        $total = filter_input(INPUT_POST, 'total' . $i);
        
        $offerProduct->clientid = $id; // Offer ID
        $offerProduct->productid = $product;
        $offerProduct->quantity = $quantproduct;
        $offerProduct->storequant = $quantstore;
        $offerProduct->availablequant = $quantavailable;
        $offerProduct->miunquant = $quantminus;
        $offerProduct->price = $price;
        $offerProduct->total = $total;
        
        $offerProductDAO->insert($offerProduct);
    }
}
```

---

### 3. **show** - Offer Listing
**Location**: Lines 94-102  
**Purpose**: Display all offers with client information

**Process Flow**:
1. Query all offer client records
2. Load client names using RedBeanPHP
3. Assign data to template
4. Display offer listing

**Client Name Enhancement**:
```php
foreach ($allclient as $client) {
    $proclient = R::findOne('client', 'clientid = ' . $client->client);
    $client->proclient = $proclient->clientname;
}
```

---

### 4. **detail** - Offer Details View
**Location**: Lines 104-121  
**Purpose**: Display detailed offer information with all products

**Process Flow**:
1. Load offer client data by ID
2. Get client information
3. Query all offer products
4. Enhance products with logos and names
5. Display detailed view

**Product Enhancement**:
```php
foreach ($offerProduct as $offerPro) {
    $productid = $ProductDAO->load($offerPro->productid);
    $offerPro->prologo = $productid->logo;
    $offerPro->proname = $productid->productName;
}
```

---

### 5. **edit** - Offer Editing Form
**Location**: Lines 122-145  
**Purpose**: Load offer data for editing

**Process Flow**:
1. Load existing offer data
2. Get client information
3. Load all offer products with details
4. Enhance products with logos, names, and IDs
5. Display edit form with populated data

**Product Data Enhancement for Editing**:
```php
foreach ($offerProduct as $offerPro) {
    $productid = $ProductDAO->load($offerPro->productid);
    $offerPro->prologo = $productid->logo;
    $offerPro->proname = $productid->productName;
    $offerPro->id = $productid->id; // Added for editing form
}
```

---

## 🔄 Workflows

### Workflow 1: Client Offer Creation
```
┌─────────────────────────────────────────────────────────────┐
│              START: Create New Client Offer                │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Display Offer Form                                      │
│     - Select client                                         │
│     - Add multiple products                                 │
│     - Set quantities for each product                       │
│     - Define store/available/shortage quantities            │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Process Form Submission                                 │
│     - Validate client and product selections               │
│     - Calculate total quantities and prices                │
│     - Prepare offer header data                             │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Save Offer Data                                         │
│     - Insert offerclient master record                     │
│     - Insert offerproduct records for each item            │
│     - Store quantity breakdowns                             │
│     - Link to original offer if applicable                 │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Confirmation                                            │
│     - Display success message                               │
│     - Redirect to success page                              │
│     - Offer ready for order conversion                      │
└─────────────────────────────────────────────────────────────┘
```

---

## 🌐 URL Routes & Actions

| URL Parameter | Function Called | Description |
|---------------|----------------|-------------|
| `do=` (empty) | Default action | Offer creation form |
| `do=add` | `add()` | Process offer creation |
| `do=show` | Show action | List all offers with client info |
| `do=detail` | Detail action | Show detailed offer information |
| `do=edit` | Edit action | Offer editing form |
| `do=sucess` | Success template | Success confirmation |
| `do=error` | Error template | Error display |

### Required Parameters by Action

**Offer Creation** (`do=add`):
- `client` - Client ID
- `mydate` - Offer date
- `alltotal` - Total offer value
- `allquantity` - Total quantity
- `allquantstore` - Total store quantity
- `allquantavailable` - Total available quantity
- `allquantminus` - Total shortage quantity
- `itr` - Number of product iterations
- `product{N}` - Product ID for line N
- `quantity{N}` - Quantity for product N
- `price{N}` - Price for product N

**Offer Details** (`do=detail`):
- `id` - Offer client ID

**Offer Edit** (`do=edit`):
- `id` - Offer client ID

---

## 🧮 Calculation Methods

### Quantity Tracking System
```php
// Three-tier quantity tracking
$storequant = filter_input(INPUT_POST, 'prostore' . $i);      // In store
$availablequant = filter_input(INPUT_POST, 'proavailable' . $i); // Available
$miunquant = filter_input(INPUT_POST, 'prominus' . $i);       // Shortage

// Total calculations across all products
$allquantstore += $storequant;         // Sum of store quantities
$allquantavailable += $availablequant; // Sum of available quantities
$allquantminus += $miunquant;          // Sum of shortage quantities
```

### Pricing Calculations
```php
// Line item total
$total = filter_input(INPUT_POST, 'total' . $i); // price * quantity

// Offer totals
$alltotal = array_sum($all_line_totals);
$pricestore = $price_for_store_quantity;
$priceavailable = $price_for_available_quantity;
$pricemiun = $price_for_shortage_quantity;
```

### Offer Reference Tracking
```php
$oldoffer += 0; // Convert to numeric, reference to previous offer
// Used for tracking offer history and revisions
```

---

## 🔒 Security & Permissions

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

### Input Sanitization
```php
// All inputs properly sanitized
$client = filter_input(INPUT_POST, 'client');
$product = filter_input(INPUT_POST, 'product' . $i);
$quantproduct = filter_input(INPUT_POST, 'quantity' . $i);
$price = filter_input(INPUT_POST, 'price' . $i);
```

### Session Management
```php
$userid = $_SESSION["userid"]; // Track offer creator
$datenow = date("Y-m-d");      // System date stamp
```

---

## 📊 Performance Considerations

### Database Optimization Tips
1. **Indexes Required**:
   - `offerclient(client, mydate)`
   - `offerproduct(clientid, productid)`
   - `client(clientid)`
   - `product(productId)`

2. **Query Optimization**:
   - Batch product loading by offer ID
   - Efficient client name lookups
   - Proper use of foreign key relationships

3. **Memory Management**:
   - Process products in iterations to handle large offers
   - Clean up product arrays after processing
   - Limit concurrent offer creation

### Known Performance Issues
```php
// N+1 query issue in client name loading
foreach ($allclient as $client) {
    $proclient = R::findOne('client', 'clientid = ' . $client->client);
    // Better: JOIN query to get all client names at once
}
```

---

## 🐛 Common Issues & Troubleshooting

### 1. **Missing Product Information**
**Issue**: Products show without names or logos in detail view  
**Cause**: Product loading failure or deleted products

**Debug**:
```sql
SELECT op.*, p.productName, p.logo 
FROM offerproduct op 
LEFT JOIN product p ON p.productId = op.productid 
WHERE op.clientid = [OFFER_ID];
```

### 2. **Quantity Calculation Errors**
**Issue**: Total quantities don't match sum of line items  
**Cause**: Invalid or missing quantity inputs

**Fix**: Add validation:
```php
// Ensure numeric values
$quantproduct = (int) filter_input(INPUT_POST, 'quantity' . $i);
$quantstore = (int) filter_input(INPUT_POST, 'prostore' . $i);
$quantavailable = (int) filter_input(INPUT_POST, 'proavailable' . $i);

// Validate quantities are positive
if ($quantproduct <= 0) continue;
```

### 3. **Client Name Display Issues**
**Issue**: Client names showing as null  
**Cause**: Client ID mismatch or deleted clients

**Debug**:
```sql
-- Check client existence
SELECT * FROM client WHERE clientid IN (
    SELECT DISTINCT client FROM offerclient WHERE del = 0
);
```

### 4. **Offer Total Mismatch**
**Issue**: Offer totals don't match line item sums  
**Cause**: JavaScript calculation errors or form manipulation

**Server-side Verification**:
```php
$serverTotal = 0;
for ($i = 1; $i <= $itr; $i++) {
    $price = (float) filter_input(INPUT_POST, 'price' . $i);
    $quantity = (int) filter_input(INPUT_POST, 'quantity' . $i);
    $serverTotal += ($price * $quantity);
}

if (abs($serverTotal - $alltotal) > 0.01) {
    // Handle total mismatch
    throw new Exception("Total mismatch detected");
}
```

---

## 🧪 Testing Scenarios

### Test Case 1: Basic Offer Creation
```
1. Access offer creation form
2. Select valid client
3. Add multiple products with different quantities
4. Set store/available/shortage amounts
5. Submit form
6. Verify offerclient and offerproduct records created
7. Check all totals calculated correctly
```

### Test Case 2: Offer with Product Variants
```
1. Create offer with same product, different quantities
2. Test different store/available combinations
3. Verify each line item stored correctly
4. Check total calculations across variants
```

### Test Case 3: Offer Editing
```
1. Create test offer
2. Load edit form with existing data
3. Modify quantities and products
4. Submit changes
5. Verify updates applied correctly
6. Check data integrity maintained
```

### Test Case 4: Large Offer Handling
```
1. Create offer with 50+ products
2. Test form submission performance
3. Verify all products processed
4. Check memory usage and timeouts
```

---

## 📚 Related Documentation

- [CLAUDE.md](/Applications/AMPPS/www/erp19/CLAUDE.md) - PHP 8.2 migration guide
- [offerorder.md](offerorder.md) - Order creation from offers
- [sellbillController.md](sellbillController.md) - Sales processing
- [Database Schema Documentation](#) - Table relationships

---

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