# Client Controller Documentation

**File**: `/controllers/clientController.php`  
**Purpose**: Manages customer/client operations, debt tracking, and client relationships  
**Last Updated**: December 19, 2024  
**Total Functions**: 14  
**Lines of Code**: 1822

---

## 📋 Overview

The Client Controller is responsible for comprehensive client/customer management in the ERP system. It handles:
- Creating and editing client records with detailed information
- Managing client debt tracking and payment history
- Client categorization and type management
- Client-supplier relationship linking
- Email verification and OTP management
- Excel import/export for bulk client operations
- Client area and geographical management
- Accounting integration for client transactions

### Primary Functions
- [x] Create new clients with full profile information
- [x] Edit existing client records
- [x] Delete clients (with validation)
- [x] View client lists with filtering and grouping
- [x] Client debt management and tracking
- [x] Email verification with OTP system
- [x] Excel import for bulk client creation
- [x] Client-supplier linking functionality
- [x] Batch operations on clients
- [x] Print client details and cards
- [x] Phone number export functionality

### Related Controllers
- [sellbillController.php](sellbillController.md) - Sales to clients
- [supplierController.php](supplierController.md) - Supplier-client linking
- [productController.php](productController.md) - Product management for sales
- [buyBillController.php](buyBillController.md) - Purchase-related client operations
- [dailyentryController.php](#) - Client accounting entries
- [clientdebtchangeController.php](#) - Debt change tracking
- [clienttypeController.php](#) - Client type management

---

## 🗄️ Database Tables

### Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **client** | Main client records | clientid, clientname, clientdebt, clientaddress, clientphone, clientmobile |
| **clientdebtchange** | Client debt tracking | clientdebtchangeid, clientid, clientdebtchangeamount, clientdebtchangebefore, clientdebtchangeafter |
| **tamweenclientdetail** | Insurance client details | id, clientid, noOfPersonsTamween, noOfPersonsDa3m, cardNum |
| **clientdetails** | Extended client info | clientid, booking_date, measurements, custom_fields |

### Related Tables
| Table Name | Purpose | Usage |
|------------|---------|-------|
| **clientarea** | Client geographical areas | Client location management |
| **government** | Government/state data | Geographical hierarchy |
| **goverarea** | Area within governments | Location subdivision |
| **store** | Store access permissions | Client-store relationships |
| **typeclient** | Client categorization | Client type assignments |
| **accountstree** | Accounting integration | Client accounts (treeId) |
| **dailyentry** | Accounting entries | Client transaction records |
| **associatedtags** | Client tagging system | Flexible client categorization |

### Reference Tables
| Table Name | Usage |
|------------|-------|
| **user** | Client creation/modification tracking |
| **usergroup** | User permissions for client operations |
| **programsetting** | System configuration settings |
| **youtubelink** | Help video links |
| **eclientsetting** | E-invoice client settings |
| **esaudiclientsetting** | Saudi e-invoice settings |

---

## 🔧 Key Functions

### 1. **add()** - Create New Client
**Signature**: `add(): int`  
**Purpose**: Creates a comprehensive client record with accounting integration  
**Parameters**: Gets extensive data from $_POST array  
**Returns**: Client ID or error codes (-1 for duplicate name, -2 for invalid number)

**Process Flow**:
```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Validate      │───▶│   Handle File   │───▶│   Create Tree   │
│   Client Data   │    │   Uploads       │    │   Element       │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                        │                        │
         ▼                        ▼                        ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Check Name    │    │   Insert        │    │   Create Daily  │
│   Duplicates    │    │   Client        │    │   Entry         │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                                │                        │
                                ▼                        ▼
                       ┌─────────────────┐    ┌─────────────────┐
                       │  Insert Debt    │    │  Handle Special │
                       │  Change Record  │    │  Settings       │
                       └─────────────────┘    └─────────────────┘
```

**Key Features**:
- **File Handling**: Supports document, tax file, and image uploads
- **Store Permissions**: Configures client access to specific stores or all stores
- **Type Management**: Assigns client to multiple categories
- **Accounting**: Creates tree element and daily entry for initial debt
- **Extended Info**: Handles custom client details for specific industries
- **E-Invoice**: Manages electronic invoice settings for clients
- **Tagging System**: Flexible client categorization

**Validation Logic**:
```php
$checkName = $clientDAO->queryByClientname($clientname);
if (!empty($checkName)) {
    return -1; // Duplicate name
}

$checknumber = filter_var($clientdebt, FILTER_VALIDATE_INT);
// Additional validation for debt amount
```

### 2. **addFromExcel()** - Bulk Client Import
**Signature**: `addFromExcel(): void`  
**Purpose**: Imports clients from Excel file with transaction support  
**Parameters**: Excel file from $_FILES and options from $_POST

**Process Flow**:
```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Upload        │───▶│   Process       │───▶│   Create        │
│   Excel File    │    │   Each Row      │    │   Client        │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                        │                        │
         ▼                        ▼                        ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Read Sheet    │    │   Skip Empty    │    │   Handle        │
│   Data          │    │   Rows          │    │   Errors        │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

**Excel Format Support**:
- Client name, code, address, phone, mobile
- Debt amount, debt limit, details
- Insurance details (Tamween, Da3m)
- Client type assignments
- Transaction rollback on errors

### 3. **show()** - Display Client List
**Signature**: `show(): void`  
**Purpose**: Displays comprehensive client list with filtering and statistics  
**Parameters**: Filter criteria from $_POST

**Features**:
- **Date Range Filtering**: Filter by creation date range
- **User Filtering**: Filter by creator user
- **Area Filtering**: Filter by geographical area
- **Type Filtering**: Filter by client type
- **Debt Summation**: Calculates total debt amounts
- **Status Separation**: Active vs inactive clients

### 4. **showByType()** - Group Clients by Type
**Signature**: `showByType(): void`  
**Purpose**: Displays clients grouped by their assigned types  
**Parameters**: None (uses session data)

**Grouping Logic**:
```php
// Special client type categories
$TypeClientAll = "كل انواع العملاء" (All types)
$TypeClientNone = "بلا نوع" (No type)
$TypeClientStop = "الموقوفين" (Suspended)

// Query clients for each type
foreach ($TypeClient as $value) {
    if ($value->typeId == ",") {
        $value->clients = $clientExt->queryByTypeclientidEqual($value->typeId);
    } else if ($value->typeId == '-000-') {
        $value->clients = $clientExt->queryByTypeclientconditions();
    } else {
        $value->clients = $clientExt->queryByTypeclientid($value->typeId);
    }
}
```

### 5. **edit()** - Load Client for Editing
**Signature**: `edit(): array`  
**Purpose**: Retrieves client data with related information for editing  
**Parameters**: Gets `id` from $_GET  
**Returns**: Array containing client data and insurance details

**Data Processing**:
```php
// Parse store permissions
if ($loadData->clientStoreIds != "-10") {
    $loadData->clientStoreIds = explode(',', $loadData->clientStoreIds);
}

// Parse client types
if ($loadData->typeclientid != ",-20,") {
    $loadData->typeclientid = explode(',', $loadData->typeclientid);
}

// Parse tags
$loadData->tagids = explode(',', $loadData->tagids);
```

### 6. **update()** - Update Client Record
**Signature**: `update(): void`  
**Purpose**: Updates existing client with new information  
**Parameters**: Gets data from $_POST array

**Update Process**:
```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Validate      │───▶│   Handle File   │───▶│   Update Tree   │
│   Input Data    │    │   Updates       │    │   Element       │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                        │                        │
         ▼                        ▼                        ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Update        │    │   Update        │    │   Handle        │
│   Client        │    │   Insurance     │    │   E-Settings    │
└─────────────────┘    └─────────────────┘    └─────────────────┘
```

**Key Features**:
- File upload handling with old file management
- Tree element name synchronization
- Insurance detail updates
- E-invoice settings management
- Client detail measurements (for tailoring businesses)

### 7. **deleteFinaly()** - Permanent Client Deletion
**Signature**: `deleteFinaly(): int`  
**Purpose**: Permanently deletes client after validation  
**Parameters**: Gets `id` from $_GET  
**Returns**: -1 if client has bills, success otherwise

**Validation Process**:
```php
$billCounter = R::getCell('select count(sellbillid) from sellbill where conditions=0 and sellbillclientid = ' . $id);
if ($id > 1 && $billCounter <= 0) {
    // Safe to delete
    reverseEntryWithItsID($rowData->dailyentryid);
    delTreeElementById($rowData->treeId);
    // Delete related records and client
} else {
    return -1; // Cannot delete
}
```

### 8. **tempdelete($clientid)** - Hide Client
**Signature**: `tempdelete($clientid): string`  
**Purpose**: Hides client (soft delete) by setting conditions = 1  
**Parameters**: 
- `$clientid` (int): Client ID to hide  
**Returns**: "success" or error message

### 9. **returndelete($clientid)** - Restore Client
**Signature**: `returndelete($clientid): string`  
**Purpose**: Restores hidden client by setting conditions = 0  
**Parameters**: 
- `$clientid` (int): Client ID to restore  
**Returns**: "success" or error message

### 10. **executeOperation()** - Batch Operations
**Signature**: `executeOperation(): void`  
**Purpose**: Performs batch operations on selected clients  
**Parameters**: Gets operation type and selected items from $_POST

**Supported Operations**:
1. **Hide Clients (1)**: Soft delete multiple clients
2. **Restore Clients (2)**: Restore hidden clients

### 11. **generateAndSendEmailOtp($clientId)** - Email Verification
**Signature**: `generateAndSendEmailOtp($clientId): void`  
**Purpose**: Generates and sends OTP for email verification  
**Parameters**: 
- `$clientId` (int): Client ID for verification

**OTP Process**:
```php
$otp = rand(1000, 9999);
$expiry = date('Y-m-d H:i:s', strtotime('+10 minutes'));

// Store OTP and send email
$client->email_otp = $otp;
$client->email_otp_expiry = $expiry;
$client->email_verified = 0;

// Send via PHPMailer with template
$body = file_get_contents($templatePath);
$body = str_replace('{{ reset_link }}', $otp, $body);
```

### 12. **verifyEmailOtp($clientId, $enteredOtp)** - Verify OTP
**Signature**: `verifyEmailOtp($clientId, $enteredOtp): void`  
**Purpose**: Verifies entered OTP and marks email as verified  
**Parameters**: 
- `$clientId` (int): Client ID
- `$enteredOtp` (string): User-entered OTP code

**Verification Logic**:
```php
if ($client->email_otp == $enteredOtp && strtotime($client->email_otp_expiry) > time()) {
    $client->email_verified = 1;
    $client->email_otp = null;
    $client->email_otp_expiry = null;
    // Success response
} else {
    // Invalid or expired OTP error
}
```

---

## 🔄 Workflows

### Client Registration Workflow
```
┌──────────────────┐
│   User Access    │
│   Client Form    │
└────────┬─────────┘
         ▼
┌──────────────────┐    ┌──────────────────┐
│   Validate       │───▶│   Check Name     │
│   Input Data     │    │   Duplicates     │
└──────────────────┘    └────────┬─────────┘
         │                       ▼
         │              ┌──────────────────┐
         │              │   Name Exists?   │◄──┐
         │              └────────┬─────────┘   │
         ▼                       ▼             │
┌──────────────────┐    ┌──────────────────┐   │
│   Handle File    │    │   Create Client  │   │
│   Uploads        │    │   Record         │   │
└────────┬─────────┘    └────────┬─────────┘   │
         ▼                       ▼             │
┌──────────────────┐    ┌──────────────────┐   │
│   Set Store      │    │   Create Tree    │   │
│   Permissions    │    │   Element        │   │
└────────┬─────────┘    └────────┬─────────┘   │
         ▼                       ▼             │
┌──────────────────┐    ┌──────────────────┐   │
│   Assign Client  │    │   Create Daily   │   │
│   Types          │    │   Entry          │   │
└────────┬─────────┘    └────────┬─────────┘   │
         ▼                       ▼             │
┌──────────────────┐    ┌──────────────────┐   │
│   Handle         │    │   Insert Debt    │   │
│   Insurance      │    │   Change         │   │
└────────┬─────────┘    └────────┬─────────┘   │
         ▼                       ▼             │
┌──────────────────┐    ┌──────────────────┐   │
│   Success        │    │   Handle         │   │
│   Response       │    │   E-Settings     │   │
└──────────────────┘    └──────────────────┘   │
                                               │
                        ┌──────────────────┐   │
                        │   Error:         │───┘
                        │   Duplicate Name │
                        └──────────────────┘
```

### Email Verification Workflow
```
┌──────────────────┐
│   Client         │
│   Requests OTP   │
└────────┬─────────┘
         ▼
┌──────────────────┐    ┌──────────────────┐
│   Check Email    │───▶│   Generate       │
│   Exists         │    │   4-digit OTP    │
└──────────────────┘    └────────┬─────────┘
         │                       ▼
         ▼              ┌──────────────────┐
┌──────────────────┐    │   Store OTP      │
│   Email Error    │    │   With Expiry    │
└──────────────────┘    └────────┬─────────┘
                                 ▼
                        ┌──────────────────┐
                        │   Send Email     │
                        │   via PHPMailer  │
                        └────────┬─────────┘
                                 ▼
                        ┌──────────────────┐
                        │   Return OTP     │
                        │   to Frontend    │
                        └────────┬─────────┘
                                 ▼
                        ┌──────────────────┐
                        │   User Enters    │
                        │   OTP Code       │
                        └────────┬─────────┘
                                 ▼
                        ┌──────────────────┐
                        │   Verify OTP     │
                        │   and Expiry     │
                        └────────┬─────────┘
                                 ▼
                        ┌──────────────────┐
                        │   Mark Email     │
                        │   Verified       │
                        └──────────────────┘
```

### Client Deletion Workflow
```
┌──────────────────┐
│   Select Client  │
│   For Deletion   │
└────────┬─────────┘
         ▼
┌──────────────────┐    ┌──────────────────┐
│   Validate       │───▶│   Check for      │
│   Client ID      │    │   Existing Bills │
└──────────────────┘    └────────┬─────────┘
                                 ▼
                        ┌──────────────────┐
                        │   Has Bills?     │◄──┐
                        └────────┬─────────┘   │
                                 ▼             │
                        ┌──────────────────┐   │
                        │   Reverse Daily  │   │
                        │   Entry          │   │
                        └────────┬─────────┘   │
                                 ▼             │
                        ┌──────────────────┐   │
                        │   Delete Tree    │   │
                        │   Element        │   │
                        └────────┬─────────┘   │
                                 ▼             │
                        ┌──────────────────┐   │
                        │   Delete         │   │
                        │   Related Data   │   │
                        └────────┬─────────┘   │
                                 ▼             │
                        ┌──────────────────┐   │
                        │   Delete Client  │   │
                        │   Record         │   │
                        └────────┬─────────┘   │
                                 ▼             │
                        ┌──────────────────┐   │
                        │   Success        │   │
                        │   Response       │   │
                        └──────────────────┘   │
                                               │
                        ┌──────────────────┐   │
                        │   Error: Cannot  │───┘
                        │   Delete Client  │
                        └──────────────────┘
```

---

## 🌐 URL Routes & Actions

| Route | Action | Purpose | Authentication |
|-------|--------|---------|----------------|
| `clientController.php` | Default (empty do) | Show add client form | Required |
| `?do=add` | `add()` | Process client creation | Required |
| `?do=addSimpleReturn` | `add()` | Create client for supplier linking | None |
| `?do=addexcel` | N/A | Show Excel upload form | Required |
| `?do=addfromexcel` | `addFromExcel()` | Process Excel import | Required |
| `?do=show` | `show()` | Display client list | Required |
| `?do=showByType` | `showByType()` | Show clients grouped by type | Required |
| `?do=edit&id={id}` | `edit()` | Show edit client form | Required |
| `?do=update` | `update()` | Process client update | Required |
| `?do=deleteFinaly&id={id}` | `deleteFinaly()` | Delete client permanently | Required |
| `?do=tempdelete&id={id}` | `tempdelete()` | Hide client (soft delete) | Required |
| `?do=returndelete&id={id}` | `returndelete()` | Restore hidden client | Required |
| `?do=executeOperation` | `executeOperation()` | Batch operations | Required |
| `?do=editprint&id={id}` | `edit()` | Show printable edit form | Required |
| `?do=printdatail&id={id}` | N/A | Print client details | Required |
| `?do=downloadphone` | N/A | Export phone numbers | Permission Required |
| `?do=sendEmailOtp` | `generateAndSendEmailOtp()` | Send OTP email | None |
| `?do=verifyEmailOtp` | `verifyEmailOtp()` | Verify OTP code | None |
| `?do=success` | N/A | Show success message | None |
| `?do=error` | N/A | Show error message | None |

### CURL Support
Most actions support CURL requests by setting `$_POST['curlpost'] = 1`:
- Returns JSON responses with status codes
- Includes error details and validation messages
- Supports both Arabic and English responses
- Returns created client data on successful add operations

---

## 🐛 Known Issues & Fixes

### 1. **Client Name Validation**
**Issue**: Duplicate client names not properly checked across all scenarios  
**Fix**: Comprehensive name validation with trim and case handling

**Code Fix**:
```php
$checkName = $clientDAO->queryByClientname(trim($clientname));
if (!empty($checkName)) {
    return -1; // Duplicate found
}
```

### 2. **File Upload Security**
**Issue**: File uploads need validation and security checks  
**Fix**: Implement proper file validation and sanitization

**Code Fix**:
```php
$handle = new upload($_FILES['file']);
$file = uploadImageswhioutresize($handle, '../upload/clientFile');
// Add file type and size validation
```

### 3. **Email OTP Security**
**Issue**: OTP codes could be predictable  
**Fix**: Use cryptographically secure random number generation

**Code Fix**:
```php
$otp = random_int(1000, 9999); // Instead of rand()
```

### 4. **Transaction Safety in Excel Import**
**Issue**: Partial imports could leave database in inconsistent state  
**Fix**: Proper transaction handling with rollback

**Code Fix**:
```php
$mytransactions = new Transaction();
try {
    // Import logic
    $mytransactions->commit();
} catch (Exception $e) {
    $mytransactions->rollback();
    throw $e;
}
```

---

## 🔒 Security & Permissions

### Authentication Requirements
- All operations require valid user session (except OTP operations)
- Authentication checked via `../public/authentication.php`
- User ID tracked in all database operations
- Special permission check for phone download functionality

### Data Validation
- Client name validation (required, uniqueness check)
- Email format validation for OTP operations
- Phone number format validation
- Debt amount validation (numeric, proper formatting)
- File upload type and size validation

### SQL Injection Prevention
- Uses DAO pattern with prepared statements
- RedBean ORM for additional query safety
- Parameter binding for all database operations
- Input sanitization for all user data

### Permission Controls
```php
$groupData = $userGroupDAO->load($_SESSION['usergroupid']);
if ($groupData->downloadClientPhones != 1) {
    header("location:login.php?do=en");
    exit();
}
```

---

## 🧪 Testing & Debugging

### Test Cases

#### Client Creation
1. **Valid Client Creation**
   - Input: Complete client data with valid email
   - Expected: Client created, tree element added, debt change recorded
   
2. **Duplicate Client Name**
   - Input: Existing client name
   - Expected: Returns -1, shows error message
   
3. **File Upload Test**
   - Input: Client with document uploads
   - Expected: Files saved, paths stored in database

#### Email Verification
1. **Valid Email OTP Generation**
   - Input: Valid client ID with email
   - Expected: OTP generated, email sent, database updated
   
2. **Invalid Email**
   - Input: Client ID without email
   - Expected: Error response about missing email
   
3. **OTP Verification**
   - Input: Valid OTP within time limit
   - Expected: Email marked as verified, OTP cleared

#### Bulk Operations
1. **Excel Import**
   - Input: Valid Excel file with client data
   - Expected: All valid clients created, duplicates skipped
   
2. **Batch Hide/Restore**
   - Input: Multiple client IDs for operation
   - Expected: All selected clients processed, results displayed

### Debugging Tips

1. **Check Client Dependencies**:
```sql
SELECT COUNT(*) FROM sellbill WHERE sellbillclientid = ? AND conditions = 0
```

2. **Verify Tree Integration**:
```sql
SELECT * FROM accountstree WHERE id IN (SELECT treeId FROM client WHERE clientid = ?)
```

3. **Monitor Debt Changes**:
```sql
SELECT * FROM clientdebtchange WHERE clientid = ? ORDER BY clientdebtchangedate DESC
```

4. **Debug File Uploads**:
```php
error_log("File upload result: " . print_r($_FILES, true));
```

---

## ⚡ Performance Considerations

### Query Optimization
- **Client List**: Implement pagination for large datasets
- **Type Filtering**: Use proper indexes on typeclientid
- **Debt Calculations**: Consider caching debt summaries
- **File Operations**: Optimize file storage and retrieval

### Indexing Recommendations
```sql
-- Client table indexes
CREATE INDEX idx_client_name ON client(clientname);
CREATE INDEX idx_client_conditions ON client(conditions);
CREATE INDEX idx_client_area ON client(clientareaid);
CREATE INDEX idx_client_type ON client(typeclientid);
CREATE INDEX idx_client_email ON client(txtemail);

-- Debt change indexes
CREATE INDEX idx_clientdebt_client ON clientdebtchange(clientid);
CREATE INDEX idx_clientdebt_date ON clientdebtchange(clientdebtchangedate);
```

### Memory Management
- Stream large Excel files instead of loading entirely
- Use result set pagination for client lists
- Optimize image resizing and storage
- Implement proper session management

### Caching Strategy
- Cache client type lists and area hierarchies
- Store calculated debt totals temporarily
- Cache email templates for OTP
- Use session caching for user permissions

---

## 📚 Related Documentation

- [Sell Bill Controller](sellbillController.md) - Sales operations to clients
- [Supplier Controller](supplierController.md) - Supplier-client linking
- [Buy Bill Controller](buyBillController.md) - Purchase-related operations
- [Daily Entry Controller](#) - Client accounting entries
- [Client Debt Change Controller](#) - Debt tracking details
- [Email System Configuration](#) - PHPMailer and OTP setup
- [File Upload Management](#) - File handling and security
- [Excel Import/Export](#) - Bulk operations documentation

---

**Last Updated**: December 19, 2024  
**Version**: 1.0  
**Maintainer**: ERP Development Team