init push
This commit is contained in:
578
docs/takeover-step-by-step.md
Normal file
578
docs/takeover-step-by-step.md
Normal file
@@ -0,0 +1,578 @@
|
||||
# Takeover Flow Step by Step
|
||||
|
||||
Dokumen ini menjelaskan flow `takeover` dari sisi frontend secara detail: endpoint yang dipakai, urutan request, payload yang wajib dan opsional, serta contoh request/response.
|
||||
|
||||
Untuk detail khusus file takeover, lihat [docs/takeover-file-api.md](./takeover-file-api.md).
|
||||
|
||||
## Ringkasan Singkat
|
||||
|
||||
`Takeover` adalah endpoint atomic untuk membuat satu paket data sekaligus:
|
||||
|
||||
1. `takeover_ac`
|
||||
2. `duty_roster`
|
||||
3. `reserve_ac`
|
||||
4. `flight_inspection`
|
||||
5. `before_flight_inspection`
|
||||
6. `flight_prep_check`
|
||||
7. `flight`
|
||||
|
||||
Artinya frontend cukup kirim **1 request create takeover**, backend akan membuat seluruh record terkait dalam satu transaksi.
|
||||
|
||||
## Endpoint Yang Tersedia
|
||||
|
||||
Ada 1 route create takeover yang menuju handler yang sama:
|
||||
|
||||
1. `POST /api/v1/takeovers/create`
|
||||
|
||||
Keduanya memakai permission:
|
||||
|
||||
`reserve_ac.create`
|
||||
|
||||
Route lain yang tersedia:
|
||||
|
||||
1. `GET /api/v1/takeovers/get-all`
|
||||
2. `GET /api/v1/takeovers/get/:id`
|
||||
3. `PATCH /api/v1/takeovers/update/:id`
|
||||
4. `DELETE /api/v1/takeovers/delete/:id`
|
||||
|
||||
Untuk dokumentasi ini fokus utama ada pada flow `create takeover`.
|
||||
|
||||
## Step by Step Flow
|
||||
|
||||
### Step 1. Siapkan data master terlebih dahulu
|
||||
|
||||
Sebelum hit create takeover, frontend harus sudah punya:
|
||||
|
||||
1. `base_id`
|
||||
2. `helicopter_id`
|
||||
3. `duty_date`
|
||||
4. daftar crew untuk roster
|
||||
5. data inspeksi sebelum terbang
|
||||
6. data persiapan flight
|
||||
|
||||
Kalau salah satu ID tidak valid atau tidak ditemukan, backend akan gagal.
|
||||
|
||||
### Step 2. Susun payload utama
|
||||
|
||||
Payload mengikuti format JSON:API sederhana:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"type": "takeover",
|
||||
"attributes": {
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Field `type` menerima:
|
||||
|
||||
1. `takeover`
|
||||
2. `takeover_create`
|
||||
|
||||
Frontend boleh kirim salah satu, tapi disarankan konsisten pakai `takeover_create` atau `takeover` sesuai standar proyek yang dipakai tim.
|
||||
|
||||
### Step 3. Kirim request create
|
||||
|
||||
Request create akan:
|
||||
|
||||
1. validasi JSON
|
||||
2. validasi struktur payload
|
||||
3. validasi UUID `base_id`
|
||||
4. validasi UUID `helicopter_id`
|
||||
5. validasi tanggal `duty_date`
|
||||
6. membangun roster crew
|
||||
7. membuat seluruh data dalam 1 transaksi
|
||||
8. mengembalikan response takeover lengkap
|
||||
|
||||
Kalau satu sub-step gagal, seluruh transaksi gagal.
|
||||
|
||||
### Step 4. Terima response
|
||||
|
||||
Response sukses akan mengembalikan struktur `takeover` lengkap berisi:
|
||||
|
||||
1. `takeover_ac_id`
|
||||
2. `duty_roster_id`
|
||||
3. `flight_id`
|
||||
4. `reserve_ac_id`
|
||||
5. `flight_inspection_id`
|
||||
6. `shift_start`
|
||||
7. `shift_end`
|
||||
8. `base`
|
||||
9. `helicopter`
|
||||
10. `roster_detail`
|
||||
11. `inspection`
|
||||
12. `flight`
|
||||
13. `duty_roster`
|
||||
|
||||
Frontend sebaiknya memakai response ini sebagai sumber data final, bukan mengasumsikan data lokal sama persis dengan hasil backend.
|
||||
|
||||
## Request Detail
|
||||
|
||||
### Endpoint
|
||||
|
||||
`POST /api/v1/takeovers/create`
|
||||
|
||||
atau
|
||||
|
||||
`POST /api/v1/reserve-acs/takeovers/create`
|
||||
|
||||
### Headers
|
||||
|
||||
Gunakan header umum API proyek:
|
||||
|
||||
```http
|
||||
Authorization: Bearer <token>
|
||||
Content-Type: application/json
|
||||
Accept: application/json
|
||||
```
|
||||
|
||||
### Body
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"type": "takeover",
|
||||
"attributes": {
|
||||
"base_id": "019d6771-5fb5-7337-837f-bc5ed85181a1",
|
||||
"duty_date": "2026-04-15",
|
||||
"notes": "Opsional catatan takeover",
|
||||
"shift_time": {
|
||||
"shift_start": "06:00",
|
||||
"shift_end": "18:00"
|
||||
},
|
||||
"roster_detail": {
|
||||
"pilot": [
|
||||
{
|
||||
"id": "018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d",
|
||||
"crew_type": "main",
|
||||
"flight_instructor": true,
|
||||
"line_checker": false,
|
||||
"supervisor": false,
|
||||
"examiner": false,
|
||||
"co_pilot": true,
|
||||
"shift_date": {
|
||||
"date_start": "2026-04-15",
|
||||
"date_end": "2026-04-15"
|
||||
},
|
||||
"shift_time": {
|
||||
"shift_start": "06:00",
|
||||
"shift_end": "14:00"
|
||||
}
|
||||
}
|
||||
],
|
||||
"doctor": [
|
||||
{
|
||||
"id": "018f3a5c-7a6f-7c2a-8d4a-4b5b1f6c8e9d"
|
||||
}
|
||||
],
|
||||
"rescuer": [],
|
||||
"helper": [],
|
||||
"other_person": [
|
||||
{
|
||||
"name": "Guest Person",
|
||||
"mobile_phone": "+43-1234",
|
||||
"email": "guest@example.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
"helicopter_id": "019d6771-5fb5-7337-837f-bc5ed85181a1",
|
||||
"inspection": {
|
||||
"inspection_date": "2026-04-15",
|
||||
"before": {
|
||||
"oil_engine_nr1_checked": true,
|
||||
"oil_engine_nr2_checked": false,
|
||||
"hydraulic_lh_checked": true,
|
||||
"hydraulic_rh_checked": true,
|
||||
"oil_transmission_mgb_checked": true,
|
||||
"oil_transmission_igb_checked": true,
|
||||
"oil_transmission_tgb_checked": true,
|
||||
"fuel_amount": 50.5,
|
||||
"fuel_unit": "LT",
|
||||
"fuel_added_amount": 10,
|
||||
"note": "Opsional note inspeksi sebelum terbang",
|
||||
"file_checklist": [
|
||||
{
|
||||
"helicopter_file_id": "019d7000-aaaa-7bbb-8ccc-111111111111",
|
||||
"is_done": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"prepare": {
|
||||
"notam_briefing": true,
|
||||
"weather_briefing": true,
|
||||
"operational_flight_plan": false,
|
||||
"file_checklist": [
|
||||
{
|
||||
"helicopter_file_id": "019d7000-bbbb-7ccc-8ddd-222222222222",
|
||||
"is_done": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Penjelasan Field
|
||||
|
||||
### `data`
|
||||
|
||||
Container utama request.
|
||||
|
||||
### `data.type`
|
||||
|
||||
Nilai yang diterima:
|
||||
|
||||
1. `takeover`
|
||||
2. `takeover_create`
|
||||
|
||||
### `data.attributes.base_id`
|
||||
|
||||
Wajib. UUID base yang dipakai untuk takeover.
|
||||
|
||||
Backend akan memvalidasi:
|
||||
|
||||
1. format UUID
|
||||
2. base harus ada di database
|
||||
|
||||
### `data.attributes.duty_date`
|
||||
|
||||
Wajib. Format tanggal harus `YYYY-MM-DD`.
|
||||
|
||||
Contoh:
|
||||
|
||||
`2026-04-15`
|
||||
|
||||
### `data.attributes.notes`
|
||||
|
||||
Opsional.
|
||||
|
||||
Gunakan untuk catatan tambahan takeover. Jika tidak ada, field ini boleh tidak dikirim atau dikirim `null`.
|
||||
|
||||
### `data.attributes.shift_time`
|
||||
|
||||
Secara schema tidak diberi `validate:"required"`, tetapi secara proses bisnis ini dianggap bagian penting dari takeover.
|
||||
|
||||
Format:
|
||||
|
||||
```json
|
||||
{
|
||||
"shift_start": "06:00",
|
||||
"shift_end": "18:00"
|
||||
}
|
||||
```
|
||||
|
||||
Keterangan:
|
||||
|
||||
1. `shift_start` adalah waktu mulai tugas.
|
||||
2. `shift_end` adalah waktu selesai tugas.
|
||||
|
||||
Jika frontend ingin aman, selalu kirim kedua field ini.
|
||||
|
||||
### `data.attributes.roster_detail`
|
||||
|
||||
Wajib secara bisnis. Berisi daftar crew yang akan masuk ke `duty_roster`.
|
||||
|
||||
Strukturnya terdiri dari:
|
||||
|
||||
1. `pilot`
|
||||
2. `doctor`
|
||||
3. `rescuer`
|
||||
4. `helper`
|
||||
5. `other_person`
|
||||
|
||||
### `data.attributes.helicopter_id`
|
||||
|
||||
Wajib. UUID helicopter yang dipakai pada takeover.
|
||||
|
||||
Backend akan memvalidasi:
|
||||
|
||||
1. format UUID
|
||||
2. helicopter harus ada di database
|
||||
|
||||
### `data.attributes.inspection`
|
||||
|
||||
Wajib. Ini adalah paket inspeksi takeover.
|
||||
|
||||
#### `inspection.inspection_date`
|
||||
|
||||
Wajib. Format `YYYY-MM-DD`.
|
||||
|
||||
#### `inspection.before`
|
||||
|
||||
Wajib sebagai objek, tetapi isi field di dalamnya sebagian besar opsional.
|
||||
|
||||
Field opsional:
|
||||
|
||||
1. `oil_engine_nr1_checked`
|
||||
2. `oil_engine_nr2_checked`
|
||||
3. `hydraulic_lh_checked`
|
||||
4. `hydraulic_rh_checked`
|
||||
5. `oil_transmission_mgb_checked`
|
||||
6. `oil_transmission_igb_checked`
|
||||
7. `oil_transmission_tgb_checked`
|
||||
8. `fuel_amount`
|
||||
9. `fuel_unit`
|
||||
10. `fuel_added_amount`
|
||||
11. `note`
|
||||
12. `file_checklist`
|
||||
|
||||
#### `inspection.before.fuel_unit`
|
||||
|
||||
Jika dikirim, nilai yang diterima backend adalah:
|
||||
|
||||
1. `LT`
|
||||
2. `KG`
|
||||
3. `POUND`
|
||||
|
||||
Kalau nilainya tidak valid, request akan gagal.
|
||||
|
||||
#### `inspection.before.file_checklist`
|
||||
|
||||
Array opsional.
|
||||
|
||||
Setiap item harus punya:
|
||||
|
||||
1. `helicopter_file_id`
|
||||
2. `is_done`
|
||||
|
||||
#### `inspection.prepare`
|
||||
|
||||
Wajib sebagai objek, tetapi field di dalamnya opsional.
|
||||
|
||||
Field opsional:
|
||||
|
||||
1. `notam_briefing`
|
||||
2. `weather_briefing`
|
||||
3. `operational_flight_plan`
|
||||
4. `file_checklist`
|
||||
|
||||
#### `inspection.prepare.file_checklist`
|
||||
|
||||
Array opsional.
|
||||
|
||||
Setiap item harus punya:
|
||||
|
||||
1. `helicopter_file_id`
|
||||
2. `is_done`
|
||||
|
||||
## Detail Roster
|
||||
|
||||
### `roster_detail.pilot`
|
||||
|
||||
Array pilot. Setiap item dapat berisi:
|
||||
|
||||
1. `id` - UUID crew
|
||||
2. `crew_type` - biasanya `main` atau `additional`
|
||||
3. `flight_instructor` - boolean
|
||||
4. `line_checker` - boolean
|
||||
5. `supervisor` - boolean
|
||||
6. `examiner` - boolean
|
||||
7. `co_pilot` - boolean
|
||||
8. `shift_date` - opsional
|
||||
9. `shift_time` - opsional
|
||||
|
||||
### `roster_detail.doctor`
|
||||
|
||||
Array crew doctor.
|
||||
|
||||
Setiap item:
|
||||
|
||||
1. `id` - UUID crew
|
||||
2. `shift_date` - opsional
|
||||
3. `shift_time` - opsional
|
||||
|
||||
### `roster_detail.rescuer`
|
||||
|
||||
Array crew rescuer.
|
||||
|
||||
Setiap item:
|
||||
|
||||
1. `id` - UUID crew
|
||||
2. `shift_date` - opsional
|
||||
3. `shift_time` - opsional
|
||||
|
||||
### `roster_detail.helper`
|
||||
|
||||
Array crew helper.
|
||||
|
||||
Setiap item:
|
||||
|
||||
1. `id` - UUID crew
|
||||
2. `shift_date` - opsional
|
||||
3. `shift_time` - opsional
|
||||
|
||||
### `roster_detail.other_person`
|
||||
|
||||
Array orang tambahan yang bukan crew terdaftar.
|
||||
|
||||
Setiap item:
|
||||
|
||||
1. `name`
|
||||
2. `mobile_phone`
|
||||
3. `email`
|
||||
|
||||
## Field Optional Yang Perlu Diperhatikan Frontend
|
||||
|
||||
Ini yang paling penting supaya frontend tidak bingung:
|
||||
|
||||
### Optional level 1
|
||||
|
||||
1. `notes`
|
||||
|
||||
### Optional level 2 di `inspection.before`
|
||||
|
||||
1. Semua checkbox `*_checked`
|
||||
2. `fuel_amount`
|
||||
3. `fuel_unit`
|
||||
4. `fuel_added_amount`
|
||||
5. `note`
|
||||
6. `file_checklist`
|
||||
|
||||
### Optional level 2 di `inspection.prepare`
|
||||
|
||||
1. `notam_briefing`
|
||||
2. `weather_briefing`
|
||||
3. `operational_flight_plan`
|
||||
4. `file_checklist`
|
||||
|
||||
### Optional level 2 di roster detail
|
||||
|
||||
1. `shift_date`
|
||||
2. `shift_time`
|
||||
|
||||
### Field yang tetap harus dianggap wajib oleh frontend
|
||||
|
||||
Walaupun beberapa field di struct tidak pakai `validate:"required"`, frontend sebaiknya tetap menyiapkan:
|
||||
|
||||
1. `base_id`
|
||||
2. `duty_date`
|
||||
3. `roster_detail`
|
||||
4. `helicopter_id`
|
||||
5. `inspection`
|
||||
6. `inspection.inspection_date`
|
||||
|
||||
Alasannya:
|
||||
|
||||
1. backend memakai data itu untuk membangun transaksi
|
||||
2. frontend akan lebih stabil jika payload selalu lengkap
|
||||
3. respons error dari backend akan lebih mudah dihindari
|
||||
|
||||
## Contoh Request Minimal Yang Aman
|
||||
|
||||
Kalau ingin payload ringkas tetapi masih aman, gunakan pola berikut:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"type": "takeover",
|
||||
"attributes": {
|
||||
"base_id": "019d6771-5fb5-7337-837f-bc5ed85181a1",
|
||||
"duty_date": "2026-04-15",
|
||||
"shift_time": {
|
||||
"shift_start": "06:00",
|
||||
"shift_end": "18:00"
|
||||
},
|
||||
"roster_detail": {
|
||||
"pilot": [],
|
||||
"doctor": [],
|
||||
"rescuer": [],
|
||||
"helper": [],
|
||||
"other_person": []
|
||||
},
|
||||
"helicopter_id": "019d6771-5fb5-7337-837f-bc5ed85181a1",
|
||||
"inspection": {
|
||||
"inspection_date": "2026-04-15",
|
||||
"before": {},
|
||||
"prepare": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Catatan:
|
||||
|
||||
1. Ini minimal secara struktur.
|
||||
2. Secara bisnis, frontend biasanya tetap perlu mengisi roster dan checklist sesuai kebutuhan operasional.
|
||||
|
||||
## Response Sukses
|
||||
|
||||
HTTP status:
|
||||
|
||||
`201 Created`
|
||||
|
||||
Contoh bentuk response:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": {
|
||||
"type": "takeover",
|
||||
"attributes": {
|
||||
"takeover_ac_id": "019d8000-aaaa-7bbb-8ccc-333333333333",
|
||||
"duty_roster_id": "019d8000-bbbb-7ccc-8ddd-444444444444",
|
||||
"flight_id": "019d8000-cccc-7ddd-8eee-555555555555",
|
||||
"reserve_ac_id": "019d8000-dddd-7eee-8fff-666666666666",
|
||||
"flight_inspection_id": "019d8000-eeee-7fff-9000-777777777777",
|
||||
"shift_start": "06:00",
|
||||
"shift_end": "18:00",
|
||||
"base_id": "019d6771-5fb5-7337-837f-bc5ed85181a1",
|
||||
"duty_date": "2026-04-15",
|
||||
"helicopter_id": "019d6771-5fb5-7337-837f-bc5ed85181a1",
|
||||
"notes": "Opsional catatan takeover",
|
||||
"roster_detail": {
|
||||
"pilot": [],
|
||||
"doctor": [],
|
||||
"rescuer": [],
|
||||
"helper": [],
|
||||
"other_person": []
|
||||
},
|
||||
"inspection": {},
|
||||
"flight": {},
|
||||
"duty_roster": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Yang Umum
|
||||
|
||||
### 400 Bad Request
|
||||
|
||||
Biasanya terjadi karena:
|
||||
|
||||
1. JSON tidak valid
|
||||
2. create gagal di service
|
||||
3. UUID tidak bisa diproses
|
||||
4. data referensi tidak ditemukan
|
||||
|
||||
### 422 Unprocessable Entity
|
||||
|
||||
Biasanya terjadi karena:
|
||||
|
||||
1. `type` salah
|
||||
2. field wajib tidak ada
|
||||
3. format UUID salah
|
||||
4. tanggal bukan format `YYYY-MM-DD`
|
||||
5. `fuel_unit` tidak valid
|
||||
6. roster detail tidak valid
|
||||
|
||||
## Saran Implementasi Frontend
|
||||
|
||||
1. Selalu kirim payload lengkap dari form state.
|
||||
2. Jangan kirim field boolean sebagai string.
|
||||
3. Pastikan UUID sudah tervalidasi sebelum submit.
|
||||
4. Validasi tanggal di frontend dengan format `YYYY-MM-DD`.
|
||||
5. Jika user tidak isi field opsional, lebih baik field itu diomit daripada dikirim string kosong.
|
||||
6. Setelah request sukses, gunakan response backend untuk refresh state halaman.
|
||||
|
||||
## Catatan Penting
|
||||
|
||||
1. `takeover` ini bersifat atomic.
|
||||
2. Jika satu bagian gagal, semua data batal dibuat.
|
||||
3. `notes` adalah satu-satunya field tingkat atas yang jelas opsional.
|
||||
4. Banyak field di nested object yang secara schema terlihat opsional, tetapi secara flow bisnis tetap perlu diisi agar hasilnya masuk akal.
|
||||
Reference in New Issue
Block a user