# HRMS Mobile API Documentation

## Base URL
```
http://your-domain.com/api
```

## Authentication
Currently, the API does not require authentication. In production, you should implement API token authentication (Laravel Sanctum).

---

## Attendance Endpoints

### 1. Clock In
Employee clocks in to start their work day.

**Endpoint:** `POST /attendance/clock-in`

**Request Body** (multipart/form-data):
```
employee_id: integer (required) - Employee ID
latitude: float (optional) - GPS latitude (-90 to 90)
longitude: float (optional) - GPS longitude (-180 to 180)
photo_in: file (optional) - Selfie photo (JPEG, PNG, JPG, max 5MB)
notes: string (optional) - Additional notes (max 500 chars)
```

**Example Request (cURL)**:
```bash
curl -X POST http://your-domain.com/api/attendance/clock-in \
  -F "employee_id=1" \
  -F "latitude=-6.200000" \
  -F "longitude=106.816666" \
  -F "photo_in=@/path/to/photo.jpg" \
  -F "notes=Arrived at office"
```

**Success Response** (201):
```json
{
  "success": true,
  "message": "Clock in successful",
  "data": {
    "id": 123,
    "employee_id": 1,
    "employee_name": "John Doe",
    "attendance_date": "2025-11-24",
    "clock_in": "2025-11-24 08:30:00",
    "latitude_in": -6.200000,
    "longitude_in": 106.816666,
    "photo_in_url": "http://your-domain.com/storage/attendance/clock-in/photo.jpg"
  }
}
```

**Error Response** (400):
```json
{
  "success": false,
  "message": "Already clocked in today",
  "data": {
    "clock_in_time": "2025-11-24 08:15:00",
    "attendance_date": "2025-11-24"
  }
}
```

---

### 2. Clock Out
Employee clocks out to end their work day.

**Endpoint:** `POST /attendance/clock-out`

**Request Body** (multipart/form-data):
```
employee_id: integer (required) - Employee ID
latitude: float (optional) - GPS latitude (-90 to 90)
longitude: float (optional) - GPS longitude (-180 to 180)
photo_out: file (optional) - Selfie photo (JPEG, PNG, JPG, max 5MB)
notes: string (optional) - Additional notes (max 500 chars)
```

**Example Request (cURL)**:
```bash
curl -X POST http://your-domain.com/api/attendance/clock-out \
  -F "employee_id=1" \
  -F "latitude=-6.200000" \
  -F "longitude=106.816666" \
  -F "photo_out=@/path/to/photo.jpg" \
  -F "notes=Leaving office"
```

**Success Response** (200):
```json
{
  "success": true,
  "message": "Clock out successful",
  "data": {
    "id": 123,
    "employee_id": 1,
    "attendance_date": "2025-11-24",
    "clock_in": "2025-11-24 08:30:00",
    "clock_out": "2025-11-24 17:15:00",
    "working_hours": 8.75,
    "latitude_out": -6.200000,
    "longitude_out": 106.816666,
    "photo_out_url": "http://your-domain.com/storage/attendance/clock-out/photo.jpg"
  }
}
```

**Error Response** (404):
```json
{
  "success": false,
  "message": "No clock in record found for today"
}
```

---

### 3. Get Today's Attendance Status
Check if employee has clocked in/out today.

**Endpoint:** `GET /attendance/today-status`

**Query Parameters**:
```
employee_id: integer (required) - Employee ID
```

**Example Request**:
```bash
curl -X GET "http://your-domain.com/api/attendance/today-status?employee_id=1"
```

**Success Response** (200) - Has clocked in:
```json
{
  "success": true,
  "message": "Attendance status retrieved",
  "data": {
    "has_clocked_in": true,
    "has_clocked_out": false,
    "attendance_date": "2025-11-24",
    "clock_in": "2025-11-24 08:30:00",
    "clock_out": null,
    "working_hours": null,
    "status": "present",
    "photo_in_url": "http://your-domain.com/storage/attendance/clock-in/photo.jpg",
    "photo_out_url": null
  }
}
```

**Success Response** (200) - No attendance record:
```json
{
  "success": true,
  "message": "No attendance record for today",
  "data": {
    "has_clocked_in": false,
    "has_clocked_out": false,
    "attendance_date": "2025-11-24"
  }
}
```

---

### 4. Get Attendance History
Get employee's attendance history for a specific month.

**Endpoint:** `GET /attendance/history`

**Query Parameters**:
```
employee_id: integer (required) - Employee ID
month: integer (optional) - Month number (1-12), default: current month
year: integer (optional) - Year (e.g., 2025), default: current year
```

