Finance → Collections → Late fees → /penalties Beta
Penalties are the platform's late-fee engine: a policy defines when a fee applies and how much it is; an assessment is the record of that policy firing against a specific overdue invoice.
The module has two tabs:
| Tab | Route | Contents |
|---|---|---|
| Late payment rules | /penalties/policies | The rules that decide what is charged, and to whom. |
| Fees charged | /penalties/assessments | Every fee the engine worked out, with its outcome. |
Late payment rules
A rule answers five questions, in the order the form asks them:
| Question | What you choose |
|---|---|
| Who does it cover? | Every property, one property, one block, one unit, or one tenant. |
| What is charged? | A fixed amount, or a percentage. A percentage also asks which balance it is taken on, and whether there is a ceiling per charge. |
| When does it start, and how often? | Days to allow after the due date, then once / every day / every week / every month while the invoice stays unpaid. |
| Who is left out? | Invoices under a live promise to pay, and invoices that were already overdue before the rule started. |
| Charge, or try it out? | With an income category the fee is billed; without one the rule only records what it would have charged. |
As you fill the form in, the panel beside it shows what the rule would charge — worked out by the server on this property's real overdue invoices, using the same arithmetic the nightly run uses. It shows the example fee, the first day it would be charged, what it comes to after several months, and how many invoices would be charged on the first run.
Rules also carry:
- Scope — every property, or one property, block, unit or tenant. When two rules could both apply, the lower priority number wins; on the same number the more specific rule wins (tenant > unit > block > property > every property).
- Bill late fees as — the income category the charge is billed under. This is what maps the fee to an income account in the chart of accounts. Left empty, the rule runs as a trial.
- Active flag — policies are deactivated, not deleted, so historical assessments keep their context.
Promises to pay
By default a rule skips any invoice covered by a live promise to pay: a tenant keeping to an arrangement you agreed is not charged for being late on it. Cover ends by itself — when the promise is missed, cancelled, or its promised date passes — and the fee resumes on the next run with nobody having to remember. A promise that names specific invoices covers those; a promise recorded against a lease without naming invoices covers that lease's overdue invoices.
Switch the behaviour off per rule if late fees should apply regardless of arrangements.
Which invoices a rule reaches
A rule's start date gates the rule, and by default it also gates the invoices: only invoices due on or after the start date are ever charged. Choosing Include invoices that are already overdue reaches backwards over existing debt — the preview says how many invoices and how much that is before you save.
Fees charged
Each fee records: the case or lease, the overdue invoice that triggered it, the basis amount, the computed fee, the rule used, the cycle key, and whether it was billed.
Assessments are idempotent by cycle. Running the engine twice over the same period does not double-charge — the cycle key prevents a second assessment for the same policy, invoice and cycle.
From assessment to invoice
When the engine posts, it writes a real penalty invoice through the standard invoice writer, using the policy's penalty service type. That means a late fee:
- appears on the tenant's statement like any other charge;
- flows into the general ledger through the normal posting path;
- is collectable, allocatable, adjustable and refundable like any other invoice.
Penalties default to non-VAT (KRA tax class D) unless the service type says otherwise.
What is already running, and what is not
There is no master switch left to turn on. The nightly sweep is registered and runs for every organisation, and it has been assessing for months — as of 26 August 2026 it has produced over 2,500 fee records across the platform.
What it has never done is bill anybody. Every fee it recorded sits at "not billed", because billing depends on one field on the rule:
| The rule has... | What the sweep does |
|---|---|
| no income category ("Bill late fees as" empty) | Works the fee out and records it. Nothing reaches the tenant, nothing reaches the ledger. This is a trial. |
| an income category | Raises a real invoice for the fee, on the tenant's account, immediately due. |
So "switching penalties on" for an organisation means setting that one field on the rule you want to bill — not asking an administrator to enable a job.
Turning late fees on for an organisation
Check there is a late-fee income category
In the chart of accounts, an income category the fee belongs under — "Fines and Penalties", "Late Payment Fee". Not "Rent": the category is what the charge is labelled as on the tenant's invoice and in the ledger.
Write the rule and leave it as a trial
Leave "Bill late fees as" empty. The rule starts recording what it would have charged that night.
Read what it produced
Give it a few days, then look at Fees charged. Compare a sample against what you would have charged by hand. This is the step that catches a grace period that is too short or a percentage taken on the wrong balance.
Decide what the rule reaches
By default it only touches invoices due on or after its start date. Including debt that was already overdue is a deliberate choice, and the preview tells you what it would cost the tenant before you make it.
Set the income category
From the next nightly run, fees are billed. Nothing that was recorded during the trial is billed retrospectively — the trial rows stay as they are.
Penalties as a collections ladder step
A strategy can include an apply_penalty step. When that step is
confirmed, the penalty engine is invoked scoped to the case's lease, using the same policies and
the same idempotency. Collections does not compute or post the money itself — it asks the penalty
engine to.
Because the ladder step can require approval, an organisation can keep late fees discretionary (officer proposes, manager approves) rather than automatic.
Waiving a fee
On Fees charged, a fee has a "Waive" action. It asks for a reason — required, because a waived fee nobody can explain is worse than the charge — and records who waived it and when.
What it does depends on whether the fee was billed. A fee that reached the tenant has its invoice cancelled, so the money comes off their balance; a fee still in trial is simply marked waived. Either way the record stays: nothing is deleted, and the sweep will not quietly charge the same fee again on its next run.
Legacy penalty settings
Two older configurations exist on the platform: penalty fields on branch settings, and
penalty after days / penalty percentage on individual charges. Neither drives this engine. Use
penalty policies for anything new, and do not extend the legacy fields.
Troubleshooting
| Symptom | Check |
|---|---|
| No assessments at all | Is the penalties job enabled? Is the master scheduler on? Does any invoice actually exceed the grace period? |
| Assessments exist but no invoice was created | The policy has no penalty service type, or the service type has no account mapping. |
| Fee amount looks wrong | Check which balance the percentage is taken on. Charging on everything the tenant owes rather than on the invoice produces much larger fees — and is charged once per tenant per round, not once per invoice. |
| A tenant under an arrangement was charged | The rule has "skip invoices under a promise to pay" switched off, or the promise had already been missed, cancelled, or passed its date. |
| Old debt was charged unexpectedly | The rule was set to include invoices that were already overdue. |
| A tenant was charged twice | Confirm the two assessments are different cycles. Within one cycle, idempotency prevents duplicates. |