Files
fm_be/docs/aog-mcf-nsr-flow.md
2026-07-16 22:16:45 +07:00

380 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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. TanyaJawab 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`).