feat: add OpenDocument PDF templates

This commit is contained in:
Marcel Peterkau
2026-06-21 22:10:16 +02:00
parent b34135b34a
commit 0622a22794
14 changed files with 942 additions and 14 deletions
+33
View File
@@ -9,6 +9,8 @@ directory containing `member.json`, `contributions.json`, an append-only
## Development
Requires Python 3.11+ with Tk support.
PDF generation from document templates additionally requires LibreOffice or
OpenOffice with a `soffice` command available on the system.
```bash
python -m venv .venv
@@ -46,6 +48,10 @@ member-store/
├── repository.json
├── housekeeper.json
├── rules/
├── templates/
│ ├── Forderung.fodt
│ ├── Mahnung.fodt
│ └── Mitglied.fodt
└── members/
└── <uuid>/
├── member.json
@@ -54,6 +60,33 @@ member-store/
└── files/
```
## Document templates
CCMA reads OpenDocument templates (`.fodt`, `.odt`, or `.ott`) from the
store's `templates/` directory. The three initial `.fodt` files are editable
with LibreOffice/OpenOffice and are copied only when their filename does not
already exist. PDF files are generated locally and stored below the member's
`files/documents/` directory. No office document content is sent to an
external service.
Placeholders use `{{group.field}}`. Available values include:
- Member: `member.number`, `member.first_name`, `member.last_name`,
`member.full_name`, `member.email`, `member.birth_date`, `member.status`,
`member.accepted_at`, `member.started_at`
- Claim: `claim.id`, `claim.title`, `claim.due_date`, `claim.total`,
`claim.paid`, `claim.balance`, `claim.status`, `claim.items`
- Reminder: `reminder.id`, `reminder.level`, `reminder.name`,
`reminder.status`, `reminder.created_at`, `reminder.sent_at`,
`reminder.payment_deadline`, `reminder.payment_deadline_days`,
`reminder.fee`, `reminder.detail`, `reminder.channel`
- Document: `document.date`, `document.datetime`
Claim placeholders are available from a claim tab. Reminder placeholders are
available when a reminder row is selected before opening the document dialog.
Unknown or unavailable placeholders stop generation with a clear error rather
than producing an incomplete letter.
## Housekeeper rules
The housekeeper runs every rule for every member. Built-in Python rules live in