# Job Verification Flow Documentation

This document details how candidates clock in/out of jobs and how partners verify these actions, with code references and flow diagrams.

## System Overview

The job verification system involves three key components:

1. Candidate Interface (web/application/modules/candidate/*)
2. Partner Interface (web/application/modules/partner/*)
3. Database Layer (job_accepted_candidate and job_employee tables)

## Verification Methods

### 1. OTP Verification Flow

```ascii
Candidate Interface         System                    Partner Interface          Database
(job_list_ajax.php)    (Controllers)             (job_verification.php)     (Tables)
       │                    │                            │                      │
       │                    │                            │                      │
1)┌────┼────────────────┐  │                            │                      │
  │Show verification    │  │                            │                      │
  │buttons when:       │  │                            │                      │
  │- job_status=3/5   │  │                            │                      │
  │- within time      │  │                            │                      │
  └────┼────────────────┘  │                            │                      │
       │                    │                            │                      │
2)     ├─Request Entry OTP─>│                            │                      │
       │                    │                            │                      │
       │              ┌─────┼────────────┐               │                      │
       │              │get_entry_code(): │               │                      │
       │              │- Generate OTP    │               │                      │
       │              │- Create Job ID   │               │                      │
       │              └─────┼────────────┘               │                      │
       │                    │                            │                      │
       │                    ├─Store OTP/Job ID─────────────────────────────────>│
       │                    │                            │     (job_accepted_candidate)
       │                    │                            │                      │
3)     │<───Send via SMS/Email                          │                      │
       │                    │                            │                      │
4)     ├─Show to Partner────────────────────────────────>│                      │
       │                    │                            │                      │
       │                    │                      ┌─────┼──────────────┐      │
       │                    │                      │confirm_otp_by_     │      │
       │                    │                      │partner():          │      │
       │                    │                      │- Validate OTP      │      │
       │                    │                      │- Check time window │      │
       │                    │                      └─────┼──────────────┘      │
       │                    │                            │                      │
       │                    │                            ├─Record Entry────────>│
       │                    │                            │  (job_employee)      │
       │                    │                            │                      │
5)     │<───────────────────┼────────Confirm Entry──────┤                      │
       │                    │                            │                      │
```

Code References:
1) candidate/views/job_list_ajax.php:
   ```php
   if (($time['job_status'] == 3 || $time['job_status'] == 5) && $time['time_wise_show_flag'] == 1) {
       echo '<button class="get_entry_otp">Get Entry OTP</button>';
   }
   ```

2) candidate/controllers/job_verification.php:
   ```php
   public function get_entry_code() {
       $confirm_otp = rand(100000, 999999);
       $update_data = array(
           'entry_confirm_otp' => $confirm_otp,
           'entry_apply_otp_time' => time(),
       );
       $this->sql->update_data_record("job_accepted_candidate", $update_data);
   }
   ```

3) SMS/Email sending:
   ```php
   $confirm_message = "Job-ID for " . $job_title . " is " . $entry_jobid .
                     " and The Entry Job OTP is: " . $confirm_otp;
   smsSend($mobile_number, $confirm_message);
   $this->mail_send->job_verification(...);
   ```

4) partner/controllers/job_verification.php:
   ```php
   public function confirm_otp_by_partner() {
       $check_otp_valid = $this->verification->check_entry_otpvalid(
           $avilibility_id, $job_verifiy_otp, $candidate_id
       );
   }
   ```

5) Recording verification:
   ```php
   $this->sql->insert_data('job_employee', array(
       'approved_time' => time(),
       'entry_loaction' => $entry_loaction,
       'entry_verify_type' => 2, // OTP verification
   ));
   ```

### 2. QR Code Verification Flow

```ascii
Candidate Interface         System                    Partner Interface          Database
(job_list_ajax.php)    (Controllers)             (job_verification.php)     (Tables)
       │                    │                            │                      │
       │                    │                            │                      │
1)┌────┼────────────────┐  │                            │                      │
  │Show QR button when: │  │                            │                      │
  │- job_status=3/5    │  │                            │                      │
  │- within time       │  │                            │                      │
  └────┼────────────────┘  │                            │                      │
       │                    │                            │                      │
2)     ├─Request QR Code──>│                            │                      │
       │              ┌─────┼────────────┐               │                      │
       │              │get_entry_qrcode()│               │                      │
       │              │- Generate QR data│               │                      │
       │              │- Create QR image │               │                      │
       │              └─────┼────────────┘               │                      │
       │                    │                            │                      │
       │                    ├─Store QR data──────────────────────────────────>│
       │                    │                            │  (job_accepted_candidate)
       │                    │                            │                      │
3)     │<───Return QR Image─┤                            │                      │
       │                    │                            │                      │
4)     ├─Show QR to Partner─────────────────────────────>│                      │
       │                    │                            │                      │
       │                    │                      ┌─────┼──────────────┐      │
       │                    │                      │job_varify():       │      │
       │                    │                      │- Decrypt QR        │      │
       │                    │                      │- Validate data     │      │
       │                    │                      │- Check time window │      │
       │                    │                      └─────┼──────────────┘      │
       │                    │                            │                      │
       │                    │                            ├─Record Entry────────>│
       │                    │                            │  (job_employee)      │
5)     │<───────────────────┼────────Confirm Entry──────┤                      │
       │                    │                            │                      │
```

Code References:
1) candidate/views/job_list_ajax.php:
   ```php
   if (($time['job_status'] == 3 || $time['job_status'] == 5) && $time['time_wise_show_flag'] == 1) {
       echo '<button class="get_entry_qrcode">Get Entry QR Code</button>';
   }
   ```

2) candidate/controllers/job_verification.php:
   ```php
   public function get_entry_qrcode() {
       $entry_qr_link = base_url() . "partner/job-varify/" . key_encrypt(
           "entry_" . $master_id . "_" . $job_id . "_" .
           $job_avability_id . "_" . $partner_id . "_" .
           $confirm_qr . "_" . time()
       );
       $this->generate_qr_code($entry_qr_link, $save_name, $dir);
   }
   ```

3) QR Generation:
   ```php
   $params['data'] = $confirm_code;
   $params['level'] = 'L';
   $params['size'] = 10;
   $params['savename'] = FCPATH . $config['imagedir'] . $save_name;
   $this->ciqrcode->generate($params);
   ```

4) partner/controllers/job_verification.php:
   ```php
   public function job_varify($qrcode) {
       $qrcode = explode("_", key_decrypt($qrcode));
       $varify = $qrcode[0];      // entry/exit
       $candidate_id = $qrcode[1];
       $job_id = $qrcode[2];
   }
   ```

5) Recording verification:
   ```php
   $this->sql->insert_data('job_employee', array(
       'approved_time' => time(),
       'entry_loaction' => $entry_loaction,
       'entry_verify_type' => 3, // QR verification
   ));
   ```

### 3. Face ID Verification Flow

```ascii
Candidate Interface         System                    Partner Interface          Database
(job_list_ajax.php)    (Controllers)             (job_verification.php)     (Tables)
       │                    │                            │                      │
       │                    │                            │                      │
1)┌────┼────────────────┐  │                            │                      │
  │Show Face ID button  │  │                            │                      │
  │when:               │  │                            │                      │
  │- job_status=3/5    │  │                            │                      │
  │- within time       │  │                            │                      │
  │- has face enrolled │  │                            │                      │
  └────┼────────────────┘  │                            │                      │
       │                    │                            │                      │
2)     ├─Capture Face Image>│                            │                      │
       │              ┌─────┼────────────┐               │                      │
       │              │verify_entry_face()│              │                      │
       │              │- Verify time window│              │                      │
       │              │- Search face      │              │                      │
       │              │- Match user ID    │              │                      │
       │              └─────┼────────────┘               │                      │
       │                    │                            │                      │
3)     │                    ├─Record Entry───────────────────────────────────>│
       │                    │                            │  (job_employee)      │
       │                    │                            │                      │
4)     │<───Confirm Entry───┤                            │                      │
       │                    │                            │                      │
```

Code References:
1) candidate/views/job_list_ajax.php:
   ```php
   if (($time['job_status'] == 3 || $time['job_status'] == 5) && $time['time_wise_show_flag'] == 1) {
       // First check if user has face enrollment
       if (has_face_enrollment($candidate_id)) {
           echo '<button class="get_entry_face">' . $this->lang->line('verify_entry_with_face') . '</button>';
       }
       // Existing buttons remain
       echo '<button class="get_entry_otp">' . $this->lang->line('get_entry_otp') . '</button>';
       echo '<button class="get_entry_qrcode">' . $this->lang->line('get_entry_qr_code') . '</button>';
   }
   ```

2) candidate/controllers/job_verification.php:
   ```php
   public function verify_entry_face() {
       if (!$this->session->userdata(CANDIDATE_LOGGED_IN)) {
           return error_response($this->lang->line('not_logged_in'));
       }

       $job_id = $this->input->post('job_id');
       $job_avability_id = $this->input->post('job_avability_id');
       $image_data = $this->input->post('image');
       
       // 1. Verify time window
       $entry_exit_status = $this->verification->check_jobid_wise_exit_status($job_id);
       if (!validate_time_window($entry_exit_status)) {
           return error_response($this->lang->line('outside_verification_window'));
       }

       // 2. Verify face using existing recognition
       $recognized_user_id = $this->face->searchFaces($image_data);
       if ($recognized_user_id != $this->session->userdata(CANDIDATE_LOGGED_IN)['id']) {
           return error_response($this->lang->line('face_not_recognized'));
       }

       // 3. Record entry with face verification type
       $this->sql->insert_data('job_employee', array(
           'job_id' => $job_id,
           'job_avability_id' => $job_avability_id,
           'employee_id' => $recognized_user_id,
           'approved_time' => time(),
           'entry_loaction' => json_encode(get_location_data()),
           'entry_verify_type' => 5, // New type for face verification
           'status' => 1
       ));

       return success_response($this->lang->line('face_verification_successful'));
   }
   ```

3) Recording verification:
   ```php
   $this->sql->insert_data('job_employee', array(
       'approved_time' => time(),
       'entry_loaction' => json_encode(get_location_data()),
       'entry_verify_type' => 5, // Face verification
   ));
   ```

4) Face capture JavaScript:
   ```javascript
   $('.get_entry_face').click(function() {
       const jobId = $(this).data('job_id');
       const jobAviId = $(this).data('job_avi_id');
       
       // Show face capture modal
       $('#faceVerificationModal').show();
       
       // Initialize video
       navigator.mediaDevices.getUserMedia({ video: true })
           .then(videoStream => {
               stream = videoStream;
               document.getElementById('faceVideo').srcObject = stream;
           });
       
       // Capture and verify handler
       $('#captureFace').click(function() {
           const canvas = document.getElementById('faceCanvas');
           const video = document.getElementById('faceVideo');
           
           // Capture frame
           canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height);
           const imageData = canvas.toDataURL('image/jpeg');
           
           // Send to server
           $.ajax({
               url: 'verify_entry_face',
               method: 'POST',
               data: {
                   job_id: jobId,
                   job_avability_id: jobAviId,
                   image: imageData
               },
               success: function(response) {
                   if (response.success) {
                       showSuccess(translations.face_verification_successful);
                       $('#faceVerificationModal').hide();
                       refreshJobList();
                   }
               }
           });
       });
   });
   ```

## Database Schema

```ascii
┌─────────────────────────┐       ┌──────────────────────┐
│  job_accepted_candidate │       │    job_employee      │
├─────────────────────────┤       ├──────────────────────┤
│ entry_confirm_otp       │       │ approved_time        │
│ exist_confirm_otp       │       │ approved_time_exit   │
│ entry_qrcode_image      │       │ entry_loaction      │
│ exit_qrcode_image       │       │ exit_loaction       │
│ entry_apply_otp_time    │       │ entry_verify_type   │
│ exist_apply_otp_time    │       │ exit_verify_type    │
└─────────────────────────┘       └──────────────────────┘
```

## Security Measures

1. Time Window Validation:
```php
// From partner/controllers/job_verification.php
$start_time = $entry_exit_status['start_time'] - jobVerificationStartTime();
$end_time = $entry_exit_status['end_time'] + jobVerificationEndTime();

if ($start_time <= time() && $end_time >= time()) {
    // Allow verification
}
```

2. Sequential Verification:
```php
// Check if entry exists before allowing exit
if ($get_approve_time_entry_exit['approved_time'] == "") {
    // Entry required first
}
```

3. Location Tracking:
```php
$loaction = array(
    'lat' => $lat,
    'lng' => $lng
);
$entry_loaction = json_encode($loaction);
```

4. Face Verification Security:
```php
// Verify user ID matches session
if ($recognized_user_id != $this->session->userdata(CANDIDATE_LOGGED_IN)['id']) {
    return error_response($this->lang->line('face_not_recognized'));
}
```

## Verification Types

The system tracks how each verification was performed:
```php
entry_verify_type/exit_verify_type values:
1 = Job ID verification
2 = OTP verification
3 = QR code verification
4 = Admin verification
5 = Face ID verification
