"""Datenmodell des Plugins „planung“. Ein Planungseintrag ordnet ein Spiel einem Rezensenten und einer Ausgabe zu. Einträge entstehen auf zwei Wegen — beide laufen durch die dedup- Prüfung des dedup-Plugins: - Verschiebung aus der Neuheitenliste (`quelle = "neuheiten"`), - händisches Nachtragen im Formular (`quelle = "manuell"`). Bei Prüftreffern wird der Befund im JSON-Feld `pruefung` mitgespeichert. """ from __future__ import annotations from datetime import datetime from sqlalchemy import DateTime, ForeignKey, Integer, JSON, String, Text, func from sqlalchemy.orm import Mapped, mapped_column from redaktionskern.db import Base #: Gültige Statuswerte in Ablaufreihenfolge. STATUS_OFFEN = "offen" STATUS_IN_BEARBEITUNG = "in_bearbeitung" STATUS_ABGESCHLOSSEN = "abgeschlossen" GUELTIGE_STATUS: tuple[str, ...] = ( STATUS_OFFEN, STATUS_IN_BEARBEITUNG, STATUS_ABGESCHLOSSEN, ) #: Deutsche Anzeigenamen der Statuswerte. STATUS_ANZEIGE: dict[str, str] = { STATUS_OFFEN: "Offen", STATUS_IN_BEARBEITUNG: "In Bearbeitung", STATUS_ABGESCHLOSSEN: "Abgeschlossen", } class Planungseintrag(Base): """Ein Spiel in der Planungsliste, zugeordnet zu Rezensent und Ausgabe.""" __tablename__ = "planungsliste" __table_args__ = {"extend_existing": True} id: Mapped[int] = mapped_column(primary_key=True) titel: Mapped[str] = mapped_column(String(300)) verlag: Mapped[str | None] = mapped_column(String(300)) autor: Mapped[str | None] = mapped_column(String(300)) #: BoardGameGeek-ID, sofern bekannt (Match-Kriterium der dedup-Prüfung). bgg_id: Mapped[int | None] = mapped_column(Integer) #: URL des Coverbildes (aus der Neuheitenliste übernommen oder leer). bild_url: Mapped[str | None] = mapped_column(String(500)) quellen_url: Mapped[str | None] = mapped_column(String(500)) #: Magazin-Ausgabe, z. B. „3/2025“ (mehrere Ausgaben parallel möglich). ausgabe: Mapped[str] = mapped_column(String(100), default="") rezensent_id: Mapped[int] = mapped_column(ForeignKey("users.id")) status: Mapped[str] = mapped_column(String(50), default=STATUS_OFFEN) notizen: Mapped[str | None] = mapped_column(Text) #: Woher stammt der Eintrag: "neuheiten" oder "manuell". quelle: Mapped[str] = mapped_column(String(50), default="manuell") #: Befund der dedup-Prüfung beim Anlegen (Liste von Konflikt-Dicts). pruefung: Mapped[list | None] = mapped_column(JSON) erstellt_am: Mapped[datetime] = mapped_column(DateTime, server_default=func.now()) aktualisiert_am: Mapped[datetime] = mapped_column( DateTime, server_default=func.now(), onupdate=func.now() ) def __repr__(self) -> str: # pragma: no cover - Debug-Hilfe return f""