feat(bausteine): Abschnitte, die mehrere Vorlagen teilen (#57)
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s

This commit was merged in pull request #57.
This commit is contained in:
2026-10-04 17:07:12 +00:00
parent b688e2ebc8
commit 80870133b8
24 changed files with 2862 additions and 46 deletions
+39 -16
View File
@@ -1,10 +1,10 @@
# #030 M17 – Wiederverwendbare Bausteine
**Status:** offen
**Status:** erledigt
**Im Tracker:** [#50](https://git.wilde-server.de/florian.wilde/Laufzettel/issues/50)
**Meilenstein:** v0.2.0
**Labels:** phase-2, backend, frontend
**Geschätzt:** 12 h **Tatsächlich:** –
**Geschätzt:** 12 h **Tatsächlich:** 2 h 25 min
## Ziel
@@ -20,7 +20,7 @@ wurden. Ein Baustein, der sich ändert, darf das nicht antasten.
## Zu entscheiden
- [ ] **Baustein mit eigener Version, beim Veröffentlichen tief kopiert** — Empfehlung. Ein
- [x] **Baustein mit eigener Version, beim Veröffentlichen tief kopiert** — Empfehlung. Ein
Entwurf **verweist** auf einen Baustein; beim Veröffentlichen löst der Dienst den Verweis in
echte Abschnitte und Schritte auf. Damit bleibt alles, was danach kommt, unberührt: `Lauf`,
`Schrittergebnis`, Druckansicht und Archiv sehen weiterhin konkrete Schritte und müssen nichts
@@ -28,32 +28,55 @@ wurden. Ein Baustein, der sich ändert, darf das nicht antasten.
Die Alternative — Läufe verweisen zur Laufzeit auf den Baustein — hieße, dass die Unveränder-
lichkeit an einer zweiten Stelle durchgesetzt werden muss, und dass jede Abfrage über Schritte
zwei Wege kennen muss. Das ist der Preis für eine Bequemlichkeit, die niemand verlangt hat.
- [ ] **Was „Baustein aktualisieren“ für laufende Arbeiten bedeutet:** nichts. Eine neue
- [x] **Was „Baustein aktualisieren“ für laufende Arbeiten bedeutet:** nichts. Eine neue
Baustein-Version wirkt erst in der **nächsten** veröffentlichten Vorlagenversion. Das muss die
Oberfläche sagen, sonst erwartet man Durchschlag.
## Aufgaben
- [ ] Modelle `Baustein` und `BausteinVersion` mit denselben Regeln wie bei Vorlagen: höchstens ein
- [x] Modelle `Baustein` und `BausteinVersion` mit denselben Regeln wie bei Vorlagen: höchstens ein
Entwurf, veröffentlichte Version unveränderlich (Trigger, nicht nur Dienst)
- [ ] `VorlagenAbschnitt` kann statt eigener Schritte einen Baustein nennen — nur im **Entwurf**
- [ ] Veröffentlichen löst auf: tiefe Kopie der Baustein-Abschnitte und -Schritte in die Version,
- [x] `VorlagenAbschnitt` kann statt eigener Schritte einen Baustein nennen — nur im **Entwurf**
- [x] Veröffentlichen löst auf: tiefe Kopie der Baustein-Abschnitte und -Schritte in die Version,
mit Vermerk, aus welchem Baustein und welcher Version sie stammen
- [ ] Editor: Baustein einfügen, als Einheit anzeigen, nicht Schritt für Schritt bearbeitbar; ein
- [x] Editor: Baustein einfügen, als Einheit anzeigen, nicht Schritt für Schritt bearbeitbar; ein
Hinweis nennt Baustein und Version
- [ ] Eigene Verwaltung für Bausteine, Recht `vorlagenBearbeiten` (wer Vorlagen pflegt, pflegt
- [x] Eigene Verwaltung für Bausteine, Recht `vorlagenBearbeiten` (wer Vorlagen pflegt, pflegt
Bausteine)
- [ ] „Wo wird dieser Baustein benutzt“ — vor dem Ändern will man das wissen
- [ ] Anleitung Kapitel 04
- [x] „Wo wird dieser Baustein benutzt“ — vor dem Ändern will man das wissen
- [x] Anleitung Kapitel 04
## Akzeptanzkriterien
- [ ] Test: eine neue Baustein-Version ändert **keine** veröffentlichte Vorlagenversion und **keinen**
- [x] Test: eine neue Baustein-Version ändert **keine** veröffentlichte Vorlagenversion und **keinen**
laufenden Lauf
- [ ] Test: die Druckansicht eines archivierten Laufs ist nach einer Baustein-Änderung Zeichen für
- [x] Test: die Druckansicht eines archivierten Laufs ist nach einer Baustein-Änderung Zeichen für
Zeichen dieselbe
- [ ] Test: die nächste veröffentlichte Vorlagenversion enthält die neue Baustein-Version
- [ ] Test: ein Baustein lässt sich nicht löschen, solange eine Vorlage ihn im Entwurf nennt
- [ ] Test: Export und Import einer Vorlage mit Baustein ergeben eine inhaltsgleiche Vorlage — die
- [x] Test: die nächste veröffentlichte Vorlagenversion enthält die neue Baustein-Version
- [x] Test: ein Baustein lässt sich nicht löschen, solange eine Vorlage ihn im Entwurf nennt
- [x] Test: Export und Import einer Vorlage mit Baustein ergeben eine inhaltsgleiche Vorlage — die
Datei trägt die aufgelösten Schritte, keinen Verweis auf einen Baustein, den die andere
Installation nicht hat
## Beim Umsetzen dazugekommen
- **Ein Baustein ist genau ein Abschnitt**, nicht eine Gruppe davon. Das stand so im Auftrag
(„Abschnitte, die mehrere Vorlagen teilen“) und spart eine Verschachtelungsebene, die niemand
gebraucht hätte.
- **Der Verweis bleibt nach dem Veröffentlichen stehen** und ist dann nur noch Herkunft. Welche der
beiden Lesarten gilt, sagt der Status der Version — ein zweites Feld dafür wäre eine zweite
Wahrheit. Die Seite eines Bausteins liest daraus „Wo er steckt“, mit der Fassung je Vorlage.
- **Der Titel kommt aus dem Baustein**, nicht aus dem Abschnitt der Vorlage. Sonst müsste man ihn in
jeder Vorlage einzeln pflegen, und zwei Vorlagen zeigten denselben Baustein unter verschiedenen
Namen.
- **Vier Garantien liegen in der Datenbank**, nicht nur im Dienst: höchstens ein Entwurf (partieller
Index), eine veröffentlichte Fassung ist unveränderlich (Trigger), der Weg zurück zum Entwurf ist
versperrt (Trigger), und ein Abschnitt kann nur auf eine **veröffentlichte** Fassung verweisen
(Trigger). Beim Aufräumen der Testdaten hat der zweite sofort zugeschlagen — gut so.
- **Das Durchklicken des gebauten Stands fand einen Fehler**, den die Suite nicht gesehen hätte:
`neuerBausteinAbschnitt` legt Platzhalter-Schritte **ohne Titel** an, damit die Anzahl in der Karte
stimmt. `alsStruktur` schickte sie mit, und `SchrittSchema` wies den ganzen Entwurf ab — das
Speichern scheiterte. Behoben, mit Test und Gegenprobe.
- Dabei habe ich **zweimal mein eigenes Prüfskript** für den Fehler gehalten: einmal griff ein zu
weiter `role=status`-Selektor den falschen Text, einmal eine Prüfung nach dem Neuladen. Die
Datenbank hat beides geklärt — sie ist der einzige Zeuge, der nicht lügt.