# Panduan Status Helikopter: AOG, MCF, NSR & Cara Menerbangkannya Lagi

> Dokumen ini menjelaskan **kapan sebuah helikopter berhenti boleh terbang**, **kenapa**, dan **langkah apa yang harus dilakukan supaya boleh terbang lagi** — lengkap dengan endpoint yang dipakai di tiap langkah.
>
> Ditulis supaya bisa dimengerti baik oleh tim operasional maupun developer. Bagian teknis (endpoint, field) ada di tiap langkah, tapi alurnya diceritakan dulu dengan bahasa sederhana.
>
> Semua endpoint berawalan `/api/v1` dan butuh login.

---

## 1. Istilah Penting (versi gampang)

Sebelum masuk alur, kenali dulu pemainnya:

| Istilah | Bahasa gampangnya |
|---|---|
| **Complaint** | Laporan kerusakan/keluhan pada helikopter. "Ada yang rusak nih." |
| **MEL** (Minimum Equipment List) | Aturan: kerusakan ini boleh ditunda berapa lama sebelum pesawat **wajib** berhenti. Ada kelas A/B/C/D (makin besar = makin lama boleh ditunda). |
| **NON-MEL** | Kerusakan yang **tidak boleh ditunda sama sekali** → pesawat langsung berhenti. |
| **AOG** (Aircraft On Ground) | Status "pesawat dikandangkan, **tidak boleh terbang**". |
| **NSR** (Non-Safety Release) | Keputusan: "kerusakan ini aman ditunda, **boleh terbang dulu**" walau belum diperbaiki. |
| **Action Taken** | Tindakan perbaikan sementara yang dicatat, supaya pesawat boleh terbang lagi — tapi **belum dianggap selesai resmi**. |
| **EASA Release** (CRS Part-145) | Surat resmi "**pesawat sudah diperbaiki & layak terbang**". Inilah yang benar-benar **menutup** kerusakan. |
| **MCF** (Maintenance Check Flight) | Penerbangan uji setelah perbaikan besar. Selama wajib MCF, pesawat berstatus khusus. |
| **Fleet Status** | Data kondisi tiap helikopter: jadwal perawatan, jam terbang, status, dll. |

**Inti yang paling sering bikin bingung** (akan diulang lagi nanti):
> **Boleh terbang lagi** ≠ **kerusakan selesai.**
> - Pesawat bisa **boleh terbang lagi** lewat *Action Taken* atau *NSR* — tapi laporannya **masih terbuka**.
> - Kerusakan baru **benar-benar selesai (ditutup)** ketika **EASA Release ditandatangani (sign)** — bukan sekadar dibuat.

---

## 2. Status Helikopter & Urutannya

Helikopter selalu ada di salah satu dari 4 status ini. Status **dihitung otomatis** dari kondisi data (bukan diisi manual):

| Status | Artinya |
|---|---|
| `mcf` | Wajib penerbangan uji (Maintenance Check Flight) dulu |
| `aog` | Dikandangkan, tidak boleh terbang |
| `booked` | Sedang dipakai misi |
| `available` | Sehat, siap terbang |

**Kalau beberapa kondisi terjadi bersamaan, yang menang urutannya begini:**

```
MCF  >  AOG  >  Booked  >  Available
```

Contoh: helikopter yang sedang wajib MCF **dan** punya kerusakan AOG → tetap tampil `mcf` (karena MCF paling tinggi). Ini sama persis dengan sistem Wucher lama.

---

## 3. Gambaran Besar: 3 Jalan Sebuah Helikopter Berhenti Terbang

Ada **3 sebab** helikopter jadi tidak boleh terbang. Tiap sebab punya cara keluar sendiri:

| Sebab berhenti | Jadi status | Cara terbang lagi |
|---|---|---|
| **A. Ada kerusakan** (complaint) | `aog` | EASA Release disign (atau ditunda dulu via Action/NSR) |
| **B. Jadwal perawatan jatuh tempo** (otomatis) | `aog` | Perbarui jadwal/selesai inspeksi → hitung ulang |
| **C. Wajib penerbangan uji** (MCF) | `mcf` | Selesaikan MCF dengan hasil "passed" |

Tiga sebab ini dibahas satu per satu di bawah.

---

## 4. JALAN A — Helikopter Rusak (Complaint → AOG → Perbaikan)

Ini alur paling sering. Ceritanya berurutan:

