Skip to content

Case study

A payroll system that turned a monthly build into a monthly review

Payroll for a growing IT services company was calculated by hand every month and payslips were emailed one by one. We built a system where the numbers come from recorded inputs and people review, rather than rebuild, each run.

Quick facts

Industry
Finance and accounting
Product type
Internal web application
Platform
Web
Timeline
In use, extended as rules change
Status
In use

At a glance

What changed

Calculated from inputs

Attendance, leave, allowances and deductions feed the payroll run instead of being added up by hand.

A review, not a build

The monthly run is prepared by the system and checked by a person before anything is final.

Payslips in one batch

Every payslip is generated as a PDF and sent in a single batch from the company mail server.

Every change logged

Corrections and approvals leave a history, so questions can be answered from the record.

The client

The client and the situation

The client is an IT services company with a growing team. Staff are on different pay structures: fixed salaries, allowances that depend on role, deductions that vary by person and leave that affects pay in different ways. As the team grew, so did the number of special cases.

The finance team is small. Payroll was one of several jobs it handled each month, and it took far more time than it should have. The company wanted a tool built for its own rules, owned by the company and run on its own infrastructure.

The challenge

The challenge

Each month, payroll was calculated by hand from attendance records, leave, allowances and deductions. Then payslips were prepared and emailed one by one. Errors were often found late, after payslips had gone out, and corrections took longer than the payroll itself.

The rules themselves were the hard part. They lived in people's heads and in old spreadsheets. Some applied only to certain roles or only in certain months. Writing them down precisely was the first real piece of work, and it had to be done before any code could be trusted.

Before

How the work was done before

At the start of each month, someone collected attendance and leave data, looked up each person's salary structure and worked out allowances and deductions in a spreadsheet. A second person checked the totals where time allowed. Payslips were then prepared individually and sent as email attachments, one message per employee.

When an employee questioned a figure, the answer meant going back through the spreadsheet and the emails. If a mistake was found, the whole process for that person was repeated, and a corrected payslip was sent by hand.

Objectives

What the project had to achieve

  • Write every pay rule down precisely and turn it into code with tests.

  • Calculate each monthly run from recorded inputs, not manual arithmetic.

  • Add a clear review step before a run is final.

  • Generate payslips as PDFs and deliver them in one batch from the company mail server.

  • Keep a history of every change and give each role the right access.

The solution

What we built

We built an internal web application that holds employee records, salary structures and the monthly inputs that drive pay. A payroll run gathers attendance, leave, allowances and deductions for the month, applies the rules and prepares a draft for review. Once a reviewer approves it, the system generates a payslip PDF for each employee and sends them all from the company mail server.

Every rule is in code, and every rule has tests. When the rules change, the tests show exactly what else changes. That is what lets the finance team trust the numbers without redoing the arithmetic. The work falls under our payroll automation solution and our internal tools service.

  • Employee records

    Each person's role, pay structure and history in one place.

  • Salary structures

    Fixed pay, allowances and deductions defined as structures and assigned to people.

  • Attendance and leave inputs

    The monthly inputs that affect pay, recorded before the run starts.

  • Monthly payroll run

    A run that applies every rule and prepares a draft for the month.

  • Review step

    A reviewer checks totals and exceptions before the run is approved.

  • Payslip PDFs

    A clear payslip for every employee, generated from the approved run.

  • Email delivery

    Payslips sent in one batch from the company mail server, with a delivery log.

  • Audit history

    Who changed what and when, for every record and every run.

  • Exports for accounting

    Run totals exported for the accounting system.

UX and UI

The UX and UI approach

The finance team uses this tool once a month under time pressure, so the main screen is the payroll run itself. It shows the state of the run, the totals, and the exceptions that need a person to look at them, such as new joiners, unpaid leave or unusual deductions. A reviewer can open any employee from the run and see how each figure was reached.

We kept the interface plain on purpose. Payroll is not a place for surprises, so labels use plain payroll terms, and the steps of a run follow the order of a manual payroll: inputs, calculation, review, payslips.

Architecture

How the pieces fit together

Attendance,leave and adjustmentsPay rules withtestsPayroll runand reviewPayslip PDFsCompany mailserverDatabase andaudit log

Monthly inputs and employee records sit in one database with an audit log. The pay rules are a separate, tested module, so they can change without touching the screens. A run applies the rules to the inputs and stores the result as a draft. After approval, payslips are generated as PDFs and handed to the company's own mail server for delivery, and each send is recorded.

Email delivery turned out to be a project of its own. When payslips were first sent from the self-hosted mail server, Gmail rejected them. Fixing that meant building the server's sender reputation properly: reverse DNS for the sending address, SPF, DKIM and DMARC records, and forcing delivery over IPv4. Only then did payslips arrive reliably in every inbox. It is the kind of detail that is invisible when it works and very visible when it does not.

AI-accelerated

