> For the complete documentation index, see [llms.txt](https://tutearnio.gitbook.io/tutearn-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tutearnio.gitbook.io/tutearn-docs/user-manual-payroll.md).

# User Manual Payroll

> Real-world guide for tutoring center admins and finance staff.\
> All examples use **Bright English Academy** demo data.

This guide covers everything in the **Payroll** menu group — Compensation Plans, Payroll Periods, Payroll Entries, and Bonuses — plus the Payouts and payslips they produce. Read it top to bottom the first time; afterwards use it as a reference for each pay run.

***

## Who can use Payroll

Payroll is staff-facing. Only the **Admin** and **Member (staff)** roles can see and use the Payroll menu. **Tutors, students, and guardians never see payroll screens** — a tutor only ever receives a payslip PDF that you send them.

Each payroll feature has the usual permissions (`read`, `create`, `update`, `delete`, `archive`, `restore`, `import`, `export`). If a teammate can't see a menu item, an admin needs to grant them the matching `read` permission.

***

## The Big Picture — How Payroll Connects

Before touching any screen, understand how the pieces fit together:

```
Compensation Plan     "How much a tutor earns per session / hour / month"
  └─ Payroll Period    "A pay cycle — e.g. June 2026, with a pay date"
       └─ Payroll Entry "One line of pay for one tutor (a session, a bonus, a deduction)"
            └─ Payout    "The money actually paid to one tutor for the period"
                 └─ Payslip "The PDF the tutor receives"
```

**The everyday flow:**

1. **Set up compensation plans once** — define how each tutor is paid.
2. **Open a payroll period** for the cycle (weekly, monthly, etc.).
3. **Generate entries** — the system reads each tutor's sessions and prices them using their plan.
4. **Review and adjust** the entries (add bonuses, deductions, fix anything).
5. **Approve** the period.
6. **Mark as paid** — this locks the period, creates one **payout** per tutor, and lets you download **payslips**.

***

## Part 1 — One-time Setup: Compensation Plans

**Payroll → Compensation Plans → New** (`/compensation-plan`)

A compensation plan answers one question: *"How is this tutor paid?"* You build plans once and reuse them every period. Generating payroll entries does nothing useful until at least one active plan exists.

### 1.1 Plan types

Choose a **Plan type** — this decides what the system needs and how sessions are priced:

| Plan type                      | How a tutor is paid                                  | Key fields to fill                | Auto-generates entries?   |
| ------------------------------ | ---------------------------------------------------- | --------------------------------- | ------------------------- |
| **Hourly**                     | A rate per hour of session time                      | Base hourly rate                  | ✅ Yes                     |
| **Per session**                | A flat amount for each session, regardless of length | Per-session rate                  | ✅ Yes                     |
| **Course based**               | A rate that depends on which course is taught        | Course rates (one row per course) | ✅ Yes                     |
| **Salary** / **Fixed monthly** | A fixed amount per period, not per session           | Salary amount, salary frequency   | ✅ Yes (one line/period)   |
| **Revenue share**              | A percentage of the revenue the tutor generated      | Revenue share %, platform fee %   | ⚠️ Not yet — add manually |
| **Tiered revenue share**       | Revenue share that changes by tier                   | Tier configuration                | ⚠️ Not yet — add manually |
| **Mixed**                      | A combination of the above                           | (varies)                          | ⚠️ Not yet — add manually |

> **Important:** Automatic entry generation currently prices **Hourly, Per session, Course based, Salary, and Fixed monthly** plans. Revenue-share, tiered, and mixed plans are skipped during generation because they need revenue figures the system doesn't compute — for those tutors, add payroll entries manually (see Part 3).

### 1.2 Course rates (for course-based plans)

A course-based plan holds a list of **course rates**. Each row sets a course, a rate, and a **rate type**:

* **Per course** — flat amount each time that course is taught.
* **Per session** — same as per course, charged per booking.
* **Per hour** — the rate is multiplied by the session length.

If a tutor teaches a course that has no matching rate row, that session is **skipped** during generation.

### 1.3 Assigning plans to tutors

* **Assigned tutors** — attach a plan directly to specific tutors. This is the plan they'll be priced with.
* **Default plan** — tick **Is default** on one plan to catch every tutor who has no plan of their own. Keep exactly one active default so nobody is missed.

### 1.4 Effective dates and status

* **Effective from / Effective until** — a plan only applies to sessions whose date falls inside this window. Raise a tutor's rate by creating a *new* plan effective from the change date rather than editing the old one — this keeps past pay runs accurate.
* **Status** — only **Active** plans are used when generating entries. `Draft`, `Suspended`, and `Expired` plans are ignored.

When two plans could apply, the system prefers the **tutor-specific** plan that is effective on the session date; if there is none, it falls back to the **active default** plan.

### 1.5 Other plan fields

* **Currency** — the currency entries are created in. Keep one currency per tutor.
* **Cancellation fee %** / **Holdback days** — informational policy fields for your records.
* **Plan document** — attach up to 3 files (e.g. a signed agreement).

***

## Part 2 — Running a Pay Cycle

This is the routine you'll repeat every week or month.

{% stepper %}
{% step %}

## Open a payroll period

**Payroll → Payroll Periods → New** (`/payroll-period`)

| Field                | What to enter                                              | Example                     |
| -------------------- | ---------------------------------------------------------- | --------------------------- |
| **Period number**    | A unique code for the cycle                                | `2026-06`                   |
| **Period name**      | A human label                                              | `June 2026`                 |
| **Period type**      | Weekly, Biweekly, Semi-monthly, Monthly, Quarterly, Custom | `Monthly`                   |
| **Start / End date** | The range of sessions this period pays for                 | `2026-06-01` → `2026-06-30` |
| **Cutoff date**      | (Optional) the deadline for entries to be included         | `2026-06-30`                |
| **Pay date**         | When tutors will actually be paid                          | `2026-07-05`                |
| **Status**           | Start as `Upcoming` or `Open`                              | `Open`                      |

Leave the **totals** (gross, tax, deductions, net), **tutor count**, and **entry count** blank — they're filled in automatically when you generate or add entries.
{% endstep %}

{% step %}

## Generate entries

On the period's **View** page, click **Generate entries**. A dialog asks what to generate from:

* **Completed bookings** — pays for every booking marked *completed* in the period's date range. Use this when attendance isn't tracked separately.
* **Attendance records** — pays for bookings that have attendance recorded. Use this if pay should follow who actually showed up.

The system then, for each session in range:

1. Finds the tutor's effective compensation plan.
2. Prices the session by the plan type (hourly × hours, per-session flat, course rate, etc.).
3. Creates a **payroll entry** with status **Pending approval**.

Salary / fixed-monthly tutors get **one** salary line for the whole period instead of one line per session.

When it finishes, a toast shows how many entries were **created** and how many were **skipped**. Entries are skipped when:

* The tutor has no effective plan (and no active default exists).
* The plan is revenue-share / tiered / mixed (priced manually).
* A course-based plan has no rate for that course.
* An entry was **already generated** for that booking — generation is safe to re-run and won't create duplicates.

> Generation is blocked if the period is **locked** (i.e. already paid). Reopen it first if you need to regenerate.
> {% endstep %}

{% step %}

## Review and adjust

Open **Payroll → Payroll Entries** (or scroll the entries on the period view) and check the generated lines. This is where you:

* Add **bonuses**, **tips**, **commissions**, or **reimbursements**.
* Add **deductions**, **clawbacks**, or **advances** as **negative amounts**.
* Fix any wrong rate or description.
* **Dispute** an entry you're unsure about so it isn't paid yet.

See Part 3 for the full mechanics of entries.
{% endstep %}

{% step %}

## Submit and approve

Use the workflow buttons on the period View page:

* **Submit for review** moves an `Upcoming`/`Open` period to **In review**.
* **Approve** moves it to **Approved**. Approving also approves every entry still in `Draft` or `Pending approval`, and stamps who approved it and when.
  {% endstep %}

{% step %}

## Mark as paid

Click **Mark as paid** and confirm. This single action:

1. **Locks** the period — entries can no longer be edited or transitioned.
2. Marks every `Approved`/`Processed` entry as **Paid**.
3. Records **one payout per tutor** for the amounts actually paid (see Part 5).
4. Enables **payslip** downloads (see Part 6).

Disputed, pending, and voided entries are **excluded** from payouts, so they never inflate what a tutor is paid.

If you mark a period paid by mistake, use **Reopen** (available while it's in review/approved/processing) — but note once it's fully **Paid** the safe path is to add a correcting entry in the next period rather than unwinding payouts.
{% endstep %}
{% endstepper %}

***

## Part 3 — Payroll Entries in Detail

**Payroll → Payroll Entries** (`/payroll-entry`)

A payroll entry is **one line of pay for one tutor** in one period. Most are generated automatically, but you can add, edit, and remove them by hand while the period is unlocked.

### 3.1 Entry types

| Type              | Use it for                                    | Sign     |
| ----------------- | --------------------------------------------- | -------- |
| **Session**       | A taught session (the default generated type) | Positive |
| **Hourly work**   | Time-based pay (generated for hourly plans)   | Positive |
| **Salary**        | A fixed periodic salary line                  | Positive |
| **Bonus**         | A reward — often linked to a Bonus record     | Positive |
| **Tip**           | A gratuity passed to the tutor                | Positive |
| **Commission**    | Performance / sales commission                | Positive |
| **Reimbursement** | Paying back an expense the tutor covered      | Positive |
| **Adjustment**    | A manual correction up or down                | Either   |
| **Deduction**     | Something withheld from pay                   | Negative |
| **Clawback**      | Recovering a previous overpayment             | Negative |
| **Advance**       | Recovering a pay advance                      | Negative |
| **Correction**    | Fixing an earlier entry                       | Either   |

**Use the sign of the Amount to control direction:** positive amounts add to gross pay; **negative amounts count as deductions** and reduce net pay.

### 3.2 Entry fields

| Field                      | Meaning                                              |
| -------------------------- | ---------------------------------------------------- |
| **Entry number**           | Unique code (auto-suffixed for generated lines)      |
| **Entry date**             | The date the work/event happened                     |
| **Description**            | Shown on the payslip — keep it meaningful            |
| **Hours / Sessions count** | Quantity behind the amount                           |
| **Rate**                   | The unit price used                                  |
| **Amount**                 | The line total (negative for deductions)             |
| **Is taxable**             | Whether tax withholding applies to this line         |
| **Tax withheld**           | The amount of tax held back from this line           |
| **Payroll period**         | Which period this line belongs to                    |
| **Tutor**                  | The educator being paid                              |
| **Currency**               | Should match the tutor's plan currency               |
| **Booking / Bonus**        | Optional links to the source session or bonus record |

### 3.3 Entry statuses and actions

| Status               | Meaning                                   |
| -------------------- | ----------------------------------------- |
| **Draft**            | Created, not yet submitted                |
| **Pending approval** | Awaiting sign-off (the generated default) |
| **Approved**         | Signed off, ready to pay                  |
| **Processed**        | Being processed for payment               |
| **Paid**             | Included in a payout                      |
| **Disputed**         | Held back pending a question              |
| **Voided**           | Cancelled, never paid                     |

Per-entry workflow buttons:

* **Approve** — `Draft` / `Pending approval` / `Disputed` → **Approved** (stamps the approver).
* **Dispute** — `Pending approval` / `Approved` → **Disputed** (pulls it out of the pay run until resolved).
* **Reset** — `Approved` / `Disputed` → **Pending approval** (clears the approver).

> All entry actions are **blocked once the period is locked** (paid). To change a paid entry, reopen the period (if not yet paid) or post a correcting entry in the next period.

### 3.4 How totals are calculated

When you generate entries, the period's totals are recomputed from all its entries:

* **Total gross** = sum of all **positive** amounts.
* **Total deductions** = sum of the absolute value of all **negative** amounts.
* **Total tax withheld** = sum of every entry's tax withheld.
* **Total net** = gross − deductions − tax withheld.
* **Tutor count / Entry count** = distinct tutors and number of lines.

***

## Part 4 — Period Status & Workflow Reference

### Status meanings

| Status         | Meaning                                 |
| -------------- | --------------------------------------- |
| **Upcoming**   | Created for a future cycle, not started |
| **Open**       | Active — generate and edit entries here |
| **In review**  | Submitted, awaiting approval            |
| **Approved**   | Signed off, ready to pay                |
| **Processing** | Payment in progress                     |
| **Paid**       | Paid out and **locked**                 |
| **Closed**     | Archived/finalized                      |
| **Voided**     | Cancelled                               |

### Allowed transitions

```
Upcoming ─submit─▶ In review ─approve─▶ Approved ─pay─▶ Paid (locked)
   │                  │                    │   │
   └────── approve ───┘                    │   └── process ─▶ Processing ─pay─▶ Paid
                                           │
        In review / Approved / Processing ─reopen─▶ Open
```

| Action      | From                            | To         | Side effects                                                       |
| ----------- | ------------------------------- | ---------- | ------------------------------------------------------------------ |
| **Submit**  | Upcoming, Open                  | In review  | —                                                                  |
| **Approve** | Open, In review                 | Approved   | Approves all draft/pending entries; stamps approver + time         |
| **Process** | Approved                        | Processing | —                                                                  |
| **Pay**     | Approved, Processing            | Paid       | **Locks period**; marks entries paid; creates one payout per tutor |
| **Reopen**  | In review, Approved, Processing | Open       | Clears approval; **unlocks**                                       |

> The View page shows one **forward** button for the current status (Submit → Approve → Mark as paid) plus a **Reopen** button when applicable. "Process" is an optional intermediate state available via the API; most centers go straight from Approved to Paid.

***

## Part 5 — Payouts

**Finance → Payouts** (`/payout`)

A **payout** is the actual money paid to **one tutor** for **one period**. You don't create payouts by hand in the normal flow — they're generated automatically when you **Mark a period as paid**:

* **One payout per tutor**, aggregated from that tutor's **paid** entries only.
* **Gross amount** = sum of positive entry amounts.
* **Other deductions** = sum of negative entry amounts.
* **Tax withheld** = sum of entry tax.
* **Net amount** = gross − tax − deductions.
* **Payout number** like `PO-2026-06-1a2b3c4d`.
* **Method** defaults to **Bank transfer**; **status** is **Completed**.

Re-running "Mark as paid" won't create duplicate payouts for a tutor who already has one for the period.

**Payout methods** available when you record or edit a payout: Bank transfer, PayPal, Stripe, Wise, KBZPay, Wave Money, PromptPay, Cash, Other.

**Payout statuses:** Pending, Processing, Completed, Failed, On hold, Cancelled, Reversed.

***

## Part 6 — Payslips

Each tutor's payslip is a clean PDF generated from their entries in a period.

On the period **View** page, the **Payslips** card lists every tutor with their **net pay**. Click **Download payslip** next to a tutor to get a PDF containing:

* Your organization name and the period name/number/status in the header.
* The tutor's name and code, the period date range, and the pay date.
* A line-by-line table of entries (date, description, type, amount), with negative amounts shown in red.
* Totals: **Gross**, **Deductions**, **Tax withheld**, and a highlighted **Net pay**.

The payslip card only appears once the period has entries. Generate or add entries first.

***

## Part 7 — Bonuses

**Payroll → Bonuses** (`/bonus`)

A **bonus** record represents an award you want to pay a tutor (e.g. a performance reward or referral bonus). Create the bonus here, then bring it into a pay run by adding a payroll entry of type **Bonus** and linking it to the bonus record. This keeps the award documented separately from the pay line that actually pays it.

***

## Tips, Pitfalls & FAQ

<details>

<summary>"Generate created 0 entries."</summary>

Check that (a) there are **completed bookings** (or attendance) in the period's date range, (b) each tutor has an **active** compensation plan effective on the session dates, and (c) for course-based plans, the taught course has a rate row.

</details>

<details>

<summary>"A tutor was skipped."</summary>

They have no effective plan and there's no active **default** plan, or their plan is revenue-share/tiered/mixed (add their entries manually).

</details>

<details>

<summary>"I raised a tutor's rate — do I edit their plan?"</summary>

No. Create a **new plan** effective from the change date. Editing the old plan's rate would re-price past periods incorrectly.

</details>

<details>

<summary>"I can't edit an entry."</summary>

The period is **locked** because it's been paid. Reopen it (if not fully paid) or post a **correction**/**adjustment** entry in the next period.

</details>

<details>

<summary>"A tutor's pay is wrong after I marked the period paid."</summary>

Don't unwind the payout. Add a positive **correction** (underpaid) or a negative **clawback**/**deduction** (overpaid) entry to the next open period.

</details>

<details>

<summary>"How do I exclude one questionable session from this run?"</summary>

**Dispute** that entry before approving — disputed entries are excluded from payouts. Resolve and approve it in a later period.

</details>

**Run order, every cycle:** Open period → Generate entries → Review/adjust → Submit → Approve → Mark as paid → Download payslips.

***

## Quick Reference

| Task                       | Where                                         |
| -------------------------- | --------------------------------------------- |
| Define how a tutor is paid | Payroll → Compensation Plans → New            |
| Start a pay cycle          | Payroll → Payroll Periods → New               |
| Price sessions into pay    | Period View → **Generate entries**            |
| Add a bonus/deduction      | Payroll → Payroll Entries → New               |
| Sign off a period          | Period View → Submit → Approve                |
| Pay tutors                 | Period View → **Mark as paid**                |
| See money paid             | Finance → Payouts                             |
| Send a tutor their payslip | Period View → Payslips → **Download payslip** |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://tutearnio.gitbook.io/tutearn-docs/user-manual-payroll.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