### Langkah 1 — Catat kerusakannya
Begitu ada kerusakan, buat laporan (complaint).

`POST /complaints/create` (permission `complaint.create`)

```jsonc
{
  "data": {
    "type": "complaint_create",
    "attributes": {
      "helicopter_id": "019d6771-5fb5-7337-837f-bc5ed85181a1",
      "description": "Getaran di Engine 2 saat cruise",
      "mel_severity": 0,                 // lihat tabel di Langkah 2
      "aircraft_hours_at_report": "1245.3"
    }
  }
}
```

### Langkah 2 — Tentukan seberapa parah (klasifikasi MEL)
Field `mel_severity` menentukan **kapan pesawat harus berhenti**:

| `mel_severity` | Kelas | Boleh terbang sampai kapan? |
|---|---|---|
| `0` | NON-MEL | **Tidak boleh sama sekali** → AOG seketika |
| `1` | A | Maksimal **1 hari**, lewat itu → AOG |
| `2` | B | Maksimal **3 hari** → AOG |
| `3` | C | Maksimal **10 hari** → AOG |
| `4` | D | Maksimal **120 hari** → AOG |
| *(dikosongkan)* | belum diklasifikasi | Statusnya `pending_classification`, **belum bikin AOG** sampai diklasifikasi |

> Klasifikasi bisa diisi belakangan lewat `PATCH /complaints/update/:id` (field `mel_severity`). Sistem mencatat siapa & kapan mengklasifikasi (audit `mel_classified_by/at`).

Selama kerusakan ini bikin AOG, di Fleet Status detail helikopter akan **muncul** data `complaints` + `easa`. Kalau sudah tidak AOG, dua data itu hilang sendiri.

### Langkah 3 (opsional) — Mau terbang dulu sebelum diperbaiki tuntas?
Kadang pesawat perlu tetap operasi sambil menunggu perbaikan resmi. Ada **2 cara**, dan ini beda fungsi:

**Cara 3a — Action Taken (tindakan sementara sudah dilakukan):**
`PATCH /complaints/update/:id` isi `action_taken`.

```jsonc
{ "data": { "type": "complaint_update", "id": "<complaint_id>",
    "attributes": {
      "action_taken": "Kencangkan engine mount, cek torsi OK",
      "aircraft_hours_at_fix": "1250.1"
    } } }
```
→ Pesawat **boleh terbang lagi**, tapi laporan **masih terbuka**.

**Cara 3b — NSR (kerusakan aman ditunda):**
`PATCH /complaints/update/:id` isi `is_nsr: true` (**butuh permission khusus `complaint.nsr`**).

```jsonc
{ "data": { "type": "complaint_update", "id": "<complaint_id>",
    "attributes": {
      "is_nsr": true,
      "nsr_reason": "Dirilis di bawah MEL, defect ditunda"
    } } }
```
→ Pesawat **boleh terbang lagi**, laporan **masih terbuka**. Sistem mencatat siapa yang memutuskan NSR (`nsr_decided_by/at`).

> **Beda Action Taken vs NSR:**
> - *Action Taken* = "sudah saya tangani sementara".
> - *NSR* = "belum ditangani, tapi memang **boleh ditunda** dengan aman".
> Keduanya sama-sama bikin pesawat boleh terbang lagi, dan **sama-sama belum menutup laporan**.
>
> Membatalkan NSR: kirim `is_nsr: false` → aturan AOG berlaku lagi.

### Langkah 4 — Tutup kerusakan secara resmi (EASA Release)
Inilah langkah yang **benar-benar menyelesaikan** kerusakan. Tiga sub-langkah:

**4a. Buat surat EASA-nya** (boleh draft / belum lengkap dulu):
`POST /easa-releases/create` (permission `easa_release.create`)

> ⚠️ **Syarat boleh membuat EASA:** semua complaint terbuka helikopter itu **harus sudah di-*Action Taken* atau di-NSR dulu** (Langkah 3). Kalau masih ada yang "mentah", create ditolak (`ErrEASAReleaseComplaintsPendingAction`). Jadi Langkah 3 itu **pintu masuk** ke Langkah 4.

**4b. Lengkapi datanya** (kalau tadi masih draft):
`PATCH /easa-releases/update/:id`

