# Panduan MCF (Maintenance Check Flight): Cara Pakai & Apa yang Terjadi

> Dokumen ini menjelaskan **cara mengelola MCF** sebuah helikopter — mengaktifkan, mengisi/edit draft, menandatangani (sign), membatalkan tanda tangan, dan membatalkan MCF — beserta **apa yang terjadi** di status helikopter, halaman fleet, dan log.
>
> Semua endpoint berawalan `/api/v1` dan butuh login. MCF adalah **entity per-helikopter** dengan lifecycle draft → signed.

---

## 1. Konsep singkat

**MCF** = penerbangan uji (check flight) yang wajib dilakukan setelah perawatan tertentu. Selama helikopter "sedang MCF", statusnya `mcf` di fleet.

Tiga pemain endpoint:

| Endpoint | Tugasnya |
|---|---|
| **`set`** | Yes/No + **tempat kerja draft** (buat, isi, edit data check-flight) |
| **`sign`** | **finalize** (tandatangani hasil) / **unsign** (balik ke draft) |
| **`get` / `get-by-helicopter`** | baca satu MCF / daftar (log, termasuk yang cancelled & signed) |

> **Tidak ada** endpoint `create`/`delete`/`unassign` lagi — semuanya lewat `set` & `sign`.

---

## 2. Status (state) sebuah MCF

| State | Artinya | `completed_at` | `cancelled_at` | Status heli |
|---|---|---|---|---|
| **Draft** | Dibuat/diisi, belum ditandatangani | kosong | kosong | `mcf` |
| **Signed – passed** | Sudah tanda tangan, hasil **lulus** | terisi | kosong | **clear** (keluar MCF) |
| **Signed – failed** | Sudah tanda tangan, hasil **gagal** | terisi | kosong | `mcf` (perlu re-flight) |
| **Cancelled** | Draft di-set No ("tidak jadi", tak pernah sign) | kosong | terisi | **lepas** (fleet placeholder) |

**Aturan penting:**
- **1 MCF terbuka (draft) per helikopter.** `set active:true` saat draft sudah ada → **meng-update** draft itu, bukan bikin baru.
- **Cancelled hanya untuk draft** (yang belum pernah di-sign). MCF yang sudah signed = **event nyata**, tidak bisa di-cancel.
- MCF yang cancelled/signed **tetap tersimpan** di list (`get-by-helicopter`) sebagai **log/history**.

---

## 3. Flow lengkap (langkah + apa yang terjadi)

### Langkah 1 — Aktifkan / isi / edit draft
`POST /mcf/set/{helicopter_id}`

```json
{
  "data": {
    "type": "mcf_set",
    "attributes": {
      "active": true,
      "flight_id": "019d6774-98e8-7fba-9ef4-3795c0da8a13",
      "af_hours": "1245.3",
      "landing_count": 3,
      "date": "2026-06-17",
      "result": "passed",
      "notes": "MCF setelah pekerjaan engine mount"
    }
  }
}
```

**Apa yang terjadi:**
- Belum ada draft → **buat draft baru** → **201**.
- Sudah ada draft terbuka → **update draft itu** dengan data yang dikirim → **200**.
- Semua field data **opsional** — boleh isi sebagian dulu, lengkapi bertahap dengan `set` lagi.
- Helikopter masuk **status `mcf`**. Di fleet, object `mcf` muncul (`sign: false`, `af_hours`/`landing_count` pre-fill dari total pesawat kalau belum diisi).

> `active` boleh diomit → dianggap `true`.

### Langkah 2 — Finalize (tanda tangan)
`POST /mcf/sign/{id}`

```json
{
  "data": {
    "type": "mcf_sign",
    "attributes": {
      "sign": true,
      "af_hours": "1245.3",
      "landing_count": 3,
      "utc_time": "2026-06-17T08:30:00Z",
      "date": "2026-06-17",
      "result": "passed"
    }
  }
}
```

**Apa yang terjadi:**
- **Wajib lengkap**: `af_hours`, `landing_count`, `utc_time`, `date`, `result` (else **422**, pointer ke field yang kurang).
- MCF jadi **signed/completed** (`completed_at` + `completed_by` terisi).
- `result: passed` → **status MCF clear** (helikopter keluar dari MCF).
- `result: failed` → helikopter **tetap `mcf`** (perlu re-flight — buat MCF baru lewat `set active:true`).

