# Executors Controller Documentation

**File**: `/controllers/executors.php`  
**Purpose**: Manage sales bill execution assignments and multi-user task delegation system  
**Last Updated**: December 20, 2024  
**Total Functions**: 8+  
**Lines of Code**: ~285

---

## 📋 Overview

The Executors Controller manages a sophisticated sales bill execution and task delegation system. It enables assignment of multiple users to handle specific sales bills and tracks execution responsibilities across the organization. This system provides accountability, task distribution, and execution tracking for sales operations.

### Key Capabilities
- Sales bill execution assignment to multiple users
- Task delegation and responsibility tracking
- Multi-user assignment with comma-separated user lists
- Client-based filtering and sales bill selection
- Execution history tracking and audit trails
- RedBean ORM integration for efficient data management
- Ajax-powered search and filtering capabilities

### Primary Functions
- [x] Assign multiple users to execute specific sales bills
- [x] Track execution assignments and responsibilities
- [x] Support client-based filtering for relevant sales bills
- [x] Provide Ajax-powered search for clients, users, and sales bills
- [x] Maintain execution history and audit trails
- [x] Enable assignment editing and management
- [x] Support soft delete for execution records
- [x] DataTables integration for advanced listing

### Related Controllers
- [sellbillController.php](sellbillController.md) - Sales bill management
- [clientController.php](clientController.md) - Client management
- [userController.php](userController.md) - User management
- [executorsreport.php](executorsreport.md) - Execution reporting

---

## 🗄️ Database Tables

### Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **executors** | Main execution assignments | id, executorsclientid, executorssellid, executorsuserids, executorsdate, userid, today, del |
| **executorsusers** | Individual user assignments | id, executorsid, executorsuserid, today, del |

### Referenced Tables (Relations)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **client** | Customer information | clientid, clientname, conditions |
| **sellbill** | Sales bills | sellbillid, sellbillclientid, sellbilldate, sellbillfinalbill, datestarting, conditions |
| **user** | System users | userid, employeename, conditions |

---

## 🔑 Key Functions

### 1. **add** - Create Execution Assignment
**Location**: Line 51-78  
**Purpose**: Create new sales bill execution assignment with multiple user delegation

**Function Signature**:
```php
// Action: do=add
// POST Parameters:
$executorsclientid = filter_input(INPUT_POST, 'executorsclientid');
$executorssellid = filter_input(INPUT_POST, 'executorssellid');
$executorsuserids = explode(',', $_POST['executorsuserids']);
```

**Process Flow**:
1. **Create Main Execution Record**:
   ```php
   $executors = R::dispense('executors');
   $executors->del = 0;
   $executors->today = $today;          
   $executors->executorsclientid = $executorsclientid;
   $executors->executorssellid = $executorssellid;
   $executors->executorsuserids = $_POST['executorsuserids']; // Comma-separated
   $executors->userid = $userid;
   $executors->executorsdate = date("Y-m-d");
   ```

2. **Store Main Record**:
   ```php
   $executorsid = R::store($executors);
   ```

3. **Create Individual User Assignments**:
   ```php
   for ($i = 0; $i <= count($executorsuserids); $i++) {
       $executorsuserid = $executorsuserids[$i];
       if (!$executorsuserid) {continue;}
           $executorsusergroup = R::dispense('executorsusers');
           $executorsusergroup->del = 0;
           $executorsusergroup->today = $today;  
           $executorsusergroup->executorsid = $executorsid;
           $executorsusergroup->executorsuserid = $executorsuserid;
           R::store($executorsusergroup);   
   }
   ```

**Features**:
- Multi-user assignment capability
- Automatic relationship creation
- Audit trail with timestamps
- Redundant storage (comma-separated and relational)

---

### 2. **update** - Modify Execution Assignment
**Location**: Line 79-111  
**Purpose**: Update existing execution assignment with user list management

**Function Signature**:
```php
// Action: do=update
// POST Parameters:
$id = filter_input(INPUT_POST, 'id');
$executorsuserids = explode(',', $_POST['executorsuserids']);
```

**Process Flow**:
1. **Update Main Record**:
   ```php
   $executors = R::load('executors',$id);
   $executors->executorsclientid = $executorsclientid;
   $executors->executorssellid = $executorssellid;
   $executors->executorsuserids = $_POST['executorsuserids'];
   R::store($executors);
   ```

