# Integrating Payroll with Your Custom ERP: From Timesheets to Payslips and Tax Reporting

> A practical guide to building payroll integration in a custom ERP — connecting HR data, attendance, and timesheets to automated payslip generation and Indonesian tax reporting.

URL: https://www.matthewswong.com/en/blog/erp-payroll-integration-hr/

- Author: Matthews Wong (https://www.matthewswong.com/en/about/)
- Published: 2025-06-10
- Updated: 2025-06-10
- Category: ERP

HRIS integrations eliminate manual data entry, errors, and compliance risks by connecting HR platforms with payroll, benefits, and other business systems. For Indonesian SMEs, payroll is one of the most operationally critical modules — get it wrong and you have unhappy staff and potential labor law violations. I've seen Indonesian companies spend 3-5 days per month on payroll processing using a combination of Excel files and manual bank transfers. In my freelance ERP consulting work, I built a payroll integration module that connects attendance data, timesheets, and HR records to automated payslip generation and bank disbursement. This is what it took to make it production-ready.

## The Payroll Data Model

Indonesian payroll has specific components that must be modeled correctly: Gaji Pokok (base salary), Tunjangan Jabatan (position allowance), Tunjangan Makan (meal allowance), Tunjangan Transport (transport allowance), Uang Lembur (overtime pay), THR (Tunjangan Hari Raya — religious holiday bonus), and various deductions (BPJS Kesehatan, BPJS Ketenagakerjaan, PPh 21 income tax, late/absence deductions). Each component has different tax treatment — some are tax-inclusive, some are tax-excluded, and THR has specific PPh 21 calculation rules.

### Attendance and Overtime Integration

The payroll module I built reads attendance data from three possible sources: biometric attendance machine (via API or CSV import), timesheet approvals in the project module, or manual entry by HR. The attendance records are aggregated per employee per month to compute: total working days, late arrivals (which trigger deduction per company policy), absences without leave (penalty deduction), and overtime hours (hours beyond 8 per day or 40 per week, paid at 1.5x or 2x per UU Ketenagakerjaan). This attendance summary is the input to payroll computation.

> From my experience building ERP systems as a freelance ERP consultant: always implement a payroll simulation run before the actual payroll. Let the HR manager run the full computation and review the payslips before any disbursement is triggered. I call this the 'dry run' — it generates all payslips with a DRAFT status and an exceptions report (employees with unusual deductions, overtime above a threshold, salary increases not yet approved). This catches errors before they become costly corrections. The dry run is the single highest-value feature in the payroll module.

## PPh 21 Tax Calculation

PPh 21 (Article 21 Income Tax) calculation in Indonesia is complex: it uses a progressive rate structure (5%, 15%, 25%, 30%, 35%), takes into account PTKP (non-taxable income threshold based on marital status and dependents), and differs for permanent employees (gross method vs. net method). The system I built implements the Annualization method required by Indonesian tax regulations: monthly gross is annualized, tax is computed on the annual amount, then divided by 12 for the monthly withholding. This must match the DJP (Directorate General of Taxes) calculation — I test against DJP's calculator on every payroll run.

### BPJS Contributions

BPJS Kesehatan (health insurance) and BPJS Ketenagakerjaan (social security) contributions are mandatory for all employees. BPJS Kesehatan: 4% employer + 1% employee of salary (capped at the BPJS premium ceiling). BPJS Ketenagakerjaan: JHT 3.7% employer + 2% employee, JKK 0.24-1.74% employer depending on business risk class, JKM 0.3% employer, JP 2% employer + 1% employee. These percentages are regulatory and must be updated whenever BPJS publishes new rates — storing them in a configuration table (not hard-coded) is essential.

> **Warning: Retroactive Payroll Corrections**

> When a payroll error is discovered after disbursement — a missed attendance record, a wrong salary tier, a BPJS ceiling that wasn't updated — the correction must be handled carefully. Never delete a paid payroll run. Instead, create an adjustment payroll run that only includes the affected employees and posts the correction amounts. The adjustment run links to the original run for audit trail. I also had a client who tried to claw back overpayments via a single large deduction from the next payslip — this violated the UU Ketenagakerjaan which limits deductions to 50% of net pay. Know the legal constraints before implementing correction logic.

## How I Approached This

The payroll module is a NestJS service that orchestrates: PayrollComputationService (reads attendance, applies formulas), TaxCalculationService (PPh 21 and BPJS), PayslipGenerationService (creates PDF payslips via Puppeteer), and DisbursementService (generates bank transfer file in BCA or Mandiri bulk transfer format). Each payroll run is a payroll_runs row with status: draft, approved, disbursed. Once disbursed, the run is locked and cannot be modified.

## Payslip Generation and Distribution

Each employee gets a PDF payslip generated by Puppeteer from an HTML template. The template shows: employee details, salary components, deductions, net pay, and a QR code linking to the online payslip for authenticity verification. Payslips are stored in Google Cloud Storage with employee-specific signed URLs (30-day expiry). The distribution email is sent automatically on payroll disbursement day — employees can access their payslip via the link without logging into the ERP.

## Annual Tax Reporting (SPT Tahunan)

Indonesian employees need a Bukti Potong PPh 21 (tax withholding proof) annually to file their SPT Tahunan (annual tax return). The system I built generates Bukti Potong documents for all employees at year-end: total gross income, total PPh 21 withheld, NPWP of both employer and employee. These are exported in the XML format required by e-SPT, the DJP's filing application. This feature alone saves the HR team 2-3 days of annual work and ensures the Bukti Potong matches the company's PPh 21 tax deposits.

## Sources & Further Reading

- Select Software Reviews — Payroll Integration Benefits & Best Practices — https://www.selectsoftwarereviews.com/blog/payroll-integration
- APIdecks — A Guide to HRIS Integrations: Best Practices and Trends for 2026 — https://www.apideck.com/blog/a-guide-to-hris-integrations-best-practices-use-cases-and-trends-for-2025
- ERP Software Blog — ERP for HR: Improve Your Payroll and Employee Management — https://erpsoftwareblog.com/2025/04/erp-for-hr-improve-your-payroll-and-employee-management/

> **Key takeaway:** Payroll is the ERP integration with the least tolerance for error, because a wrong figure is visible to every employee on the same day. Connecting timesheets, payslips and tax reporting through one flow removes the manual re-entry where Indonesian SME payroll mistakes usually originate.

## Source links

- https://www.selectsoftwarereviews.com/blog/payroll-integration
- https://www.apideck.com/blog/a-guide-to-hris-integrations-best-practices-use-cases-and-trends-for-2025
- https://erpsoftwareblog.com/2025/04/erp-for-hr-improve-your-payroll-and-employee-management/

## FAQ

### Why is a 'dry run' before payroll disbursement so important?

A dry run generates all payslips in DRAFT status along with an exceptions report — flagging employees with unusual deductions, overtime above a threshold, or unapproved salary changes. This lets the HR manager review and correct errors before any funds are transferred. It is described as the single highest-value feature in the payroll module because catching mistakes before disbursement avoids costly retroactive corrections.

### How does the system calculate PPh 21 income tax?

The system uses the Annualization method required by Indonesian tax regulations: the monthly gross salary is annualized, PPh 21 is calculated on the full annual amount using the progressive rate structure (5%, 15%, 25%, 30%, 35%), then divided by 12 to get the monthly withholding. PTKP (the non-taxable income threshold based on marital status and dependents) is also applied. Results are tested against the DJP's own calculator on every payroll run to ensure compliance.

### Why must BPJS contribution rates be stored in a configuration table rather than hard-coded?

BPJS Kesehatan and BPJS Ketenagakerjaan rates are set by regulation and can be updated whenever BPJS publishes new rates. Hard-coding the percentages means a rate change requires a code deployment; storing them in a configuration table lets HR administrators update the values without a release. This is especially important for the several BPJS Ketenagakerjaan components whose rates vary by business risk class.

### How should payroll errors discovered after disbursement be corrected?

The post advises never deleting a paid payroll run. Instead, an adjustment payroll run is created that includes only the affected employees, posts the correction amounts, and links back to the original run for audit trail purposes. Additionally, clawing back overpayments via a single large deduction from the next payslip is prohibited by UU Ketenagakerjaan, which caps total deductions at 50% of net pay.

### What does the system generate for annual tax reporting, and how much time does it save?

At year-end the system generates Bukti Potong PPh 21 documents for every employee, covering total gross income, total PPh 21 withheld, and the NPWP of both employer and employee. These are exported in the XML format required by e-SPT, the DJP's tax filing application. This feature alone saves the HR team an estimated 2–3 days of annual work and ensures the Bukti Potong figures match the company's own PPh 21 tax deposit records.

---

- HTML version: https://www.matthewswong.com/en/blog/erp-payroll-integration-hr/
- Bahasa Indonesia: https://www.matthewswong.com/id/blog/erp-payroll-integration-hr/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
