/payroll (the runs list). Open a run at /payroll/:id. A live analytics view is at /payroll/dashboard.
📷 Screenshot: a payroll run detail page with the entries table and the action bar (Generate / Submit / Pay) — to be added.
Multi-business: a run belongs to one business and posts to that business’s accounting book — set by the period you choose. Confirm the business switcher first.
The run lifecycle (statuses)
A run moves through these states. The status tells you what you can do next.
Two moments matter most:
- Approval posts to the ledger. A Draft or Generated run has no effect on your accounts; submitting/approving it is when the salary accrual is recognised.
- Paying is separate from approving. Recording payments comes after approval and posts its own cash entry.
Creating a run
From the runs list, choose New Payroll. The create form asks for:
A new run starts as a Draft.
Generate, approve, pay
The actions on the run detail page, and the permission each needs:Separation of duties. Preparing a run (payroll:write) and approving it (payroll:approve) are different permissions on purpose. The maker generates; the checker approves. Approval is the gate that touches money and the ledger.
Preview before you commit
You can dry-run a slip without creating anything via Salary slip preview (/payroll/preview) — useful for checking a structure or a new hire’s first slip. It computes and shows the breakdown without persisting.
Off-cycle runs
An off-cycle run is an ad-hoc payment outside the normal cycle — a bonus, a terminal/separation payout, or a catch-up. Off-cycle (and correction) runs:- require an explicit list of employees (no “all active” default),
- can coexist with a regular run for the same period — they’re exempt from the one-regular-run-per-period rule, and
- generate their own separate payslips so they never collide with the regular run.
Partial (instalment) payment
You don’t have to pay everyone at once. Once a run is Approved, the Pay action opens a sheet where you choose employees and amounts and the cash/bank/mobile-money source account. As you record payments:- each payslip’s amount paid and payment status (unpaid / partially paid / paid) update,
- the run status moves Approved → Partially paid → Paid as the outstanding balance falls to zero,
- a per-employee payment ledger (net pay, paid, outstanding) is available on the run.
The double-run guard
To stop you accidentally paying everyone twice, only one non-cancelled regular run per period is allowed for a business. If a draft or approved regular run already exists for that period, creating another regular run is refused with a conflict. (Off-cycle and correction runs are exempt, since they’re meant to run alongside.) On submit, the run is also locked so two people can’t approve the same run at the same time. This guard is what the internal terminal-run handling and pessimistic locks enforce — you’ll experience it as a clear “a run already exists for this period” message rather than a silent double-pay.Statutory remittances (paying PAYE / NSSF / LST)
Approving a run recognises what you owe the authorities (PAYE, NSSF, LST). To actually pay it over, open Statutory remittances from the run (/payroll/:id/statutory-remittances):
- Build remittances materialises the period’s PAYE / NSSF / LST liabilities as payable rows (needs
payroll:approve). - Each row shows the amount and a status (Pending / Paid / Void).
- Pay on a pending row records the payment to URA / NSSF (select source account, date, reference), posting the cash entry that clears the payable.
payroll:read, building and paying need payroll:approve.
Behind the scenes — the accounting
Payroll posts to the general ledger at two moments.When the run is approved — the salary accrual
A balanced journal entry recognises the wage cost and the liabilities you now owe. In plain double-entry terms (per cost centre, so cost-centre reports stay accurate):
So the business recognises the full cost of employing people, parks each employee’s net pay as a payable, and parks each statutory amount in its own payable account until it is remitted. Statutory items always route to their dedicated payables (
paye_payable, nssf_payable, lst_payable); earnings and employer contributions use each component’s mapped account, falling back to a blanket payroll-expenses account if a component isn’t mapped.
When you record a payment — the disbursement
This clears the net-pay liability raised at approval and shows the cash leaving the business. Each debit is tagged to the employee so the payables sub-ledger reconciles per person.
When a run is cancelled or a payment reversed
The original entry is reversed — every debit and credit posts in the opposite direction — returning expense, payables and cash to where they were.If approval fails with a message about a missing payable or expense system account, your chart of accounts is missing one of the payroll accounts (e.g. PAYE payable). Configure it in the chart of accounts and try again — the run can be re-bridged once the account exists.
Permissions
Related
- Payslips — the per-employee output of a run
- Payroll periods — what a run is created for
- Salary structures — how each slip is computed
- Income-tax slabs — the PAYE bands applied during a run
- Payroll overview — the whole chain