feat(archiv): Uebersicht, Volltextsuche und Druckansicht
Prüfung / pruefung (pull_request) Canceled after 0s
Prüfung / pruefung (push) Canceled after 0s
Prüfung / e2e (pull_request) Canceled after 0s
Prüfung / e2e (push) Canceled after 0s

Der Einstieg am Schreibtisch und das Gedaechtnis der Anwendung. Die Uebersicht
sortiert nach Dringlichkeit — ueberfaellig zuerst, und das ist das Einzige in
Warnfarbe; alles andere auf der Seite ist Auskunft.

Das Archiv sucht ueber Titel, Notizen, erfasste Werte und Kommentare in einer
SQL-Anweisung: `Schrittergebnis.wert` ist ein Json, und nur `("wert")::text`
trifft den Trigramm-Index aus #006. Vor allem aber gehoert die Fundstelle zum
Treffer — ein Treffer ohne sichtbaren Grund ist fuer den Suchenden wertlos.

Die Druckansicht ist ein eigenes Lesemodell und kein Schalter an
`laufZumAbarbeiten`: dort entsteht beim Fuellen der Befehle ein Passwort, und auf
einem Blatt, das jemand abheftet, darf keines stehen. Vom Mitarbeiter holt sie
nur Name, UPN und Abteilung — nicht alles und dann gefiltert.

Der unabhaengige Review fand zwei Blocker, beide im Dashboard: „ueberfaellig“
verglich mit dem Augenblick statt mit dem Tagesbeginn, und der Schnellstart
zaehlte Laeufe fremder Kunden mit. Was „ueberfaellig“ heisst, steht seitdem in
`src/lib/fristen.ts` — eine Regel fuer Lesemodell und Anzeige.

Closes #15

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-25 22:59:02 +02:00
co-authored by Claude Opus 5
parent e7a2e2d5c7
commit 8146e33f48
32 changed files with 4202 additions and 38 deletions
+57 -2
View File
@@ -17,11 +17,12 @@ als Unterpunkte mit Aufgabe und Dauer.
| #012 | M7 – Platzhalter, Namensregeln, Escaping | 2 h 30 min |
| #013 | M8 – Läufe: Service und Abarbeitung | 3 h 05 min |
| #014 | M9 – QR-Tags, Geräteseite, Etiketten, Scanner | 3 h 35 min |
| | **Summe** | **20 h 25 min** |
| #015 | M10 – Dashboard und Archiv | 2 h 20 min |
| | **Summe** | **22 h 45 min** |
| Meilenstein | Tatsächlich | Status |
|---|---|---|
| v0.1.0 | 20 h 25 min | in Arbeit |
| v0.1.0 | 22 h 45 min | in Arbeit |
---
@@ -625,3 +626,57 @@ als Unterpunkte mit Aufgabe und Dauer.
- #015 Dashboard und Archiv — die Übersicht für den Alltag und die Volltextsuche über alles, was
abgearbeitet wurde.
---
## 2026-09-25 · Sitzung 11 · 21:35–23:00
**Issue:** #015 (M10)
**Version:** 0.1.0
### Erledigt
- **Drei Teile parallel**: Archiv (Sub-Agent), Druckansicht (Sub-Agent), Übersicht (selbst)
- Archiv mit Volltextsuche über Titel, Notizen, Werte und Kommentare, Fundstellen im Treffer,
sechs Filtern und Mandantensicht in jeder Abfrage
- Druckansicht eines Laufs: hell, ohne Navigation, A4 — ersetzt im MVP den PDF-Export
- Übersicht mit Überfälligem, eigenen Zuweisungen, zuletzt Bearbeitetem und Schnellstart
- Unabhängiger Review: **zwei Blocker**, fünf Befunde, neun Anmerkungen — alle abgearbeitet
- **980 Tests** (vorher 930) und **67 Ende-zu-Ende-Tests** grün
### Entscheidungen
- **`ABGESCHLOSSEN` gehört ins Archiv.** „Abgeschlossen ist nicht archiviert" betrifft den
Schreibschutz, nicht das Suchen: wer die Seriennummer von letzter Woche sucht, weiß nicht, ob
schon jemand archiviert hat.
- **Eine SQL-Anweisung für drei Tabellen.** `Schrittergebnis.wert` ist ein Json — nur
`("wert")::text` trifft den Trigramm-Index, und über Prisma lässt sich eine Json-Spalte nicht als
Text durchsuchen. Vor allem aber gehört die **Fundstelle** zum Treffer: ein Treffer ohne
sichtbaren Grund ist für den Suchenden wertlos.
- **Die Druckansicht ist ein eigenes Lesemodell**, kein Schalter an `laufZumAbarbeiten`. Dort
entsteht beim Füllen der Befehle ein Passwort; auf einem Blatt, das jemand abheftet, darf keines
stehen.
- **Was „überfällig" heißt, steht jetzt in `src/lib/fristen.ts`** — eine Regel, zwei Benutzer
(Lesemodell und Anzeige). Zwei Fassungen derselben Regel laufen auseinander.
### Probleme
- **Beide Blocker steckten in meinem eigenen Teil.** „Überfällig" verglich mit dem Augenblick
statt mit dem Tagesbeginn — ein heute fälliger Lauf stand ab zwei Uhr morgens in Warnfarbe. Und
der Schnellstart zählte Läufe fremder Kunden mit: eine Vorlage ohne Kundenbezug gilt für alle,
ihr Zähler nicht.
- **Mein Test ließ genau die Grenze aus, an der der Fehler saß.** Er kannte „gestern" und
„morgen", aber nicht „heute". Seitdem steht die Regel in einer reinen Funktion mit eigenen
Grenztests.
- **Ein E2E-Test, der nicht scheitern konnte:** „trägt kein Passwort" lief gegen eine Vorlage ohne
Passwortschritt. Er hätte auch bestanden, wenn die Druckansicht Passwörter erzeugte.
- **Der Trigramm-Index auf `Lauf.titel` war strukturell unerreichbar**, weil der Titeltreffer aus
der sechsmal gelesenen und deshalb materialisierten CTE las. Der Review hat das mit 40 000
Läufen gemessen, nicht vermutet — das ist der Unterschied zwischen „sollte passen" und „passt".
- **Siebter Meilenstein in Folge mit einer Zusage ohne Deckung:** „kein
`{{generiertes_passwort}}` im Druck" galt nur für Vorlagentexte.
### Nächster Schritt
- #016 Verzeichnis und LDAP-Abgleich — der größte verbleibende Brocken: `ldapts`, Attribut-Mapping,
Zeitplan, verschlüsseltes Bind-Passwort und ein Integrationstest gegen einen OpenLDAP-Container.