Files
AbelBirdNest-Stock/docs/project-spec/walet-api-spec.md

6.6 KiB

API Spec Backend Sistem Inventory Walet

1. Prinsip API

API berbasis REST JSON dengan fokus pada:

  • lot-based inventory
  • traceability
  • partial allocation
  • shrinkage and adjustment
  • barcode/QR lookup

Base path contoh: /api/v1

2. Auth

POST /auth/login

Request:

{
  "email": "admin@example.com",
  "password": "secret"
}

Response:

{
  "token": "jwt-token",
  "user": {
    "id": 1,
    "name": "Admin",
    "role": "ADMIN"
  }
}

3. Master Data

GET /suppliers

POST /suppliers

Field penting supplier:

  • code
  • name
  • phone
  • email
  • bank_name
  • bank_account_number
  • address

GET /suppliers/{id}

PUT /suppliers/{id}

DELETE /suppliers/{id}

GET /customers

POST /customers

Field penting customer:

  • code
  • name
  • phone
  • email
  • bank_name
  • bank_account_number
  • address

GET /item-types

POST /item-types

GET /item-grades

POST /item-grades

GET /warehouses

POST /warehouses

GET /warehouse-locations

POST /warehouse-locations

GET /adjustment-reasons

POST /adjustment-reasons


4. Purchasing

GET /purchases

Filter:

  • supplier_id
  • status
  • date_from
  • date_to

POST /purchases

{
  "supplier_id": 1,
  "purchase_date": "2026-04-28",
  "supplier_invoice_no": "INV-8891",
  "notes": "Pembelian campuran",
  "lines": [
    {
      "item_type_id": 1,
      "item_grade_id": 1,
      "qty_ordered": 50,
      "unit_id": 1,
      "unit_price": 18000000,
      "classification_status": "FINAL"
    },
    {
      "item_type_id": 1,
      "item_grade_id": null,
      "qty_ordered": 40,
      "unit_id": 1,
      "unit_price": 17500000,
      "classification_status": "PROVISIONAL"
    }
  ]
}

GET /purchases/{id}

PUT /purchases/{id}

POST /purchases/{id}/submit

POST /purchases/{id}/cancel


5. Receiving

GET /receipts

POST /receipts

{
  "purchase_id": 1,
  "supplier_id": 1,
  "receipt_date": "2026-04-28",
  "notes": "Barang diterima baik",
  "lines": [
    {
      "purchase_line_id": 1,
      "item_type_id": 1,
      "item_grade_id": 1,
      "qty_received": 50,
      "qty_accepted": 50,
      "qty_rejected": 0,
      "unit_id": 1,
      "unit_cost": 18000000,
      "warehouse_id": 1,
      "warehouse_location_id": 1
    }
  ]
}

GET /receipts/{id}

POST /receipts/{id}/generate-lots

Response contoh:

{
  "receipt_id": 1,
  "lots": [
    {
      "id": 10,
      "lot_code": "LOT-260428-SPA-001",
      "qr_code_value": "LOT-260428-SPA-001"
    }
  ]
}

6. Inventory Lots

GET /lots

Filter:

  • supplier_id
  • item_type_id
  • item_grade_id
  • warehouse_id
  • status
  • keyword

GET /lots/{id}

GET /lots/{id}/movements

GET /lots/{id}/trace

POST /lots/{id}/hold

POST /lots/{id}/release

POST /lots/{id}/transfer

{
  "to_warehouse_id": 2,
  "to_location_id": 5,
  "qty": 10,
  "notes": "Pindah ke gudang cabang"
}

7. Sorting / Regrade

POST /sorting-sessions