2. **Manage User Assignment Changes**:
   ```php
   $executorsusers = R::findAll('executorsusers', 'executorsid = ? ',[$id]);
   foreach ($executorsusers as $value) {
       if (!in_array($value->executorsid, $executorsuserids)) {
           R::exec("DELETE FROM `executorsusers` WHERE id = $value->id ");
       }
   }
   ```

3. **Add New User Assignments**:
   ```php
   for ($i = 0; $i <= count($executorsuserids); $i++) {
       $executorsuserid = $executorsuserids[$i];
       $count = R::count('executorsusers', 'executorsid = ? and executorsuserid = ?', [$id, $executorsuserid]);
       if (!$executorsuserid || $count > 0) {continue;}
           $executorsusergroup = R::dispense('executorsusers');
           $executorsusergroup->del = 0;
           $executorsusergroup->today = $today;  
           $executorsusergroup->executorsid = $id;
           $executorsusergroup->executorsuserid = $executorsuserid;
           R::store($executorsusergroup);   
   }
   ```

**Features**:
- Intelligent user list synchronization
- Prevents duplicate assignments
- Maintains relationship integrity
- Handles user removal and addition

---

### 3. **del** - Soft Delete Execution Assignment
**Location**: Line 29-42  
**Purpose**: Soft delete execution assignment while preserving audit trail

**Implementation**:
```php
$id = filter_input(INPUT_POST, 'id');  
$tasks = R::load('executors', $id);
$tasks->del = 1;
$tasks->useriddel = $userid;
$tasks->todaydel = $today;
try {
    R::store($tasks);   
    echo 1;
} catch (Exception $e) {
    echo 0;
}
```

**Features**:
- Preserves execution history
- Tracks deletion user and timestamp
- Ajax response for frontend integration
- Exception handling

---

### 4. **showajax** - DataTables Integration
**Location**: Line 170-278  
**Purpose**: Provide paginated, searchable, and sortable execution listing

**Function Signature**:
```php
function showajax()
// POST Parameters for DataTables:
$start_date, $end_date, $data1 (client), $data2 (user), $data3 (executor user), $data4 (sellbill)
```

**Query Building**:
```php
$searchQuery = " ";
if($data1 != ''){
  $searchQuery .=  " and executors.executorsclientid = ".$data1. " ";
}
if($data2 != ''){
   $searchQuery .= " and executors.userid = ".$data2. " ";
}
if($data3 != ''){
   $searchQuery .= " and executorsusers.executorsuserid = ".$data3. " ";
   $searchjoin .= " LEFT JOIN executorsusers ON executorsusers.executorsid = executors.id  ";
}
if($data4 != ''){
   $searchQuery .= " and executors.executorssellid = ".$data4. " ";
}
```

**Response Format**:
```php
foreach ($rResult as $row) {
    $users = R::getAll('select * from user where userid in  ('.$row["executorsuserids"] .')');
    $usertext = '';
    foreach($users as $user){
       $usertext .= $user['employeename'] . '/';
    }
    $sub_array = array();
    $sub_array[] = $row["id"];
    $sub_array[] = $row["clientname"];
    $sub_array[] = $usertext;
    $sub_array[] = $row["sellbilldate"] . '  / ' . $row["sellbillfinalbill"];
    $sub_array[] = $row["datestarting"];
    // ... additional columns
}
```

---

### 5. **Ajax Search Functions**

**select2client()** - Client Search:
```php
function select2client() {
    $name = $_POST['searchTerm'];
    $productsData = R::getAll("SELECT clientid, clientname as name
        FROM client 
        WHERE conditions = 0 and clientname LIKE '%" . $name . "%'  limit 50");
    
    foreach ($productsData as $pro) {
        $row_array['id'] = $pro['clientid'];
        $row_array['text'] = $pro['name'];
        array_push($return_arr, $row_array);
    }
    echo json_encode($return_arr);
}
```

**select2user()** - User Search:
```php
function select2user() {
    $name = $_POST['searchTerm'];
    $productsData = R::getAll("SELECT userid, employeename as name
        FROM user 
        WHERE conditions = 0 and employeename LIKE '%" . $name . "%'  limit 50");
    // Similar structure to client search
}
```

