RESTForge

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)

PropertiNilai
MethodPOST
URL/api/{project}/{endpoint}/change-status
Content-Typeapplication/json
Status Sukses200 OK
DatabasePostgreSQL
CacheInvalidasi otomatis setelah perubahan status berhasil
Distributed LockWRITE lock per-record
Event LifecycleonBeforeWorkflow → 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)

ParameterTipeWajibKeterangan
{primaryKey}stringYaPrimary key record target. Dapat menggunakan alias id sebagai pengganti nama field PK eksplisit
statusstringYaStatus tujuan yang akan diterapkan pada record
remarksstringTidakCatatan atau alasan perubahan status
updated_bystringTidakIdentitas 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:

POST /api/mini-inventory/stock-inbound/change-status
{
    "stock_inbound_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "approved"
}

Menggunakan alias id sebagai primary key:

POST /api/mini-inventory/stock-inbound/change-status
{
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "approved",
    "remarks": "Dokumen penerimaan sudah lengkap"
}

Dengan informasi pelaku perubahan:

POST /api/mini-inventory/stock-inbound/change-status
{
    "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.

Contoh konfigurasi workflow.transitions
{
    "workflow": {
        "transitions": {
            "draft": ["pending"],
            "pending": ["approved", "rejected"],
            "approved": ["completed"],
            "rejected": ["pending"],
            "completed": []
        }
    }
}

Berdasarkan konfigurasi di atas:

  • Status draft hanya dapat berpindah ke pending
  • Status pending dapat berpindah ke approved atau rejected
  • Status rejected dapat dikembalikan ke pending
  • Status completed adalah 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).

Contoh konfigurasi workflow hooks
{
    "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

ModePerilakuKegagalan
blocking: trueMenunggu response dari service eksternal sebelum melanjutkanROLLBACK seluruh operasi dan mengembalikan error 502
blocking: falseFire-and-forget, tidak menunggu responseOperasi 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.

VariableKeterangan
{{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 OK

Distributed 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

On this page