# Brief — Kas Tunai / BCA / Omzet Medis·OTC

**Status:** Diimplementasi (`feat/kas-tunai-bca` + `feat/kas-tunai-per-cabang`)  
**Sumber kebenaran UI + posting:** dokumen ini + `business-rules.md` (bagian penjualan & cash flow)

---

## 1. Tujuan

Memisahkan dua sudut pandang admin:

| Menu sidebar | Pertanyaan | Angka utama |
|--------------|------------|-------------|
| **Kas Tunai** | Berapa di laci Medis / OTC **cabang aktif**? | Neto `Kas Medis` / `Kas OTC` untuk `cabang_id` = cabang aktif |
| **Rekening BCA** | Berapa di bank? | Running saldo `BCA` (global) |
| **Omzet Medis/OTC** | Berapa arus bisnis jenis ini (tunai + transfer)? | Total masuk / keluar / neto (**bukan** saldo gabungan) |

Enum DB `mutasi_kas.sumber_kas` **tetap** `Kas Medis` | `Kas OTC` | `BCA`.

| Rekening | Scope saldo UI |
|----------|----------------|
| **BCA** | Running saldo global (`getSaldoTerakhir('BCA')`) — rekening bersama owner |
| **Kas Tunai** | Neto per cabang aktif (`SUM(pemasukan) - SUM(pengeluaran)` di `cabang_id` aktif) — laci per cabang |
| **Kolom `mutasi_kas.saldo`** | Tetap running **global per `sumber_kas`** (dipakai tulis baris + tampil di BCA saja) |

---

## 2. Jejak cabang (`cabang_id` nullable)

Kolom `mutasi_kas.cabang_id` menandai asal cabang. Untuk Kas Tunai, kolom ini juga menjadi **filter saldo & daftar**.

| Peristiwa | `cabang_id` |
|-----------|-------------|
| Penjualan CASH / TRANSFER | Dari `penjualan.cabang_id`; keterangan memuat nama cabang |
| Mutasi manual | Dikunci ke **cabang aktif** (UI readonly; server ignore input client) |
| Bayar PBF dari **BCA** | `null` (rekening bersama) |
| Bayar PBF dari **Kas Medis / Kas OTC** | Cabang aktif saat bayar |

### Filter index

| Halaman | Filter cabang |
|---------|---------------|
| **Kas Tunai** | Selalu `cabang_id = cabang aktif` (tanpa baris `NULL`). Ganti cabang lewat switcher header. Owner **tidak** punya dropdown filter cabang di sini. |
| **BCA / Omzet** | Owner: opsional `cabang_id` → `(cabang_id = X OR cabang_id IS NULL)`. Admin cabang: terkunci ke cabangnya + baris global. |

---

## 3. Aturan posting penjualan

| Kondisi | `sumber_kas` | Kategori mutasi |
|---------|--------------|-----------------|
| CASH + Medis | `Kas Medis` | `Penjualan Medis` |
| CASH + OTC | `Kas OTC` | `Penjualan OTC` |
| TRANSFER + Medis/OTC | `BCA` | `Penjualan Medis` / `Penjualan OTC` |

Kompensasi edit/hapus: `Batal Penjualan {jenis}` di sumber yang sama; `cabang_id` ikut penjualan.

Resolve `sumber_kas` di `PenjualanController` (server otoritatif).

Data historis TRANSFER lama ke Kas Medis/OTC **tidak** dimigrasi; `cabang_id` historis tetap null (tidak masuk saldo Kas Tunai per cabang).

---

## 4. Kontrak query UI (`kas.index`)

| Halaman | Query | Kartu | Filter daftar |
|---------|-------|-------|-----------------|
| Kas Tunai Medis | `rekening=tunai&arus=Medis` | Neto `Kas Medis` · cabang aktif | `sumber_kas = Kas Medis` **dan** `cabang_id = aktif` |
| Kas Tunai OTC | `rekening=tunai&arus=OTC` | Neto `Kas OTC` · cabang aktif | `sumber_kas = Kas OTC` **dan** `cabang_id = aktif` |
| BCA | `rekening=bca` | Saldo `BCA` (global) | `sumber_kas = BCA` |
| BCA + arus | `rekening=bca&arus=Medis\|OTC` | Saldo `BCA` (global) | BCA + kategori terkait arus |
| Omzet Medis | `rekening=omzet&arus=Medis` | Masuk / keluar / neto | Semua sumber; kategori Medis |
| Omzet OTC | `rekening=omzet&arus=OTC` | Masuk / keluar / neto | Semua sumber; kategori OTC |

- Kolom running saldo baris: **hanya di BCA** (`showSaldoRunningColumn`). Kas Tunai menyembunyikannya (nilai global menyesatkan untuk laci cabang).
- Omzet default rentang = bulan berjalan.
- Kompatibilitas: `?sumber_kas=...` lama di-map ke `rekening` / `arus`.

### Dashboard

| Kartu | Cara hitung |
|-------|-------------|
| Saldo BCA (global) | `getSaldoTerakhir('BCA')` |
| Saldo Kas Tunai · {cabang aktif} | `getSaldoKasTunaiCabang(cabangAktif)` = neto Medis + OTC cabang itu |
| Hint kartu tunai | Rincian neto Medis / OTC cabang aktif |
| Kas masuk/keluar bulan ini | Masih global (`getRingkasanBulanIni`) — label UI menyebut global |

---

## 5. File utama

| Area | Path |
|------|------|
| Controller | `MutasiKasController`, `DashboardController`, `TagihanPbfController`, `PenjualanController` |
| Service | `KasService` (`getSaldoNetoPerCabang`, `getSaldoKasTunaiCabang`), `PenjualanService` |
| Model / migrasi | `MutasiKas`, `*_add_cabang_id_to_mutasi_kas_table` |
| Views | `kas/index`, `kas/create`, `dashboard/index`, `tagihan/edit`, `penjualan/_form`, sidebar |
| Tests | `tests/Feature/KasTunaiBcaTest.php` |

---

## 6. Out of scope / backlog

- Tabungan / Celengan
- Migrasi koreksi penjualan TRANSFER lama ke BCA
- Ubah cara tulis running saldo agar benar-benar per cabang di kolom `mutasi_kas.saldo` (saat ini UI Kas Tunai memakai neto agregat)
- Backfill `cabang_id` historis
- Scope kas masuk/keluar bulan ini per cabang di dashboard
