Skip to main content
ChintoLabChintoLab
Hair Focus payroll page for August, all ten staff listed with cycle, basic, commission, deductions and net
Case Studies

Hair Focus: a case study

A salon management system that computes payroll on the server from attendance, bookings, advances and loans. Built for a grooming salon in Pakistan.

ChintoLab TeamSeptember 14, 20265 min readUpdated September 15, 2026
A salon management system that computes payroll on the server from attendance, bookings, advances and loans. Built for a grooming salon in Pakistan.

Hair Focus is a hair and grooming salon in Pakistan, owned by Arman, with ten working staff covering haircuts, beard work, facials, keratin treatments and hair patches. Before this project the salon's complete record was a paper register: who attended, what they did, what was paid, and what each person had drawn against wages.

We built three applications on one shared codebase: an admin portal for the owner and manager, a mobile app for staff, and an API that performs every write. Development began on 4 July 2026 and the payroll rewrite was completed on 31 August, 618 commits later. The system carries the salon's name because it is the salon's own working tool. It is not a product for sale and has no public address.

The problem

Payroll was the most serious problem. Commission was paid in cash each week and noted in the register, but the monthly payslip had no record of it. The same commission was therefore paid twice: once in cash during the week and again as part of the month's salary. When we reconciled August against the register, Rs 13,430 was about to be paid a second time.

Advances and loans were recorded as the same thing. A loan is repaid on a schedule over several months. An advance is deducted in full from the next payslip. Because both were stored as loans, two genuine loans carried a monthly instalment equal to their entire outstanding balance. Either would have taken a person's full month's pay in one deduction.

Attendance had a less visible fault. Absences were calculated by subtraction: expected days minus recorded days. A day that nobody had written down produced the same result as a day somebody had missed, and both were deducted. By the end of August, fifty working days across six people had no record of any kind.

Attendance month grid for August, present and absent marked per person per day

What we built

Every number has one source. Every write rule in Firestore is set to false, so the browser can read and nothing more. Every change passes through the API, which reads attendance, bookings, advances and loans directly and computes the result. No screen can calculate its own total, so no screen can report a wrong one.

Payroll previously ran on a rolling window from each person's last pay date, so no two people shared a period, and a 34 day cycle cost the same basic salary as a 27 day one. It now runs on the calendar month, with one payslip per person, keyed by a document id derived from the month. A second run in the same month finds the existing record rather than creating another.

Admin Dashboard scoped to August, showing takings, bookings, staff in, spend and stock alerts

Advances and loans are separate ledgers drawing on one capacity: what the month earned after absences and fines. Loans take their scheduled instalment first, advances take what remains, and neither takes more than is available. Any amount that does not fit carries to the following month and is reported on the payslip rather than dropped.

Before payroll generates, the API counts the working days in each person's month that have no attendance record. If any exist it refuses to run, names the person and the dates, and states what the missing days would cost. A person taking home nothing because they drew their full salary in advances is reported as a warning, not a blocker: the data is complete and the figure is correct. Blocking on correct figures would train the owner to override, and a genuine blocker would eventually be overridden with them.

New Booking POS with the service menu, a bill and the four payment methods

Two things were left out deliberately. The public website was removed in August at the salon's request, and seven collections that had been readable without sign-in were closed at the same time. No leave system was built. A day not worked is unpaid regardless of the reason, and a second category for the same outcome would add nothing but explanation.

Staff app Earnings for August: commission earned, services at 10 percent and basic salary

Results

  • Rs 13,430 of weekly cash commission is now recorded as advances and recovered once, through the payslip, rather than paid twice
  • Six of eight records stored as loans were reclassified as advances. The two genuine loans now run at a 5,000 monthly instalment
  • Fifty unrecorded working days across six people were held by the pre-flight check instead of being deducted as absences
  • 3,012 clients, 191 products, 31 services, 8 packages and 149 bookings in the live database on 11 September 2026
  • 1,887 tests across 176 files, including 130 against the Firestore rules and 281 against the API on the emulator

Time saved on payroll has not yet been measured. August is the first month run on the new system.

Features

  • Server-side payroll: the API reads attendance, bookings, advances and loans and writes every figure. The browser reports what happened, never what it is worth
  • Closed Firestore rules: 780 lines, every write denied, verified by 130 rules tests
  • Payroll pre-flight: unrecorded days block the run and are priced. A zero take-home is reported and not blocked
  • Capacity ledger: loans first, then advances, capped at what the month earned, with the shortfall carried forward and reported
  • Commission stamped at sale: service, product and manager rates are written onto each booking line at the point of sale
  • Deterministic ids as locks: attendance, payslips and register-day bookings are keyed by person and date, so a repeated write overwrites rather than duplicates
  • Weekly off day per person: one fixed weekday each, 52 a year, plus salon holidays, excluded before any absence is counted
  • Staff app: Schedule, Earnings and My hours, with each day priced by the same functions payroll uses
  • Owner-editable lists: 11 lists including payment methods, job categories and units, changed in Settings without a code change
  • Register reconciliation: a completed sheet is compared line by line against the database and every difference is reported, none decided

Built with

Next.js 15, React 19, TypeScript and Tailwind CSS on the front end, Firebase Authentication, Cloud Firestore, Cloud Messaging and the Firebase Admin SDK behind the API, Zod for validation, Vitest for the 1,887 tests, Cloudinary for media and Vercel for hosting.

Start a project like this

Related service

Management Systems

We build custom management systems that help businesses manage sales, inventory, staff, reports, customers, and daily work in one clean platform, so daily operations stay organized, easier, and clear.

Explore service

Ready to Build Smarter Systems?

ChintoLab creates modern digital systems that help businesses work smarter, manage better, and grow faster.

Share this article

X LinkedIn

ChintoLab Team

ChintoLab