# Employee Attendance Controller Documentation

**File**: `/controllers/employeeAttendance.php`  
**Purpose**: Handles real-time employee attendance tracking with biometric integration and photo capture  
**Last Updated**: December 20, 2024  
**Total Functions**: 4+  
**Lines of Code**: ~417

---

## 📋 Overview

The Employee Attendance Controller is a real-time attendance tracking system that provides biometric-enabled employee check-in/check-out functionality. It handles:
- Real-time attendance recording via webcam photo capture
- Biometric integration (fingerprint and RFID)
- Daily attendance history management
- Image processing with timestamp watermarking
- Cross-origin API support for external devices
- Automated daily attendance initialization
- Employee attendance reporting with filtering
- JSON API responses for mobile/external systems

### Primary Functions
- [x] Real-time attendance capture with photo verification
- [x] Biometric authentication (fingerprint/RFID)
- [x] Daily attendance history tracking
- [x] Image watermarking with timestamps
- [x] Cross-origin API compatibility
- [x] Automated daily attendance setup
- [x] Attendance report generation
- [x] Transaction-safe operations
- [x] Employee group status tracking
- [x] Branch-based filtering

### Related Controllers
- [employeeAttendanceSystems.php](employeeAttendanceSystems.md) - Attendance system configuration
- [EmployeeAttendanceExcelController.php](EmployeeAttendanceExcelController.md) - Excel import/export
- [employeePersonalajex.php](employeePersonalajex.md) - Employee personal operations
- [employeeController.php](employeeController.md) - Employee management

---

## 🗄️ Database Tables

### Primary Tables (Direct Operations)
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **employeeattendance** | Individual attendance logs | employeeattendanceid, empid, theImage, sysdate, fingerid, rfid, accessType, syncToServer |
| **employeeclosedayhistory** | Daily attendance summaries | id, employeeid, day, attendanceTime, departureTime, isAbsent, absentHasPermission, status |
| **employee** | Employee master data | employeeId, empCode, employeeName, employeesubgroupid, employeegroupid, branchid |

### Attendance System Tables
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **employeesubgroup** | Employee sub-group organization | employeesubgroupid, name, employeegroupid |
| **employeegroup** | Employee group organization | employeegroupid, name |
| **employeeclosedaygroupstatus** | Group closure tracking | day, employeegroupid, status |
| **employeeclosedaysubgroupstatus** | Sub-group closure tracking | day, employeesubgroupid, status |
| **employeeclosedaystatus** | Daily closure status | day, status |

### Reference Tables
| Table Name | Purpose | Key Columns |
|------------|---------|-------------|
| **youtubelink** | Tutorial links | youtubelinkid, title, url |
| **user** | System users | userid, username |

---

## 🔑 Key Functions

### 1. **Default Action / add()** - Real-Time Attendance Recording
**Location**: Line 134  
**Purpose**: Record employee attendance via webcam with photo capture and timestamp watermarking

**Function Signature**:
```php
// Triggered when: do=add or empty $do
$empid = (int) filter_input(INPUT_GET, 'empid');
$testdate = $_GET['testdate']; // Optional test mode
```

**Process Flow**:
1. Initialize daily attendance records if first of day
2. Capture and process webcam image
3. Add timestamp watermark to image
4. Record attendance log in database
5. Update daily attendance history
6. Return JSON response with success/failure

**Key Features**:
- **Photo Verification**: Saves webcam capture with timestamp
- **Image Processing**: Adds date/time watermark using GD library
- **Transaction Safety**: Rollback on any failure
- **Cross-Origin Support**: CORS headers for API access
- **Daily Initialization**: Auto-creates daily attendance records

**Image Processing Code**:
```php
$filename = time() . '.jpg';
$filepath = '../upload/employeeAttendance/';
move_uploaded_file($_FILES['webcam']['tmp_name'], $filepath . $filename);
$img = imagecreatefromjpeg($filepath . $filename);

$white = imagecolorallocate($img, 255, 0, 255);
$txt = $sysdate;
$font = "arial.ttf";
imagettftext($img, 24, 0, 5, 24, $white, $font, $txt);
imagejpeg($img, $filepath . $filename, 100);
imagedestroy($img);
```

