wahfix / nadi
NADI — Loan Management System: prototipe fungsional end-to-end untuk pengelolaan pinjaman, pembayaran, agunan, dan penagihan.
Requires
- php: ^8.3
- laravel/chisel: ^0.1.0
- laravel/fortify: ^1.37.2
- laravel/framework: ^13.17
- laravel/tinker: ^3.0
- livewire/blaze: ^1.0
- livewire/flux: ^2.13.1
- livewire/livewire: ^4.1
Requires (Dev)
- fakerphp/faker: ^1.24
- larastan/larastan: ^3.9
- laravel/boost: ^2.2
- laravel/pail: ^1.2.5
- laravel/pao: ^1.0.6
- laravel/pint: ^1.27
- laravel/sail: ^1.53
- mockery/mockery: ^1.6
- nunomaduro/collision: ^8.9.3
- pestphp/pest: ^5.1
- pestphp/pest-plugin-laravel: ^5.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is not auto-updated.
Last update: 2026-09-07 08:22:36 UTC
README
Status: Prototipe fungsional end-to-end (BUKAN produksi). NADI dirancang sebagai sistem internal manajemen nasabah, pinjaman, pembayaran, penagihan, dan jaminan. Seluruh skenario dikerjakan terhadap SQLite dengan data sintetis (demo) saja.
Daftar Isi
- Ringkasan Aplikasi
- Stack Teknologi
- Struktur Proyek
- Instalasi & Konfigurasi
- Akun Demo
- Arsitektur & Service Layer
- Basis Data
- Model Bisnis Nomor & Format
- Kalkulasi Bunga
- State Machine Pinjaman
- Angsuran & Deteksi Tunggakan
- Pembayaran, Alokasi & Reversal
- Modul Penagihan / Loan Collector
- RBAC — Peran & Izin
- Audit Log
- Dashboard & Aturan UI/UX
- Keamanan
- Laporan & Dokumen Cetak
- Pengujian
- Status Roadmap 9 Fase
- Keterbatasan Prototipe
- Konvensi Git & Kontribusi
- Lisensi
1. Ringkasan Aplikasi
NADI mengelola:
- Nasabah dan data pekerjaan (employment)
- Pengajuan pinjaman → kontrak pinjaman (pokok, bunga, tenor, metode bunga)
- Jadwal angsuran otomatis setelah pencairan
- Pembayaran dengan urutan alokasi wajib Denda → Bunga → Pokok
- Reversal/pembalikan pembayaran (imutabilitas finansial)
- Aktivitas penagihan dan jangka bayar oleh Loan Collector (LC)
- Jaminan (collateral), verifikasi identitas, dan serah terima/pengambilan jaminan
- Users, roles, permissions, dan audit log yang lengkap
- Dashboard, laporan, dan dokumen cetak
Prioritas tertinggi (tidak bisa ditawar):
DATA INTEGRITY > FINANCIAL CORRECTNESS > SECURITY > AUDITABILITY > UX > VISUAL POLISH
Prinsip mutlak yang ditegakkan sistem
| # | Invarian | Implementasi |
|---|---|---|
| 1 | Uang disimpan INTEGER Rupiah (bukan float) | Seluruh kolom *amount, *_component, *_paid, outstanding_* bertipe integer |
| 2 | Bunga disimpan presisi (basis points) | interest_rate_bps integer; 1% = 100 bps |
| 3 | Mutasi finansial dibungkus DB::transaction() |
Approval, disbursement, payment, reversal, collateral, verifikasi, release |
| 4 | Nomor bisnis sequential (bukan auto-increment mentah) | SequentialNumberService |
| 5 | Imutabilitas historis transaksi | Nilai kontraktual dikunci saat aktivasi; pembayaran tidak bisa diedit/dihapus |
| 6 | Koreksi hanya lewat reversal | Tabel payment_reversals + jejak audit |
| 7 | Logika finansial hanya di Service Layer | Tidak ada rumus bunga di controller/Blade |
| 8 | Validasi server-side untuk semua input | Form Request + policy + middleware RBAC |
| 9 | Teks UI 100% Bahasa Indonesia | Kode tetap English (tabel/kolom/variabel) |
| 10 | Pelepasan jaminan melewati 8 syarat server-side | Diblokir bila satu saja gagal |
2. Stack Teknologi
| Lapisan | Teknologi |
|---|---|
| Bahasa | PHP ^8.3 |
| Framework | Laravel Framework ^13.17 |
| Database | SQLite (database/database.sqlite) — tanpa sintaks MySQL/PostgreSQL spesifik |
| Otentikasi | Laravel Fortify ^1.37 (+ passkeys) |
| Frontend | Blade, Tailwind CSS, Alpine.js, Vite |
| Komponen UI | Livewire ^4.1 + Flux ^2.13 |
| QA / CI | Pest ^5.1, Laravel Pint ^1.27, Larastan / PHPStan, Laravel Sail |
Ekstensi PHP yang dibutuhkan: pdo_sqlite, bcmath (dipakai kalkulasi annuity REDUCING_BALANCE), DLL standar Laravel.
Skrip composer tersedia:
composer ci:check # config:clear → pint --test → phpstan analyse → pest composer lint # pint otomatis memperbaiki style
3. Struktur Proyek
app/
├── Http/
│ ├── Controllers/ # Controller tipis (validasi + delegasi ke service)
│ ├── Middleware/ # CheckPermission, CheckRole
│ └── Requests/ # Form Request validasi server-side (9 request)
├── Models/ # 16 model Eloquent
├── Policies/ # CustomerPolicy, LoanPolicy, PaymentPolicy,
│ # CollectionActivityPolicy, UserPolicy
├── Services/ # 12 service business/domain (lihat Bagian 6)
└── Helpers/helpers.php # format_rupiah(), format_date(), format_date_indonesian(), …
database/
├── migrations/ # 15 file migrasi (25 tabel, lihat Bagian 7)
└── seeders/ # RoleSeeder, PermissionSeeder, UserSeeder,
# DemoDataSeeder, LoanSeeder
resources/views/
├── dashboard.blade.php # dasbor umum + menu cepat berbasis permission
└── modules/ # customers, loans, installments, payments,
# collections, collaterals, verifications,
# releases, reports, audit-log, users
routes/
├── web.php # route modul operasional (permission-gated)
└── settings.php # profile, appearance, security (Fortify/Livewire)
tests/Feature/ # 9 file test (Pest)
bootstrap/app.php # registrasi alias middleware 'permission', 'role'
4. Instalasi & Konfigurasi
Prasyarat
- PHP
>= 8.3(denganpdo_sqlite,bcmath) - Composer
- Node.js + npm
- PHP CLI (untuk
php artisan serve/php artisan dev)
Langkah instalasi
# 1. Install dependencies composer install npm install # 2. Siapkan konfigurasi .env cp .env.example .env php artisan key:generate # 3. Arahkan ke SQLite # Di .env, pastikan: # DB_CONNECTION=sqlite # 4. Buat file database SQLite touch database/database.sqlite # 5. Jalankan migrasi + seeder php artisan migrate --seed # 6. Build aset frontend npm run build # 7. Jalankan aplikasi php artisan dev # (atau: php artisan serve)
Setelah selesai, buka http://localhost:8000 dan login dengan salah satu akun demo.
Untuk pengembangan aset frontend gunakan npm run dev bersamaan dengan php artisan serve.
Lupa password? Semua akun demo memakai password
password(hanya untuk pengembangan, lihat Bagian 5).
5. Akun Demo
Seeder membuat 7 akun, satu untuk setiap peran. Kata sandi: password
| Peran | Keterangan | |
|---|---|---|
| ADMIN | admin@example.test |
Akses penuh, persetujuan & pencairan pinjaman, kelola pengguna |
| LO | lo@example.test |
Membuat nasabah & mengajukan pinjaman |
| LC | lc@example.test |
Penagihan, dasbor tunggakan, janji bayar |
| CASHIER | cashier@example.test |
Mencatat pembayaran & mencetak kuitansi |
| COLLATERAL OFFICER | collateral@example.test |
Terima & kelola penyimpanan jaminan |
| IDENTITY VERIFIER | verifier@example.test |
Verifikasi identitas |
| AUDITOR | auditor@example.test |
Akses baca-saja + laporan + audit log |
Seeds juga menyediakan ±20 nasabah sintetis, pinjaman di berbagai status state machine (DRAFT s.d. COMPLETED), instalments, beberapa pembayaran, aktivitas penagihan, dan audit log — semuanya data fiktif.
6. Arsitektur & Service Layer
Logika bisnis wajib berada di service, controller tipis hanya: validasi input → panggil service → return response. Berikut 12 service yang sudah ada:
| Service | Tanggung Jawab |
|---|---|
LoanCalculationService |
Rumus FLAT & REDUCING_BALANCE (aritmatika integer + bcmath) |
InterestCalculationService |
Fasad resmi kalkulasi bunga pinjaman |
InstallmentScheduleService |
Generate jadwal angsuran, jatuh tempo, refresh status OVERDUE |
LoanStatusService |
State machine 11 status + transisi legal |
LoanService |
Lifecycle pinjaman (draft, submit, review, approve, disburse, complete, syncOverdue) |
CustomerService |
CRUD nasabah + kode CUS-YYYY-XXXXXX |
SequentialNumberService |
Nomor bisnis CUS/NADI-LOAN/PAY/COL/REL |
PaymentAllocationService |
Alokasi pembayaran (Denda → Bunga → Pokok) + pencatatan |
PaymentReversalService |
Pembalikan simetris + restore saldo |
CollectionService |
Dasbor LC, aktivitas penagihan, Promise-to-Pay |
UserService |
Kelola user + penentuan peran |
AuditLogService |
18+ event audit dengan JSON diff before/after |
Policies & akses: CustomerPolicy, LoanPolicy, PaymentPolicy, CollectionActivityPolicy, UserPolicy + middleware permission/role.
7. Basis Data
26 tabel hasil migrasi: 13 tabel bisnis + 5 tabel akses/otentikasi + 8 tabel infrastruktur Laravel.
Tabel Bisnis & RBAC
| Tabel | Isi |
|---|---|
customers |
Profil nasabah (kode CUS-*, NIK, kontak, status ACTIVE/INACTIVE/BLOCKED) |
employments |
Pekerjaan nasabah (perusahaan, jabatan, penghasilan, status) |
loans |
Pinjaman + nilai kontraktual (pokok, bunga, tenor, total, outstanding, status, penanda approval/disbursement) |
loan_status_histories |
Riwayat transisi status (from → to, petugas, alasan) |
installments |
Jadwal angsuran (principal/interest/penalty due & paid, remaining, status) |
payments |
Pembayaran + alokasi riil (principal/interest/penalty_component) |
payment_reversals |
Pembalikan pembayaran (alasan, petugas, waktu) |
collection_activities |
Aktivitas penagihan LC + Promise-to-Pay |
collaterals |
Jaminan (kode COL-*, tipe, nilai, lokasi, custody_status) |
identity_verifications |
Verifikasi identitas (metode, hasil, verifier) |
collateral_releases |
Serah terima jaminan (nomor REL-*, penerima, saksi) |
audit_logs |
Jejak audit (action, entity, JSON old/new, ip, user_agent) |
document_references |
Referensi dokumen terkait |
roles, permissions, role_user, permission_role |
RBAC |
Relasi utama (Eloquent)
Customer 1─n Employment
Customer 1─n Loan Loan n─1 Customer
Loan 1─n Installment Installment n─1 Loan
Loan 1─n Payment Payment n─1 Loan / Customer / Installment
Loan 1─n CollectionActivity CollectionActivity n─1 Loan / Customer / Collector(User)
Loan 1─n Collateral Collateral n─1 Loan / Customer
Customer 1─n IdentityVerification (opsional terkait Loan)
Collateral 1─n CollateralRelease (Loan & Customer terkait)
AuditLog n─1 User
Payment 1─1 PaymentReversal (relasi opsional)
Konvensi data
- Uang: selalu
INTEGER(integer Rupiah). ContohRp 1.500.000→1500000.float/double/decimaldilarang. - Bunga:
interest_rate_bpsinteger (1% = 100 bps). - Index: dibuat pada kolom pencarian utama (kode bisnis, NIK, telepon,
status,due_date,loan_id,customer_id,created_at, dll.). - Unique: kode bisnis (customer_code, loan_number, payment_number, collateral_code, release_number).
8. Model Bisnis Nomor & Format
Nomor bisnis sequential (per tahun)
Nasabah: CUS-YYYY-XXXXXX → CUS-2026-000001
Pinjaman: NADI-LOAN-YYYY-XXXXXX → NADI-LOAN-2026-000001
Pembayaran: PAY-YYYY-XXXXXX → PAY-2026-000001
Jaminan: COL-YYYY-XXXXXX → COL-2026-000001
Pelepasan: REL-YYYY-XXXXXX → REL-2026-000001
Dibuat oleh SequentialNumberService — tidak hanya mengandalkan auto-increment ID database.
Format tampilan
- Uang:
Rp 1.500.000(titik ribuan) — helperformat_rupiah(). - Tanggal:
DD/MM/YYYY(format_date()) atauDD Bulan YYYYIndonesia (format_date_indonesian(), contoh10 September 2026).
9. Kalkulasi Bunga
FLAT
total_interest = principal × (interest_rate_bps ÷ 10000) × tenor
total_payable = principal + total_interest
installment = total_payable ÷ tenor
Contoh (pokok Rp 10.000.000, 2%/bulan, 10 bulan):
- Bunga = 10.000.000 × 2% × 10 = Rp 2.000.000
- Total = Rp 12.000.000
- Angsuran = Rp 1.200.000
REDUCING_BALANCE (annuitas)
A = P × r × (1+r)^n / ((1+r)^n − 1)
A= angsuran tetap,P= pokok,r= bunga periodik,n= jumlah periode.- Annuitas dihitung menggunakan bcmath (tanpa binary floating point).
- Jadwal amortisasi dihitung dengan aritmatika integer eksak (pembulatan setengah ke atas per periode); angsuran terakhir menyerap selisih pembulatan sehingga total tercatat presisi.
- Jika
r = 0, angsuran =principal ÷ n.
Semua nilai dikembalikan sebagai integer (Rupiah utuh). Tanggal jatuh tempo dihitung dari first_due_date mengikuti frekuensi (MONTHLY/WEEKLY) dikali tenor.
10. State Machine Pinjaman
11 status legal — tidak ada perubahan status arbitrer:
DRAFT → SUBMITTED → UNDER_REVIEW → APPROVED → READY_FOR_DISBURSEMENT → ACTIVE
↘ REJECTED (terminal)
ACTIVE → OVERDUE → ACTIVE / COMPLETED / DEFAULTED
ACTIVE → COMPLETED
COMPLETED → ACTIVE (khusus: pembayaran pelunasan dibalikkan / reversal)
DRAFT / SUBMITTED / READY_FOR_DISBURSEMENT → CANCELLED
Transisi legal persis (di LoanStatusService::TRANSITIONS):
| Dari | Ke |
|---|---|
DRAFT |
SUBMITTED, CANCELLED |
SUBMITTED |
UNDER_REVIEW, CANCELLED |
UNDER_REVIEW |
APPROVED, REJECTED |
APPROVED |
READY_FOR_DISBURSEMENT |
READY_FOR_DISBURSEMENT |
ACTIVE, CANCELLED |
ACTIVE |
OVERDUE, COMPLETED, DEFAULTED |
OVERDUE |
ACTIVE, COMPLETED, DEFAULTED |
COMPLETED |
ACTIVE (reversal pelunasan) |
REJECTED / DEFAULTED / CANCELLED |
terminal |
Setiap transisi tercatat di loan_status_histories + audit LOAN_STATUS_CHANGED. Pencairan (DISBURSED) akan otomatis membuat jadwal angsuran dan mengubah status READY_FOR_DISBURSEMENT → ACTIVE.
11. Angsuran & Deteksi Tunggakan
installments dibuat otomatis saat pencairan dengan pembagian pokok/bunga per periode (sesuai metode bunga), status awal PENDING.
Status angsuran:
PENDING → PARTIALLY_PAID → PAID
→ OVERDUE (jatuh tempo lewat & belum lunas)
→ WAIVED
LoanService::syncOverdue() menjalankan refreshOverdueStatuses(): angsuran PENDING/PARTIALLY_PAID yang due_date-nya sudah lewat di-set OVERDUE; jika pinjaman ACTIVE memiliki angsuran OVERDUE, pinjaman dipromosikan ke status OVERDUE (dengan audit).
Catatan: akrual otomatis denda (penalty) belum diimplementasikan (lihat Keterbatasan, Bagian 21). Struktur data & alokasi denda sudah didukung penuh.
12. Pembayaran, Alokasi & Reversal
Pencatatan pembayaran
- Nomor
PAY-YYYY-XXXXXX. - Divalidasi: nominal integer ≥ Rp 1, tanggal tidak boleh masa depan, metode wajib salah satu
CASH/BANK_TRANSFER/QRIS/OTHER. - Setiap pembayaran menyimpan alokasi riil di dalam record — historis tidak pernah dihitung ulang dari kondisi terkini.
Urutan alokasi (WAJIB)
1. Denda (penalty) → dialokasikan PERTAMA
2. Bunga (interest) → dialokasikan KEDUA
3. Pokok (principal) → dialokasikan TERAKHIR
Contoh: pembayaran Rp 1.100.000 dengan denda Rp 0, bunga Rp 100.000, pokok Rp 1.000.000
→ penalty_component = 0, interest_component = 100000, principal_component = 1000000.
Imutabilitas
- Pembayaran yang tersimpan tidak bisa di-edit/di-delete (tidak ada route edit/delete).
- Satu-satunya koreksi: reversal via
PaymentReversalService. - Reversal: validasi (pembayaran aktif), restore
outstanding_*pinjaman & status angsuran secara simetris, cantumkanreason(min 5 karakter), catatpayment_reversals+ auditPAYMENT_REVERSED. - Jika pembayaran yang dibalikkan adalah pelunasan (pinjaman
COMPLETED), pinjaman dibuka kembali keACTIVEviaLoanService::reopenCompletedLoan().
Pendeteksian otomatis
- Setelah pembayaran penuh memenuhi seluruh sisa tagihan, pinjaman otomatis menjadi
COMPLETED(completed_atdiisi). - Overpayment ditolak server-side.
13. Modul Penagihan / Loan Collector
LC = Loan Collector (jabatan internal NADI).
Dasbor Penagihan (LC Dashboard)
- Total Nasabah Binaan (nasabah pinjaman aktif/menunggak yang ditangani LC)
- Jatuh Tempo Hari Ini
- Menunggak (overdue installments)
- Jatuh Tempo 7 Hari
- Total Sisa Tagihan
- Janji Bayar Aktif (Promise-to-Pay)
Aktivitas penagihan (collection_activities)
- Metode kontak:
PHONE,WHATSAPP,IN_PERSON,OTHER - Hasil:
PAID,PROMISE_TO_PAY,NO_RESPONSE,CONTACT_FAILED,DISPUTED,OTHER - Data janji bayar (tanggal + nominal) hanya diperbolehkan saat hasil
PROMISE_TO_PAY; divalidasi server-side, minimal Rp 1. - Aktivitas imutabel (hanya pencatatan, tanpa edit/hapus).
- Setiap aktivitas dicatat
collector_id+ auditCOLLECTION_CREATED. - Hanya pinjaman
ACTIVE/OVERDUEyang memiliki sisa tagihan yang dapat dicatat penagihannya.
Batasan kewenangan LC (diblokir server-side)
LC dilarang: mengubah pokok pinjaman, mengubah suku bunga, menyetujui pinjaman, membalikkan pembayaran, melepas jaminan.
14. RBAC — Peran & Izin
7 peran: ADMIN, LO, LC, CASHIER, COLLATERAL_OFFICER, IDENTITY_VERIFIER, AUDITOR.
Daftar izin (permission) terdaftar:
customers.view, customers.create, customers.edit, customers.delete
loans.view, loans.create, loans.edit, loans.review, loans.approve, loans.disburse
installments.view
payments.view, payments.create, payments.reverse, payments.receipt
collections.view, collections.create
collaterals.view, collaterals.receive, collaterals.update_custody, collaterals.release
verifications.view, verifications.create, verifications.review
releases.view, releases.execute
audit_logs.view
reports.view
users.view, users.manage
settings.view, settings.manage
Matriks akses per peran (non-admin)
| Peran | Dapat | Tidak dapat |
|---|---|---|
| LO | customers.view/create/edit; loans.view/create/edit; installments.view | menyetujui/mencairkan/membalikkan/melepas jaminan |
| LC | customers.view; loans.view; installments.view; payments.view; collections.view/create | approval, reversal, release, mengubah terms |
| CASHIER | installments.view; payments.view/create/receipt | approval, mengubah terms pinjaman, release |
| COLLATERAL_OFFICER | collaterals.view/receive/update_custody/release; releases.view/execute | melewati aturan kelayakan finansial |
| IDENTITY_VERIFIER | verifications.view/create/review | melepas jaminan secara independen |
| AUDITOR | baca-saja customers/loans/payments/collections/collaterals/verifications/releases/audit_logs/reports | memodifikasi data |
| ADMIN | semua izin | — |
Enforcement: middleware permission:... di route + policy (Gate::authorize) di controller + pemeriksaan ulang di service. Menyembunyikan tombol saja tidak cukup; request langsung pun tetap divalidasi.
15. Audit Log
Tabel audit_logs menyimpan: user_id, action, entity_type, entity_id, old_values (JSON), new_values (JSON), ip_address, user_agent, created_at.
18 event yang sudah didukung konstannya (AuditLogService):
CUSTOMER_CREATED CUSTOMER_UPDATED LOAN_CREATED
LOAN_SUBMITTED LOAN_APPROVED LOAN_REJECTED
LOAN_DISBURSED LOAN_STATUS_CHANGED PAYMENT_CREATED
PAYMENT_REVERSED COLLECTION_CREATED COLLATERAL_RECEIVED
IDENTITY_VERIFIED IDENTITY_FAILED RELEASE_CREATED
COLLATERAL_RELEASED USER_CREATED PERMISSION_CHANGED
Log tidak dapat dihapus melalui UI normal. (Halaman Audit UI final direncanakan di Fase 8 — audit_logs sudah tercatat sejak Fase 1.)
16. Dashboard & Aturan UX
- Teks UI: 100% Bahasa Indonesia.
- Uang:
Rp X.XXX.XXX; tanggal:DD/MM/YYYYatauDD Bulan YYYY. - Aksi destruktif/mutasi: modal konfirmasi wajib.
- Empty states: pesan informatif (bukan halaman kosong).
- Paginasi: 15 item/halaman default; tabel besar selalu di-paginasi.
- Notifikasi: flash success/error.
- Responsif: sidebar desktop, navigasi dapat dilipat di mobile, tabel scroll horizontal.
- Dasbor umum menyediakan menu cepat yang difilter oleh izin peran; dasbor spesifik peran (portofolio, penagihan ala admin, kasir, agunan) direncanakan di Fase 7.
17. Keamanan
- CSRF, session security, password di-hash (tidak pernah plaintext).
- Otentikasi + verifikasi email (
auth,verified) + rate limiting login Fortify. - RBAC di route (middleware), policy (Gate), dan service.
- Validasi server-side via Form Request untuk semua input.
- Peran diuji: LC tidak bisa approval, Cashier tidak bisa release, Auditor baca-saja, dsb (lihat Bagian 19).
- Dokumen pribadi direncanakan disimpan di
storage/app/private/dengan unduhan berotorisasi; bukan di public direktori. - Hanya data sintetis — dilarang data pribadi nyata/NIK riil.
18. Laporan & Dokumen Cetak
Laporan (10 modul — migrasi lengkap, UI di Fase 8)
1. Daftar nasabah 6. Pembayaran
2. Daftar pinjaman 7. Jaminan
3. Outstanding pinjaman 8. Pengambilan jaminan
4. Jatuh tempo 9. Aktivitas LC
5. Tunggakan 10. Audit log
Dokumen cetak (6 — tujuan print-friendly)
1. Ringkasan pinjaman 4. Kuitansi penerimaan jaminan
2. Jadwal angsuran 5. Hasil verifikasi identitas
3. Kuitansi pembayaran 6. Berita acara serah terima jaminan
Implementasi saat ini: kuitansi pembayaran (payment receipt) sudah berfungsi penuh (standalone printable, header NADI, nomor dokumen, tanda tangan). Modul laporan bersama dokumen lain direncanakan di Fase 8.
19. Pengujian
Framework: Pest 5. Selain unit/feature, suite mencakup pengujian keamanan RBAC.
php artisan test # jalankan seluruh suite php artisan test --filter CollectionTest composer ci:check # pint + phpstan + pest (pipeline CI)
File test:
tests/Feature/
├── Auth/ # otentikasi (Fortify)
├── Settings/ # pengaturan profil/appearance/security
├── CustomerTest.php # CRUD nasabah + validasi + kode CUS
├── LoanTest.php # lifecycle pinjaman, kalkulasi, state machine
├── PaymentTest.php # alokasi, overpayment, reversal, imutabilitas
├── CollectionTest.php # aktivitas LC, Promise-to-Pay, RBAC
├── RbacAccessTest.php # akses modul mengikuti izin peran
└── DashboardTest.php
Status saat ini: 99 tests / 504 assertions PASS (Pint & PHPStan level 7 clean).
Skenario keamanan yang sudah dites
- LC tidak dapat menyetujui pinjaman / reversal pembayaran.
- Cashier tidak dapat melepas jaminan / menyetujui pinjaman.
- Auditor baca-saja (semua aksi mutasi = 403).
- Pengguna tidak berizin diblokir di level route dan policy.
- Aksi finansial yang tidak sah ditolak di level service (mis. overpayment, penagihan pinjaman non-aktif, promise-to-pay tanpa hasil PTP).
20. Status Roadmap 9 Fase
Pembangunan dilakukan incremental per fase (bukan dump kode raksasa).
| Fase | Modul | Status |
|---|---|---|
| 1 | Foundation: auth, RBAC, schema, layout | ✅ Selesai |
| 2 | Customer Management (+ employment) | ✅ Selesai |
| 3 | Loan Engine & Financials (bunga, state machine, jadwal) | ✅ Selesai (PR #1; style fix PR #2) |
| 4 | Payment, Allocation & Reversal + kuitansi | ✅ Selesai (PR #3) |
| 5 | Collection / LC Module + dasbor LC | ✅ Selesai (PR #4) |
| 6 | Collateral: penerimaan & penyimpanan | ⏳ Berikutnya |
| 7 | Identity Verification & Collateral Release (8 syarat) | ⏳ Pending |
| 8 | Audit UI, Reports & Printable documents | ⏳ Pending |
| 9 | Testing, Security Review & UX polish | ⏳ Pending |
Setiap fase diverifikasi: php artisan migrate:fresh --seed + php artisan test sebelum dilanjutkan.
21. Keterbatasan Prototipe
NADI adalah prototipe fungsional end-to-end, bukan produk produksi. Hal yang tidak boleh diklaim:
- Kepatuhan/regulasi (OJK, dsb.), keabsahan hukum, lisensi pinjaman.
- Verifikasi identitas pemerintah resmi (verifikasi di sini hanyalah workflow record).
- Sertifikasi keamanan produksi / kepatuhan akuntansi / jaminan perlindungan data.
Batasan fungsional yang jujur untuk dicatat:
| Area | Status di prototipe ini |
|---|---|
| Denda/penalty akrual otomatis | Belum diimplementasikan — struktur data & alokasi denda tersedia, tapi penambahan denda otomatis saat terlambat belum ada |
| Collateral & Release (Fase 6–7) | Belum dibangun — termasuk 8 syarat pelepasan, verifikasi identitas, berita acara serah terima |
| Laporan & dokumen cetak (Fase 8) | Belum dibangun (kecuali kuitansi pembayaran) |
| Dasbor spesifik peran (Fase 7) | Dasbor umum aktif; dasbor peran lengkap menyusul |
| Global search & filter lintas entitas | Belum dibangun (pencarian per-modul ada) |
| Upload dokumen | Belum diaktifkan; desain menyimpan private storage |
| Audit UI | AuditLogService aktif; halaman audit formal di Fase 8 |
| Hardening produksi | Rate limiting login dasar (Fortify); review keamanan/legal menyeluruh masih diperlukan |
Sebelum digunakan di lingkungan nyata, aplikasi memerlukan review profesional (hukum, akuntansi, keamanan), data riil yang sah, dan hardening tambahan.
22. Konvensi Git & Kontribusi
Sesuai dokumen direktif proyek (AGENTS.md):
main= branch stabil — perubahan kode tidak boleh langsung dimain.- Setiap fase/modul dikerjakan di branch terpisah:
fase/<nama-fase>(contohfase/6-collateral-release)- branch non-fase (contoh
docs/readme,fix/...)
- Alur:
checkout main→git pull→checkout -b <branch>→ kerja → commit → push → PR ke main → review → merge. - Format commit:
<Tipe>: <deskripsi>dengan tipeFase X,Fix,Add,Update,Refactor,Test,Docs,Chore(deskripsi 1 baris, tanpa titik akhir).
git checkout main && git pull origin main git checkout -b fase/6-collateral-release # ... kerja ... git add -A && git commit -m "Fase 6: penerimaan dan penyimpanan jaminan" git push origin fase/6-collateral-release # buka PR ke main → review → merge
23. Lisensi
MIT — proyek ini dibangun di atas starter kit Laravel resmi (laravel/livewire-starter-kit).
Prototipe NADI: database, aturan bisnis, izin akses, dan UI menegakkan alur kerja yang sama. Data integrity first — kalkulasi keliru = kegagalan, tanpa audit = kegagalan, pelepasan jaminan tanpa validasi = kegagalan.