SHRM
HR and payroll for Indonesian companies, from one system.
- Role
- Product Owner & Developer
- Period
- May 2026 - Present
- Status
- Launched, web and desktop
Overview
A web and desktop HR and payroll platform that runs payroll, PPh 21 income tax, BPJS, payslips, and employee records for several companies, with data kept separate per company.
Problem
HR teams were running payroll in spreadsheets: PPh 21 TER income tax, BPJS Kesehatan and Ketenagakerjaan, overtime, bonus, and THR all calculated by hand every month.
Payslips and annual tax slips had to be produced and sent to every employee, and employees had to ask HR for documents and leave balances.
Several companies needed to share one system without seeing each other's employees, payroll, or leave requests.
My role
Owned the product end to end: requirements, feature specification, architecture, implementation, testing, and handover documentation.
Designed the payroll rules, access model, and security controls, and built both the Flask backend and the React frontend.
Packaged two deployment targets: a Windows desktop app and a Dockerized web app.
Approach
Specify
Mapped the monthly payroll cycle, tax rules (PPh 21 TER, PMK 168/2023), BPJS contributions, and year-end reconciliation into feature specifications before writing code.
Build the core
Automated payroll with gross-up and net methods, plus a one-click refresh that updates draft payroll from employee records while keeping overtime, bonus, and THR inputs.
Serve employees directly
Launched an Employee Self Service portal for payslips, tax slips, leave requests, and leave balances, so staff no longer need to contact HR for them.
Harden and hand over
Added two-factor login, encrypted PDFs, an audit trail, and a scheduled email queue, then wrote user guides and deployment runbooks.
Key decisions
Two deployment targets from one codebase
Shipped as a Windows desktop app (PyInstaller, SQLite) and as a web app (PostgreSQL 16 in Docker with gunicorn and Caddy), so each company can run it the way its IT setup allows.
Per-company data isolation with three admin levels
Role-based access means each admin sees only their own group's employees, payroll, and leave requests.
Payslips protected by default
Payslips and BPA1 tax slips (Form 1721-A1) are generated as password-protected PDFs with AES-256 encrypted attachments before they are emailed.
An email queue that survives restarts
Bulk and scheduled sends use atomic job claiming, heartbeat leases, and automatic recovery after a server restart, so a reboot does not drop or duplicate payslip emails.
Outcome
- Payroll, income tax, BPJS, and employee records run from one system instead of spreadsheets.
- HR can email payslips to all staff at once or schedule the send for a set date and time.
- Employees download payslips and tax slips, and submit or cancel leave, without contacting HR.
- Contract-expiry reminders go out by email 7 days ahead; year-end tax reconciliation is built in.
- Bilingual (ID/EN) interface with light and dark themes, plus payroll and self-service user guides.
- 186
- automated tests across payroll, access control, leave approval, and email scheduling
- 2FA
- TOTP and email OTP, PBKDF2-SHA256 hashing, 5-rule password policy
- 2
- deployment targets: Windows desktop and Dockerized web
Test counts describe engineering coverage, not business results.
Stack
- Backend
- Python
- Flask 3
- gunicorn
- Frontend
- React 18
- Vite
- Tailwind CSS
- Data
- PostgreSQL 16
- SQLite
- Delivery
- Docker
- Caddy
- PyInstaller