---

### 2. **saveaccesslog()** - Biometric Attendance Recording
**Location**: Line 267  
**Purpose**: Process bulk attendance logs from biometric devices (fingerprint/RFID)

**Function Signature**:
```php
// Triggered when: do=saveaccesslog
$accessLogArr = json_decode($_POST['data_arr']);
```

**Process Flow**:
1. Parse JSON array of attendance logs
2. For each log:
   - Identify employee by fingerprint ID or RFID
   - Process base64 image if provided
   - Add timestamp watermark to image
   - Record attendance in database
   - Update daily history
3. Return comma-separated list of processed IDs

**Biometric Integration**:
```php
if ($log->accessType == 0) { // Fingerprint
    $empid = (int) $employeeEX->getEmpIdWithFingerId($log->fingerid);
} else { // RFID
    $empid = (int) $employeeEX->getEmpIdWithRFID($log->rfid);
}
```

**Image Processing for Base64**:
```php
$success = file_put_contents($filepath . $filename, base64_decode($log->theImage_base64));
$img = imagecreatefrompng($filepath . $filename);
// Add watermark and save
imagepng($img, $filepath . $filename, 0);
```

---

### 3. **attendanceReport()** - Attendance Report Generation
**Location**: Line 372  
**Purpose**: Generate filtered attendance reports with employee and date filtering

**Function Signature**:
```php
// Triggered when: do=attendanceReport
$empid = (int) filter_input(INPUT_POST, 'empid');
$from = filter_input(INPUT_POST, 'from');
$to = filter_input(INPUT_POST, 'to');
```

**Process Flow**:
1. Load all employees for dropdown (branch filtered)
2. Build query string with filters:
   - Employee ID filter
   - Date range filter
   - Branch filter if applicable
3. Query attendance records
4. Load YouTube tutorial links
5. Display via Smarty template

**Query Building**:
```php
if ($_SESSION['branchId'] > 0)
    $queryString .= ' AND  branchid = ' . $_SESSION['branchId'];

if ($empid > 0) {
    $queryString .= " and empid = $empid ";
}
if ($from != '') {
    $queryString .= " and date(employeeattendance.sysdate) >= '" . $from . "' ";
}
if ($to != '') {
    $queryString .= " and date(employeeattendance.sysdate) <= '" . $to . "' ";
}
```

---

### 4. **Daily Attendance Initialization** - Automated Setup
**Location**: Lines 143-145, 288-290  
**Purpose**: Automatically create daily attendance records for all active employees

**Function Logic**:
```php
if ((int) $employeeCloseDayHistoryEX->dayAttendanceCount($day) == 0) {
    $employeeCloseDayHistoryEX->beginDayAttendance($day, $sysdate, 1);
}
```

**Features**:
- Runs on first attendance of each day
- Creates records for all active employees
- Prevents duplicate daily records
- Initializes attendance/departure times to "00:00:00"

---

## 🔄 Workflows

### Workflow 1: Real-Time Attendance Capture
```
┌─────────────────────────────────────────────────────────────┐
│                START: Employee Check-in/out                │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Validate Employee ID                                    │
│     - Check empid parameter                                 │
│     - Verify employee exists and is active                  │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Initialize Daily Records (if first of day)             │
│     - Check if daily attendance count = 0                  │
│     - Create daily records for all employees               │
│     - Set default times to "00:00:00"                      │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Process Webcam Image                                    │
│     - Generate unique filename (timestamp.jpg)             │
│     - Save uploaded file to upload directory               │
│     - Load image using GD library                          │
│     - Add timestamp watermark                              │
│     - Save processed image                                  │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  4. Record Attendance Log                                   │
│     - Create employeeattendance record                     │
│     - Set empid, image filename, timestamp                 │
│     - Set accessType = 0 (manual entry)                    │
│     - Set syncToServer = 0                                 │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  5. Update Daily History                                    │
│     - Load existing daily history record                   │
│     - If attendanceTime = "00:00:00":                      │
│       └─→ Set attendanceTime = current time               │
│     - Else:                                                │
│       └─→ Set departureTime = current time                │
│     - Set isAbsent = 0, clear absence flags               │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  6. Return JSON Response                                    │
│     - Success: {"ststus": 1, "msg": "sucess", "image": url}│
│     - Employee not found: {"ststus": 2, "msg": "...", ...} │
│     - Error: {"ststus": 0, "msg": "error", "image": ''}   │
└─────────────────────────────────────────────────────────────┘
```