**4c. TANDA TANGAN (sign) — ini momen kerusakan benar-benar ditutup:**
`POST /easa-releases/sign/:id` (permission `easa_release.sign`, **tanpa body** — penandatangan = user yang sedang login).

```bash
POST /api/v1/easa-releases/sign/019d6772-471c-7b70-b42a-d94020ef61e4
```

**Sebelum bisa sign, 5 field ini WAJIB terisi:**

| Field | Contoh |
|---|---|
| `easa_date` | `2026-06-16` |
| `easa_ac_hours` | `1245.3` |
| `easa_location` | `LOWI` |
| `easa_wo_no` | `WO-2026-001` |
| `easa_signer_id` | `145.A.50` |

Kalau ada yang kosong → ditolak (`ErrEASAReleaseIncompleteForSign`) beserta daftar `missing_sign_fields`. Aturannya tegas: **EASA yang belum lengkap tidak boleh dianggap selesai.**

> **Jalan pintas:** kalau datanya sudah lengkap dari awal, kamu bisa langsung sign **saat create** — tambahkan `"sign": true` di body create. (Catatan: flag `sign` ini **hanya ada di create**, tidak ada di update.)

**Begitu sign berhasil, otomatis terjadi:**
1. Surat EASA tercatat `signed_at` + `signed_by`.
2. **Semua complaint terbuka** helikopter itu ditutup → statusnya jadi `serviced`.
3. Karena tidak ada lagi kerusakan yang menggantung → **AOG hilang**, data `complaints`/`easa` di Fleet Status ikut hilang.
4. Tercatat di riwayat (history): "Release to Service (EASA signed)".

### Ringkasan Jalan A (urut)
```
Rusak → buat complaint → klasifikasi MEL
   → (opsional) Action Taken / NSR  ➜ boleh terbang, laporan MASIH terbuka
   → EASA create → EASA lengkapi → EASA SIGN  ✅ ➜ laporan DITUTUP, AOG hilang
```

---

## 5. JALAN B — Jadwal Perawatan Jatuh Tempo (AOG Otomatis)

### Apa ini?
Tiap helikopter punya jadwal inspeksi di Fleet Status (mis. inspeksi tiap 100 jam, atau jatuh tempo di tanggal tertentu). Kalau **jam terbang** atau **tanggal** sudah melewati batas, sistem **otomatis** men-AOG-kan pesawat — tanpa perlu ada yang lapor.

### Cara masuk AOG
Diatur di Fleet Status, tiap jadwal punya:
- `due` = batas normal (boleh berupa **jam**, mis. `1200`, atau **tanggal**, mis. `2026-09-01`)
- `ext` = batas perpanjangan (kalau diisi, ini yang dipakai menggantikan `due`)

Saat jam/tanggal aktual melewati batas → status jadi `aog` dengan keterangan otomatis (`AOG: ... next due reached`).

> Engine yang tidak aktif di helikopter (flag `NR1`/`NR2` = false) **dilewati** — jadwal engine itu tidak ikut bikin AOG.

### Kapan sistem menghitung ulang?
AOG jenis ini **disimpan**, jadi perlu pemicu untuk berubah:
- Saat data penerbangan (flight data) dibuat/diubah/dihapus.
- Saat Fleet Status helikopter itu di-update.
- **Otomatis tiap 1 jam** (cron) — supaya AOG berbasis tanggal tetap nyala walau tidak ada aktivitas.

### Cara terbang lagi
Perbarui jadwalnya supaya tidak lagi lewat tempo (mis. setelah inspeksi selesai, isi `due`/`ext` yang baru):

`PATCH /fleet-status/update/:id`
```jsonc
{ "data": { "type": "fleet_status_update", "id": "<fleet_status_id>",
    "attributes": { "maintenance_schedules": [
      { "inspection_type": "100H", "due": "1400", "ext": "" }
    ] } } }
```
Pada perhitungan ulang berikutnya, AOG otomatis ini dilepas. (Catatan: sistem hanya melepas AOG yang dibuatnya sendiri secara otomatis; AOG manual tidak disentuh.)

---

## 6. JALAN C — Wajib Penerbangan Uji (MCF)

### Apa ini?
Setelah pekerjaan perawatan besar, helikopter kadang wajib menjalani **penerbangan uji (MCF)** dulu sebelum dianggap normal. Selama wajib MCF, statusnya `mcf` (mengalahkan AOG).

