# Porting deposit customer dan reseller ke CI4

Pembaruan: 16 Oktober 2026.

Seluruh enam URL `pos/deposit/*.php` sudah tersedia sebagai route GET/POST CI4, termasuk varian `.php`, dengan filter `auth` dan `csrf`.

| URL | Controller | Fungsi |
| --- | --- | --- |
| `deposit/deposit_topup` | `DepositDepositTopup` | Pengajuan topup customer |
| `deposit/deposit_admin` | `DepositDepositAdmin` | Redirect ke verifikasi tab customer |
| `deposit/reseller_topup` | `DepositResellerTopup` | Pengajuan topup/pengurangan reseller, bukti pembayaran, riwayat pengajuan |
| `deposit/reseller_topup_requests` | `DepositResellerTopupRequests` | Verifikasi customer dan reseller |
| `deposit/reseller_deposit` | `DepositResellerDeposit` | Histori ledger, filter tanggal/reseller/jenis, saldo awal, pagination, penyesuaian manual |
| `deposit/reseller_saldo` | `DepositResellerSaldo` | Saldo reseller per toko dan akses penyesuaian |

Lima view berada di `app/Views/deposit/`. Tidak ada eksekusi runtime atau include PHP dari folder `pos`; seluruh query memakai koneksi CI4.

## Perilaku penyimpanan

- Pengajuan topup customer/reseller selalu berstatus **pending**, tanpa langsung mengubah saldo.
- Pengajuan customer hanya menerima customer aktif milik toko dan nominal positif. Pengajuan reseller memeriksa reseller aktif yang dimiliki toko atau terhubung melalui `store_resellers` berstatus approved.
- Nominal mengikuti format input HTML number, misalnya `1000.25`. Pemisah ribuan, notasi eksponen, nol, dan lebih dari dua angka desimal ditolak. Nominal negatif reseller menjadi pengajuan deduction.
- Verifikasi approve/reject serta penyesuaian manual memerlukan **Super Admin toko**. Ini memperketat verifikasi pada aplikasi lama yang hanya mensyaratkan login. Pengguna biasa tetap dapat melihat riwayat dan mengajukan topup.
- Semua form POST modul ini memuat token CSRF, termasuk form penyesuaian di halaman saldo.
- Bukti pembayaran menggunakan upload CI4: JPG, PNG, WebP, atau PDF maksimal 3 MiB, nama acak, disimpan di `public/uploads/reseller_deposits/`. Upload gagal ditolak; file yang sudah tersimpan dibersihkan bila insert pengajuan gagal. URL lama pada data existing tetap digunakan.

## Konsistensi saldo

`App\Libraries\DepositLedger` menangani approval, rejection, dan penyesuaian. Pengajuan dikunci menggunakan `SELECT ... FOR UPDATE` berdasarkan ID **dan toko**, lalu status pending diperiksa di dalam transaksi. Request yang sudah disetujui/ditolak tidak dapat diproses ulang. Approval mengunci pula reseller/customer sebelum membaca saldo.

Saldo, ledger, dan perubahan status berada dalam transaksi database yang sama. Kegagalan penulisan membatalkan semuanya. Penolakan hanya mengubah status dan alasan, tanpa mengubah saldo. Topup customer hanya dapat memproses transaksi bertipe topup; transaksi pemakaian tidak dapat dikreditkan lewat menu ini.

Untuk reseller, topup menambahkan nominal dan kode unik sesuai perilaku sumber. Deduction wajib negatif dan tidak menambahkan kode unik. Penyesuaian manual dan deduction tetap boleh menghasilkan saldo negatif sesuai aplikasi lama. Nilai saldo tetap dibatasi kapasitas kolom DECIMAL(15,2).

**Semantik saldo lama dipertahankan:** `resellers.deposit_balance` adalah saldo global pada satu record reseller, sedangkan tampilan saldo/history per toko dihitung dari ledger `reseller_deposit_transactions.store_id`. Karena satu reseller dapat terhubung ke beberapa toko, kedua angka tersebut dapat berbeda. Tahap ini tidak mengubah model saldo aplikasi menjadi rekening terpisah per toko dan tidak memigrasikan histori lama. Ledger `balance_after` merekam saldo global setelah mutasi, seperti sumber.

`App\Libraries\DepositSchema` menyiapkan tabel/kolom kompatibilitas sebelum transaksi saldo dimulai, mengikuti pola schema aplikasi yang sudah ada. Tidak ada DDL yang dijalankan oleh `DepositLedger` di dalam transaksi approval. Database aplikasi beserta master yang sudah ada tetap menjadi prasyarat; ini bukan installer database lengkap.

## Verifikasi

- PHPUnit seluruh aplikasi: **134 tes, 1.626 assertion**, lulus.
- Termasuk **21 tes deposit**: route/auth/CSRF, render lima halaman, redirect lama, nominal desimal, topup pending, pembatasan toko/role, approval berulang, kode unik, deduction, adjustment, rejection, dan rollback ledger/customer.
- Lint **300 file PHP**: tanpa kesalahan sintaks.
- Pengujian memakai koneksi database tiruan dan renderer CI4. Tidak mengubah saldo nyata atau data produksi. Penguncian SQL diperiksa melalui query dan simulasi status; konkurensi dua koneksi MySQL nyata belum diuji. Upload file nyata dan alur browser masih perlu diuji pada lingkungan staging.

## Berikutnya

Lanjutkan endpoint `pos/api/` dan webhook, dimulai dari kontrak transaksi `api_create_sale.php`, pemeriksaan stok, kemudian integrasi marketplace/WhatsApp. Cron selain worker stok Shopee, area CRM/admin, dan halaman publik masih perlu diaudit terpisah.
