# Porting stok ke CI4

Pembaruan: 16 Oktober 2026.

Seluruh enam halaman dalam `pos/stok` sudah mempunyai controller, view, serta route GET/POST dengan filter `auth`, termasuk URL `.php`.

| URL | Controller | Cakupan |
| --- | --- | --- |
| `stok/cek-stok` | `CekStok` | Daftar/filter, stok paket, nilai stok, CSV, pause/resume produk |
| `stok/history-stok` | `HistoryStok` | Riwayat pergerakan dan saldo stok |
| `stok/stock-opname` | `StockOpname` | Mulai sesi, snapshot, scan stok fisik, template XLSX, upload/selesai, penyelesaian draft, hapus |
| `stok/stock-opname-form` | `StockOpnameForm` | Buat draft opname manual |
| `stok/stock-opname-excel` | `StockOpnameExcel` | Template XLSX, upload/preview XLSX/CSV, simpan draft |
| `stok/stock-opname-detail` | `StockOpnameDetail` | Fragmen detail opname |

Query menggunakan koneksi CI4, tampilan memakai layout CI4, dan unduhan dikembalikan sebagai HTTP response. Tidak ada dependensi runtime pada PHP dari folder `pos`.

## Validasi dan penyesuaian

- ID produk diperiksa ulang berdasarkan toko saat draft disimpan; snapshot stok dari browser tidak dipercaya.
- Stok fisik nol valid. Input negatif, pecahan, produk duplikat, serta SKU duplikat pada file penyelesaian ditolak.
- File penyelesaian wajib mempunyai header SKU/Barcode dan Stok Fisik.
- Sesi dimulai dengan penguncian toko dan pemeriksaan ulang sesi aktif. Penyelesaian mengunci serta memeriksa ulang status sesi untuk mencegah penerapan berulang.
- Penyelesaian draft membatasi pembaruan produk berdasarkan toko; kegagalan penulisan menggulung balik transaksi.
- Penghapusan opname selesai membalik selisih yang diterapkan tanpa menghapus efek transaksi selama sesi.
- Histori dan perhitungan movement pembelian memakai konversi satuan (`conv_factor`).
- Rumus penyelesaian sesi mengikuti aplikasi lama: `final_stock = physical_stock - abs(movement) - pending_order_qty`, dengan pembatasan nol bila `check_stock` aktif. Kebijakan rumus ini belum diubah dan perlu dicocokkan dengan praktik penghitungan fisik, khususnya saat ada pembelian selama sesi.

## Verifikasi

- PHP lint: **145 file**, lulus.
- Seluruh PHPUnit suite: **58 tes, 756 assertion**, lulus.
- `tests/unit/StockPortTest.php`: **21 tes, 87 assertion**, mencakup render halaman, autentikasi route, respons CSV/XLSX, validasi file/draft, batas toko, penyelesaian dan rollback, penguncian sesi, serta pembalikan adjustment.
- Tes memakai database tiruan. Tidak ada data MySQL aplikasi yang diubah atau sinkronisasi Shopee yang dijalankan saat pengujian.

Jalankan dari folder `pos_kiosq_id_ci`:

```sh
/Applications/MAMP/bin/php/php8.3.14/bin/php vendor/bin/phpunit --no-coverage
```

## Masih perlu diuji langsung

Uji dengan MySQL dan browser: hitung fisik nol, upload file XLSX yang sebenarnya, scan barcode/kamera, transaksi berjalan selama opname, dua pengguna yang memulai/menyelesaikan bersamaan, pause/resume ke marketplace, dan penghapusan sesi selesai setelah ada transaksi lanjutan.

Tahap berikutnya adalah laporan. Pengaturan, tools, deposit, API/webhook, cron, CRM, dan halaman publik tetap di luar tahap stok ini.