**select2sellbill()** - Sales Bill Search:
```php
function select2sellbill() {
    $name = $_POST['searchTerm'];
    $clientid = $_POST['clientid'];
    
    $productsData = R::getAll("SELECT sellbillid, CONCAT(sellbillid,'/',datestarting) as texts
        FROM sellbill 
        WHERE conditions = 0 and CONCAT(sellbillid,'/',datestarting) LIKE '%" . $name . "%' 
        and sellbill.sellbillclientid = $clientid limit 50");
}
```

---

## 🔄 Workflows

### Workflow 1: Sales Bill Execution Assignment
```
┌─────────────────────────────────────────────────────────────┐
│           START: Create Execution Assignment                │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Select Client                                           │
│     - Use Ajax search to find client                       │
│     - Select relevant customer                              │
│     - Load client's sales bills                            │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Select Sales Bill                                       │
│     - Choose from client's sales bills                     │
│     - View bill amount and date information                │
│     - Confirm bill requires execution                      │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Assign Multiple Users                                   │
│     - Select users responsible for execution               │
│     - Build comma-separated user list                      │
│     - Define execution responsibilities                     │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Create Execution Records                                │
│     - Insert main executors record                         │
│     - Create individual executorsusers records             │
│     - Set execution date and audit fields                  │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  5. Track and Monitor                                       │
│     - Record appears in execution listings                 │
│     - Users can view their assigned executions             │
│     - Management can track execution progress              │
└─────────────────────────────────────────────────────────────┘
```

---

### Workflow 2: Execution Assignment Update
```
┌─────────────────────────────────────────────────────────────┐
│              START: Modify Execution Assignment             │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Load Existing Assignment                                │
│     - Retrieve execution record by ID                      │
│     - Load current client and sales bill information       │
│     - Display current user assignments                     │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Modify Assignments                                      │
│     - Update client if needed                               │
│     - Change sales bill if applicable                      │
│     - Modify user assignment list                          │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Synchronize User Relationships                         │
│     - Identify removed users                               │
│     - Delete obsolete executorsusers records               │
│     - Add new user assignments                             │
│     - Prevent duplicate assignments                        │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Update Main Record                                      │
│     - Save updated comma-separated user list               │
│     - Maintain audit trail                                 │
│     - Preserve execution history                           │
└─────────────────────────────────────────────────────────────┘
```

---

## 🌐 URL Routes & Actions

| URL Parameter | Function Called | Description | Ajax |
|---------------|----------------|-------------|------|
| (empty) | Default display | Show execution assignment form | No |
| `do=show` | Show listing | Display execution management interface | No |
| `do=edit` | Edit form | Show execution assignment edit form | No |
| `do=add` | `add()` | Create new execution assignment | No |
| `do=update` | `update()` | Update existing assignment | No |
| `do=del` | `del()` | Soft delete execution assignment | Yes |
| `do=select2client` | `select2client()` | Ajax client search | Yes |
| `do=select2user` | `select2user()` | Ajax user search | Yes |
| `do=select2sellbill` | `select2sellbill()` | Ajax sales bill search | Yes |
| `do=showajax` | `showajax()` | DataTables data provider | Yes |

### Required Parameters by Action

**Create Assignment** (`do=add`):
- `executorsclientid` - Client ID (required)
- `executorssellid` - Sales bill ID (required)
- `executorsuserids` - Comma-separated user IDs (required)

**Update Assignment** (`do=update`):
- `id` - Execution ID (required)
- `executorsclientid` - Updated client ID
- `executorssellid` - Updated sales bill ID
- `executorsuserids` - Updated user assignments

**Ajax Search Operations**:
- `select2client`: `searchTerm` - Client name search
- `select2user`: `searchTerm` - User name search  
- `select2sellbill`: `searchTerm` - Bill search, `clientid` - Client filter

**DataTables** (`showajax`):
- Standard DataTables parameters (draw, start, length, search, order)
- `fromdate`, `todate` - Date range filter
- `data1` - Client filter
- `data2` - Creating user filter
- `data3` - Executor user filter
- `data4` - Sales bill filter

---

## 🔒 Security & Permissions

### Session-Based Security
```php
$userid = $_SESSION['userid'];
```
- All operations track the creating user
- Session-based user identification
- User context maintained throughout

### Input Validation
```php
$id = filter_input(INPUT_POST, 'id');
$executorsclientid = filter_input(INPUT_POST, 'executorsclientid');
$executorssellid = filter_input(INPUT_POST, 'executorssellid');
```

**Security Features**:
- Input filtering on all parameters
- RedBean ORM provides SQL injection protection
- Soft delete preserves audit trails
- User tracking for all operations

