Year End and Jobs
What runs on its own, what HR must do by hand, and the one thing that is never automatic.
The nightly job (01:30)
For every company, in this order:
- Lifecycle. Undecided requests whose start date has passed become Expired (closure reason Start date passed without a decision). Approved requests whose start date has arrived become In progress. Requests in progress whose end date has passed become Ended.
- Accrual. Every active employee's entitlement row for the current leave year is recomputed: entitled, accrued, carried in, adjustments, taken, booked, pending, day rate. A closed year is never recomputed.
- Return reconciliation. Anyone whose leave has ended and who has since clocked in (attendance Reported or Reported late on or after the resumption date) has their actual return date written and the request marked Ended.
Without step 1 every approved request would stay "approved" forever and "out today" would include people who came back in March. Without step 2 balances would be a guess. Run accrual on Leave Setup or Entitlements does all three on demand.
The Entitlements page warns when its figures are more than 12 hours old, and the dashboard recomputes on the spot if no rows exist at all, so a new company sees real numbers on its first visit.
The month-end job (02:30 on the 1st)
Freezes the previous day's liability into a snapshot: one company-wide row plus one per department, with headcount, untaken days, value, average day rate and days taken in the month. The dashboard's liability trend draws these snapshots rather than re-deriving history, so last March does not quietly change when somebody edits an old request. Snapshot on Leave Setup writes one by hand, for backfilling.
The year-end close (HR, by hand)
Nobody's days are forfeited by a timer. The close is an explicit HR action from Leave Setup → Leave Years → Close year, and the dashboard prompts for it from the forfeit-warning date onward.
Step 1: preview. The dialog states, before anything is written: Closing 2026 will forfeit N days across N employees, carry N days forward into 2027, and create that leave year, with a table of every affected employee showing remaining, carried and forfeited days. If nobody loses anything it says so. This cannot be undone. Employees should have had the forfeit warning before you continue.
Step 2: confirm. Pressing Close 2026 does, in order:
- Forfeits each employee's days above the carry-over cap and writes them to the row.
- Marks the year Closed. Its rows become read-only: no grants, no adjustments, no accrual.
- Creates the next leave year, rolling the dates forward and copying the cap, warning days, SLA, ceiling and encashment settings.
- Carries each employee's grants forward and writes carried in = the smaller of what was left and the cap, once. It is never recomputed, so leave booked in the old year after the new one opened cannot change the new year's opening balance.
Per employee: carried = min(remaining, cap); forfeited = remaining − carried; both zero when remaining is zero or negative.
Before you close: run the accrual, work the dashboard's What needs fixing before the forfeit date list, and confirm the next year's settings are what you want, because the new year inherits them.
Exit settlements
Accrued leave has to be paid out on termination. Propose on Leave Setup raises, for every exited employee still holding accrued untaken days of the accruing type, a settlement proposal at their own day rate. Proposals are not payments: HR authorises, payroll pays, and only then are the days written off the balance, so nothing disappears from a record without a countersigned trail.
Normalising older requests
Requests written before the module gained separate decision and lifecycle statuses carry a single legacy status. Normalise on Leave Setup converts them: pending becomes Undergoing approval / Awaiting decision, rejected becomes Undergoing approval / Rejected, approved becomes Approved with the lifecycle placed by its dates. Safe to repeat.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Balance, liability and compliance bands empty | The accrual has never run | Dashboard banner, or Run accrual |
| Balances all zero | No entitlement resolvable: no individual figure, no rank allocation, type default 0 | Set days on the type or the rank |
| Liability trend empty | No snapshots yet | Snapshot, once per missing month end |
| Eight-week grid shows counts but never a breach | No staffing floors | Write defaults, or set floors by hand |
| Queue shows no approver resolved | Nobody holds the stage's role | Set the supervisor, the department head, or the HR Leave Approval Manager |
| Absent, no request is high on first run | Attendance and leave have never been compared before | Work the list once; it stays small afterwards |
| A request shows Unknown decision | Legacy data | Normalise |
