Introduction
Time off in Brainy HR is configured on two levels: Time Off Types (what kind of leave employees have) and Policies (how that leave is earned). Optionally, Approval Workflows control who reviews time-off requests before they are applied. This guide walks you through each part and explains how they interact.
Table of contents
- Time Off Structure — Types vs Policies
- Accrual Basis — Policy Start Date vs Employee Hire Date
- Period Types and compatibility
- How Accrual Periods Are Created
- Mid-Period Joins and Proration
- Editing a Policy — what to expect
- Deactivating a Policy
- Approval Workflows — multi-level approvals
- Approval Workflows — scenarios and edge cases
- Frequently asked questions
1. Time Off Structure — Types vs Policies
Brainy HR splits time-off configuration into two complementary layers:
- Time Off Type — a category of leave (for example, Vacation, Sick Leave, Personal Days, Study Leave). Types are what employees see in their balance and what they select when creating a request.
- Policy — a rule that describes how that leave is earned over time. Policies define the accrual amount, the accrual period, how partial periods are handled, and what happens to unused time.
Multiple policies can be attached to the same Type. The system combines their accruals into a single balance bucket for that Type. Employees do not see individual policies — they see one total per Type.
Why the split?
This design lets you support different rules for different employee groups, seniority tiers, or offices while keeping the employee experience simple.
For example, a single Vacation type can be fed by:
- A base policy: 16 hours per month for everyone;
- A seniority bonus policy: additional 8 hours per month after 5 years of service;
- An office-specific policy: extra 4 hours per quarter for the Berlin office.
All three contribute to the same "Vacation" balance the employee sees.
What each level defines
Level | Defines |
|---|---|
Type | Name shown to employees, whether requests auto-approve, which balance bucket aggregates the hours/days. |
Policy | Accrual amount, period length, accrual basis, partial-period behavior, roll-over/lose-it rule, audience (all / office / department), seniority tier. |
2. Accrual Basis — Policy Start Date vs Employee Hire Date
Every policy has an Accrual Basis that answers one question: "From which date should each employee's earning cycle be counted?"
Option 1 — Policy Start Date (shared company calendar)
All employees follow the same accrual calendar, anchored to the policy's Policy start date setting. Everyone's periods line up: every employee earns on the same schedule.
Example. Policy start date = January 1; period = Monthly.
- Period 1: 1 Jan – 31 Jan (for everyone);
- Period 2: 1 Feb – 28/29 Feb;
- Period 3: 1 Mar – 31 Mar; and so on.
Best for companies where vacation, sick leave, and reporting all follow a company-wide calendar (fiscal year, quarters, "everyone gets X hours per month").
Option 2 — Employee Hire Date (personal cycles)
Each employee has their own accrual cycle anchored to the day they were hired. Period boundaries shift from person to person, following each employee's work anniversary rhythm.
Example. Period = Monthly.
- Jane was hired on March 10 → her monthly periods run 10 Mar – 9 Apr, 10 Apr – 9 May, etc.;
- John was hired on July 1 → his monthly periods run 1 Jul – 31 Jul, 1 Aug – 31 Aug, etc.
Best for companies where time off accrues along each employee's personal work anniversary (common in regions where "one vacation per year of service" is the norm).
Special case: hire date before policy start date
If an employee was hired before the policy existed, the Hire Date basis doesn't generate periods in the past. Instead, the system anchors the periods to the most recent anniversary of the employee's hire date before the policy start, and begins generating periods from there. The first eligible period starts on the policy start date (or later), and prior periods are skipped.
3. Period Types and compatibility
Supported period lengths: Weekly, Biweekly, Monthly, Quarterly, Half-Year, Yearly. Not every period length is compatible with every accrual basis.
Accrual Basis | Allowed period types | Why |
|---|---|---|
Policy Start Date | Weekly, Biweekly, Monthly, Quarterly, Half-Year, Yearly | A shared calendar means all employees share the same period boundaries — reports ("this quarter", "last week") have a single meaning. |
Employee Hire Date | Monthly, Yearly only | Personal cycles make sense for months and years. Weekly/Biweekly/Quarterly would make each employee have different "weeks" or "quarters", which breaks team-level and finance reporting. |
The settings UI automatically hides incompatible period types when you change the Accrual Basis.
4. How Accrual Periods Are Created
Policy Start Date basis
The system generates consecutive periods starting from the policy start date, following the chosen period length. All employees on the policy get identical period rows. When an employee was hired mid-period, they receive a partial first period (see proration).
Employee Hire Date basis
The system computes the employee's anchor date:
- If the employee was hired on or after the policy start date → anchor = the hire date itself;
- If the employee was hired before the policy start date → anchor = the most recent anniversary of the hire date that falls before the policy start. Periods then run forward from this anchor.
Periods that fall entirely before the policy start date are skipped. The first period that overlaps the policy start is generated as partial, with accrual starting on the policy start date.
Worked example — monthly, Hire Date basis
Policy start date = 2026-01-01, period = Monthly, 10 hours/month. Jane was hired on 2024-05-15.
- Anchor = most recent anniversary of May 15 before Jan 1, 2026 → 2025-05-15.
- Periods 2025-05-15…2025-06-14, 2025-06-15…2025-07-14, …, 2025-12-15…2026-01-14 all end before or at the policy start — skipped or partial.
- First full period after policy start: 2026-01-15…2026-02-14 (Jane accrues 10 hours).
5. Mid-Period Joins and Proration
When an employee is hired during a period, or when a policy starts inside an already-running period, the system does not give them the full period's accrual. Instead, it prorates the accrual for the days they were actually covered.
Policy Start Date basis — mid-period hire
Policy: Monthly, 10 hours/month, Policy Start = Jan 1. Employee hired: Jan 10.
- Period dates are the same for everyone: Jan 1 – Jan 31.
- Employee's accrual for this period is prorated for Jan 10 – Jan 31.
- From February onwards, the employee gets the full 10 hours each month.
No manual adjustment is needed.
Employee Hire Date basis — policy starts mid-cycle
Policy: Monthly, 10 hours/month, Policy Start = 2026-06-15. Employee hired: 2024-05-10.
- Anchor = 2026-05-10 (anniversary before policy start).
- First generated period 2026-05-10 – 2026-06-09 → entirely before policy start → skipped.
- Next period 2026-06-10 – 2026-07-09 → overlaps policy start (2026-06-15) → partial, accruing only for 2026-06-15 – 2026-07-09.
- 2026-07-10 onwards: full monthly periods.
6. Editing a Policy — what to expect
A policy can be edited freely before any employee has used time off accrued under it. Once the first hour is consumed, the policy is considered in use and further editing is disabled.
While the policy is not in use
All fields are editable: name, audience (office / department), accrual basis, policy start date, period type, accrual amount, apply-at, unused-hours action, and everything else. When you save, the system rebuilds the employee period history from scratch inside a single database transaction — if anything fails, nothing is changed.
Once the policy is in use
The edit button is disabled in the policy grid and the backend rejects any attempt to update the policy. This is intentional: allowing edits on an in-use policy can change how past accruals were calculated, which breaks historical balances and reports.
If you need to change the rules of an in-use policy, follow this pattern:
- Deactivate the existing policy on a chosen cut-off date (see Deactivation);
- Create a new policy attached to the same Time Off Type, with the new rules, starting on the day after the cut-off.
Employees keep everything they accrued under the old policy; new accruals follow the new policy. The combined balance per Time Off Type stays consistent for the employee.
Tip. The only action available on an in-use policy is Deactivate. Use it freely when rules change — deactivation is designed to be safe and non-destructive.
7. Deactivating a Policy
Deactivation is the safe way to stop a policy from generating new accruals without breaking historical data.
What deactivation does
- Stops future accruals. The policy no longer creates new earned time in future periods.
- Keeps earned balances. Hours and days already accrued remain in the employee's balance and can still be used.
- Preserves history. Past periods, accruals, and requests are not recalculated or modified.
What deactivation does not do
- It does not remove already-earned balance.
- It does not cancel approved time-off requests.
- It does not retroactively change any past accrual period.
Why policies cannot be reactivated
To keep balances correct, deactivation is one-way. Reactivation would force the system to retroactively recalculate missed periods, which can produce duplicate or missing accruals and inconsistencies between employees. If accrual should start again, create a new policy attached to the same Type — the old policy covers history, the new one covers the future.
8. Approval Workflows — multi-level approvals
An Approval Workflow describes who must approve a time-off request, in what order, before it becomes active. You can attach the same workflow to any number of policies, and different policies can use different workflows (or none at all).
When do you need a workflow?
Workflows are optional. Without a workflow, a request is approved by whoever has the "approve time off" permission for the employee (the legacy single-approver behaviour). Add a workflow when any of the following applies:
- A request must pass through more than one reviewer (e.g. direct manager and then HR);
- Some leave types need special sign-off (e.g. CEO approves long absences);
- Different offices, departments, or seniority levels need different chains of approval.
Enabling multi-level approvals
Approval Workflows appear only after the feature is enabled in Settings → Time Off → Advanced Settings → Multi-level Approvals. Until then the workflow grid is locked and the legacy single-approver behaviour is used.
Anatomy of a workflow
A workflow has:
- Name and description — used when admins attach the workflow to a policy.
- Levels (steps) — ordered list of approvers. A request moves to level N+1 only after level N approves (sequential by design).
- Assigned policies — the policies that route their requests through this workflow.
How a level is resolved to a real person
Each level specifies an approver source. Brainy HR supports:
- Specific user — always the same person (e.g. a named HR manager, a CEO). Configured directly in the workflow;
- Direct manager of requester — the person listed in the Direct Manager field on the requester's profile (Job tab). Resolved dynamically at submission time. At most one such level per workflow.
Approver resolution happens once, at the moment the employee submits the time-off request. The concrete approver (name and ID) is captured as an immutable snapshot stored with the request. From that point on, the request is bound to that specific person for the whole approval flow — see "When Direct Manager changes" below for what this means in practice.
When Direct Manager changes on an employee's profile. A change to the Direct Manager field takes effect for new time-off requests only. Already-submitted requests keep the approver who was captured at submission time — the manager change does not reroute pending requests.
Why: this keeps the approval trail auditable (you can always see who was supposed to approve at the time of submission) and prevents accidental reroutes if HR corrects the manager mid-flight. If a pending request must be rerouted to the new manager, ask the employee to cancel it and submit a new one.
What if the requester has no Direct Manager? The Direct Manager level is auto-skipped with the reason "requester has no direct manager assigned", and the request moves on to the next level. Same behaviour when the resolved Direct Manager is deactivated or is the requester themselves.
What if the same person ends up on more than one level? For example, L1 = Direct Manager resolves to the company owner, and L2 = the same owner as a Specific user. The second occurrence is auto-skipped with the reason "this approver already appears on an earlier level" — the person only clicks Approve once, and their approval on the earlier level implicitly clears the later one too.
Not yet supported (future work): "Manager of manager" (2+ hops up the reporting chain), "Head of department" (would require department hierarchy that Brainy HR does not currently model), role-based routing. Clients needing these patterns today should split their time-off policy per department and configure one workflow per policy.
Sequential vs parallel
Current workflows are sequential: one level at a time. A pending level must be approved (or skipped — see below) before the next level activates. Parallel approvals at a single level are not supported; if two different people should both weigh in, configure them as two separate levels.
Skip logic
Some levels can be automatically skipped when they would otherwise create a redundant or impossible step. Typical skip reasons:
- The resolved approver is the requester themselves — a person cannot approve their own request;
- The resolved approver is the same person as a previous level (duplicate step);
- The approver cannot be resolved (e.g. the employee has no manager in the org chart).
Skipped levels are recorded with a skip reason so the audit trail remains complete. A level that is skipped does not count as an approval or rejection — the request simply moves on to the next level.
What if an approver doesn't have the Approve Time Off permission?
A workflow level can be assigned to a person who does not hold the Approve Time Off (pto_approve_decline or pto_manage) permission. This can happen when:
- An admin picks a specific user as approver and forgets to grant them the permission;
- A workflow uses Direct manager of requester and the direct manager is a regular employee with no HR permissions.
Brainy HR does not silently auto-skip such levels. Doing so would remove that person's opportunity to reject a request they might have had legitimate reasons to reject (schedule conflict, coverage gap, etc.), and the next approver could easily miss that the earlier voice never got to weigh in. Instead the request stays Pending and the stuck state is surfaced in three places:
- Workflow editor — shows a yellow warning under the level when a picked Specific-user approver lacks the permission, and a generic reminder near Direct-manager levels;
- Time Off Requests grid — the stuck row shows a red "Stuck: awaiting :name (no permission)" line under the request status;
- Request detail view — a red banner at the top of the approval history names the stuck approver and explains how to unblock.
Two ways to unblock a stuck request:
- Grant the permission to that user (via Settings → Users → Access Roles). Once they hold
pto_approve_declineorpto_manage, they can act on the request immediately — no resubmission needed. - Use Skip Level to explicitly bypass the stuck approver. The skip modal shows an additional red warning when the level is stuck for this reason, making it clear that a real potential decision-maker is being bypassed. This is a deliberate admin action — unlike a silent auto-skip.
Manual skip (Skip Level)
On top of automatic skips, users with the Skip Approval Level permission (pto_approve_skip) — or general pto_manage — can manually skip the current pending level from the request detail page. This is meant for situations where the assigned approver cannot act (out of office long-term, left the company, etc.) and the flow needs to move on.
A manual skip:
- requires a written reason (mandatory) — stored in the audit trail;
- records who skipped the level and when;
- advances the request to the next pending level and notifies that approver.
What happens if every pending level gets skipped? The request becomes Approved — same outcome as if the very last remaining approver had clicked Approve. Rationale: a skip is a deliberate admin action ("this level is not applicable to this request"), so if no level is applicable, the workflow effectively doesn't apply and the request should not sit forever in Pending. This mirrors the automatic behaviour at submission time when every resolved approver ends up being auto-skipped (e.g. the requester is the only approver on every level).
The full history is preserved: every skipped level shows the reason, the actor, and the timestamp, so it is always clear that no explicit approval was given. To surface this at the moment of action, the Skip Level modal shows a "Heads up: this is the last pending level" warning when applicable.
Rejection
If any approver rejects the request at their level, the whole request becomes Rejected. Subsequent levels are not evaluated. The employee can submit a new request with corrections.
Cascade on approval
Approving a level automatically activates the next level, runs its skip checks, and notifies its approver. If the final level is approved (or skipped after all previous ones approved), the request becomes Approved and its hours are deducted from the balance.
Attaching a workflow to a policy
Each policy can reference at most one workflow. To assign:
- Open the Approval Workflow in Settings → Time Off → Approval Workflows;
- Select the policies this workflow should govern in the "Policies" field;
- Save.
A policy that has no workflow attached uses the legacy single-approver flow associated with its Time Off Type.
Permissions
- Configure workflows — admins with the Settings / Time Off permission. The workflow grid is hidden for everyone else.
- Be an approver — any active user can be selected as an approver, but the user must have the corresponding time-off approval permission at the moment the level activates. If the permission is revoked later, the level is skipped (with a skip reason) and the request moves on.
- Submit a request — every employee can submit their own request; they cannot act on any level as approver for their own request.
What each role sees
Role | What they see on the request |
|---|---|
Requester | The full approval chain with each level's status (Pending / Approved / Rejected / Skipped + reason) and the current approver name. |
Approver at the active level | An action panel with Approve and Reject buttons, plus the history of previous levels (read-only). |
Approvers at later levels | A read-only view of the chain. They are notified when their level becomes active. |
Admins | Full view, including any skip reasons and the ability to cancel requests if the flow is stuck. |
9. Approval Workflows — scenarios and edge cases
Scenario A — classic two-level chain
Vacation request must pass direct manager, then HR.
- Level 1: Direct manager — resolved at activation;
- Level 2: Specific user (HR lead).
If the requester has no manager in the org chart, Level 1 is skipped and the request goes straight to HR.
Scenario B — self-request by a manager
If a manager submits their own vacation request and the first level is "Direct manager", that resolves to the manager themselves and is automatically skipped (a person cannot approve their own request). The request advances to Level 2.
Scenario C — approver leaves the company
If the resolved approver has been deleted or deactivated at the moment the level becomes active, the level is skipped with reason "approver unavailable". Admins can see the skip reason in the history. Best practice: use role-based or manager-based sources rather than a named individual for long-lived workflows.
Scenario D — policy with no workflow
Requests against a policy with no workflow attached follow the legacy single-approver rule: the user configured as approver for the Time Off Type must approve. Existing policies keep working exactly as before until you attach a workflow.
Scenario E — changing the workflow of a policy
Reassigning a policy to a different workflow affects new requests only. Requests that were already in flight keep the workflow they started with, so approvers see a consistent chain throughout the lifecycle of a request.
Scenario F — deleting a workflow
A workflow that is referenced by one or more policies cannot be deleted until those references are removed. This prevents orphaned requests.
10. Frequently asked questions
Q. I changed an employee's hire date. Will their accrual be recalculated automatically?
A. No. Changing the hire date does not retroactively rebuild past periods. If rules need to follow the new hire date going forward, deactivate the policy on a cut-off date and create a new policy. For a one-off correction, use a manual time-off adjustment.
Q. Can two policies of the same Type overlap for the same employee?
A. Yes, and their accruals are combined. This is how seniority bonuses or office-specific top-ups work — a base policy plus an additional policy both feed the same Type balance.
Q. What happens to partial periods when I change a policy's settings?
A. Editing is only allowed on policies that have no used hours yet. When you edit, the full period history is rebuilt using the new settings inside a single database transaction — if anything fails, nothing is changed. Once any hour has been used, the policy becomes read-only; use Deactivate + Create New (see section 6).
Q. Do approvers see the whole chain, or only their step?
A. Approvers see the whole chain with the current status of every level. Action buttons are enabled only on the level that is currently active and assigned to them.
Q. Can I have parallel approvers?
A. Not directly — levels are evaluated sequentially. To require sign-off from two people, create two consecutive levels. The request still advances only after both have approved.
Q. Where are workflows and skip reasons audited?
A. Each level records its status, the acting user, the timestamp, and any skip reason. Admins can inspect this history on every request.