### Data Access Control
- Users can view executions assigned to them
- Management can view all executions
- Client-based filtering ensures relevance
- Branch/department filtering could be added

---

## 🐛 Common Issues & Troubleshooting

### 1. **User Assignment Synchronization Issues**
**Issue**: Orphaned executorsusers records after updates  
**Cause**: Incomplete cleanup during user list updates

**Debug Query**:
```sql
-- Find orphaned user assignments
SELECT eu.id, eu.executorsid, eu.executorsuserid 
FROM executorsusers eu 
LEFT JOIN executors e ON eu.executorsid = e.id 
WHERE e.id IS NULL OR e.del = 1;
```

**Prevention**: Enhance update logic with transaction support

### 2. **Comma-Separated User List Issues**
**Issue**: Invalid user IDs in comma-separated string  
**Solution**: Add validation:
```php
function validateUserList($userIds) {
    $ids = explode(',', $userIds);
    $validIds = array();
    foreach($ids as $id) {
        $user = R::load('user', trim($id));
        if($user->id && $user->conditions == 0) {
            $validIds[] = $user->id;
        }
    }
    return implode(',', $validIds);
}
```

### 3. **Sales Bill Availability Issues**
**Issue**: Assigned sales bills that are cancelled or completed  
**Enhancement**: Add bill status checking:
```sql
SELECT sellbillid, datestarting, conditions, status 
FROM sellbill 
WHERE sellbillclientid = ? 
  AND conditions = 0 
  AND status NOT IN ('completed', 'cancelled')
```

### 4. **Performance Issues with Large Datasets**
**Issue**: Slow loading of execution listings  
**Solutions**:
- Implement proper indexing on foreign keys
- Add pagination limits
- Optimize JOIN queries in showajax()

---

## 📊 Performance Considerations

### Database Optimization
1. **Essential Indexes**:
   ```sql
   -- Executors table
   CREATE INDEX idx_executors_client ON executors(executorsclientid, del);
   CREATE INDEX idx_executors_sellbill ON executors(executorssellid, del);
   CREATE INDEX idx_executors_date ON executors(executorsdate, del);
   CREATE INDEX idx_executors_user ON executors(userid, del);
   
   -- Executorsusers table
   CREATE INDEX idx_executorsusers_executor ON executorsusers(executorsid, del);
   CREATE INDEX idx_executorsusers_user ON executorsusers(executorsuserid, del);
   
   -- Related tables
   CREATE INDEX idx_client_conditions ON client(conditions);
   CREATE INDEX idx_sellbill_client_conditions ON sellbill(sellbillclientid, conditions);
   CREATE INDEX idx_user_conditions ON user(conditions);
   ```

2. **Query Optimization**:
   - Use prepared statements for repeated queries
   - Limit search results (currently 50 records)
   - Optimize JOIN conditions in DataTables queries

### Memory Management
- Efficient handling of user assignment arrays
- Proper cleanup of temporary variables
- Optimized JSON response generation

### Ajax Performance
- Implement result caching for static data
- Use debouncing on search inputs
- Optimize DataTables server-side processing

---

## 🧪 Testing Scenarios

### Test Case 1: Execution Assignment Creation
```
1. Create assignment with single user
2. Create assignment with multiple users
3. Verify executorsusers records created correctly
4. Test with invalid client/bill/user IDs
5. Check audit trail fields populated
```

### Test Case 2: Assignment Updates
```
1. Update assignment with user additions
2. Update assignment with user removals
3. Test mixed user changes (add/remove)
4. Verify no duplicate user assignments
5. Check orphaned record cleanup
```

### Test Case 3: Ajax Search Functionality
```
1. Test client search with partial names
2. Test user search with various criteria
3. Test sales bill search with client filtering
4. Verify result limiting works (50 records)
5. Check response format compatibility with Select2
```

### Test Case 4: DataTables Integration
```
1. Test pagination with large datasets
2. Verify search functionality across columns
3. Test sorting on different columns
4. Check filtering by date ranges and entities
5. Validate delete operations from listing
```

---

## 📚 Related Documentation

- [CLAUDE.md](/Applications/AMPPS/www/erp19/CLAUDE.md) - PHP 8.2 migration guide
- [sellbillController.md](sellbillController.md) - Sales bill management
- [clientController.md](clientController.md) - Client management
- [executorsreport.md](executorsreport.md) - Execution reporting

---

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