summaryrefslogtreecommitdiff
path: root/docs/PAYROLL.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/PAYROLL.md')
-rw-r--r--docs/PAYROLL.md35
1 files changed, 28 insertions, 7 deletions
diff --git a/docs/PAYROLL.md b/docs/PAYROLL.md
index ffb0eee..b821754 100644
--- a/docs/PAYROLL.md
+++ b/docs/PAYROLL.md
@@ -4,7 +4,8 @@ Status: Design draft · 2026-09-21 · License: GPL-3.0-or-later
Payroll for a small Swedish AB that runs monthly salaries from the books.
Wave 1 is the engine and the mandatory steps; the employee is the owner but
-the schema and commands are multi-employee from the start.
+the schema and commands are multi-employee from the start. Wave 2 (the
+lönebesked PDF and its delivery) is done; wave 3 is the TUI.
## 1. Scope
@@ -23,6 +24,15 @@ the schema and commands are multi-employee from the start.
contributions to the tax account (its own voucher), matched by the bank
reconciliation.
+**In (wave 2, done)**
+
+- Employee e-mail (`employees.email`, schema v11) as the default lönebesked
+ recipient.
+- Lönebesked: one A4 PDF per employee and run, rendered with the invoice's
+ visual language, stored as an attachment on the run's voucher and mailable
+ with the existing SMTP path (`payroll.payslip`,
+ `payroll.payslip_mail`). See §6.
+
**Out (later)**
- Semester/vacation accrual and vacation pay (skipped for now).
@@ -46,7 +56,7 @@ the account is a per-employee setting. Settings: `payroll_salary_account`
(`7510`), `payroll_avgift_liability` (`2731`), `payroll_tax_payment_account`
(`1630`), `payroll_avgift_rate_bp` (default `3142`, basis points).
-## 3. Schema v10
+## 3. Schema v10 (v11 adds the employee e-mail)
```sql
CREATE TABLE employees (
@@ -65,6 +75,7 @@ CREATE TABLE employees (
active INTEGER NOT NULL DEFAULT 1 CHECK (active IN (0,1)),
created_at TEXT NOT NULL,
updated_at TEXT,
+ email TEXT NOT NULL DEFAULT '', -- v11, lönebesked recipient
UNIQUE (org_id, id)
) STRICT;
@@ -129,7 +140,9 @@ CREATE TABLE tax_table_meta (
```
`vouchers.source` allows `'payroll'` and `'payroll_tax'` (widened CHECK in
-v10; the same table rebuild as v9).
+v10; the same table rebuild as v9). v11 adds `employees.email` in a forward
+migration (`ALTER TABLE`); `employee.create/update` accept it (at most 254
+characters, no control characters) and `employee.list/get` return it.
## 4. Tax tables
@@ -202,10 +215,18 @@ the base is the gross.
## 6. Documents and TUI
-- **Lönebesked** (wave 2): one PDF per employee and run, stored as an
- attachment and mailable with the existing SMTP path. Layout: employer,
- employee (personnummer masked except the last four), period, pay date,
- gross, tax, net, vacation note omitted, payment account.
+- **Lönebesked** (wave 2, done): `payroll.payslip` renders one A4 page per
+ employee and run with the invoice's visual language — dark `#314c59`
+ header bar, employer and employee blocks, gross, preliminary tax (shown
+ negative), net and the employer-contribution note; the personnummer is
+ masked except the last four. `payroll.payslip_mail` stores the PDF as an
+ `application/pdf` attachment on the run's voucher, links it with
+ `voucher_attachments` and e-mails it through the org's `smtp_*` settings
+ to the employee's `email` (subject `Lönebesked <period>`, a short Swedish
+ body with the net amount). A missing address is `INVALID_ARGS`, missing
+ SMTP configuration `SMTP_NOT_CONFIGURED` and a failed delivery
+ `SMTP_FAILED` (the stored attachment stays linked). `dry_run` validates,
+ renders and stores nothing. See `PROTOCOL.md` §7.12.
- **TUI — Lön** (new section after Fakturering): `Lönekörningar` (list,
Ctrl+N for a new run), `Anställda` under Register, and a **Skattetabeller**
action/status that fetches and warns.