{
  "source_lot_id": 10,
  "sorting_date": "2026-04-28T15:00:00Z",
  "input_qty": 40,
  "shrinkage_qty": 3,
  "notes": "Sortasi batch campuran",
  "results": [
    {
      "item_type_id": 1,
      "item_grade_id": 1,
      "qty_result": 18,
      "unit_cost": 17500000
    },
    {
      "item_type_id": 1,
      "item_grade_id": 2,
      "qty_result": 12,
      "unit_cost": 17500000
    },
    {
      "item_type_id": 2,
      "item_grade_id": 1,
      "qty_result": 7,
      "unit_cost": 17500000
    }
  ]
}

GET /sorting-sessions

GET /sorting-sessions/{id}

POST /lots/{id}/regrade

{
  "target_grade_id": 2,
  "qty": 5,
  "reason_id": 3,
  "notes": "Turun grade setelah QC"
}

8. Sales

GET /sales

POST /sales

{
  "customer_id": 1,
  "sales_date": "2026-04-28",
  "notes": "Order customer X",
  "lines": [
    {
      "item_type_id": 1,
      "item_grade_id": 1,
      "qty_sold": 30,
      "unit_id": 1,
      "selling_price": 22000000
    }
  ]
}

GET /sales/{id}

POST /sales/{id}/allocate

{
  "lines": [
    {
      "sales_line_id": 1,
      "allocations": [
        {
          "inventory_lot_id": 10,
          "qty_allocated": 20
        },
        {
          "inventory_lot_id": 11,
          "qty_allocated": 10
        }
      ]
    }
  ]
}

POST /sales/{id}/auto-allocate

{
  "policy": "FIFO"
}

POST /sales/{id}/confirm-picking

{
  "lines": [
    {
      "sales_line_id": 1,
      "picked_allocations": [
        {
          "inventory_lot_id": 10,
          "qty_picked": 20
        },
        {
          "inventory_lot_id": 11,
          "qty_picked": 10
        }
      ]
    }
  ]
}

9. Adjustments & Shrinkage

POST /stock-adjustments

{
  "inventory_lot_id": 11,
  "adjustment_type": "SHRINKAGE",
  "reason_id": 1,
  "qty_change": -1.2,
  "notes": "Selisih opname"
}

GET /stock-adjustments


10. Returns

POST /sales-returns

POST /purchase-returns

POST /sales-returns

{
  "sales_id": 1,
  "customer_id": 1,
  "return_date": "2026-04-29",
  "lines": [
    {
      "sales_line_id": 1,
      "inventory_lot_id": 10,
      "item_type_id": 1,
      "item_grade_id": 1,
      "qty_returned": 2,
      "return_condition": "GOOD",
      "resolution": "RESTOCK"
    }
  ]
}

11. Barcode / QR

GET /barcode/lookup/{value}

Response:

{
  "lot_id": 10,
  "lot_code": "LOT-260428-SPA-001",
  "supplier": "Supplier A",
  "supplier_bank_name": "BCA",
  "supplier_bank_account_number": "1234567890",
  "item_type": "Jenis A",
  "grade": "Grade A",
  "available_qty": 30,
  "warehouse": "Gudang Pusat",
  "location": "Rak A1",
  "status": "ACTIVE"
}

POST /lots/{id}/print-label

GET /lots/{id}/labels


12. Reports

GET /reports/stock-summary

GET /reports/stock-lots

GET /reports/purchases

GET /reports/sales

GET /reports/margins

GET /reports/shrinkage

GET /reports/supplier-quality

GET /reports/traceability

Contoh:

GET /reports/traceability?sales_id=1

GET /reports/traceability?lot_id=10


13. Error Rules

Format error:

{
  "message": "Validation error",
  "errors": {
    "qty_allocated": ["qty allocated melebihi stok tersedia"]
  }
}

14. Business Validation Rules

  • total allocation harus sama dengan qty sales line
  • qty allocation tidak boleh melebihi available qty lot
  • sorting result total + shrinkage tidak boleh melebihi input qty
  • lot hold tidak boleh dipakai untuk sales allocation
  • lot closed tidak boleh dipakai lagi
  • transfer dan adjustment harus menghasilkan movement ledger
  • receipt yang belum finalized tidak boleh dipakai untuk sales