POST /create-composite
Spesifikasi endpoint create-composite untuk operasi master-detail
Endpoint /create-composite digunakan untuk menyisipkan data header (master) beserta detail item dalam satu request atomik. Seluruh operasi dijalankan dalam satu transaksi database sehingga jika salah satu bagian gagal, seluruh operasi di-rollback.
Referensi Cepat (Quick Reference)
| Properti | Nilai |
|---|---|
| Method | POST |
| URL | /api/{project}/{endpoint}/create-composite |
| Content-Type | application/json |
| Status Sukses | 201 Created |
| Database | PostgreSQL, MySQL, Oracle |
| Transaksi | Atomik (header + detail dalam satu transaksi) |
| Cache | Invalidasi otomatis setelah create berhasil |
| Event Lifecycle | onBeforeInsert → INSERT header → INSERT details → onAfterInsert |
Ikhtisar (Overview)
Endpoint ini dirancang untuk skenario master-detail seperti invoice dengan item, purchase order dengan line item, atau stock inbound dengan detail barang. Dalam satu request, data header di-insert terlebih dahulu, kemudian seluruh detail item di-insert secara berurutan. Jika terjadi kegagalan pada tahap manapun, seluruh transaksi di-rollback untuk menjaga konsistensi (consistency) data.
Primary key untuk header dan setiap detail item di-generate otomatis sebagai UUID. Foreign key pada detail item yang mereferensikan header juga diisi secara otomatis dari primary key header yang baru dibuat.
Format Request (Request Format)
Struktur Bersarang (Nested Structure)
Request body menggunakan struktur bersarang di mana root key adalah nama tabel header. Di dalam object header, terdapat array dengan nama tabel detail yang berisi item-item detail.
{
"{header_table}": {
field_1: value,
field_2: value,
"{detail_table}": [
{ detail_field_1: value, detail_field_2: value },
{ detail_field_1: value, detail_field_2: value }
]
}
}| Komponen | Keterangan |
|---|---|
| Root key | Nama tabel header (contoh: stock_inbound) |
| Field header | Pasangan field-value untuk record header |
| Array detail | Array object berisi item-item detail, menggunakan nama tabel detail sebagai key |
Root key pada request body harus sesuai dengan nama tabel header yang dikonfigurasi di payload. Jika root key tidak cocok, server mengembalikan response error 400.
Contoh Request (Request Example)
{
"stock_inbound": {
"inbound_number": "INB/2026/001",
"inbound_date": "2026-04-16",
"supplier_id": "b1000000-0000-0000-0000-000000000000",
"warehouse_id": "d1000000-0000-0000-0000-000000000000",
"notes": "First batch delivery",
"stock_inbound_item": [
{
"line_number": 1,
"item_product_id": "04d71c62-0000-0000-0000-000000000000",
"qty_received": 25,
"uom": "pcs",
"unit_price": 500000
},
{
"line_number": 2,
"item_product_id": "15e82d73-0000-0000-0000-000000000000",
"qty_received": 10,
"uom": "pcs",
"unit_price": 750000
}
]
}
}Body Options
Endpoint /create-composite 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.
{
"data": {
"stock_inbound": {
"inbound_number": "INB/2026/001",
"inbound_date": "2026-04-16",
"supplier_id": "b1000000-0000-0000-0000-000000000000",
"warehouse_id": "d1000000-0000-0000-0000-000000000000",
"stock_inbound_item": [
{
"line_number": 1,
"item_product_id": "04d71c62-0000-0000-0000-000000000000",
"qty_received": 25,
"uom": "pcs",
"unit_price": 500000
}
]
}
},
"options": {
"auto_approve": false
}
}Format Response (Response Format)
Response Sukses (Success Response)
HTTP 201 Created
{
"success": true,
"message": "stock_inbound data successfully added",
"data": {
"stock_inbound_id": "a1b2c3d4-0000-0000-0000-000000000000",
"inbound_number": "INB/2026/001",
"inbound_date": "2026-04-16",
"supplier_id": "b1000000-0000-0000-0000-000000000000",
"warehouse_id": "d1000000-0000-0000-0000-000000000000",
"notes": "First batch delivery",
"total_items": 2,
"total_qty": 35,
"total_amount": 20000000,
"created_at": "2026-04-16T10:30:00.000Z",
"created_by": "Input from API",
"stock_inbound_item": [
{
"stock_inbound_item_id": "e5f6a7b8-0000-0000-0000-000000000001",
"stock_inbound_id": "a1b2c3d4-0000-0000-0000-000000000000",
"line_number": 1,
"item_product_id": "04d71c62-0000-0000-0000-000000000000",
"qty_received": 25,
"uom": "pcs",
"unit_price": 500000,
"amount": 12500000,
"created_at": "2026-04-16T10:30:00.000Z",
"created_by": "Input from API"
},
{
"stock_inbound_item_id": "e5f6a7b8-0000-0000-0000-000000000002",
"stock_inbound_id": "a1b2c3d4-0000-0000-0000-000000000000",
"line_number": 2,
"item_product_id": "15e82d73-0000-0000-0000-000000000000",
"qty_received": 10,
"uom": "pcs",
"unit_price": 750000,
"amount": 7500000,
"created_at": "2026-04-16T10:30:00.000Z",
"created_by": "Input from API"
}
]
},
"timestamp": "2026-04-16T10:30:00.000Z"
}Response Error (Error Responses)
400 — Root key tidak sesuai:
{
"success": false,
"error": "Invalid payload",
"message": "Root key must be 'stock_inbound'",
"timestamp": "2026-04-16T10:30:00.000Z"
}400 — Array detail kosong:
{
"success": false,
"error": "Invalid payload",
"message": "Detail items cannot be empty",
"timestamp": "2026-04-16T10:30:00.000Z"
}400 — Validasi gagal:
{
"success": false,
"error": "Validation failed",
"message": "Invalid data",
"errors": {
"inbound_number": ["Field inbound_number is required"],
"stock_inbound_item[0].qty_received": ["Field qty_received must be greater than 0"]
},
"timestamp": "2026-04-16T10:30:00.000Z"
}409 — Duplicate key:
{
"success": false,
"error": "Duplicate entry",
"message": "Inbound number already exists",
"timestamp": "2026-04-16T10:30:00.000Z"
}500 — Server error:
{
"success": false,
"error": "Internal server error",
"message": "An unexpected error occurred",
"timestamp": "2026-04-16T10:30:00.000Z"
}Field Otomatis (Auto-Populated Fields)
| Field | Nilai | Keterangan |
|---|---|---|
| Header primary key | UUID v4 | Di-generate otomatis untuk record header |
| Detail primary key | UUID v4 | Di-generate otomatis untuk setiap record detail |
| Detail foreign key | UUID header | Diisi otomatis dari primary key header yang baru dibuat |
created_at | Timestamp saat ini | Di-set pada header dan setiap detail |
created_by | "Input from API" | Di-set pada header dan setiap detail |
Kalkulasi Otomatis (Auto Calculate)
Jika konfigurasi kalkulasi diaktifkan di payload, sistem menjalankan perhitungan otomatis pada dua level:
Level detail item:
| Kalkulasi | Contoh Formula |
|---|---|
| Perkalian field | amount = qty_received * unit_price |
Level header (agregasi dari detail):
| Kalkulasi | Contoh Formula |
|---|---|
| Count detail | total_items = COUNT(stock_inbound_item) |
| Sum field | total_qty = SUM(qty_received) |
| Sum field | total_amount = SUM(amount) |
Kalkulasi otomatis dijalankan setelah seluruh detail item berhasil di-insert. Hasil kalkulasi level header kemudian di-update ke record header sebelum transaksi di-commit.
Perilaku Cache (Cache Behavior)
Setelah operasi create-composite 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 /read-composite untuk mengambil data header beserta detail
- POST /update-composite untuk memperbarui data header dan detail
- Kode Error untuk referensi lengkap HTTP status code