Skip to Content

The payroll bug that wasn't arithmetic

Half a day, a handful of people, every month — and four parts of the system with four opinions.

The problem arrived as one sentence: payroll is wrong. Not by much — half a day, for a handful of people, every month — and nobody could find the bug.

The bug wasn't arithmetic. Four separate parts of the system — the payslip engine, the attendance dashboard, the monthly report and the leave module — each decided for itself what counted as a working day. An employee with a half-day of attendance and a half-day of leave got credited for both.

The tempting fix is a fifth check that reconciles the other four. We did the opposite: one canonical day classifier that everything now calls. It turns a day's worked hours into a payable fraction of that day's expected hours — a full day, a configurable half-day fraction, or absent — with the thresholds set per working calendar rather than hardcoded.

Expected hours get the same care as worked hours: lunch breaks, separator lines and overtime slots are left out before the ratio is taken. Attendance and leave on the same day are split, never both counted, and the payslip exposes its day breakdown — attendance, weekend, leave, paid, absence — so the report reads the same numbers the payslip used.

It shipped with 19 automated tests covering the thresholds, the fractional splits and the report rendering, and the discrepancy stopped. When numbers are quietly wrong, look for the places that are allowed to disagree.

Read the case study: Payroll that was off by half a day, every month

One punch, three records
Making biometric attendance trustworthy — and the WhatsApp flood that taught us about stale events.