init push

This commit is contained in:
2026-07-16 22:16:45 +07:00
commit 8b068bdb10
1021 changed files with 332816 additions and 0 deletions

165
docs/mcf-flow.md Normal file
View File

@@ -0,0 +1,165 @@
# 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).