POST /change-status
Spesifikasi endpoint change-status untuk transisi status workflow
Endpoint /change-status digunakan untuk mengubah status workflow pada sebuah record. Endpoint ini mendukung validasi transisi, hook API call per-status, dan distributed lock.
Referensi Cepat (Quick Reference)
| Properti | Nilai |
|---|---|
| Method | POST |
| URL | /api/{project}/{endpoint}/change-status |
| Content-Type | application/json |
| Status Sukses | 200 OK |
| Database | PostgreSQL |
| Cache | Invalidasi otomatis setelah perubahan status berhasil |
| Distributed Lock | WRITE lock per-record |
| Event Lifecycle | onBeforeWorkflow → Workflow hooks → UPDATE → onAfterWorkflow |
Endpoint /change-status saat ini hanya tersedia untuk database PostgreSQL. Dukungan untuk MySQL dan Oracle belum dikonfirmasi.
Ikhtisar (Overview)
Request body wajib menyertakan primary key dan status tujuan. Sistem akan memvalidasi transisi status (jika dikonfigurasi), menjalankan hook API call terkait, kemudian memperbarui field status pada record target. Seluruh proses berjalan dalam mekanisme distributed lock untuk mencegah race condition.
Jika konfigurasi workflow.transitions tidak didefinisikan, perubahan status bersifat bebas tanpa pembatasan. Jika dikonfigurasi, hanya transisi yang terdaftar dalam mapping yang diperbolehkan.
Format Request (Request Format)
Parameter (Parameters)
| Parameter | Tipe | Wajib | Keterangan |
|---|---|---|---|
{primaryKey} | string | Ya | Primary key record target. Dapat menggunakan alias id sebagai pengganti nama field PK eksplisit |
status | string | Ya | Status tujuan yang akan diterapkan pada record |
remarks | string | Tidak | Catatan atau alasan perubahan status |
updated_by | string | Tidak | Identitas pelaku perubahan. Jika tidak dikirim, diisi otomatis oleh sistem |
Primary key dan status bersifat wajib pada setiap request /change-status. Request tanpa salah satu dari keduanya akan menghasilkan response error 400.
Contoh Request (Request Examples)
Perubahan status dasar:
{
"stock_inbound_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "approved"
}Menggunakan alias id sebagai primary key:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "approved",
"remarks": "Dokumen penerimaan sudah lengkap"
}Dengan informasi pelaku perubahan:
{
"stock_inbound_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "rejected",
"remarks": "Jumlah barang tidak sesuai dengan PO",
"updated_by": "admin@warehouse.com"
}Body Options
Endpoint /change-status mendukung format request body alternatif {data, options} untuk mengirimkan opsi tambahan yang dapat dibaca oleh component handler dan processor. Detail lengkap tersedia di halaman Body Options.
Format Response (Response Format)
Response Sukses (Success Response)
HTTP 200 OK
{
"success": true,
"message": "stock_inbound status changed successfully",
"data": {
"stock_inbound_id": "550e8400-e29b-41d4-a716-446655440000",
"inbound_code": "INB-2026-0042",
"status": "approved",
"updated_at": "2026-04-16T10:30:00.000Z",
"updated_by": "admin@warehouse.com"
},
"workflow": {
"previousStatus": "pending",
"newStatus": "approved",
"hooksExecuted": ["onBefore:notify-approval-service", "onAfter:sync-inventory"]
},
"timestamp": "2026-04-16T10:30:00.000Z"
}Response Error (Error Responses)
400 — Payload kosong:
{
"success": false,
"error": "Invalid payload",
"message": "Payload cannot be empty",
"timestamp": "2026-04-16T10:30:00.000Z"
}400 — Primary key atau status tidak dikirim:
{
"success": false,
"error": "Invalid payload",
"message": "Primary key and status are required for change-status",
"timestamp": "2026-04-16T10:30:00.000Z"
}404 — Record tidak ditemukan:
{
"success": false,
"error": "Not found",
"message": "stock_inbound data not found",
"timestamp": "2026-04-16T10:30:00.000Z"
}409 — Lock conflict:
{
"success": false,
"error": "Lock conflict",
"message": "Record is currently being modified by another process",
"timestamp": "2026-04-16T10:30:00.000Z"
}422 — Transisi tidak diperbolehkan:
{
"success": false,
"error": "Transition not allowed",
"message": "Cannot transition from 'rejected' to 'approved'",
"timestamp": "2026-04-16T10:30:00.000Z"
}502 — Blocking hook gagal:
{
"success": false,
"error": "Hook execution failed",
"message": "Blocking hook 'notify-approval-service' failed: upstream service returned 500",
"timestamp": "2026-04-16T10:30:00.000Z"
}500 — Internal server error:
{
"success": false,
"error": "Internal server error",
"message": "An unexpected error occurred",
"timestamp": "2026-04-16T10:30:00.000Z"
}Validasi Transisi (Transition Validation)
Validasi transisi dikonfigurasi melalui objek workflow.transitions di payload. Objek ini memetakan setiap status ke daftar status tujuan yang diperbolehkan.
{
"workflow": {
"transitions": {
"draft": ["pending"],
"pending": ["approved", "rejected"],
"approved": ["completed"],
"rejected": ["pending"],
"completed": []
}
}
}Berdasarkan konfigurasi di atas:
- Status
drafthanya dapat berpindah kepending - Status
pendingdapat berpindah keapprovedataurejected - Status
rejecteddapat dikembalikan kepending - Status
completedadalah terminal state (array kosong) dan tidak dapat berpindah ke status manapun
Jika objek workflow.transitions tidak dikonfigurasi, perubahan status bersifat bebas tanpa pembatasan transisi.
Terminal state ditandai dengan array kosong ([]) pada mapping transisi. Setiap upaya mengubah status dari terminal state akan menghasilkan error 422.
Hook API Call
Endpoint /change-status mendukung hook berupa API call yang dieksekusi pada setiap transisi status. Hook dikonfigurasi per status tujuan dengan dua timing eksekusi: onBefore (sebelum UPDATE) dan onAfter (setelah UPDATE).
{
"workflow": {
"hooks": {
"approved": {
"onBefore": [
{
"name": "notify-approval-service",
"url": "https://api.internal/approval/confirm",
"method": "POST",
"blocking": true,
"body": {
"record_id": "{{id}}",
"new_status": "{{newStatus}}",
"changed_by": "{{user_id}}"
}
}
],
"onAfter": [
{
"name": "sync-inventory",
"url": "https://api.internal/inventory/sync",
"method": "POST",
"blocking": false,
"body": {
"inbound_id": "{{id}}",
"table": "{{tableName}}"
}
}
]
}
}
}
}Blocking vs Non-Blocking
| Mode | Perilaku | Kegagalan |
|---|---|---|
blocking: true | Menunggu response dari service eksternal sebelum melanjutkan | ROLLBACK seluruh operasi dan mengembalikan error 502 |
blocking: false | Fire-and-forget, tidak menunggu response | Operasi tetap dilanjutkan, kegagalan hook diabaikan |
Hook onBefore dengan blocking: true berjalan sebelum statement UPDATE dieksekusi. Jika hook gagal, seluruh operasi di-rollback dan status record tidak berubah.
Hook onAfter dengan blocking: false cocok untuk side effect seperti notifikasi atau sinkronisasi yang tidak mempengaruhi keberhasilan operasi utama.
Template Variable
Hook body dan URL mendukung template variable yang di-resolve secara dinamis pada saat eksekusi.
| Variable | Keterangan |
|---|---|
{{id}} | Nilai primary key record target |
{{newStatus}} | Status tujuan yang diminta |
{{oldStatus}} | Status record saat ini (sebelum perubahan) |
{{remarks}} | Nilai field remarks dari request body |
{{tableName}} | Nama tabel database dari endpoint |
{{user_id}} | Identitas pelaku perubahan |
{{timestamp}} | Timestamp eksekusi dalam format ISO 8601 |
{{record.<field>}} | Nilai field dari record saat ini di database, misalnya {{record.inbound_code}} |
{{requestData.<field>}} | Nilai field dari request body, misalnya {{requestData.remarks}} |
Alur Eksekusi (Execution Flow)
Request masuk
│
▼
Akuisisi distributed lock (WRITE)
│
▼
Validasi: primary key + status ada?
│ Tidak → 400
▼
Cari record di database
│ Tidak ditemukan → 404
▼
Validasi transisi (jika dikonfigurasi)
│ Tidak diperbolehkan → 422
▼
onBeforeWorkflow hook
│
▼
Jalankan onBefore hooks (per target status)
│ Blocking hook gagal → 502 + ROLLBACK
▼
UPDATE status di database
│
▼
Jalankan onAfter hooks (per target status)
│
▼
onAfterWorkflow hook
│
▼
Invalidasi cache
│
▼
Lepaskan distributed lock
│
▼
Response 200 OKDistributed Lock
Endpoint /change-status mengakuisisi WRITE lock per-record berdasarkan primary key sebelum memulai proses. Lock ini mencegah operasi tulis lain (update, adjust, delete, change-status) pada record yang sama berjalan secara bersamaan.
Jika lock tidak dapat diperoleh karena record sedang diproses oleh request lain, server mengembalikan response error 409.
Lock dilepaskan secara otomatis setelah seluruh proses selesai, baik berhasil maupun gagal.
Perilaku Cache (Cache Behavior)
Setelah operasi change-status berhasil, seluruh cache terkait endpoint ini di-invalidasi secara otomatis. Hal ini memastikan endpoint /read, /datatables, dan /lookup mengembalikan data terbaru pada request berikutnya.
Langkah Selanjutnya (Next Steps)
- POST /update untuk memperbarui field selain status
- POST /first untuk mengambil data record setelah perubahan status
- Kode Error untuk referensi lengkap HTTP status code