From 4297c2d8bfd85e3727b9c2f5de478b6b0af2d63f Mon Sep 17 00:00:00 2001
From: "Adrian A. Baumann"
Date: Mon, 1 Dec 2025 14:15:42 +0100
Subject: [PATCH] Documentation of all models added
---
Documentation/modelle.md | 544 ++++++++++++++++++++++++++++++++++++++
argocd/deployment.yaml | 2 +-
pages/templates/base.html | 2 +-
3 files changed, 546 insertions(+), 2 deletions(-)
create mode 100644 Documentation/modelle.md
diff --git a/Documentation/modelle.md b/Documentation/modelle.md
new file mode 100644
index 0000000..5f34e86
--- /dev/null
+++ b/Documentation/modelle.md
@@ -0,0 +1,544 @@
+# Alle Modelle der vgui-cicd Django-Anwendung
+
+Dieses Dokument beschreibt alle Datenmodelle in der vgui-cicd Anwendung mit ihren Eigenschaften, Beziehungen und Verwendungszwecken.
+
+---
+
+## App: dokumente
+
+Die Hauptmodelle für die Verwaltung von Dokumenten, Vorgaben und deren Metadaten.
+
+### Dokumententyp
+
+**Zweck**: Kategorisierung von Dokumenten (z. B. Richtlinie, Standard).
+
+**Wichtige Felder**:
+- `name` (CharField, max_length=100, **PRIMARY KEY**)
+- `verantwortliche_ve` (CharField, max_length=255): Die verantwortliche Verwaltungseinheit
+
+**Besonderheiten**:
+- `__str__()` gibt den Namen zurück
+- Dient als Klassifizierungskategorie für Dokumente
+
+**Meta**:
+- `verbose_name = "Dokumententyp"`
+- `verbose_name_plural = "Dokumententypen"`
+
+---
+
+### Person
+
+**Zweck**: Repräsentiert Personen, die als Autoren, Prüfer oder in anderen Rollen tätig sind.
+
+**Wichtige Felder**:
+- `name` (CharField, max_length=100, **PRIMARY KEY**)
+- `funktion` (CharField, max_length=255): Funktionsbezeichnung der Person
+
+**Beziehungen**:
+- Many-to-Many mit `Dokument` über `verfasste_dokumente` (Autoren)
+- Many-to-Many mit `Dokument` über `gepruefte_dokumente` (Prüfer)
+
+**Besonderheiten**:
+- `__str__()` gibt den Namen zurück
+- `ordering = ['name']`: Alphabetische Sortierung
+
+**Meta**:
+- `verbose_name_plural = "Personen"`
+
+---
+
+### Thema
+
+**Zweck**: Thematische Einordnung und Kategorisierung von Vorgaben innerhalb von Dokumenten.
+
+**Wichtige Felder**:
+- `name` (CharField, max_length=100, **PRIMARY KEY**)
+- `erklaerung` (TextField, blank=True): Optionale Erklärung des Themas
+
+**Besonderheiten**:
+- `__str__()` gibt den Namen zurück
+- Der erste Buchstabe des Themas wird in Vorgabennummern verwendet
+
+**Meta**:
+- `verbose_name_plural = "Themen"`
+
+---
+
+### Dokument
+
+**Zweck**: Hauptmodell für ein einzelnes Dokument mit allen zugehörigen Metadaten und Inhalten.
+
+**Wichtige Felder**:
+- `nummer` (CharField, max_length=50, **PRIMARY KEY**): Eindeutige Dokumentennummer
+- `dokumententyp` (ForeignKey → Dokumententyp, on_delete=PROTECT): Klassifizierung
+- `name` (CharField, max_length=255): Dokumenttitel
+- `autoren` (ManyToManyField → Person, related_name='verfasste_dokumente')
+- `pruefende` (ManyToManyField → Person, related_name='gepruefte_dokumente')
+- `gueltigkeit_von` (DateField, null=True, blank=True): Gültig ab Datum
+- `gueltigkeit_bis` (DateField, null=True, blank=True): Gültig bis Datum
+- `signatur_cso` (CharField, max_length=255, blank=True): CSO-Signatur
+- `anhaenge` (TextField, blank=True): Beschreibung von Anhängen
+- `aktiv` (BooleanField, blank=True): Aktivierungsstatus
+
+**Beziehungen**:
+- 1-to-Many mit `Vorgabe` (über related_name='vorgaben')
+- 1-to-Many mit `Geltungsbereich`
+- 1-to-Many mit `Einleitung`
+- 1-to-Many mit `Changelog`
+
+**Besonderheiten**:
+- `__str__()` formatiert als "nummer – name"
+
+**Meta**:
+- `verbose_name = "Dokument"`
+- `verbose_name_plural = "Dokumente"`
+
+---
+
+### Vorgabe
+
+**Zweck**: Repräsentiert eine einzelne Vorgabe oder Anforderung innerhalb eines Dokuments.
+
+**Wichtige Felder**:
+- `order` (IntegerField): Sortierreihenfolge für die Darstellung
+- `nummer` (IntegerField): Nummer innerhalb eines Themas/Dokuments. Muss nicht eindeutig sein (z.B. für geänderte Vorgaben)
+- `dokument` (ForeignKey → Dokument, on_delete=CASCADE, related_name='vorgaben')
+- `thema` (ForeignKey → Thema, on_delete=PROTECT): Thematische Einordnung
+- `titel` (CharField, max_length=255): Titel der Vorgabe
+- `referenzen` (ManyToManyField → Referenz, blank=True): Verweise auf externe Referenzen
+- `gueltigkeit_von` (DateField): Gültig ab Datum
+- `gueltigkeit_bis` (DateField, blank=True, null=True): Gültig bis Datum (offen = unbegrenzt)
+- `stichworte` (ManyToManyField → Stichwort, blank=True): Tags zur Kategorisierung
+- `relevanz` (ManyToManyField → Rolle, blank=True): Relevante Rollen
+
+**Beziehungen**:
+- Foreign Key zu `Dokument` und `Thema`
+- Many-to-Many zu `Referenz`, `Stichwort`, `Rolle`
+- 1-to-Many zu `VorgabeLangtext`, `VorgabeKurztext`
+- 1-to-Many zu `Checklistenfrage`
+
+**Wichtige Methoden**:
+
+- `Vorgabennummer()` → str
+ - Generiert eine eindeutige, lesbare Kennummer
+ - Format: "{dokument.nummer}.{thema.name[0]}.{nummer}"
+ - Beispiel: "R0066.A.1"
+
+- `get_status(check_date=None, verbose=False)` → str
+ - Bestimmt den Status einer Vorgabe zu einem gegebenen Datum
+ - Parameter: `check_date` (Default: heute), `verbose` (Deutsche Beschreibung ja/nein)
+ - Rückgabewerte:
+ - "future": Vorgabe ist noch nicht gültig
+ - "active": Vorgabe ist aktuell gültig
+ - "expired": Vorgabe ist nicht mehr gültig
+ - Verbose-Ausgaben enthalten Datumsangaben
+
+- `sanity_check_vorgaben()` (statisch) → list
+ - Findet zeitliche Konflikte zwischen Vorgaben mit gleicher Nummer/Thema/Dokument
+ - Überprüft, ob sich Geltungszeiträume überschneiden
+ - Gibt Liste mit Konflikt-Dictionaries zurück
+
+- `clean()`
+ - Validiert die Vorgabe vor dem Speichern
+ - Ruft `find_conflicts()` auf
+ - Wirft `ValidationError` bei erkannten Konflikten
+
+- `find_conflicts()` → list
+ - Findet Konflikte mit bestehenden Vorgaben (ausgenommen self)
+ - Überprüft auf zeitliche Überschneidungen
+ - Gibt Liste mit Konflikt-Details zurück
+
+- `_date_ranges_intersect(start1, end1, start2, end2)` (statisch) → bool
+ - Prüft, ob zwei Datumsbereiche sich überschneiden
+ - `None` als Enddatum = unbegrenzter Bereich
+ - Gibt `True` bei Überschneidung zurück
+
+**Besonderheiten**:
+- `__str__()` gibt "Vorgabennummer: titel" zurück
+- Validierung von Gültigkeitszeiträumen ist implementiert
+- Sehr wichtiges Modell im Geschäftslogik-Kontext
+
+**Meta**:
+- `ordering = ['order']`
+- `verbose_name_plural = "Vorgaben"`
+
+---
+
+### VorgabeLangtext
+
+**Zweck**: Speichert ausführliche Textinhalte (Langtext) einer Vorgabe.
+
+**Wichtige Felder**:
+- `abschnitt` (ForeignKey → Vorgabe, on_delete=CASCADE): Referenz zur Vorgabe
+- Erbt von `Textabschnitt` (siehe App: abschnitte):
+ - `abschnitttyp` (ForeignKey → AbschnittTyp, optional)
+ - `inhalt` (TextField, blank=True, null=True)
+ - `order` (PositiveIntegerField, default=0)
+
+**Meta**:
+- `verbose_name = "Langtext-Abschnitt"`
+- `verbose_name_plural = "Langtext"`
+
+---
+
+### VorgabeKurztext
+
+**Zweck**: Speichert kurze Textinhalte (Kurztext) einer Vorgabe.
+
+**Wichtige Felder**:
+- `abschnitt` (ForeignKey → Vorgabe, on_delete=CASCADE): Referenz zur Vorgabe
+- Erbt von `Textabschnitt` (siehe App: abschnitte):
+ - `abschnitttyp` (ForeignKey → AbschnittTyp, optional)
+ - `inhalt` (TextField, blank=True, null=True)
+ - `order` (PositiveIntegerField, default=0)
+
+**Meta**:
+- `verbose_name = "Kurztext-Abschnitt"`
+- `verbose_name_plural = "Kurztext"`
+
+---
+
+### Geltungsbereich
+
+**Zweck**: Speichert den Geltungsbereich-Abschnitt eines Dokuments.
+
+**Wichtige Felder**:
+- `geltungsbereich` (ForeignKey → Dokument, on_delete=CASCADE): Referenz zum Dokument
+- Erbt von `Textabschnitt` (siehe App: abschnitte):
+ - `abschnitttyp` (ForeignKey → AbschnittTyp, optional)
+ - `inhalt` (TextField, blank=True, null=True)
+ - `order` (PositiveIntegerField, default=0)
+
+**Meta**:
+- `verbose_name = "Geltungsbereichs-Abschnitt"`
+- `verbose_name_plural = "Geltungsbereich"`
+
+---
+
+### Einleitung
+
+**Zweck**: Speichert die Einleitungs-Abschnitte eines Dokuments.
+
+**Wichtige Felder**:
+- `einleitung` (ForeignKey → Dokument, on_delete=CASCADE): Referenz zum Dokument
+- Erbt von `Textabschnitt` (siehe App: abschnitte):
+ - `abschnitttyp` (ForeignKey → AbschnittTyp, optional)
+ - `inhalt` (TextField, blank=True, null=True)
+ - `order` (PositiveIntegerField, default=0)
+
+**Meta**:
+- `verbose_name = "Einleitungs-Abschnitt"`
+- `verbose_name_plural = "Einleitung"`
+
+---
+
+### Checklistenfrage
+
+**Zweck**: Repräsentiert eine Frage für die Checkliste zu einer Vorgabe.
+
+**Wichtige Felder**:
+- `vorgabe` (ForeignKey → Vorgabe, on_delete=CASCADE, related_name='checklistenfragen')
+- `frage` (CharField, max_length=255): Text der Checklistenfrage
+
+**Besonderheiten**:
+- `__str__()` gibt den Fragetext zurück
+
+**Meta**:
+- `verbose_name = "Frage für Checkliste"`
+- `verbose_name_plural = "Fragen für Checkliste"`
+
+---
+
+### VorgabenTable
+
+**Zweck**: Proxy-Modell für `Vorgabe` für die Darstellung von Vorgaben in Tabellenform.
+
+**Besonderheiten**:
+- Proxy-Modell (kein eigenes Datenbankschema)
+- Ermöglicht alternative Django-Admin-Ansicht
+- Erbt alle Felder und Methoden von `Vorgabe`
+
+**Meta**:
+- `proxy = True`
+- `verbose_name = "Vorgabe (Tabellenansicht)"`
+- `verbose_name_plural = "Vorgaben (Tabellenansicht)"`
+
+---
+
+### Changelog
+
+**Zweck**: Dokumentiert Änderungen und Versionshistorie für Dokumente.
+
+**Wichtige Felder**:
+- `dokument` (ForeignKey → Dokument, on_delete=CASCADE, related_name='changelog'): Referenz zum Dokument
+- `autoren` (ManyToManyField → Person): Personen, die die Änderung vorgenommen haben
+- `datum` (DateField): Datum der Änderung
+- `aenderung` (TextField): Beschreibung der Änderung
+
+**Beziehungen**:
+- Foreign Key zu `Dokument`
+- Many-to-Many zu `Person`
+
+**Besonderheiten**:
+- `__str__()` formatiert als "datum – dokumentnummer"
+
+**Meta**:
+- `verbose_name = "Changelog-Eintrag"`
+- `verbose_name_plural = "Changelog"`
+
+---
+
+## App: abschnitte
+
+Modelle für die Verwaltung von Textabschnitten, die von mehreren Modellen geerbt werden.
+
+### AbschnittTyp
+
+**Zweck**: Klassifizierung von Textabschnitten (z. B. "Beschreibung", "Erklärung", "Anleitung").
+
+**Wichtige Felder**:
+- `abschnitttyp` (CharField, max_length=100, **PRIMARY KEY**): Name des Abschnitttyps
+
+**Besonderheiten**:
+- `__str__()` gibt den Namen zurück
+
+**Meta**:
+- `verbose_name_plural = "Abschnitttypen"`
+
+---
+
+### Textabschnitt (abstrakt)
+
+**Zweck**: Abstrakte Basisklasse für Textinhalte, die mit anderen Modellen verknüpft sind.
+
+**Wichtige Felder**:
+- `abschnitttyp` (ForeignKey → AbschnittTyp, on_delete=PROTECT, optional)
+- `inhalt` (TextField, blank=True, null=True): Der Textinhalt
+- `order` (PositiveIntegerField, default=0): Sortierreihenfolge
+
+**Besonderheiten**:
+- Abstrakte Klasse (wird nicht direkt in der Datenbank gespeichert)
+- Wird von anderen Modellen geerbt: `VorgabeLangtext`, `VorgabeKurztext`, `Geltungsbereich`, `Einleitung`, `Referenzerklaerung`, `Stichworterklaerung`, `RollenBeschreibung`
+
+**Meta**:
+- `abstract = True`
+- `verbose_name = "Abschnitt"`
+- `verbose_name_plural = "Abschnitte"`
+
+---
+
+## App: referenzen
+
+Modelle für die Verwaltung von Referenzen und Verweisen auf externe Standards.
+
+### Referenz (MPTT-Tree)
+
+**Zweck**: Hierarchische Verwaltung von Referenzen und externen Normen (z. B. ISO-Standards, Gesetze, übergeordnete Vorgaben).
+
+**Wichtige Felder**:
+- `id` (AutoField, **PRIMARY KEY**)
+- `name_nummer` (CharField, max_length=100): Nummer/Kennung der Referenz (z. B. "ISO 27001")
+- `name_text` (CharField, max_length=255, blank=True): Ausführlicher Name/Beschreibung
+- `oberreferenz` (TreeForeignKey zu self, optional): Parent-Referenz für Hierarchien
+- `url` (URLField, blank=True): Link zur Referenz
+
+**Beziehungen**:
+- Many-to-Many mit `Vorgabe`
+- MPTT Tree-Struktur für hierarchische Referenzen
+
+**Wichtige Methoden**:
+
+- `Path()` → str
+ - Gibt die vollständige Pfad-Hierarchie als String zurück
+ - Format: "Referenz → Subreferenz → Unterreferenz (Beschreibung)"
+ - Beispiel: "ISO → 27000 → 27001 (Information Security Management)"
+
+**Besonderheiten**:
+- Verwendet MPPT (Modified Preorder Tree Traversal) für Baumoperationen
+- `get_ancestors(include_self=True)`: Gibt alle Vorfahren zurück
+- `unterreferenzen`: Related_name für Kindreferenzen
+- Sortierung: Nach `name_nummer`
+
+**Meta**:
+- `verbose_name_plural = "Referenzen"`
+- **MPTTMeta**:
+ - `parent_attr = 'oberreferenz'`
+ - `order_insertion_by = ['name_nummer']`
+
+---
+
+### Referenzerklaerung
+
+**Zweck**: Speichert Erklärungen und zusätzliche Informationen zu einer Referenz.
+
+**Wichtige Felder**:
+- `erklaerung` (ForeignKey → Referenz, on_delete=CASCADE): Referenz zur Referenz
+- Erbt von `Textabschnitt`:
+ - `abschnitttyp` (ForeignKey → AbschnittTyp, optional)
+ - `inhalt` (TextField, blank=True, null=True)
+ - `order` (PositiveIntegerField, default=0)
+
+**Meta**:
+- `verbose_name = "Erklärung"`
+- `verbose_name_plural = "Erklärungen"`
+
+---
+
+## App: stichworte
+
+Modelle für die Verwaltung von Stichworte und Tags.
+
+### Stichwort
+
+**Zweck**: Einfache Tag/Keyword-Modell zur Kategorisierung von Vorgaben.
+
+**Wichtige Felder**:
+- `stichwort` (CharField, max_length=50, **PRIMARY KEY**): Das Stichwort
+
+**Beziehungen**:
+- Many-to-Many mit `Vorgabe`
+
+**Besonderheiten**:
+- `__str__()` gibt das Stichwort zurück
+
+**Meta**:
+- `verbose_name_plural = "Stichworte"`
+
+---
+
+### Stichworterklaerung
+
+**Zweck**: Speichert Erklärungen zu Stichworten.
+
+**Wichtige Felder**:
+- `erklaerung` (ForeignKey → Stichwort, on_delete=CASCADE): Referenz zum Stichwort
+- Erbt von `Textabschnitt`:
+ - `abschnitttyp` (ForeignKey → AbschnittTyp, optional)
+ - `inhalt` (TextField, blank=True, null=True)
+ - `order` (PositiveIntegerField, default=0)
+
+**Meta**:
+- `verbose_name = "Erklärung"`
+- `verbose_name_plural = "Erklärungen"`
+
+---
+
+## App: rollen
+
+Modelle für die Verwaltung von Rollen und deren Beschreibungen.
+
+### Rolle
+
+**Zweck**: Definiert Rollen/Positionen im Unternehmen (z. B. "Geschäftsleiter", "IT-Sicherheit", "Datenschutzbeauftragter").
+
+**Wichtige Felder**:
+- `name` (CharField, max_length=100, **PRIMARY KEY**): Name der Rolle
+
+**Beziehungen**:
+- Many-to-Many mit `Vorgabe` (über `relevanz`)
+
+**Besonderheiten**:
+- `__str__()` gibt den Namen zurück
+- Wird verwendet, um Rollen zu markieren, die von einer Vorgabe betroffen sind
+
+**Meta**:
+- `verbose_name_plural = "Rollen"`
+
+---
+
+### RollenBeschreibung
+
+**Zweck**: Speichert detaillierte Beschreibungen und Informationen zu einer Rolle.
+
+**Wichtige Felder**:
+- `abschnitt` (ForeignKey → Rolle, on_delete=CASCADE): Referenz zur Rolle
+- Erbt von `Textabschnitt`:
+ - `abschnitttyp` (ForeignKey → AbschnittTyp, optional)
+ - `inhalt` (TextField, blank=True, null=True)
+ - `order` (PositiveIntegerField, default=0)
+
+**Meta**:
+- `verbose_name = "Rollenbeschreibungs-Abschnitt"`
+- `verbose_name_plural = "Rollenbeschreibung"`
+
+---
+
+## Allgemeine Hinweise zur Modellverwaltung
+
+### Primärschlüssel-Strategie
+- Viele Modelle verwenden CharField-basierte Primärschlüssel (`name`, `nummer`, `stichwort`)
+- Dies ermöglicht direkte Verwendung von Strings als Identifikatoren
+- Vorteil: Lesbarkeit; Nachteil: Umbenennungen sind kritisch
+
+### On-Delete-Strategien
+- **PROTECT**: Verwendet für wichtige Beziehungen (z. B. Dokumententyp, Thema, AbschnittTyp)
+ - Verhindert versehentliches Löschen von Daten, auf die verwiesen wird
+- **CASCADE**: Verwendet für Unterkomponenten (z. B. Vorgabe → Dokument)
+ - Löscht abhängige Datensätze automatisch
+- **SET_NULL**: Nur bei optionalen Referenzen (z. B. Oberreferenz in Referenz-Tree)
+
+### Validierungsmechanismen
+- **Vorgabe.clean()**: Validiert Gültigkeitszeiträume
+- **Vorgabe.find_conflicts()**: Prüft zeitliche Überschneidungen
+- Wird von Django-Admin automatisch aufgerufen vor dem Speichern
+
+### MPTT (Modified Preorder Tree Traversal)
+- Verwendet in `Referenz` für hierarchische Strukturen
+- Ermöglicht effiziente Abfragen von Vorfahren und Nachkommen
+- Zusätzliche Datenbank-Felder für Tree-Management (automatisch verwaltet)
+
+### Textabschnitt-Vererbung
+- Mehrere Modelle erben von `Textabschnitt`
+- Wird verwendet für Lang-/Kurztexte, Erklärungen, Beschreibungen
+- `order`-Feld ermöglicht Sortierung mehrerer Abschnitte
+
+### Datumsverwaltung
+- `gueltigkeit_von`: Immer erforderlich für Vorgaben
+- `gueltigkeit_bis`: Optional; `None` bedeutet unbegrenzte Gültigkeit
+- `_date_ranges_intersect()` prüft korrekt auf Überschneidungen mit None-Werten
+
+### Many-to-Many-Beziehungen
+- Vielfach verwendet für flexible Zuordnungen (Autoren, Stichworte, Rollen, Referenzen)
+- `related_name`-Attribute ermöglichen rückwärts Zugriff
+- Beispiel: `dokument.vorgaben.all()`, `person.verfasste_dokumente.all()`
+
+---
+
+## Zusammenfassung der Beziehungen
+
+```
+Dokumententyp ← Dokument
+Person ← Dokument (Autoren/Prüfer)
+Dokument → Vorgabe (1-to-Many)
+Dokument → Geltungsbereich (1-to-Many)
+Dokument → Einleitung (1-to-Many)
+Dokument → Changelog (1-to-Many)
+
+Thema ← Vorgabe
+Vorgabe → VorgabeLangtext (1-to-Many)
+Vorgabe → VorgabeKurztext (1-to-Many)
+Vorgabe → Checklistenfrage (1-to-Many)
+Vorgabe ← Referenz (Many-to-Many)
+Vorgabe ← Stichwort (Many-to-Many)
+Vorgabe ← Rolle (Many-to-Many)
+
+Referenz → Referenz (Hierarchie via MPPT)
+Referenz → Referenzerklaerung (1-to-Many)
+
+Stichwort → Stichworterklaerung (1-to-Many)
+
+Rolle → RollenBeschreibung (1-to-Many)
+
+AbschnittTyp ← Textabschnitt (von verschiedenen Modellen geerbt)
+```
+
+---
+
+## Entwicklungsrichtlinien
+
+- Alle Modelle sollten aussagekräftige `__str__()`-Methoden haben
+- `verbose_name` und `verbose_name_plural` sollten auf Deutsch sein (für Django-Admin)
+- Validierungslogik (z. B. `clean()`) sollte implementiert werden für komplexe Business-Logic
+- Related-Names sollten aussagekräftig und konsistent sein
+- Textinhalte sollten die `Textabschnitt`-Basisklasse erben
+- Datumsverwaltung: Immer auf None-Werte bei `gueltigkeit_bis` achten, wenn Vorgaben noch aktiv sind.
diff --git a/argocd/deployment.yaml b/argocd/deployment.yaml
index ab2534c..a9541c5 100644
--- a/argocd/deployment.yaml
+++ b/argocd/deployment.yaml
@@ -25,7 +25,7 @@ spec:
mountPath: /data
containers:
- name: web
- image: git.baumann.gr/adebaumann/vui:0.957-xss
+ image: git.baumann.gr/adebaumann/vui:0.958
imagePullPolicy: Always
ports:
- containerPort: 8000
diff --git a/pages/templates/base.html b/pages/templates/base.html
index e377297..cd71670 100644
--- a/pages/templates/base.html
+++ b/pages/templates/base.html
@@ -215,7 +215,7 @@
-
Version {{ version|default:"0.957-xss" }}
+
Version {{ version|default:"0.958" }}