# 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: ```json { "data": [], "meta": { "page": 1, "per_page": 20, "total": 100 } } ``` Contoh standar response detail: ```json { "data": { "id": 1 } } ``` Contoh error: ```json { "message": "Validation error", "errors": { "qty": ["qty harus lebih besar dari 0"] } } ``` ## 4. Purchase Contract ### Purchase list item ```json { "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 ```json { "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 ```json { "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 ```json { "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 ```json { "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 ```json { "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 ```json { "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 ```json { "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 ```json { "lines": [ { "sales_line_id": 1, "allocations": [ { "inventory_lot_id": 1, "qty_allocated": 20 }, { "inventory_lot_id": 4, "qty_allocated": 10 } ] } ] } ``` ### Allocation summary response ```json { "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 ```json { "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 ```json { "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 ```json { "item_type": "Jenis A", "item_grade": "Grade A", "warehouse": "Gudang Pusat", "qty_total": 38, "inventory_value": 730000000, "active_lot_count": 2 } ``` ### Traceability row ```json { "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.