Files
eatme/docs/data-model/payroll.md
Michal Pemcak 94933cac5c Update OKF docs bundle, README, and CLAUDE.md for today's features
Documents the shift planning and closure/payroll modules (new tables,
routes, stores), the dark redesign, and the docker-compose-broken-host
workaround. Adds CLAUDE.md pointing agents at docs/. Translates README to
English and keeps host-specific infrastructure details out of the repo.
2026-08-16 18:41:11 +02:00

65 lines
2.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
type: SQLite Table
title: payroll
description: Computed + admin-adjusted pay per employee per month — base hours pay, tips, bonus, other, and payment status.
resource: backend/src/db/index.ts
tags: [data-model, sqlite, payroll]
timestamp: 2026-08-16T00:00:00Z
---
# payroll
One row per employee per period, created the first time the admin either
saves a draft adjustment or locks the month.
# Schema
| Column | Type | Description |
|---|---|---|
| `id` | INTEGER PK | autoincrement |
| `employee_id` | INTEGER | references [employees](./employees.md) |
| `period` | TEXT | `YYYY-MM` |
| `worked_minutes` | INTEGER | snapshotted at last save/lock, not live |
| `base_amount` | REAL | worked hours × the rate active on each shift's own date — see [pay_rates](./pay-rates.md) |
| `tips_amount` / `bonus_amount` / `other_amount` | REAL | admin-entered, default 0 |
| `final_amount` | REAL | sum of the four amounts above |
| `status` | TEXT | `draft` \| `ready` \| `paid` |
| `payment_date` | TEXT \| NULL | set when marked `paid` |
| `updated_at` | TEXT | ISO 8601 UTC |
`UNIQUE (employee_id, period)`.
# Status lifecycle
```
draft --admin locks the month closure--> ready --admin marks paid--> paid
ready --admin reopens--> draft
```
- **`draft`**: editable. `saveDraftAdjustments`
(`backend/src/services/payroll.ts`) recomputes `base_amount` /
`worked_minutes` fresh from
[attendance_events](./attendance-events.md) on every save, and requires
the linked [month_closures](./month-closures.md) row to be at least
`confirmed` (not still `waiting_employee`).
- **`ready`**: frozen. Set by `lockAndFinalizePayroll`, which locks the
closure in the same call. `saveDraftAdjustments` refuses to touch a
non-`draft` row — this is what turns "already locked" into the right
error message instead of the generic "not confirmed yet" one (a real bug
caught by `payroll.test.ts`: the two checks used to overlap).
- **`paid`**: terminal. Set by `markPaid`, stamps today's date. Not
reopenable — a mistake past this point needs a manual correction, not a
silent rewrite.
This collapses the source system's four-stage accountant pipeline
(`READY_FOR_ACCOUNTANT` / `PROCESSING` / `PROCESSED` / `PAID` in
`gscript/PayrollService.js`) down to two — `ready` and `paid` — since
there's no separate accountant role here for the intermediate stages to
mean anything.
# Related
- [month_closures](./month-closures.md)
- [pay_rates](./pay-rates.md)
- [Closure API](/docs/api/closure-routes.md), [Admin API](/docs/api/admin-routes.md)