---

### Workflow 2: Biometric Device Integration
```
┌─────────────────────────────────────────────────────────────┐
│           START: Biometric Device Sync Request             │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Parse JSON Attendance Logs                             │
│     - Decode $_POST['data_arr']                            │
│     - Extract log entries array                            │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  2. Process Each Log Entry                                  │
│     FOR EACH log in logs array:                            │
│       │                                                     │
│       ├─→ Identify Employee                                │
│       │   ├─ If accessType = 0: use fingerprint ID        │
│       │   └─ If accessType = 1: use RFID                  │
│       │                                                     │
│       ├─→ Validate Employee Exists                         │
│       │   └─ Skip if empid = 0                             │
│       │                                                     │
│       ├─→ Process Image (if provided)                      │
│       │   ├─ Decode base64 image                           │
│       │   ├─ Save to file system                           │
│       │   ├─ Add timestamp watermark                       │
│       │   └─ Save processed PNG                            │
│       │                                                     │
│       ├─→ Record Attendance                                │
│       │   ├─ Insert employeeattendance record              │
│       │   └─ Set syncToServer = 1                          │
│       │                                                     │
│       ├─→ Update Daily History                             │
│       │   └─ Same logic as manual entry                    │
│       │                                                     │
│       └─→ Add log ID to success list                       │
└────────────────────┬────────────────────────────────────────┘
                     │
                     ▼
┌─────────────────────────────────────────────────────────────┐
│  3. Return Processed IDs                                    │
│     - Success: Return comma-separated success IDs          │
│     - Error: Return -1                                      │
└─────────────────────────────────────────────────────────────┘
```

---

## 🌐 URL Routes & Actions

| URL Parameter | Function Called | Description |
|---------------|----------------|-------------|
| `do=` (empty) or `do=add` | Default action | Real-time attendance capture |
| `do=saveaccesslog` | `saveaccesslog()` | Biometric device data sync |
| `do=attendanceReport` | `attendanceReport()` | Generate attendance reports |

### Required Parameters by Action

**Real-Time Attendance** (`do=add`):
- `empid` - Employee ID (integer)
- `webcam` - Uploaded image file ($_FILES)
- `testdate` - Optional: Override system date for testing

**Biometric Sync** (`do=saveaccesslog`):
- `data_arr` - JSON array of attendance logs (POST)

**Attendance Report** (`do=attendanceReport`):
- `empid` - Employee ID filter (optional, 0 = all)
- `from` - Start date filter (optional)
- `to` - End date filter (optional)

---

## 🧮 Calculation Methods

### Attendance Time Logic
```php
// Determine if this is arrival or departure
if ($employeeCloseDayHistory->attendanceTime == "00:00:00") {
    $employeeCloseDayHistory->attendanceTime = $time; // First check-in
} else {
    $employeeCloseDayHistory->departureTime = $time; // Check-out
}
```

### Image Filename Generation
```php
$filename = time() . '.jpg'; // Unique timestamp-based filename
$filepath = '../upload/employeeAttendance/';
```

### Biometric Employee Lookup
```php
// Fingerprint lookup
$empid = (int) $employeeEX->getEmpIdWithFingerId($log->fingerid);

// RFID lookup  
$empid = (int) $employeeEX->getEmpIdWithRFID($log->rfid);
```

---

## 🔒 Security & Permissions

### API Security
- **CORS Headers**: Allows cross-origin requests for mobile/device integration
- **Input Filtering**: Uses `filter_input()` for parameter validation
- **Transaction Safety**: Database rollback on any failure

### File Upload Security
- **Restricted Extensions**: Only .jpg images allowed for webcam
- **Unique Filenames**: Timestamp-based to prevent collisions
- **Directory Isolation**: Files stored in dedicated upload folder

