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

409 lines
6.6 KiB
Markdown

# 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