MailTemplate holds subject + body_html with plain {{variable}}
placeholders (no loops/conditionals — the user edits these directly
and is comfortable generating list-shaped content like the wine
catalog in code instead, per the real "Kvitering" email reviewed in
old-emails/). One template per (route, event_type), matching the
three CLAUDE.md mail-events (round_announced, order_confirmed,
payment_confirmed); UNIQUE(route_id, event_type) enforces that and
IntegrityError is caught as 409, same pattern as prior tasks.
Route gains nullable sender_name/sender_email — the real old emails
show a per-route sender identity (e.g. "Finn Gram <finn@vinindkoeb.dk>"
for this route), so it lives on Route rather than being duplicated
across each of its templates.
This is data + CRUD only. Actual Postal sending, the round-announce
action, and per-participant send logging are task 7b; a Postal
webhook receiver for delivery status is task 7c — both need real
Postal API access, still to be arranged.
old-emails/ (real historical order/participant data) is gitignored,
same treatment as old_participants.json.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
28 lines
309 B
Text
28 lines
309 B
Text
# Python
|
|
__pycache__/
|
|
*.py[oc]
|
|
*.egg-info/
|
|
build/
|
|
dist/
|
|
|
|
# venv / uv
|
|
.venv/
|
|
|
|
# Env / secrets
|
|
.env
|
|
|
|
# DB
|
|
*.db
|
|
*.sqlite3
|
|
|
|
# Editors / OS
|
|
.vscode/
|
|
.idea/
|
|
.DS_Store
|
|
|
|
# Test cache
|
|
.pytest_cache/
|
|
|
|
# Raw personal-data exports used for one-off migrations — not for version control
|
|
old_participants.json
|
|
old-emails/
|