### Authentication
- **Session Required**: User must be logged in for attendance reports
- **Branch Filtering**: Attendance data filtered by user's branch access

---

## 📊 Performance Considerations

### Image Processing Optimization
1. **File Size**: Images compressed with quality=100 for JPEG, 0 for PNG
2. **Memory Management**: `imagedestroy()` called to free memory
3. **File Cleanup**: No automatic cleanup of old attendance images

### Database Optimization
1. **Batch Operations**: `saveaccesslog()` processes multiple records in single transaction
2. **Efficient Queries**: Direct employee lookups by fingerprint/RFID
3. **Index Requirements**:
   - `employeeattendance(empid, sysdate)`
   - `employeeclosedayhistory(employeeid, day)`
   - `employee(employeeId, conditions)`

### Known Performance Issues
- **Daily Initialization**: First attendance of day creates records for ALL employees
- **Image Storage**: No automatic cleanup of attendance photos
- **No Pagination**: Attendance reports load all matching records

---

## 🐛 Common Issues & Troubleshooting

### 1. **Image Upload Failures**
**Issue**: Webcam upload fails or images not processed  
**Causes**:
- Missing upload directory permissions
- PHP upload_max_filesize too small
- GD library not installed

**Debug**:
```php
// Check upload errors
if ($_FILES['webcam']['error'] != UPLOAD_ERR_OK) {
    echo "Upload error: " . $_FILES['webcam']['error'];
}

// Verify GD library
if (!extension_loaded('gd')) {
    echo "GD library not installed";
}
```

### 2. **Biometric Device Not Syncing**
**Issue**: `saveaccesslog` returns -1 or no success IDs  
**Causes**:
- Invalid JSON in `data_arr`
- Employee not found by fingerprint/RFID
- Database transaction failure

**Debug**:
```php
$accessLogArr = json_decode($_POST['data_arr']);
if (json_last_error() != JSON_ERROR_NONE) {
    echo "JSON decode error: " . json_last_error_msg();
}
```

### 3. **Daily Records Not Initialized**
**Issue**: Attendance recording fails because no daily record exists  
**Cause**: `beginDayAttendance()` function failed

**Fix**:
```sql
-- Manual daily record creation
INSERT INTO employeeclosedayhistory (employeeid, day, attendanceTime, departureTime, isAbsent, del)
SELECT employeeId, CURDATE(), '00:00:00', '00:00:00', 1, 0
FROM employee 
WHERE conditions = 0;
```

### 4. **CORS Issues with External Devices**
**Issue**: Browser blocks cross-origin requests  
**Fix**: Verify headers are set correctly:
```php
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
```

---

## 🧪 Testing Scenarios

### Test Case 1: Manual Attendance Recording
```
1. Access: ?do=add&empid=1
2. Upload webcam image via form
3. Verify image saved with timestamp watermark
4. Check database record created
5. Confirm JSON response indicates success
6. Test second attendance (departure) for same employee/day
```

### Test Case 2: Biometric Device Integration
```
1. Prepare JSON payload with attendance logs
2. POST to ?do=saveaccesslog
3. Verify employee identification by fingerprint/RFID
4. Check image processing from base64
5. Confirm batch processing of multiple logs
6. Validate returned success ID list
```

### Test Case 3: Daily Initialization
```
1. Ensure no daily records exist for test date
2. Record first attendance of day
3. Verify all employee daily records created
4. Check attendance/departure times set to "00:00:00"
5. Confirm specific employee record updated correctly
```

### Test Case 4: Attendance Report
```
1. Create test attendance data for multiple employees/dates
2. Access report with no filters
3. Test employee-specific filtering
4. Test date range filtering
5. Verify branch filtering applies correctly
```

---

## 📚 Related Documentation

- [CLAUDE.md](/Applications/AMPPS/www/erp19/CLAUDE.md) - PHP 8.2 migration guide
- [employeeAttendanceSystems.md](employeeAttendanceSystems.md) - Attendance system configuration
- [EmployeeAttendanceExcelController.md](EmployeeAttendanceExcelController.md) - Excel integration
- [employeeController.md](employeeController.md) - Employee management

---

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