Where AI sped up the build

Honest about what AI did, and what people did.

  • Rules to code: AI turned the written pay rules into first versions of calculation code quickly. Engineers checked each rule against the finance team's examples.

  • Edge cases and tests: AI helped list the edge cases for each rule, such as mid-month joiners and partial leave, and we turned them into unit tests.

  • Documentation: AI drafted the guide for the finance team, explaining each step of a run in plain language. The team edited it before use.

Integrations

Integrations

  • Company mail server

    Payslips sent from the company's own mail server, with SPF, DKIM, DMARC and reverse DNS set up for reliable delivery.

  • Accounting exports

    Approved run totals exported for the accounting system.

  • Role-based access

    Finance, reviewer and admin roles with different permissions.

Screens

Concept screens

Simple mockups of the described interface. Real screenshots will replace them.

payroll.internal/runs
Payroll runsEmployeesSalary structuresAttendance and leavePayslipsEmail logSettingsSearchApprove runPayroll run: SeptemberDraft, waiting for reviewEmployees in run48Gross pay0,000,000Deductions000,000Exceptions5EmployeeReasonChangeStatusEmployee 014Joined mid-monthPro-ratedReviewEmployee 022Unpaid leave, 2 daysDeductionReviewEmployee 031New allowanceAddedApprovedEmployee 040Salary changeUpdatedApprovedEmployee 047Loan deductionDeductionPending
The monthly payroll run with totals and exceptions
payroll.internal/runs
Payroll runsEmployeesSalary structuresAttendance and leavePayslipsEmail logSettingsSearchEmployee 014Software engineer, joined this monthRoleSoftware engineerSalary structureEngineering, level 2Start date15 SeptemberPayment methodBank transferDateChangeBy15 SepEmployee record createdFinance15 SepSalary structure assignedFinance16 SepBank details verifiedReviewer
An employee profile with sample data
PayslipSeptember payslipBasic salary000,000Allowances00,000Overtime0,000Tax-00,000Other deductions-0,000Net pay000,000Sample figures. Sent as a PDF attachment.

Concept screen

Payslip preview with sample figures
payroll.internal/runs
Payroll runsEmployeesSalary structuresAttendance and leavePayslipsEmail logSettingsSearchResend failedEmail logSeptember payslipsSent48Delivered48Failed0EmployeeSent atStatusEmployee 00130 Sep, 17:02SentEmployee 00230 Sep, 17:02SentEmployee 00330 Sep, 17:02SentEmployee 00430 Sep, 17:03Sent
The email log showing delivery of each payslip

Results

The results

The monthly run is now a review, not a build. The system prepares the numbers from recorded inputs, and a person checks the totals and the exceptions before approving. Payslips go out in one batch instead of one email at a time, and they arrive, because the mail server is now set up the way receiving servers expect.

Every change is logged, so an employee's question can be answered from the record rather than from memory. We do not have measured before and after times to publish. If the client shares them, they will appear here.

What the team can do now

  • Run payroll for every employee from recorded inputs.

  • Review totals and exceptions before anything is final.

  • Send every payslip in one batch and see a delivery log.

  • Answer questions about any figure from the audit history.

  • Change a pay rule and see its effect through the tests before it goes live.

Before and after

Before and after

Before

Spreadsheets and single emails

  1. Pay is calculated by hand from several sources each month.

  2. Rules live in people's heads and old spreadsheets.

  3. Payslips are sent one email at a time.

  4. Errors are found late, after payslips have gone out.

  5. Corrections take longer than the payroll itself.

After

A tested system with a review step

  1. Inputs are recorded once and feed the run.

  2. Every rule is in code with tests.

  3. A reviewer checks totals and exceptions before approval.

  4. Payslips go out in one batch, with reliable delivery.

  5. Every change is logged and easy to trace.

What comes next

What we would do next

We would next connect attendance directly to the source the company uses to record it, so inputs arrive without an import step. We would also give employees a simple self-service page for past payslips and tax summaries, which removes most of the remaining email requests.

For finance, we would add approval workflows for salary changes, so every change is proposed, approved and logged before the next run. Where it helps, a light AI layer could read supporting documents such as expense claims into the inputs, as in our receipt processing solution.

Solutions in this project

Problems this project solved

Payroll automation

Turn pay rules, attendance and leave into tested software so the monthly run becomes a review and payslips go out in one batch.

Approval workflows

Requests, approvals and reminders in one place, with clear owners and deadlines instead of long email threads.

Automated reporting

Reports that build themselves from your systems on schedule, with a plain-language summary of what changed.

Keep exploring

Start a project

Have a similar problem? Tell us about it.

Send a short brief. We reply with questions, a suggested plan and an estimate you can compare with other offers.

Your privacy choices

We use necessary storage to run this site. With your permission we also use Google Analytics to see which pages help people, and load maps from Google. You can change this at any time. Read the cookie policy.