Sovereign Ledger
A comprehensive financial management system built for a health-worker cooperative in Garut, Indonesia, deployed on-premise and in active use.
The Problem
KPRI Warga Kesehatan Kabupaten Garut, a health-worker cooperative in Garut, Indonesia, needed a complete financial management system. They had been running on Excel spreadsheets for years, with their full transaction history locked in legacy files. Off-the-shelf solutions were either too expensive or couldn't handle the cooperative-specific business logic (compulsory savings, social funds, multi-type loans).
The core challenge was to build and deploy a production-grade financial system as a solo developer: double-entry accounting, role-based access for five user roles, automated monthly batch processing, professional reporting, and a full data migration from their existing Excel records.
The Architecture
Why It's Hard
- Double-entry accounting from scratch: Every transaction must balance. A full Chart of Accounts hierarchy, audit trails, and period locking. Getting this right as a solo developer, without an accounting background, required deep domain learning.
- Legacy data migration: The cooperative's complete transaction history lived in Excel files spanning years. Importing, cleaning, and reconciling this into a normalized PostgreSQL schema was a data engineering challenge in itself.
- Five distinct user roles: Admin, teller, member, auditor, and super-admin, each with different permissions, views, and workflows. Role-based access control had to be airtight for a financial system handling real money.
- On-premise Docker deployment: The system runs on the cooperative's own hardware: PHP-FPM + Nginx + PostgreSQL in Docker containers, with Supervisor-managed scheduling for automated monthly batch jobs and persistent volume backups.
Key Features Delivered
- Full Chart of Accounts: hierarchical account structure with double-entry enforcement
- Automated monthly batch processing: compulsory savings deductions, social fund contributions, and loan installment postings run on schedule
- Multi-type loan management: automatic installment scheduling, interest calculation, and repayment tracking
- Role-based access control: five user roles with granular permissions
- Professional reporting: PDF reports with KOP letterhead branding, CSV exports, and printable ledgers via Laravel DOMPDF + PhpSpreadsheet
- Legacy data reconciliation: full import and reconciliation of years of cooperative transaction history from Excel
Inside the System
Three screens from the deployment. The dashboard is the operational view, grouping member, loan, and savings totals in one place. The transaction form is where the accounting model becomes concrete: every entry names a source and a destination account from the Chart of Accounts, so the journal is balanced at the point of capture rather than corrected afterwards.
What I'd Do Differently
- Add automated testing earlier. Financial software without tests is terrifying. I added PHPUnit tests partway through, but having them from day one, especially for the double-entry balance checks and loan calculations, would have saved debugging time.
- Use Laravel's built-in features more aggressively. I initially underused Laravel's queuing, notifications, and event system. Refactoring batch processing to use Laravel queues with Supervisor made the system significantly more robust.
- Design the role-permission system with more granularity. Five roles worked for the initial deployment, but as the cooperative grows, finer-grained permissions would reduce the need for custom overrides per user.
- Build a dedicated data import pipeline. The legacy Excel migration was done semi-manually. A repeatable ETL pipeline would have made the reconciliation process faster and more auditable.
Key Takeaways
Building a production financial system for a real institution, as a solo developer, teaches you more than any tutorial. Double-entry accounting is a constraint that shapes every design decision. The system is deployed on-premise at the cooperative and used daily. That's a different level of accountability than a side project.
I'm open to full-time, contract, and freelance work.