### Langkah 1 — Tandai wajib MCF (cukup minimal)
`POST /mcf/create` (permission `mcf.create`) — body cukup `helicopter_id` saja (+ `notes` opsional). Tujuannya hanya menandai pesawat ini wajib MCF.

```jsonc
{ "data": { "type": "mcf_create",
    "attributes": {
      "helicopter_id": "019d6771-5fb5-7337-837f-bc5ed85181a1",
      "notes": "Wajib MCF setelah kerja engine mount"
    } } }
```

### Langkah 2 — Selesaikan MCF setelah terbang uji
`POST /mcf/complete/:helicopter_id` (permission `mcf.complete`) — **pakai helicopter_id**, bukan id MCF. Wajib isi semua field hasil uji:

```jsonc
{ "data": { "type": "mcf_complete",
    "attributes": {
      "af_hours": "1245.3",
      "landing_count": 3,
      "utc_time": "2026-06-17T08:30:00Z",   // format RFC3339
      "date": "2026-06-17",                  // format YYYY-MM-DD
      "result": "passed",                    // passed atau failed
      "notes": "Getaran dalam batas normal"
    } } }
```

**Hasilnya menentukan:**

| `result` | Yang terjadi |
|---|---|
| `passed` | MCF beres → pesawat **lepas dari status MCF** (kembali ke status lain sesuai kondisi) |
| `failed` | Pesawat **tetap MCF**, hasil gagal dicatat ke riwayat → ulangi sampai `passed` |

> Catatan: kalau tidak ada MCF terbuka untuk helikopter itu, complete ditolak (`409`).

---

## 7. Melihat Riwayat (History)

Semua kejadian penting di atas — dari kerusakan dilaporkan, diklasifikasi, NSR, perbaikan, EASA disign, hasil MCF, sampai AOG otomatis nyala/mati — **tercatat otomatis** dalam satu garis waktu (timeline) per helikopter. Berguna untuk audit: *siapa* melakukan *apa* dan *kapan*.

### Di mana lihatnya?
`GET /fleet-status/history/:helicopter_id` (permission `flight.read`)

```bash
GET /api/v1/fleet-status/history/019d6771-5fb5-7337-837f-bc5ed85181a1?page=1&page_size=20
```

- Diurutkan **terbaru di atas**.
- Mendukung halaman: `page` (default 1) & `page_size` (default 20).
- Timeline ini **gabungan dua sumber**: catatan perawatan yang diselesaikan (service log) + semua kejadian aksi (complaint, EASA, MCF, AOG).

### Kejadian apa saja yang tercatat?

| `action` | Tercatat ketika… |
|---|---|
| `complaint_filed` | Laporan kerusakan dibuat |
| `mel_classified` | Kerusakan diklasifikasi MEL (A/B/C/D atau NON-MEL) |
| `nsr_done` | NSR diberikan (boleh terbang walau defect terbuka) |
| `nsr_cancelled` | NSR dibatalkan |
| `action_taken` | Tindakan perbaikan sementara dicatat |
| `easa_created` | Surat EASA dibuat (draft) |
| `easa_signed` | **EASA ditandatangani → kerusakan ditutup** |
| `mcf_result` | Hasil MCF diisi (`passed`/`failed`) |
| `aog_set` | AOG otomatis dinyalakan (jadwal jatuh tempo) |
| `aog_cleared` | AOG otomatis dilepas |
| `serviced` | Inspeksi/perawatan diselesaikan |

### Bentuk responsnya

Tiap baris timeline berisi: kapan, jenisnya, aksinya, pesan, dan **siapa pelakunya** (nama langsung tersedia di `actor_name`).

```jsonc
{
  "data": [
    {
      "at": "2026-06-17T10:15:00Z",
      "entity_type": "easa_release",
      "entity_id": "019d6772-471c-7b70-b42a-d94020ef61e4",
      "action": "easa_signed",
      "message": "Release to Service (EASA signed)",
      "actor": "019e91e6-2908-7f37-93e6-015ed1b7587d",
      "actor_name": "John Doe"
    },
    {
      "at": "2026-06-17T09:40:00Z",
      "entity_type": "complaint",
      "action": "action_taken",
      "message": "Action taken — Kencangkan engine mount, cek torsi OK",
      "actor_name": "Jane Tech"
    }
  ],
  "meta": { "page_number": 1, "page_size": 20, "total": 12 }
}
```

