HRMS Portal
The internal HR platform for a whole company: leave with real accrual arithmetic, biometric timesheets parsed from the door system, an approvals queue, a shared calendar, templated email and spreadsheet export. Two repos, 312 commits, sole author, still receiving fixes three years on.







Overview
An internal HR system that replaced spreadsheets and email threads as the company's record of who is off, who is in, and who owes whom a day. Leave, timesheets, employee records, an org feed, birthdays and weekly forms. I built both halves — the NestJS API and the Next.js client — and I am still the only person who has committed to either.
Leave is arithmetic, not CRUD
This is the part people underestimate. Casual and sick leave accrue monthly at fractional rates, pro-rated from the date an employee is confirmed rather than the date they joined, so a mid-year starter gets the remaining months and not the full allowance. Fractions have to be rounded to something a human can be told — half a day — and the rounding is tuned to the specific accrual rates rather than being a generic round-half-up, because a generic one gives people a day they have not earned. Requesting more than the balance does not fail; the excess silently converts to unpaid leave, which is what the policy actually says and what a naive implementation gets wrong.
The balance is a ledger, not a number
Every balance change is expressed as one atomic increment over a per-type map, with the direction as a parameter — so applying, approving, cancelling and reverting are all the same primitive with a different sign. The interesting case is an administrator editing the allotment at the moment of approval: that becomes a single increment that merges a decrement of the old split with an increment of the new one, so there is never a window where the balance is wrong. Eight leave types, each with its own unit — including a quarter-day short leave capped at one per calendar month, enforced with a month-and-year aggregation rather than a lookup, and a zero-day late-coming record that still notifies.
Timesheets from the door
Attendance comes from the biometric access system as a spreadsheet of raw punches. Parsing it means pairing ins with outs, detecting an overnight shift when a later punch has an earlier clock time than the first, and bulk-upserting the result. Ideal hours are then computed by subtracting weekends and the holiday calendar from the period, which is the only way the number means anything. Dates run in a single fixed timezone set at bootstrap, deliberately — an HR system that disagrees with itself about which day a punch belongs to is worse than no system.
The rest of it
Access and refresh tokens with a roles guard over three levels, Google sign-in verified server-side, request validation with typed DTOs and environment validation at boot. Transactional email is rendered from templates for apply, cancel and action, and the subject line branches on whether the request is a whole number of days, so a two-hour short leave does not arrive announcing a date range. Spreadsheet import and export both, because HR lives in spreadsheets and pretending otherwise loses the argument.
Honest scope
312 commits across the two repositories, June 2023 onwards, all mine; most of the build landed in 2023 and it has been maintenance since. There are no automated tests — Jest is configured and was never used — and no migrations, which for a system that computes people's leave balances is the honest weak point rather than a footnote. Approval is one step: an administrator approves an employee. There is no multi-level chain.