SIMKEU Web.
Finance and HR ERP for a container port terminal operator in Indonesia. One web app replacing a legacy Oracle Forms/Reports system.
The source code is proprietary and is not published here. This page describes my work on it.
About the system
SIMKEU Web is the company-wide back-office system for a container port terminal in Indonesia. It replaces a legacy Oracle Forms/Reports application with a single web app.
It has more than 1,200 Java classes, more than 700 screens and fragments, and several hundred menus behind role-based access.
Performance
- Finance dashboard went from 5.6 s to about 330 ms. I profiled it and fixed four bottlenecks: N+1 queries, missing indexes, repeated view scans, and uncached lookups.
- A budget-allocation list that timed out after 49.8 s now loads normally. The cause was a per-row "already paid" subquery, which I rewrote as one set-based query.
- Static asset delivery: I fixed caching headers on an 8.7 MB application shell that had been re-downloaded on every visit.
HR module port
Personalia and Payroll, moved from a separate legacy app into the main system.
- Ported the personnel and payroll screens from
simpersweb. That covered 73 HR menus mapped to their tables. - Built and wired 29 payroll reports in PDF and Excel.
- Ran an HR audit that found about 58 issues and wrote 6 fix plans. Risky access rules first ran in a shadow-logging mode, so they could be checked for three working days before being switched on.
- Wrote the HR user documentation: an SOP in PDF and a training deck.
Dashboards
- Finance dashboard: live cash and bank position (closed months plus the open month), 8 financial ratios, and P/L. Every card drills down to the underlying vouchers.
- Human Capital dashboard: headcount and composition, read from one source of truth.
- Fuel (BBM) dashboard: replaced the old fuel issuance log with request tracking and consumption analytics.
Rebuilding legacy reports
I re-implemented about 30 Oracle Reports (.rdf) so the web output matches the legacy printouts figure for figure, including quirks that accountants rely on.
- Balance sheet, income statement and cash-flow reports, with per-account breakdowns
- Receivable, payable and cash-advance aging
- Cash book, sub-ledgers, expense summaries, stock movement and valuation
- A tax report in the 13-column layout the new national tax system (Coretax) requires
- Excel exports with Apache POI and PDFs with iText
Data integrity
- Found and repaired vouchers that were only half posted (header posted, journal lines not). I fixed 301 lines in production after taking a backup, and closed the code path that caused them.
- Reconciled report pairs that should agree but didn't: cash book vs cashier report, inventory GL vs stock movement, stock card vs balance. Then fixed the root causes, including sign conventions, period filters and unposted months.
- Traced wrong inventory values to a ghost stock unit that had inflated the moving-average cost.
Security & access
- Fixed CSRF token handling across the single-page app and tightened the Content Security Policy.
- Added an account-status check that runs during the session, so disabled users lose access right away.
- Designed a role-based privilege matrix: 26 role classes, 1,314 menu grants, 45 users.
- Fixed multi-stage approval workflows, such as directors who were missing their decision buttons and supervisors who couldn't see documents in their queue.
Integrations & delivery
Integrations
- e-Meterai (digital stamp duty): fixed token handling and serial-number pool management.
- RabbitMQ notification consumer for approval and e-mail events.
Testing and delivery
- Built a Playwright smoke-test harness that clicks through the whole app (all menus and screens) to catch broken pages before release.
- Set up Docker-based local environments and documented the Payara deployment pitfalls.
What I learned
- Matching a legacy system's results is harder than copying its features. Accountants trust numbers, not screens.
- Most "bugs" in an ERP are business-process gaps: a posting job never run, a missing approval step, master data with no owner.
- Measure before optimizing. One profiling session found the 17× dashboard speedup.