# Backend Architecture & Database Design: Supplier Management

Dokumen ini adalah panduan teknis bagi tim *Backend Developer* untuk merancang arsitektur kode dan *database* pada modul Supplier & Konsinyasi.

## 1. Konsep Dasar Arsitektur
Untuk menjaga agar *Controller* tetap ringan dan bersih (*Thin Controller*), semua logika bisnis yang kompleks (validasi, perhitungan stok, *forecasting*) **wajib** dipisahkan ke dalam *Service Classes*.

---

## 2. Struktur Database (Schema Design)

Berikut adalah entitas tabel yang perlu dibuat beserta kolom pentingnya:

### A. Tabel `purchase_orders`
Mencatat *request* pesanan dari Minimarket ke Supplier.
- `id`, `po_number` (Unik, String)
- `supplier_id` (FK ke `suppliers`)
- `status` (Enum: `PENDING`, `APPROVED`, `SHIPPED`, `COMPLETED`, `CANCELLED`)
- `order_date` (Tanggal pesan)
- `expected_delivery_date` (Estimasi tanggal tiba)
- `compliance_score` (Integer/Decimal - Opsional untuk *rating* seberapa patuh pengiriman supplier terhadap pesanan ini)

### B. Tabel `purchase_order_items`
- `id`, `purchase_order_id` (FK)
- `product_id` (FK ke `products`)
- `qty_ordered` (Integer)
- `unit_cost_price` (Decimal - *Snapshot* harga beli saat PO dibuat)

### C. Tabel `receivings` (Penerimaan Barang)
- `id`, `purchase_order_id` (FK)
- `received_by` (FK ke `users` kasir/staf)
- `received_date` (Datetime)
- `status` (Enum: `VALIDATED`, `DISPUTE`)

### D. Tabel `receiving_items` (Detail Penerimaan & Tracking Kepatuhan)
Tabel ini krusial untuk melacak tingkat kepatuhan (*compliance*) supplier.
- `id`, `receiving_id` (FK)
- `product_id` (FK)
- `qty_received` (Integer - Jumlah fisik barang yang diantar)
- `qty_rejected` (Integer - Jumlah fisik yang dtolak/rusak/basi)
- `qty_accepted` (Integer - Otomatis: `qty_received` - `qty_rejected`)
- `reject_reason` (Text - Alasan penolakan)
- `variance_qty` (Integer - Selisih antara `qty_accepted` dengan `qty_ordered` di PO. Bisa minus jika kurang kirim, atau plus jika lebih kirim).

### E. Tabel `supplier_settlements` (Pencairan Uang)
- `id`, `supplier_id` (FK)
- `amount` (Decimal - Total rupiah)
- `payment_method` (Enum: `CASH`, `BANK_TRANSFER`)
- `payment_date` (Datetime)
- `processed_by` (FK ke `users`)
- `reference_number` (String)

---

## 3. Business Logic Layer (Service Classes)

Buatlah direktori `app/Services` jika belum ada.

### `PurchasingService.php`
Service ini menangani logika pergerakan barang.
1. **`generateSuggestedRestock(int $daysBuffer)`**
   - **Tujuan:** Membuat draf PO otomatis.
   - **Logika:** Melakukan *query* ke `pos_transaction_items` dalam kurun waktu `X` hari terakhir. Menghitung kecepatan laku rata-rata per hari (`sales_velocity`). Lalu mengkalikannya dengan `daysBuffer` dikurangi sisa stok di rak.

2. **`processReceiving(PurchaseOrder $po, array $items)`**
   - **Tujuan:** Mengeksekusi penerimaan fisik.
   - **Aturan 20% Tolerance:** Looping ke setiap *item*. Jika `qty_received` melebihi `qty_ordered * 1.2`, sistem **wajib menolak** (*throw ValidationException*).
   - **Aturan Short Shipment (Barang Kurang):** Jika barang yang datang kurang dari pesanan, sisa pesanan dianggap **hangus** (tidak ada *backorder*). Status PO langsung ditutup menjadi `COMPLETED`.
   - **Tracking Kepatuhan (Compliance Tracking):** Sistem harus menghitung *variance* (selisih) pesanan vs kedatangan. Data *variance* ini dikumpulkan menjadi rapor supplier. Supplier yang selalu *under-deliver* (sering kurang) atau *over-deliver* akan mudah dilacak oleh manajemen Koperasi.
   - **Update Stok:** Jika validasi lolos, tambahkan `qty_accepted` ke kolom `stock` di tabel `products`.

### `SupplierSettlementService.php`
Service ini menangani uang dan pencairan (Konsinyasi).
1. **`calculateDailyPayable(Supplier $supplier, string $date)`**
   - **Tujuan:** Menghitung hak supplier.
   - **Logika:** Menggabungkan data dari tabel `pos_transaction_items` (penjualan hari ini) untuk semua `product_id` milik supplier tersebut. Menjumlahkan total berdasarkan `cost_price` saat terjual.
2. **`processPayout(Supplier $supplier, $amount, $method)`**
   - Jika *method* adalah `CASH`, harus dibuatkan jurnal integrasi pengeluaran ke `shift_logs` agar laci kasir Koperasi tidak selisih saat tutup warung.

---

## 4. Controllers (Thin Layer)
Controller hanya bertugas memproses *Request* dari antarmuka pengguna (React/Inertia) lalu mengopernya ke *Service Class*.
- `Admin\PurchasingController`
- `Admin\SettlementController`
- `Supplier\DashboardController` (Untuk grafik *realtime sales*)

## 5. Kesimpulan
Dengan arsitektur ini, kita mematikan siklus PO (tidak ada utang barang gantung), menerapkan batas toleransi *over-supply* (20%), dan menciptakan rapor otomatis (*Supplier Compliance*) tanpa harus merepotkan admin untuk menghitung kinerja supplier secara manual.
