8.5 KiB
8.5 KiB
UI Data Contract Frontend-Backend Sistem Inventory Walet
1. Tujuan
Dokumen ini menjelaskan kontrak data utama antara frontend dan backend agar implementasi UI tidak salah tafsir, terutama pada area lot, allocation, costing, sorting, dan traceability.
2. Prinsip Umum
- backend adalah source of truth untuk data transaksi
- frontend boleh menyimpan draft workflow lokal sebelum submit
- angka quantity dan cost harus selalu dikirim dalam bentuk numerik
- ID utama menggunakan integer/bigint
- status harus dikirim dalam kode string yang konsisten
- field read-only harus dibedakan jelas dari field editable
3. Format Response Umum
Contoh standar response list:
{
"data": [],
"meta": {
"page": 1,
"per_page": 20,
"total": 100
}
}
Contoh standar response detail:
{
"data": {
"id": 1
}
}
Contoh error:
{
"message": "Validation error",
"errors": {
"qty": ["qty harus lebih besar dari 0"]
}
}
4. Purchase Contract
Purchase list item
{
"id": 1,
"purchase_no": "PO-20260428-001",
"supplier": {
"id": 1,
"name": "Supplier A",
"bank_name": "BCA",
"bank_account_number": "1234567890"
},
"purchase_date": "2026-04-28",
"status": "SUBMITTED",
"line_count": 3,
"grand_total": 1220000000
}
Purchase detail
{
"id": 1,
"purchase_no": "PO-20260428-001",
"supplier": {
"id": 1,
"name": "Supplier A",
"bank_name": "BCA",
"bank_account_number": "1234567890"
},
"purchase_date": "2026-04-28",
"supplier_invoice_no": "INV-SUP-A-001",
"status": "SUBMITTED",
"notes": "Pembelian campuran",
"lines": [
{
"id": 1,
"item_type": { "id": 1, "name": "Jenis A" },
"item_grade": { "id": 1, "name": "Grade A" },
"qty_ordered": 50,
"unit": { "id": 1, "code": "KG" },
"unit_price": 18000000,
"subtotal": 900000000,
"classification_status": "FINAL"
}
]
}
5. Receipt Contract
Receipt detail
{
"id": 1,
"receipt_no": "RCV-20260428-001",
"purchase": {
"id": 1,
"purchase_no": "PO-20260428-001"
},
"supplier": {
"id": 1,
"name": "Supplier A",
"bank_name": "BCA",
"bank_account_number": "1234567890"
},
"receipt_date": "2026-04-28",
"status": "FINALIZED",
"lines": [
{
"id": 1,
"purchase_line_id": 1,
"item_type": { "id": 1, "name": "Jenis A" },
"item_grade": { "id": 1, "name": "Grade A" },
"qty_received": 50,
"qty_accepted": 50,
"qty_rejected": 0,
"unit_cost": 18000000,
"warehouse": { "id": 1, "name": "Gudang Pusat" },
"location": { "id": 1, "name": "Rak A1" }
}
],
"generated_lots": [
{
"id": 1,
"lot_code": "LOT-260428-SUPA-001",
"status": "ACTIVE"
}
]
}
6. Lot Contract
Lot list item
{
"id": 1,
"lot_code": "LOT-260428-SUPA-001",
"supplier": "Supplier A",
"item_type": "Jenis A",
"item_grade": "Grade A",
"original_qty": 50,
"available_qty": 30,
"unit_cost": 18000000,
"warehouse": "Gudang Pusat",
"location": "Rak A1",
"aging_days": 3,
"status": "ACTIVE"
}
Lot detail
{
"id": 1,
"lot_code": "LOT-260428-SUPA-001",
"supplier": {
"id": 1,
"name": "Supplier A",
"bank_name": "BCA",
"bank_account_number": "1234567890"
},
"item_type": {
"id": 1,
"name": "Jenis A"
},
"item_grade": {
"id": 1,
"name": "Grade A"
},
"original_qty": 50,
"available_qty": 30,
"reserved_qty": 0,
"damaged_qty": 0,
"shrinkage_qty": 0,
"unit_cost": 18000000,
"warehouse": {
"id": 1,
"name": "Gudang Pusat"
},
"location": {
"id": 1,
"name": "Rak A1"
},
"status": "ACTIVE",
"parent_lot": null,
"child_lots": [],
"labels": [
{
"type": "QR",
"value": "LOT-260428-SUPA-001"
}
]
}
7. Sales Contract
Sales list item
{
"id": 1,
"sales_no": "SLS-20260428-001",
"customer": {
"id": 1,
"name": "Customer A",
"bank_name": "BRI",
"bank_account_number": "111222333444"
},
"sales_date": "2026-04-28",
"status": "CONFIRMED",
"grand_total": 660000000,
"costing_total": 550000000,
"gross_margin": 110000000
}
Sales detail
{
"id": 1,
"sales_no": "SLS-20260428-001",
"customer": {
"id": 1,
"name": "Customer A",
"bank_name": "BRI",
"bank_account_number": "111222333444"
},
"sales_date": "2026-04-28",
"status": "CONFIRMED",
"lines": [
{
"id": 1,
"item_type": { "id": 1, "name": "Jenis A" },
"item_grade": { "id": 1, "name": "Grade A" },
"qty_sold": 30,
"selling_price": 22000000,
"subtotal": 660000000,
"costing_total": 550000000,
"gross_margin": 110000000,
"allocations": [
{
"lot_id": 1,
"lot_code": "LOT-260428-SUPA-001",
"supplier": "Supplier A",
"qty_allocated": 20,
"unit_cost": 18000000,
"total_cost": 360000000
},
{
"lot_id": 4,
"lot_code": "LOT-260428-SUPB-001-S1",
"supplier": "Supplier B",
"qty_allocated": 10,
"unit_cost": 19000000,
"total_cost": 190000000
}
]
}
]
}
8. Allocation Screen Contract
Available lots response
{
"data": [
{
"lot_id": 1,
"lot_code": "LOT-260428-SUPA-001",
"supplier": "Supplier A",
"available_qty": 30,
"unit_cost": 18000000,
"received_at": "2026-04-28T09:00:00Z",
"is_fifo_recommended": true,
"status": "ACTIVE"
},
{
"lot_id": 4,
"lot_code": "LOT-260428-SUPB-001-S1",
"supplier": "Supplier B",
"available_qty": 8,
"unit_cost": 19000000,
"received_at": "2026-04-28T11:00:00Z",
"is_fifo_recommended": false,
"status": "ACTIVE"
}
]
}
Allocation submit payload
{
"lines": [
{
"sales_line_id": 1,
"allocations": [
{
"inventory_lot_id": 1,
"qty_allocated": 20
},
{
"inventory_lot_id": 4,
"qty_allocated": 10
}
]
}
]
}
Allocation summary response
{
"sales_line_id": 1,
"qty_required": 30,
"qty_allocated": 30,
"costing_total": 550000000,
"avg_cost": 18333333.33,
"is_complete": true
}
9. Sorting Contract
Sorting session detail
{
"id": 1,
"sorting_no": "SRT-20260428-001",
"source_lot": {
"id": 3,
"lot_code": "LOT-260428-SUPB-001"
},
"input_qty": 40,
"output_qty": 37,
"shrinkage_qty": 3,
"results": [
{
"lot_id": 4,
"lot_code": "LOT-260428-SUPB-001-S1",
"item_type": "Jenis A",
"item_grade": "Grade A",
"qty_result": 18
}
]
}
10. Barcode Lookup Contract
{
"lot_id": 1,
"lot_code": "LOT-260428-SUPA-001",
"supplier": "Supplier A",
"item_type": "Jenis A",
"grade": "Grade A",
"available_qty": 30,
"warehouse": "Gudang Pusat",
"location": "Rak A1",
"status": "ACTIVE",
"actions": {
"can_hold": true,
"can_release": false,
"can_transfer": true,
"can_pick": true
}
}
11. Report Contract
Stock summary row
{
"item_type": "Jenis A",
"item_grade": "Grade A",
"warehouse": "Gudang Pusat",
"qty_total": 38,
"inventory_value": 730000000,
"active_lot_count": 2
}
Traceability row
{
"sales_no": "SLS-20260428-001",
"customer": "Customer A",
"item": "Jenis A / Grade A",
"qty_sold": 30,
"sources": [
{
"lot_code": "LOT-260428-SUPA-001",
"supplier": "Supplier A",
"qty": 20,
"purchase_no": "PO-20260428-001"
}
]
}
12. Frontend Editable vs Readonly Rules
Editable examples
- qty_received
- qty_accepted
- selling_price
- qty_allocated draft
- qty_picked actual
- notes
Readonly examples
- lot_code
- costing_total final hasil backend
- gross_margin final hasil backend
- parent_lot relation
- source trace fields
13. Status Codes yang Harus Konsisten
Purchase
- DRAFT
- SUBMITTED
- CANCELLED
Receipt
- DRAFT
- FINALIZED
Lot
- ACTIVE
- HOLD
- CLOSED
- REJECTED
Sales
- DRAFT
- ALLOCATED
- PICKED
- CONFIRMED
- CANCELLED
14. UI Validation Expectations
Frontend harus validasi cepat untuk:
- qty > 0
- total allocation sama dengan qty line
- qty result sorting tidak melebihi input
- required fields tidak kosong
Namun final validation tetap di backend.
15. Kesimpulan
Kontrak data ini dibuat agar frontend dan backend bicara bahasa yang sama, khususnya pada lot, allocation, sorting, traceability, dan costing yang merupakan inti sistem walet ini.