**Example Request**:
```bash
curl -X GET "http://your-domain.com/api/attendance/history?employee_id=1&month=11&year=2025"
```

**Success Response** (200):
```json
{
  "success": true,
  "message": "Attendance history retrieved",
  "data": {
    "month": 11,
    "year": 2025,
    "total_records": 15,
    "records": [
      {
        "id": 123,
        "attendance_date": "2025-11-24",
        "clock_in": "2025-11-24 08:30:00",
        "clock_out": "2025-11-24 17:15:00",
        "working_hours": 8.75,
        "status": "present",
        "late_minutes": 0,
        "photo_in_url": "http://your-domain.com/storage/attendance/clock-in/photo1.jpg",
        "photo_out_url": "http://your-domain.com/storage/attendance/clock-out/photo1.jpg"
      },
      {
        "id": 122,
        "attendance_date": "2025-11-23",
        "clock_in": "2025-11-23 08:45:00",
        "clock_out": "2025-11-23 17:30:00",
        "working_hours": 8.75,
        "status": "present",
        "late_minutes": 15,
        "photo_in_url": "http://your-domain.com/storage/attendance/clock-in/photo2.jpg",
        "photo_out_url": "http://your-domain.com/storage/attendance/clock-out/photo2.jpg"
      }
    ]
  }
}
```

---

## Error Codes

| Status Code | Description |
|-------------|-------------|
| 200 | Success |
| 201 | Created (Clock in successful) |
| 400 | Bad Request (Invalid data or already clocked in/out) |
| 404 | Not Found (Employee or attendance record not found) |
| 422 | Validation Error (Invalid input) |
| 500 | Internal Server Error |

---

## Validation Errors

When validation fails, you'll receive a 422 response with error details:

```json
{
  "message": "The employee id field is required.",
  "errors": {
    "employee_id": [
      "The employee id field is required."
    ],
    "photo_in": [
      "The photo in must be an image."
    ]
  }
}
```

---

## Implementation Notes

### Photo Upload
- Photos are stored in `storage/app/public/attendance/`
- Supported formats: JPEG, PNG, JPG
- Maximum file size: 5MB
- Photos are automatically accessible via the `storage` link

### GPS Coordinates
- Latitude range: -90 to 90
- Longitude range: -180 to 180
- GPS data is optional but recommended for location verification

### Working Hours Calculation
- Calculated automatically when clocking out
- Based on difference between clock_in and clock_out times
- Stored as decimal hours (e.g., 8.75 = 8 hours 45 minutes)

### Attendance Status
- `present`: Employee clocked in
- `absent`: No clock in for the day
- `late`: Clocked in after scheduled time
- `leave`: On approved leave
- `holiday`: Public holiday

---

## Testing with Postman

1. Import this collection or create requests manually
2. Set base URL to your local/staging environment
3. For photo upload, use form-data body type
4. Test sequence:
   - Get today's status (should show no record)
   - Clock in with photo
   - Get today's status (should show clocked in)
   - Clock out with photo
   - Get today's status (should show clocked out)
   - Get history for current month

---

## Security Recommendations

Before deploying to production:

1. **Implement Authentication**: Add Laravel Sanctum for API tokens
2. **Rate Limiting**: Prevent abuse with rate limiters
3. **HTTPS Only**: Ensure all API calls use HTTPS
4. **Input Sanitization**: Already handled by Laravel validation
5. **CORS Configuration**: Configure allowed origins in `config/cors.php`
6. **GPS Validation**: Implement geofencing to verify employee location
7. **Photo Verification**: Consider implementing face recognition

---

## Example Mobile App Integration (Flutter)

```dart
import 'package:http/http.dart' as http;
import 'dart:convert';

class AttendanceService {
  final String baseUrl = 'http://your-domain.com/api';

  Future<Map<String, dynamic>> clockIn({
    required int employeeId,
    required double latitude,
    required double longitude,
    File? photo,
  }) async {
    var request = http.MultipartRequest(
      'POST',
      Uri.parse('$baseUrl/attendance/clock-in'),
    );

    request.fields['employee_id'] = employeeId.toString();
    request.fields['latitude'] = latitude.toString();
    request.fields['longitude'] = longitude.toString();

    if (photo != null) {
      request.files.add(
        await http.MultipartFile.fromPath('photo_in', photo.path),
      );
    }

    var response = await request.send();
    var responseData = await response.stream.bytesToString();
    return json.decode(responseData);
  }

  Future<Map<String, dynamic>> getTodayStatus(int employeeId) async {
    var response = await http.get(
      Uri.parse('$baseUrl/attendance/today-status?employee_id=$employeeId'),
    );
    return json.decode(response.body);
  }
}
```
