# Kontrak API — Fase 2 Mobile (checklist, profil, ganti sandi)

Dikunci PM 5 Jul 2026. Backend & Android membangun terhadap kontrak ini
secara paralel. Semua path relatif `/api/v1/`. Semua respons dibatasi
`property_id` token. Nilai enum PERSIS skema `0001_init.sql`.

## 1. GET `wo/{id}/checklist`
Ambil item checklist untuk WO preventif (dari `work_orders.checklist_version_id`)
beserta hasil draft yang sudah tersimpan (bila ada).

Respons 200:
```json
{
  "wo_id": "124",
  "checklist_id": "5",
  "checklist_name": "HACCP suhu harian",
  "items": [
    {
      "id": "40", "seq": 1, "text": "Suhu cold room",
      "type": "numeric", "unit": "°C",
      "min_value": 0.0, "max_value": 5.0,
      "photo_required_on_fail": true,
      "guidance": "Baca termometer digital pintu",
      "result": null, "value_numeric": null, "note": null, "photo": null
    }
  ]
}
```
- `type`: pass_fail | numeric | text | photo
- `result`/`value_numeric`/`note`/`photo` = draft tersimpan (null bila belum).
- Bila WO tidak punya checklist → 404 `{"error":"not_found"}`.

## 2. POST `wo/{id}/checklist` (simpan draft — parsial diperbolehkan)
Body JSON:
```json
{ "results": [
  { "item_id": "40", "result": "ok", "value_numeric": 3.5, "note": "" },
  { "item_id": "41", "result": "fail", "note": "bocor kecil" }
]}
```
- `result`: ok | fail | na (untuk numeric, server boleh auto-fail bila di luar
  ambang — samakan dengan aturan web `ChecklistExecutionService`).
- Upsert per (wo_id, item_id) ke `wo_checklist_results`. Boleh dipanggil
  berulang (draft). Respons 200 `{"saved": N}`.
- Item bertipe `photo`: Fase 2 mobile kirim path/keterangan di `note`;
  upload file foto per item TIDAK wajib di iterasi ini (dokumentasikan).

Catatan: penyelesaian WO tetap lewat `POST wo/{id}/done` yang sudah ada —
server sudah menolak (422) bila checklist belum lengkap. Jadi alur mobile:
isi checklist (endpoint #2) → Tag done (endpoint lama).

## 3. GET `me`
Profil user token + skill.
```json
{
  "user": { "id":"4","username":"tech.candra","full_name":"Candra",
            "role":"technician","department":"engineering",
            "property_name":"Hotel Demo Satu" },
  "skills": [
    { "category_name":"Genset","level":"certified",
      "valid_until":"2026-08-19","expiring_soon":true }
  ]
}
```
`expiring_soon` = valid_until dalam < 60 hari atau sudah lewat.

## 4. POST `auth/change-password`
Body `{ "old_password":"...", "new_password":"..." }`.
- old_password wajib cocok; new_password min 8 karакter.
- Sukses 200 `{"ok":true}`; gagal 422 `{"error":"unprocessable","message":"..."}`.

## Penambahan HotelFixApi.kt (Android)
```
@GET("wo/{id}/checklist")  suspend fun woChecklist(@Path("id") id): WoChecklistResponse
@POST("wo/{id}/checklist") suspend fun submitChecklist(@Path("id") id, @Body body: ChecklistSubmit): SavedResponse
@GET("me")                 suspend fun me(): MeResponse
@POST("auth/change-password") suspend fun changePassword(@Body body: ChangePasswordRequest)
```
Front controller `public/api/v1/index.php` harus memetakan
`wo/{id}/checklist` (GET & POST) dan `me` dan `auth/change-password`.
