# CHM-D-20260618-71 — Pekerjaan Client CHM (18 Juni 2026)

## Pekerjaan 1 — Rename Submenu & Judul Halaman Penjualan Langsung

### Context
Nama submenu "Transaksi Penjualan" dan judul halaman penjualan diganti
menjadi "Penjualan Langsung" agar lebih deskriptif.

### Komponen yang Diubah
- `config/menu.php`: `'title' => 'Penjualan Langsung'`
- `resources/views/penjualan/index.blade.php`: title, heading, breadcrumb

---

## Pekerjaan 2 — Alur Penjualan KSO

### Context
KSO (Kerjasama Operasional) adalah sistem konsinyasi di mana barang dititipkan
ke gudang faskes mitra. Sales mencatat pemakaian barang oleh pasien, lalu alur
validasi berjenjang memastikan dokumen PPN sebelum proses dinyatakan selesai.
Stok diambil dari Gudang KSO milik faskes yang dipilih (`tipe='faskes'`, `faskes_id`).

### Alur Status
```
draft_pemakaian
  → [staf_sales: Ajukan] → stok KSO berkurang (FEFO dari gudang faskes)
diajukan         ← [kepala_sales: Kembalikan ke draft + restore stok]
  → [kepala_sales: Validasi]
valid            ← [Admin Pajak: Kembalikan ke diajukan]
  → [Admin Pajak: Upload eFaktur + Selesaikan]
selesai          ← [kepala_sales: Batalkan → draft_pemakaian + restore stok]
```

### Label Display
| Status DB       | Label Tampil      | Badge     |
|-----------------|-------------------|-----------|
| draft_pemakaian | Draft Pemakaian   | secondary |
| diajukan        | Menunggu Validasi | primary   |
| valid           | Upload eFaktur PPN| warning   |
| selesai         | Selesai           | success   |

### Permissions (4 baru)
| Permission              | Peran                    | Aksi                                      |
|-------------------------|--------------------------|-------------------------------------------|
| `penjualan_kso.sales`   | staf_sales, kepala_sales | Buat/edit/hapus/ajukan                    |
| `penjualan_kso.validasi`| kepala_sales, admin      | Validasi, kembalikan dari diajukan, cetak |
| `penjualan_kso.pajak`   | (seperti penjualan.pajak)| Upload eFaktur, selesaikan, kembalikan    |
| `penjualan_kso.batal`   | kepala_sales, admin      | Batalkan dari selesai                     |

### Database
- `2026_06_18_000001_create_penjualan_ksos_table.php`
- `2026_06_18_000002_create_penjualan_kso_items_table.php`
- `2026_06_18_000003_create_penjualan_kso_item_stoks_table.php`
- `2026_06_18_000004_seed_penjualan_kso_permissions.php`

### Model
- `app/Models/PenjualanKso.php` — nomor prefix `KSO/yyyy/mm/0001`
- `app/Models/PenjualanKsoItem.php`
- `app/Models/PenjualanKsoItemStok.php`

### Controller
`app/Http/Controllers/Penjualan/PenjualanKsoController.php`

Key methods:
- `ajukan()` — decrement stok Gudang KSO (FEFO, `Gudang::where('tipe','faskes')->where('faskes_id',...)->first()`)
- `validasi()` — kepala_sales: `diajukan → valid`
- `kembalikanDariValidasi()` — restore stok via KartuStok reversal
- `selesaikan()` — pajak: `valid → selesai`
- `kembalikanDariPajak()` — pajak: `valid → diajukan`
- `batalkan()` — kepala_sales: `selesai → draft_pemakaian` + restore stok
- `pdfFaktur()`, `pdfTandaTerima()`, `pdfKwitansi()` — 3 dokumen cetak

### Routes
Group prefix `penjualan-kso`, name `penjualan-kso.`

### Views
- `resources/views/penjualan-kso/index.blade.php`
- `resources/views/penjualan-kso/form.blade.php` — tambah: Nama Pasien, No. Transaksi, Tgl. Pemakaian; faskes filter `has_gudang_kso=true`
- `resources/views/penjualan-kso/show.blade.php`
- `resources/views/penjualan-kso/pdf-faktur.blade.php`
- `resources/views/penjualan-kso/pdf-tanda-terima.blade.php`
- `resources/views/penjualan-kso/pdf-kwitansi.blade.php`

---

## Bugfix & Penyempurnaan (Post-Testing)

### 1. `cariBarang()` filter stok KSO
Form Penjualan KSO: dropdown barang hanya menampilkan barang yang memiliki stok
di gudang KSO faskes terpilih. Implementasi: `whereHas('stoks', fn => where('gudang_id', $gudangKso->id)->where('kondisi','baik')->where('qty','>',0))`.

### 2. Kolom `tipe` bukan `jenis` pada model Gudang
Bug: query gudang KSO menggunakan `where('jenis','faskes')` — kolom tidak ada.
Fix: ganti ke `where('tipe','faskes')` (sesuai `Gudang::$fillable` dan `getDefault()`).
Berlaku di `ajukan()`, `kembalikanDariValidasi()`, `batalkan()`, `stokTersedia()`, `cariBarang()`.

### 3. Relasi `stoks()` di model Barang
Tambah `public function stoks(): HasMany` ke `app/Models/Barang.php` agar `whereHas('stoks',...)` bisa digunakan.

### 4. JS form: `faskes_id` dikirim saat AJAX cari barang
Select2 barang mengirim `faskes_id` di setiap request sehingga server bisa filter
per gudang KSO. `cache: false` agar list di-refresh tiap kali faskes berganti.
