# API_DOCUMENTATION — BANDUNGCRAFT.COM

> Kontrak target untuk Phase 4 (Laravel). Base: `/api`. Semua endpoint kecuali login/register membutuhkan Sanctum cookie session. Error standar: `422` validasi, `409` konflik idempotency/duplicate, `403` authorization, `404` not found.

## Authentication
| Method & Path | Auth | Catatan |
|---|---|---|
| `POST /api/auth/login` | publik | `{email,password}` → 200 + session; 422 kredensial salah |
| `POST /api/auth/logout` | session | invalidate |
| `GET /api/auth/me` | session | user + roles + permissions |

## Products
- `GET /api/products` — filter `q`, `category_id`, `status`, `featured`, pagination.
- `POST /api/products` — permission `products.manage`; body: sku (unique), name, category_id, description, cost_price, base_price, discount %, stock, colors[], size_variants[], weight_gram, status, featured, photos[].
- `GET /api/products/{id}`, `PUT /api/products/{id}`, `DELETE /api/products/{id}` (soft delete; jika ada order/transaction historis, 410 permanen-ditolak).

## Custom Order & Quotation
- `POST /api/custom-orders` — publik (form toko); validasi file referensi (JPEG/PNG/WEBP, ≤5 MB, ≤4 foto).
- `GET /api/custom-orders`, `GET /api/custom-orders/{id}` — admin.
- `POST /api/custom-orders/{id}/quotation` — buat quotation baru dari custom order (satu klik ulang saat revisi).
- `POST /api/quotations` — `custom_order_id`, `customer`, `design`, items breakdown (design/material/printing/finishing/additional), discount, `valid_until`, notes.
- `PUT /api/quotations/{id}` — hanya saat status `draft/terkirim`.
- `POST /api/quotations/{id}/send`, `POST /api/quotations/{id}/approve` — approve mengunci quotation dan mengizinkan konversi ke order.

## Orders & Payments
- `GET /api/orders`, `POST /api/orders`, `GET /api/orders/{id}`.
- `PATCH /api/orders/{id}/status` — validasi graf transisi 11 status; 422 jika lompatan tidak diizinkan.
- `POST /api/payments` — wajib header `Idempotency-Key: uuid`; body: `order_id`, `amount`, `method`, `kind(dp|pelunasan|pembayaran)`, `proof`. Server clamp amount ≤ sisa tagihan, catat `paid/due` tanpa double-count.
- `GET /api/payments` (filter order_id, status), `GET /api/payments/{id}`.

> **Multiple payment**: satu order dapat membayar DP lalu pelunasan. `orders.paid = SUM(success payments)`, `orders.due = total - paid`.

## POS
- `POST /api/pos/checkout` — `{customer|walk-in, items[{product_id,qty}], discount, additional, method, amount_tendered}` → hitung `change = tendered - total`; mutasi stok atomik dalam DB transaction.
- `GET /api/pos/transactions`
- `POST /api/pos/cash-sessions/open` — `{opening_balance}`.
- `POST /api/pos/cash-sessions/close` — `{counted_balance}` → hitung `closing = opening + cash_in - cash_out`, `variance = counted - closing`.

## Production
- `GET /api/production` (filter stage, machine), `POST /api/production`, `PATCH /api/production/{id}/status` (+ `progress`).

## Finance
- `GET /api/reports/sales` (harian/bulanan, per produk/kategori/channel)
- `GET /api/reports/expenses`
- `GET /api/reports/profit-loss` — laba kotor = penjualan bersih − HPP, laba bersih = laba kotor − beban operasional
- `GET /api/reports/cash-flow` — piutang, DP diterima, arus kas

## Settings
- `GET /api/settings`, `PUT /api/settings` — permission `settings.manage`.

## Contoh transaksi POS
```
POST /api/pos/checkout
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
{ "customer": "Walk-in", "items": [{"product_id": 1, "qty": 1}], "discount": 0, "method": "tunai", "amount_tendered": 200000 }
→ { "id": "POS-2026-0001", "total": 189000, "change": 11000 }
```

Contoh status order tidak valid: `409 { "message": "Transisi tidak diizinkan: produksi -> selesai" }`.
