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

166 lines
7.0 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 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).