# Attendance API Documentation

## Overview

Sistem Attendance terintegrasi dengan Fingerprint Biometric dan Photo untuk verifikasi identitas employee. Ada dua type API:
1. **PUBLIC API** - Untuk mobile app (no authentication)
2. **PROTECTED API** - Untuk web/admin (JWT authentication)

## Database Schema

### fingerprint_data (dalam employees table)
- Menyimpan fingerprint biometric data (base64 encoded)
- longText untuk accommodate large biometric data
- Diperbarui saat fingerprint registration

### attendance_bypasses table
- Menyimpan log bypass attendance oleh admin
- Berguna untuk audit trail

## PUBLIC API (Mobile App)

### 1. Register Fingerprint
Endpoint untuk register fingerprint employee pertama kali.

```
POST /api/public/attendance/register-fingerprint
Content-Type: application/json

{
  "email": "employee@example.com",
  "fingerprint_data": "base64_encoded_fingerprint_data"
}

Response (201):
{
  "success": true,
  "data": {
    "employee_id": 1,
    "fingerprint_registered": true,
    "message": "Fingerprint registered successfully"
  },
  "message": "Fingerprint registered"
}
```

**Fingerprint Data Format:**
- Base64 encoded biometric data dari mobile device
- Dapat dari library fingerprint sensor (e.g., BiometricPrompt pada Android)

### 2. Get Employee Info
Endpoint untuk ambil info employee sebelum absensi.

```
GET /api/public/employee?email=employee@example.com

Response (200):
{
  "success": true,
  "data": {
    "id": 1,
    "name": "John Doe",
    "email": "john@example.com",
    "company": "PT ABC",
    "department": "IT",
    "fingerprint_registered": true
  }
}
```

### 3. Join Attendance (Check-in/Check-out)
**Endpoint utama untuk mobile app absensi**

Fingerprint verification + Photo capture + Location tracking

```
POST /api/public/attendance/join
Content-Type: multipart/form-data

Parameters:
- email (required): employee email
- fingerprint_data (required): biometric fingerprint data (base64)
- photo (optional): photo file (JPEG/PNG, max 5MB)
- location_latitude (optional): GPS latitude
- location_longitude (optional): GPS longitude
- type (optional): 'check_in' atau 'check_out' (default: check_in)

Response (200):
{
  "success": true,
  "data": {
    "attendance": {
      "id": 1,
      "id_employee": 1,
      "date": "2025-11-10",
      "check_in": "08:30:45",
      "check_out": null,
      "status": "present",
      "location_in": "-6.1234,106.5678",
      "photo_check_in": "attendances/1/xxx.jpg",
      "photo_check_out": null
    },
    "working_hours": {
      "within_hours": true,
      "current_time": "08:30:45",
      "work_start": "08:00:00",
      "work_end": "17:00:00",
      "message": "Within working hours"
    },
    "fingerprint_similarity": "94.5%"
  },
  "message": "Check-in successful"
}
```

**Flow Aplikasi Mobile:**
1. User input email
2. Hit `/api/public/employee` untuk ambil info
3. Mobile device capture fingerprint
4. (Optional) Capture photo
5. Get GPS coordinates
6. Hit `/api/public/attendance/join` dengan semua data
7. Server verifikasi fingerprint
8. Record attendance + foto

**Error Responses:**

```javascript
// Employee tidak ada
{
  "success": false,
  "data": null,
  "message": "Employee not found"
}

// Fingerprint tidak terdaftar
{
  "success": false,
  "data": null,
  "message": "Employee has not registered fingerprint yet"
}

// Fingerprint tidak match
{
  "success": false,
  "data": null,
  "message": "Fingerprint verification failed: Fingerprint mismatch. Similarity: 72%"
}

// Sudah check-in
{
  "success": false,
  "data": null,
  "message": "Already checked in today"
}
```

## PROTECTED API (Web/Admin)

Semua protected API memerlukan JWT token di header:
```
Authorization: Bearer {token}
```

### 1. List Attendances

```
GET /api/attendance?page=1&per_page=10&search=john&date_from=2025-11-01&date_to=2025-11-30&id_employee=1&status=present

Query Parameters:
- page: Nomor halaman (default: 1)
- per_page: Items per halaman (default: 10)
- search: Cari berdasarkan nama/email employee
- date_from: Tanggal dari (format: YYYY-MM-DD)
- date_to: Tanggal sampai (format: YYYY-MM-DD)
- id_employee: Filter berdasarkan employee ID
- status: Filter berdasarkan status (present, absent, late, approved_by_admin)

Response (200):
{
  "success": true,
  "data": {
    "data": [
      {
        "id": 1,
        "id_employee": 1,
        "date": "2025-11-10",
        "check_in": "08:30:45",
        "check_out": "17:15:30",
        "status": "present",
        "location_in": "-6.1234,106.5678",
        "location_out": "-6.1235,106.5679",
        "photo_check_in": "attendances/1/xxx.jpg",
        "photo_check_out": "attendances/1/yyy.jpg",
        "employee": {
          "id": 1,
          "name": "John Doe",
          "email": "john@example.com",
          "company": {...},
          "department": {...}
        },
        "created_at": "2025-11-10T08:30:45Z"
      }
    ],
    "current_page": 1,
    "total": 100,
    "per_page": 10,
    "last_page": 10
  }
}
```

