from __future__ import annotations import tkinter as tk from collections.abc import Callable from datetime import date from pathlib import Path from tkinter import messagebox, ttk from ccma.services.documents import DocumentError, DocumentService, GeneratedDocument from ccma.storage.repository import MemberRepository, RepositoryError class DocumentTemplateDialog(tk.Toplevel): def __init__( self, master: tk.Misc, repository: MemberRepository, member_id: str, on_generated: Callable[[Path], None], *, claim_id: str | None = None, reminder_id: str | None = None, ): super().__init__(master) self.service = DocumentService(repository) self.member_id = member_id self.claim_id = claim_id self.reminder_id = reminder_id self.on_generated = on_generated self.templates = self.service.compatible_templates( has_claim=claim_id is not None, has_reminder=reminder_id is not None, ) self.template_by_label = { f"{template.name} ({template.relative_path})": template for template in self.templates } self.title("Dokument aus Template erzeugen") self.transient(master.winfo_toplevel()) self.resizable(False, False) self.template_var = tk.StringVar() self.filename_var = tk.StringVar() self._build_ui() self.bind("", lambda _event: self.destroy()) self.after_idle(self._grab_if_visible) def _grab_if_visible(self) -> None: try: if self.winfo_exists() and self.winfo_viewable(): self.grab_set() except tk.TclError: pass def _build_ui(self) -> None: frame = ttk.Frame(self, padding=18) frame.pack(fill="both", expand=True) ttk.Label(frame, text="OpenDocument-Template").grid( row=0, column=0, sticky="w", pady=5, padx=(0, 12) ) template_box = ttk.Combobox( frame, textvariable=self.template_var, values=list(self.template_by_label), state="readonly", width=56, ) template_box.grid(row=0, column=1, sticky="ew", pady=5) template_box.bind("<>", lambda _event: self._template_selected()) ttk.Label(frame, text="PDF-Dateiname").grid( row=1, column=0, sticky="w", pady=5, padx=(0, 12) ) ttk.Entry(frame, textvariable=self.filename_var, width=58).grid( row=1, column=1, sticky="ew", pady=5 ) context = "Mitglied" if self.claim_id: context += " · Forderung" if self.reminder_id: context += " · ausgewählte Mahnung" ttk.Label(frame, text=f"Kontext: {context}", style="Mono.TLabel").grid( row=2, column=0, columnspan=2, sticky="w", pady=(8, 0) ) ttk.Label( frame, text="Das PDF wird unter files/documents in der Mitgliederakte abgelegt.", style="Muted.TLabel", ).grid(row=3, column=0, columnspan=2, sticky="w", pady=(4, 0)) buttons = ttk.Frame(frame) buttons.grid(row=4, column=0, columnspan=2, sticky="e", pady=(18, 0)) ttk.Button(buttons, text="Abbrechen", command=self.destroy).pack(side="left", padx=(0, 8)) self.generate_button = ttk.Button( buttons, text="PDF erzeugen", style="Accent.TButton", command=self._generate, ) self.generate_button.pack(side="left") if self.template_by_label: self.template_var.set(next(iter(self.template_by_label))) self._template_selected() else: self.generate_button.configure(state="disabled") ttk.Label( frame, text="Für diesen Kontext ist kein passendes Template vorhanden.", style="Warning.TLabel", ).grid(row=5, column=0, columnspan=2, sticky="w", pady=(12, 0)) def _template_selected(self) -> None: template = self.template_by_label.get(self.template_var.get()) if template: self.filename_var.set(f"{date.today().isoformat()} - {template.name}.pdf") def _generate(self) -> None: template = self.template_by_label.get(self.template_var.get()) if template is None: messagebox.showerror("Template auswählen", "Bitte ein Template auswählen.", parent=self) return self.generate_button.configure(state="disabled") self.configure(cursor="watch") self.update_idletasks() try: generated: GeneratedDocument = self.service.generate( template, self.member_id, output_name=self.filename_var.get(), claim_id=self.claim_id, reminder_id=self.reminder_id, ) except (DocumentError, RepositoryError, OSError) as exc: messagebox.showerror("Dokument konnte nicht erzeugt werden", str(exc), parent=self) self.generate_button.configure(state="normal") self.configure(cursor="") return self.destroy() self.on_generated(generated.path) messagebox.showinfo("Dokument erzeugt", f"PDF gespeichert:\n{generated.path}", parent=self.master)