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
+48
View File
@@ -2,6 +2,7 @@ from __future__ import annotations
import json
import os
import shutil
import unicodedata
from collections.abc import Iterable
from datetime import date, datetime, timedelta
@@ -88,6 +89,14 @@ class MemberRepository:
def initialize(self) -> None:
self.members_root.mkdir(parents=True, exist_ok=True)
(self.root / "rules").mkdir(parents=True, exist_ok=True)
templates_root = self.root / "templates"
templates_root.mkdir(parents=True, exist_ok=True)
builtin_templates = Path(__file__).resolve().parent.parent / "assets" / "templates"
if builtin_templates.is_dir():
for source in builtin_templates.iterdir():
destination = templates_root / source.name
if source.is_file() and not destination.exists():
shutil.copyfile(source, destination)
config_path = self.root / "repository.json"
if not config_path.exists():
write_json_atomic(config_path, DEFAULT_CONFIGURATION)
@@ -541,6 +550,45 @@ class MemberRepository:
references={"claim_id": claim_id, "reminder_id": reminder_id},
)
def register_reminder_document(
self,
member_id: str,
claim_id: str,
reminder_id: str,
*,
relative_path: str,
sha256: str,
template: str,
) -> None:
document_path = Path(relative_path)
if document_path.is_absolute() or ".." in document_path.parts:
raise RepositoryError("Der Dokumentpfad muss innerhalb des Mitglieder-Dateiordners liegen.")
data, _claim = self.get_claim(member_id, claim_id)
reminder = self._find_reminder(data, claim_id, reminder_id)
reminder["document"] = {
"path": relative_path,
"sha256": sha256,
"template": template,
"generated_at": datetime.now().astimezone().isoformat(timespec="seconds"),
}
if str(reminder.get("status", "draft")) == "draft":
reminder["status"] = "generated"
reminder["generated_at"] = reminder["document"]["generated_at"]
self.save_contributions(member_id, data)
self.append_event(
member_id,
event_type="reminder_document_generated",
summary=f"Mahndokument erzeugt: {Path(relative_path).name}",
actor_type="user",
actor_name="Vorstand",
references={
"claim_id": claim_id,
"reminder_id": reminder_id,
"document": relative_path,
},
data={"template": template, "sha256": sha256},
)
def set_dunning_hold(
self,
member_id: str,