### 2. Get Single Attendance

```
GET /api/attendance/{id}

Response (200):
{
  "success": true,
  "data": {
    "id": 1,
    "id_employee": 1,
    "date": "2025-11-10",
    "check_in": "08:30:45",
    "check_out": "17:15:30",
    "status": "present",
    "location_in": "-6.1234,106.5678",
    "location_out": "-6.1235,106.5679",
    "photo_check_in": "attendances/1/xxx.jpg",
    "photo_check_out": "attendances/1/yyy.jpg",
    "employee": {...}
  }
}
```

### 3. Bypass Attendance (Admin)
**Untuk input absensi manual atau revisi**

```
POST /api/attendance/bypass
Content-Type: application/json
Authorization: Bearer {token}

{
  "id_employee": 1,
  "date": "2025-11-09",
  "type": "full",  // "check_in", "check_out", atau "full"
  "manual_check_in": "08:00:00",
  "manual_check_out": "17:00:00",
  "reason": "Late register due to system error"
}

Response (201):
{
  "success": true,
  "data": {
    "attendance": {
      "id": 2,
      "id_employee": 1,
      "date": "2025-11-09",
      "check_in": "08:00:00",
      "check_out": "17:00:00",
      "status": "approved_by_admin"
    },
    "bypass": {
      "id": 1,
      "id_employee": 1,
      "id_attendance": 2,
      "id_admin": 1,
      "type": "full",
      "reason": "Late register due to system error",
      "status": "approved"
    }
  },
  "message": "Attendance bypass recorded successfully"
}
```

## Fingerprint Verification Flow

### 1. Registration (First Time)
```
Employee Phone App:
[Input Email] → [Register Fingerprint] → API POST /api/public/attendance/register-fingerprint
                                     ↓
                        Store fingerprint_data in DB
                        Set fingerprint_registered = true
```

### 2. Daily Attendance
```
Employee Phone App:
[Input Email] → [Capture Fingerprint + Photo] → API POST /api/public/attendance/join
                                            ↓
                        Verify incoming fingerprint vs stored
                        If similarity >= 85%: Record attendance
                        If similarity < 85%: Return error
```

### 3. Fingerprint Matching Algorithm
Default menggunakan:
- **Levenshtein Distance** untuk string comparison
- **Threshold: 85%** similarity

**Untuk Production:**
Integrasikan dengan proper biometric library seperti:
- NeuroTechnology VeriSpire
- NIST NBIS (NFIQ)
- NEC NeoFace
- Daon BioDNA

Edit `FingerprintService::calculateSimilarity()` untuk menggunakan library tersebut.

## Storage Configuration

Photos disimpan di:
```
storage/app/public/attendances/{employee_id}/{filename}

Accessible via:
/storage/attendances/{employee_id}/{filename}
```

Pastikan storage link sudah dibuat:
```bash
php artisan storage:link
```

## Attendance Status Values

- `present`: Normal attendance
- `absent`: No check-in/out
- `late`: Check-in after work start + 30min buffer
- `approved_by_admin`: Admin bypass

## Migration Instructions

```bash
# Run migrations untuk tambah fingerprint fields dan bypass table
php artisan migrate

# Rollback jika diperlukan
php artisan migrate:rollback
```

## Notes

1. **Fingerprint Data Storage:**
   - Data disimpan as-is (base64 encoded dari mobile)
   - Pastikan privacy dan security untuk biometric data
   - Consider encryption untuk production: `php artisan tinker` → backup data sebelum migration

2. **Photo Storage:**
   - Max 5MB per photo
   - Stored dalam `storage/app/public/attendances/`
   - Accessible via `/storage/attendances/`

3. **Working Hours Check:**
   - Default allow check-in 30 menit sebelum jam kerja
   - Based on WorkSchedule model
   - Jika tidak ada schedule untuk hari ini: allow attendance

4. **Audit Trail:**
   - Setiap bypass attendance tercatat di attendance_bypasses table
   - Include admin ID dan reason
   - Useful untuk compliance reporting

5. **Security Considerations:**
   - Fingerprint verification threshold: 85% (adjustable)
   - Levenshtein comparison is basic (upgrade untuk production)
   - Consider rate limiting untuk public API
   - Log all verification attempts untuk security monitoring
