# 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:
```json
{
  "email": "admin@example.com",
  "password": "secret"
}
```
Response:
```json
{
  "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
```json
{
  "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
```json
{
  "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:
```json
{
  "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
```json
{
  "to_warehouse_id": 2,
  "to_location_id": 5,
  "qty": 10,
  "notes": "Pindah ke gudang cabang"
}
```

---

## 7. Sorting / Regrade
### POST /sorting-sessions
```json
{
  "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
```json
{
  "target_grade_id": 2,
  "qty": 5,
  "reason_id": 3,
  "notes": "Turun grade setelah QC"
}
```

---

## 8. Sales
### GET /sales
### POST /sales
```json
{
  "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
```json
{
  "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
```json
{
  "policy": "FIFO"
}
```

### POST /sales/{id}/confirm-picking
```json
{
  "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
```json
{
  "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
```json
{
  "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:
```json
{
  "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:
```json
{
  "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