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.
2.4 KiB
2.4 KiB
type, title, description, resource, tags, timestamp
| type | title | description | resource | tags | timestamp | |||
|---|---|---|---|---|---|---|---|---|
| SQLite Table | month_closures | One row per employee per calendar month tracking the confirm -> lock workflow that gates payroll. | backend/src/db/index.ts |
|
2026-08-16T00:00:00Z |
month_closures
Tracks where a given employee's given month is in the confirm/lock workflow. Rows are created lazily — the first time the employee opens that period — not proactively for every employee/month combination.
Schema
| Column | Type | Description |
|---|---|---|
id |
INTEGER PK | autoincrement |
employee_id |
INTEGER | references employees |
period |
TEXT | YYYY-MM |
status |
TEXT | waiting_employee | confirmed | locked |
employee_confirmed_at |
TEXT | NULL | set on confirm |
locked_at |
TEXT | NULL | set on lock, cleared on reopen |
UNIQUE (employee_id, period).
State machine
waiting_employee --employee confirms--> confirmed
confirmed --admin locks--> locked
locked --admin reopens--> confirmed (undoes a premature lock)
- Confirm (
confirmClosure,backend/src/services/closure.ts): employee-only action, blocked while any session in that period is stillopen(see attendance_events). Idempotent — confirming an already-confirmed month is a no-op, not an error. - Lock (
lockClosure, called fromlockAndFinalizePayrollinbackend/src/services/payroll.ts): admin-only, requiresconfirmed, re-checks for an open session (defensive — time may have passed since confirm), freezes the payroll row. - Reopen (
reopenPayroll): undoes a lock made before the numbers were actually right (e.g. the hourly rate wasn't set yet) — back toconfirmed, with the payroll row reset todraft. Only possible while payroll status isready, not oncepaid— that's the point past which a mistake has to be corrected some other way, not silently rewritten.
Unlike the source Google Apps Script this was ported from
(gscript/ClosureService.js), there's no separate MANAGER_APPROVED
state — that system modeled independent ADMIN/MANAGER/ACCOUNTANT roles;
this app has one owner-admin, so "manager approves" and "admin locks"
collapse into a single action here.
Related
- payroll
- attendance_events —
hasOpenSessionInPeriodgate - Closure API