> Selain timeline ini, daftar **kerusakan per helikopter** (beserta status terkini, NSR, action, dan EASA terkait) bisa dilihat lewat `GET /complaints/get-by-helicopter/:helicopter_id`, dan kondisi terkini helikopter (status + complaint + EASA aktif) lewat `GET /fleet-status/get-by-helicopter/:helicopter_id`.

---

## 8. Tabel Endpoint Ringkas

| Mau apa | Endpoint | Permission |
|---|---|---|
| Lapor kerusakan | `POST /complaints/create` | `complaint.create` |
| Klasifikasi MEL / Action Taken / NSR | `PATCH /complaints/update/:id` | `complaint.update` (+`complaint.nsr` utk NSR) |
| Lihat kerusakan per helikopter | `GET /complaints/get-by-helicopter/:helicopter_id` | `complaint.read` |
| Buat surat EASA | `POST /easa-releases/create` | `easa_release.create` |
| Lengkapi EASA | `PATCH /easa-releases/update/:id` | `easa_release.update` |
| **Tanda tangan EASA (tutup kerusakan)** | `POST /easa-releases/sign/:id` | `easa_release.sign` |
| Tandai wajib MCF | `POST /mcf/create` | `mcf.create` |
| **Selesaikan MCF** | `POST /mcf/complete/:helicopter_id` | `mcf.complete` |
| Atur jadwal perawatan & jam | `POST /fleet-status/create` · `PATCH /fleet-status/update/:id` | `flight.create` / `flight.update` |
| Lihat status + complaint + EASA | `GET /fleet-status/get-by-helicopter/:helicopter_id` | `flight.read` |
| Lihat riwayat helikopter | `GET /fleet-status/history/:helicopter_id` | `flight.read` |

---

## 9. Tanya–Jawab Cepat (FAQ)

**T: Kerusakan dianggap selesai saat EASA dibuat atau saat disign?**
J: Saat **disign**. Membuat (create) atau melengkapi (update) EASA **belum** menutup apa pun. Penutupan complaint terjadi tepat di endpoint `sign`.

**T: Bedanya Action Taken, NSR, dan EASA Sign?**
J:
- **Action Taken** & **NSR** → bikin pesawat **boleh terbang lagi**, tapi laporan **masih terbuka**.
- **EASA Sign** → **menutup** laporan secara resmi (status `serviced`).

**T: Kalau cuma isi Action Taken, kapan laporannya hilang dari daftar AOG?**
J: AOG-nya langsung hilang begitu Action Taken diisi (pesawat boleh terbang). Tapi laporannya **tetap tercatat terbuka** sampai EASA disign.

**T: Kenapa saya tidak bisa membuat EASA?**
J: Kemungkinan masih ada complaint yang belum di-Action/NSR. Selesaikan Langkah 3 dulu untuk tiap complaint terbuka.

**T: Helikopter wajib MCF tapi juga ada kerusakan AOG, tampil yang mana?**
J: Tampil `mcf`, karena MCF prioritas tertinggi.

**T: AOG karena jadwal jatuh tempo kok tidak langsung hilang setelah saya update jadwal?**
J: AOG jenis ini dihitung ulang saat ada flight data baru, update fleet status, atau otomatis tiap 1 jam. Tunggu pemicu berikutnya.

**T: Di mana saya bisa lihat riwayat apa saja yang sudah terjadi pada satu helikopter?**
J: Di `GET /fleet-status/history/:helicopter_id` — timeline lengkap (terbaru di atas) berisi siapa melakukan apa & kapan. Lihat §7.

---

## 10. Catatan untuk Developer

- **AOG karena kerusakan** dihitung *saat dibaca* (real-time dari complaint terbuka) → berubah instan, tidak perlu job.
- **AOG karena jadwal** *disimpan* di helikopter → perlu pemicu (flight data / update fleet / cron 1 jam). Hanya AOG otomatis yang dilepas otomatis; AOG manual tidak.
- **MCF mengalahkan AOG** dalam prioritas status.
- **Penutupan kerusakan hanya lewat EASA sign** — `action_taken` & `is_nsr` hanya mengangkat larangan terbang, tidak menutup laporan.
- **Masa tenggang MEL dihitung dalam HARI** (A=1, B=3, C=10, D=120) di `internal/domain/complaint/model.go` fungsi `MELDeadline` (`* 24 * time.Hour`).
