# Payroll and billing

> Generate payroll and server-authoritative billing from approved attendance, then approve, invoice, export and lock each period with GST and audit controls.

**Payroll Prep** (route `/payroll-prep`) and **Billing Prep** (route `/billing-prep`) turn attendance into pay and invoices. They work the same way: pick a period, **Generate**, check, approve, export, lock.

**Who can do this:** Payroll: Admin, HR Manager (`payroll.manage`). Billing: Admin, Ops Manager (`billing.manage`). Client logins can view and export their own billing and invoices but cannot generate, approve, edit, lock, cancel or reissue financial records.

## How amounts are worked out

Each attendance day in the period is followed to its **roster assignment** and from there to the **deployment**, which holds the rates.

| Attendance status                                  | Payroll days | Billing service units |
| -------------------------------------------------- | ------------ | --------------------- |
| present, late                                      | 1            | 1                     |
| half day                                           | 0.5          | 0.5                   |
| leave, holiday                                     | 1            | 0                     |
| absent, rejected/unapproved, weekly off, exception | 0            | 0                     |

**Payroll**, per employee:

- **Days** = sum of days counted.
- **Overtime hours** = hours worked beyond 8 in a day (check-in to check-out).
- **Gross** = days × **pay rate** + overtime hours × (pay rate ÷ 8 × 1.5).
- **Deductions** start at 0 (edit the row); **Net** = gross − deductions.

**Billing**, per client and site: the server recomputes service units and amount = units × the **bill rate** effective on each attendance date. The browser sends only the client, site and period. A day without a rate is still counted at ₹0, and generation reports the affected groups: fix the roster or deployment and generate again.

**Where the rate comes from.** A day normally takes its rate from the deployment its roster entry belongs to. A day with no roster entry, or whose roster entry isn't linked to a deployment — a **reliever** covering, or a guard nobody rostered — takes it from the worker's own deployment that covers that date:

- **Payroll** uses that deployment wherever the day was worked: a worker's pay doesn't depend on which post they covered.
- **Billing** uses it only when the day was worked at that deployment's site. A reliever covering at another client's site is not billed at their home site's rate; that day is left out of billing for you to settle with the client.

The saved row records how many days were priced this way (`rate_from_deployment_count`).

A day that still has no rate (no covering deployment, or the deployment has no rate) is counted at ₹0, and the generation summary reports it: "N attendance records had no pay rate". Fix the deployment and generate again.
For taxable billing, the client needs a GST registration status, GSTIN when registered, GST treatment and place of supply. The supplier detail comes from the tenant **Billing Profile**. The client's explicit GST treatment wins over the tenant default; exempt or nil clients are not asked for taxable-only GSTIN, place-of-supply or supplier-state details. There is no silent fallback to a default client tax identity. A taxable invoice is blocked until both sides are valid.

## Generate

1. Set **Period start** and **Period end** (e.g. the 1st to the last day of the month).
2. Press **Generate**.

   ![Payroll Prep: (1) first day, (2) last day, (3) Generate](/docs-images/guide/payroll-generate.webp)

3. Review the **Generation summary**: rows saved, locked or approved overlaps skipped, manual rows preserved, groups with no approved service units, missing or unverified rates, unapproved attendance still in the period, and GST configuration gaps.

   ![Generated: (1) the summary, (2) Approve drafts, (3) Export](/docs-images/guide/payroll-generated.webp)

**Billing Prep** works the same way, per client and site:

![Billing Prep, generated for the month](/docs-images/guide/billing-generated.webp)

Generated rows appear in **Billing Inputs** as **Draft**, with client, site, period, units, taxable value, GST and total. Billing rows are server-generated; use **Manual** only for a service that approved attendance cannot capture. A manual request needs a reason, private evidence (PDF, JPEG, PNG or WebP up to 10 MB) and a different reviewer. Review the request's reason and evidence from its **Review** action before approving it.

## Approve, invoice and lock

**Period finalization** moves billing groups through:

- **Approve drafts** — the preparer cannot approve their own row. A stale row must be regenerated if attendance, rates, assignments or tax data changed.
- **Issue invoices** — creates the numbered invoice from approved billing.
- **Lock invoiced** — freezes the period and needs a recorded reason of at least 10 characters.
- **Unlock** — needs the separate `billing.period.unlock` permission and a recorded reason.

Approval overrides also need a reason of at least 10 characters. Finalization refuses overlapping billing groups, and an active period lock blocks approval, cancellation and invoice issue until it is unlocked.

Cancelling an issued invoice requires a reason of at least 10 characters, blocks invoices with active payment allocations, keeps the invoice history, and moves billing to **Reissue ready**. Unlock a locked period before cancelling it. Reissue creates a new invoice while the cancelled invoice remains in the audit trail, and does not require the unlock permission because the period is no longer locked.

**Export** downloads the rows for your accounting software. Locked rows can't be regenerated, so lock only when the month is final.

## Before you generate

1. Every day in the period is recorded and **approved** in the [muster](/docs/field-attendance#muster).
2. Every roster entry names the person's **deployment** ([Shifts and roster](/docs/shifts-and-roster)).
3. Every deployment has a **pay rate** and **bill rate** ([Deployment](/docs/deployment)). Workers placed with [Approve & Deploy](/docs/approve-and-deploy) get their pay rate from the approved [salary structure](/docs/hr-approval#the-salary-table) (gross ÷ working days) and their bill rate from the deploy form.
4. Unpaid leave days are marked **Absent**, not **Leave** ([Leave](/docs/leave)).

## Employee Salary

**Employee Salary** (`/salary`) is the single workspace for the rest of the salary lifecycle. Its tabs are **Overview**, **Employees**, **Deductions & Loans**, **Statutory**, **Payments**, **Payslips**, **Disputes**, **Approvals**, **Reports** and **Audit**.

- **Deductions & Loans** records advances, loans, deductions and reimbursements. They are applied when the payroll period is committed and unbooked amounts carry forward.
- **Payments** records a salary disbursement and applies it to finalized payroll rows, partially or across several employees. Reversals keep the audit trail.
- **Payslips** generates an immutable payslip per payroll input. Voided payslips can be re-issued.
- **Disputes** and **Approvals** record employee queries and approval decisions with author and timestamp.
- **Reports** filters by period and site; **Audit** lists the salary-payment audit trail.

**Who can do this:** read access follows the salary permissions (`payroll.manage` for HR Manager, `salary_payments.read` for Admin, Ops Manager, HR Manager and Viewer). Recording and reversing salary payments requires `salary_payments.manage` (Admin, Ops Manager). Admin always has full access.