### Langkah 3 — Batal tanda tangan (unsign)
`POST /mcf/sign/{id}` dengan `{ "sign": false }`

**Apa yang terjadi:**
- MCF yang signed **balik jadi draft** (`completed_at` dikosongkan) — **datanya tetap**.
- Bisa di-edit lagi lewat `set`, lalu di-`sign` ulang.

### Langkah 4 — Nonaktifkan / batal (set No)
`POST /mcf/set/{helicopter_id}` dengan `{ "active": false }`

**Apa yang terjadi:**
- Draft (belum sign) → ditandai **`cancelled`** ("tidak jadi") → **status MCF lepas** → fleet balik **placeholder**. Record **tetap di list** sebagai log cancelled.
- **Sudah signed → BUKAN batal** (event nyata). MCF dibiarkan; response mengembalikan MCF signed itu apa adanya. Di fleet **datanya tetap muncul** (lihat §5): untuk `passed` helikopter sudah **keluar status MCF** ("active no") tapi data MCF sebelumnya **tetap tampil**; untuk `failed` helikopter tetap `mcf`.
- Tidak ada MCF sama sekali → **no-op** (idempotent, sudah "No").

---

## 4. Contoh alur khas

```
set  {active:true, af_hours, result, ...}   → draft dibuat (201)
set  {active:true, ...revisi...}            → draft di-update (200)
sign {sign:true, ...lengkap...}             → signed  (passed=clear / failed=tetap)
    ── kalau salah ──
sign {sign:false}                           → balik draft (data tetap) → edit → sign lagi
    ── kalau tidak jadi ──
set  {active:false}                         → cancelled (lepas status, tetap jadi log)
```

---

## 5. Efek ke Fleet Status

Object `mcf` di response fleet (`GET /api/v1/fleet-status/...`) selalu mencerminkan **MCF terbaru** helikopter. Field **`active`** = apakah helikopter **sedang dalam MCF** (draft, atau signed-failed yang perlu re-flight); `false` kalau cleared/cancelled/tidak ada.

| Kondisi MCF terbaru | `active` | Object `mcf` di fleet |
|---|---|---|
| Tidak ada / cancelled | `false` | **placeholder** — `id: ""`, `sign: false`, `af_hours`/`landing_count` dari total pesawat |
| Draft (belum sign) | `true` | id draft, `sign: false`, data pre-fill dari pesawat kalau kosong |
| Signed – passed | `false` | id, `sign: true`, snapshot MCF + `signed_by` (data tetap tampil walau status sudah clear) |
| Signed – failed | `true` | id, `sign: true`, snapshot + `signed_by` (masih MCF, perlu re-flight) |

Urutan status di fleet & hold list: **MCF → AOG → Booked → Available** (paling kritikal dulu).

---

## 6. Ringkasan endpoint

| Method | Path | Fungsi |
|---|---|---|
| `POST` | `/api/v1/mcf/set/{helicopter_id}` | activate/edit draft (`active:true`) · cancel (`active:false`) |
| `POST` | `/api/v1/mcf/sign/{id}` | finalize (`sign:true`) · unsign (`sign:false`) |
| `GET` | `/api/v1/mcf/get/{id}` | baca satu MCF |
| `GET` | `/api/v1/mcf/get-by-helicopter/{helicopter_id}` | daftar MCF helikopter (log) |

**Permission:** `mcf.create` (untuk `set`), `mcf.complete` (untuk `sign`), `mcf.read` (untuk `get`).

---

## 7. Kode error umum

| Kode | Kapan |
|---|---|
| `MCF_INVALID_UUID` | `helicopter_id` / `id` bukan UUID valid (422) |
| `MCF_INVALID_JSON` | body JSON rusak (400) |
| `INVALID_DATA_TYPE` | tipe field salah (mis. `flight_id` dikirim angka) (422) |
| `MCF_INVALID_PAYLOAD` | field check-flight kurang/salah saat `sign:true` (422, pointer ke field) |
| `MCF_NOT_FOUND` | MCF id tidak ada (404) |

> **Catatan:** relasi MCF ke penerbangan lewat `flight_id` (opsional). Lihat juga [aog-mcf-nsr-flow.md](aog-mcf-nsr-flow.md) untuk gambaran status helikopter secara keseluruhan (AOG/MCF/NSR).
