Files
AbelBirdNest-Stock/docs/project-spec/walet-ui-data-contract.md

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.