docs: alte arbeitskarten (Karte 01-14) gegen arbeitskacheln-Backlog abgeglichen
CI / backend-tests (push) Failing after 1m57s
CI / frontend-build (push) Successful in 18s

7 Karten (02,03,06,09,10,11,14) inhaltlich bereits abgedeckt - gelöscht.
7 Karten (01,04,05,07,08,12,13) enthielten nicht erfasste Inhalte:
- neues Epic 17 Zuständigkeit (Karte 01+04)
- neues Epic 18 Notifications/Eskalation (Karte 05+12)
- neues Epic 19 Satelliten-Server (Karte 13, zurückgestellt)
- INV-006 ergänzt um Sofort-Nachfüllung (Karte 07) + Mindermengen-Gültigkeit (Karte 08)

arbeitskarten/ ist damit aufgelöst, nur Index mit Verweis auf arbeitskacheln bleibt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
This commit is contained in:
2026-09-05 17:06:42 +02:00
co-authored by Claude Sonnet 5
parent 0ee3ecec2d
commit 2bd97aa435
21 changed files with 281 additions and 357 deletions
+13 -21
View File
@@ -1,24 +1,16 @@
# Arbeitskarten Index
# Arbeitskarten Index (aufgelöst, 2026-09-05)
Status: entstanden aus Klärungsrunde vor Prompt 01. Jede Karte = ein entschiedener oder offener Punkt, mit Bezug zu `prompts.md`.
**Dieser Ordner ist aufgelöst.** Alle 14 Karten (0114) wurden gegen das neue
Epic-/Kachel-Backlog in `arbeitskacheln/` geprüft und übernommen:
| Nr | Karte | Status | Bezug |
|----|-------|--------|-------|
| 01 | [Rollen & Zuordnung](01_rollen_zuordnung.md) | entschieden | Prompt 05 |
| 02 | [Rechte: Stammdaten vs. Ist-Menge](02_rechte_stammdaten.md) | entschieden | Prompt 05 |
| 03 | [Sollmengen-Recht Materialverantwortlicher](03_sollmengen_recht.md) | entschieden | Prompt 04, 05 |
| 04 | [Organisationsstruktur / Zuständigkeiten](04_organisationsstruktur.md) | entschieden, Detail offen | Prompt 05, 06 |
| 05 | [Benachrichtigungen](05_benachrichtigungen.md) | entschieden | Prompt 12 |
| 06 | [Geräteanforderung PC/Mobil](06_geraet_pc_mobil.md) | entschieden | Prompt 11, 17 |
| 07 | [Sofort-Nachfüllung während Kontrolle](07_sofort_nachfuellung.md) | entschieden | Prompt 02, 03 |
| 08 | [Mindermengen-Gültigkeit](08_mindermenge_gueltigkeit.md) | entschieden | Prompt 04 |
| 09 | [Authentifizierung](09_authentifizierung.md) | entschieden | Prompt 05, 19 |
| 10 | [QR-Code / Barcode](10_qr_barcode.md) | Roadmap, Datenmodell-Vorbereitung nötig | Prompt 06, 24 |
| 11 | [Systemumfang: generisches Ressourcenmanagement](11_systemumfang_ressourcenmanagement.md) | entschieden, grundlegend | Prompt 06, 07 |
| 12 | [Eskalation offener Fehlbestände](12_eskalation.md) | Roadmap, Datenmodell-Vorbereitung nötig | Prompt 03, 24 |
| 13 | [Hauptserver mit Satelliten-Servern](13_satelliten_server.md) | entschieden, Betrieb Roadmap, Datenmodell-Vorbereitung nötig | Prompt 17, 19, 20 |
| 14 | [Prüf- und wartungspflichtige Geräte](14_pruef_wartungspflicht.md) | Datenmodell entschieden, Umsetzung offen (geraet_instanz-Tabelle nötig) | Prompt 06, 10, 24 |
- Karte 02, 03, 06, 09, 10, 11, 14 — inhaltlich bereits vollständig in bestehenden Epics
abgedeckt (FOUND-003/004, LOAD-001/002, MOBILE-001, IDENT-\*, ASSET-Grundprämisse,
INSP-Epic), Karten-Dateien gelöscht.
- Karte 01, 04, 05, 07, 08, 12, 13 — enthielten Inhalte ohne Gegenstück im Backlog, daraus
entstanden `arbeitskacheln/17_zustaendigkeit.md`, `18_notifications.md`,
`19_satelliten_server.md` sowie zwei Ergänzungen in `06_inventory.md` (INV-006).
Karten-Dateien gelöscht.
Nächster Schritt: Prompt `01_anforderungsanalyse` unter Berücksichtigung aller entschiedenen Karten bearbeiten.
**Hinweis (Gesamtprüfung):** Wiki-Link-Aliase (`[[name]]`) sind uneinheitlich benannt (z. B. Datei `10_individuelle_beladung.md` wird teils als `[[10_individuelle_beladung]]`, teils sinngemäß referenziert). Vor Code-Umsetzung/Migration einmal Alias-Konsistenz gegen tatsächliche Dateinamen prüfen.
Siehe `arbeitskacheln/00_index.md`, Abschnitt "Nachtrag: Abgleich mit alten
Arbeitskarten" für Details. Alle fachlichen Entscheidungen leben jetzt ausschließlich in
`arbeitskacheln/` weiter — dieser Ordner wird nicht mehr gepflegt.
-14
View File
@@ -1,14 +0,0 @@
# Karte 01 Rollen & Zuordnung
**Status:** entschieden
## Entscheidung
Grundsätzlich darf jeder Mitarbeiter jedes Rucksack/Fahrzeug kontrollieren (keine feste Pflichtzuordnung). Zusätzlich können Verantwortliche gezielt zuweisen entweder an eine Einzelperson oder an eine Gruppe.
## Konsequenz für Datenmodell / Fachkonzept
- Zuweisung ist optional, nicht Pflichtfeld.
- Zuweisungsmodell muss sowohl Einzelperson als auch Gruppe unterstützen (z. B. Tabelle Zuweisung: Objekt ↔ Benutzer ODER Objekt ↔ Gruppe).
- UI: Mitarbeiter sieht alle Objekte, ggf. zugewiesene hervorgehoben/priorisiert.
## Geklärt (vormals offen)
- Zuweisung erzwingt KEINE Pflichtkontrolle reine Empfehlung/Sichtbarkeit/Priorisierung. Schutz vor Doppelarbeit übernimmt die Objekt-Sperre nach Scan/Kontrollstart (Prompt 02.8), nicht die Zuweisung.
-10
View File
@@ -1,10 +0,0 @@
# Karte 02 Rechte: Stammdaten vs. Ist-Menge
**Status:** entschieden
## Entscheidung
Mitarbeiter/Kontrollorgan darf nur die tatsächliche Ist-Menge melden. Materialstammdaten (Bezeichnung, Artikelnummer usw.) sind für diese Rolle gesperrt.
## Konsequenz
- Rechtematrix (Prompt 05): Mitarbeiter = Ist-Menge erfassen, keine Stammdaten-Schreibrechte.
- Stammdatenpflege bleibt Administration bzw. ggf. Materialverantwortlichem vorbehalten (siehe Karte 03).
-11
View File
@@ -1,11 +0,0 @@
# Karte 03 Sollmengen-Recht Materialverantwortlicher
**Status:** entschieden
## Entscheidung
Materialverantwortlicher darf Sollmengen (Beladungsvorlagen) selbst ändern nicht nur Mindermengen genehmigen.
## Konsequenz
- Rechtematrix (Prompt 05): Materialverantwortlicher = Mindermengen genehmigen UND Sollmengen/Vorlagen bearbeiten.
- Prompt 08 (Beladungsvorlagen): Vorlagenänderung muss diese Rolle als Berechtigten vorsehen, nicht nur Administration.
- Historie/Audit (Prompt 13): Sollmengenänderungen durch Materialverantwortlichen müssen protokolliert werden (wer, wann, alt/neu).
-15
View File
@@ -1,15 +0,0 @@
# Karte 04 Organisationsstruktur / Zuständigkeiten
**Status:** entschieden
## Entscheidung
Keine starre zentrale ODER dezentrale Struktur vorgeben. Administrator muss Zuständigkeiten (welcher Verantwortliche für welchen Standort/welches Objekt) flexibel selbst einteilen können.
## Konsequenz für Datenmodell
- Zuständigkeit ist eigene, konfigurierbare Zuordnung: Verantwortlicher(e) ↔ Standort und/oder Objekt (Rucksack/Fahrzeug), n:m-Beziehung.
- Kein Hardcoding von "eine Wache = ein Verantwortlicher".
- Administration benötigt UI/Funktion zum Verwalten dieser Zuordnungen (Prompt 05).
## Geklärt (vormals offen)
- Ein Objekt kann mehrere Verantwortliche gleichzeitig haben (n:m, kein Limit).
- Zuständigkeit vererbt sich vom Standort automatisch auf alle Objekte an diesem Standort. Zusätzliche objektspezifische Zuordnung (`zustaendigkeit.objekt_id` gesetzt) ist eine feinere Ergänzung obendrauf, kein Ersatz Auswertelogik: ein Benutzer ist für ein Objekt zuständig, wenn ENTWEDER eine Standort-Zeile für dessen Standort ODER eine Objekt-Zeile für das Objekt selbst existiert (Vereinigung, keine Überschreibung).
-15
View File
@@ -1,15 +0,0 @@
# Karte 05 Benachrichtigungen
**Status:** entschieden
## Entscheidung
Bei neuem Fehlbestand wird Verantwortlicher benachrichtigt über:
- Dashboard (Portal)
- E-Mail
Kein Push/App in V1.
## Konsequenz
- Prompt 12 (Dashboard): Dashboard-Anzeige ist Pflichtbestandteil.
- Technische Architektur (Prompt 19): E-Mail-Versand-Komponente einplanen (z. B. Trigger bei Statuswechsel "offen").
- Push/App bleibt spätere Ausbaustufe (Roadmap, Prompt 24).
-11
View File
@@ -1,11 +0,0 @@
# Karte 06 Geräteanforderung PC/Mobil
**Status:** entschieden
## Entscheidung
Kontrolle muss sowohl auf PC als auch auf Smartphone/Tablet funktionieren kein "mobile-only" oder "PC-only".
## Konsequenz
- Prompt 11 (Mitarbeiter-UI): Responsive Design, keine reine Mobile-App-Annahme.
- Prompt 17 (Mobile/Offline): Offline-Fähigkeit bleibt separat zu bewerten, unabhängig von Geräteklasse.
- Technische Architektur (Prompt 19): Web-basiert sinnvoll, um beide Geräteklassen mit einer Codebasis abzudecken.
-10
View File
@@ -1,10 +0,0 @@
# Karte 07 Sofort-Nachfüllung während Kontrolle
**Status:** entschieden
## Entscheidung
Wenn Besatzung Fehlmenge noch während laufender Kontrolle direkt aus Lager nachfüllt, gilt: Fehlbestand entsteht trotzdem als Vorgang und wird im selben Moment als erledigt markiert. Kein "verschwindet spurlos".
## Konsequenz
- Prompt 03 (Fehlbestandsmanagement): Statuswechsel "offen" → "erledigt" muss auch innerhalb derselben Kontrollsitzung möglich sein (nicht nur über mehrere Kontrollen hinweg).
- Historie (Prompt 13) muss diesen Fall abbilden: Fehlmenge festgestellt, Fehlbestand angelegt, Nachfüllung, erledigt alles mit Zeitstempel, auch wenn zeitlich sehr nah beieinander.
@@ -1,11 +0,0 @@
# Karte 08 Mindermengen-Gültigkeit
**Status:** entschieden
## Entscheidung
Genehmigte Mindermenge gilt automatisch nur bis zur nächsten Kontrolle des betroffenen Objekts kein festes Ablaufdatum, kein unbefristetes Gelten.
## Konsequenz
- Prompt 04 (Mindermengen): Genehmigung ist an "nächste Kontrolle" gekoppelt, nicht an Kalenderdatum.
- Bei nächster Kontrolle: Ist-Menge wird neu erfasst; ist die Abweichung weiterhin vorhanden, muss neu entschieden werden (neuer Genehmigungsvorgang oder Fehlbestand wieder aktiv).
- Datenmodell: Genehmigung referenziert die Kontrolle, ab der sie NICHT mehr automatisch gilt (z. B. "gültig_bis_kontrolle_id" oder Statuslogik beim Kontrollabschluss).
-10
View File
@@ -1,10 +0,0 @@
# Karte 09 Authentifizierung
**Status:** entschieden
## Entscheidung
Version 1 benötigt echte Benutzerkonten mit Login (Passwort/PIN) keine einfache Namensauswahl ohne Absicherung.
## Konsequenz
- Prompt 05 (Rollen/Rechte) und Prompt 19 (Architektur): Authentifizierungskomponente ist Pflichtbestandteil des MVP, nicht optional.
- Zurechenbarkeit von Kontrollen/Genehmigungen/Änderungen (Prompt 13, Historie) basiert auf echtem Login, nicht auf Selbstauskunft.
-42
View File
@@ -1,42 +0,0 @@
# Karte 10 QR-Code / Barcode
**Status:** Roadmap-Feature, Datenmodell-Vorbereitung schon in V1 nötig
## Entscheidung
QR/Barcode-Scan ist gewünschte spätere Funktion:
- Objekt-Code (Rucksack/Fahrzeug) → Direktsprung ins Kontroll-Screen (statt Portal → Standort → Fahrzeug → Rucksack suchen).
- Geräte-Code (Einzelgerät) → automatische Seriennummer-Erkennung.
## Konsequenz für V1 (jetzt schon vorsehen)
- Prompt 06 (Datenmodell): Objekt (Rucksack/Fahrzeug) und Einzelgerät bekommen je ein eindeutiges Code-/ID-Feld, auch wenn Scan-UI erst später kommt.
- Kein Schema-Umbau später nötig, nur Scan-Funktion (Kamera/Reader) ergänzen.
## Umsetzung
- Eigentliche Scan-Funktion → Prompt 24 (Roadmap), nicht MVP.
## Barcode-Format (Nutzerentscheidung)
- Standard: **Code128**, eindimensional, weit verbreitet.
- Bewusste Wahl statt proprietärem/2D-Format, um Geräteauswahl offen zu halten.
- Konsequenz Datenmodell: Code-Feld (Objekt/Gerät) muss Code128-kompatiblen Zeichensatz aufnehmen können (alphanumerisch, keine Sonderzeichen-Einschränkung nötig, Code128 deckt ASCII ab).
- Zusatzanforderung: Code muss per Tablet-/Smartphone-Kamera lesbar sein (Software-Scan). Code128 ist per Kamera grundsätzlich lesbar, aber empfindlicher gegenüber Druckqualität/Abstand/Winkel als 2D-Codes wie QR. Konsequenz: Drucklayout (Größe, Kontrast) muss auf Kamera-Scan getestet werden.
## Label-Design (offener Punkt, Prompt 24 vertiefend)
- Physisches Label-Design (Größe, Material, Kontrast, Schriftgröße Klartext unter Code, Anbringungsort am Objekt) muss mit aufgenommen werden, nicht nur der Code-Inhalt selbst.
- Anforderungen an Label aus Einsatzumfeld: witterungsbeständig/abriebfest (Rucksäcke/Fahrzeuge im Rettungsdiensteinsatz), Kontrast/Größe für zuverlässigen Kamera-Scan (siehe oben).
- Klartext-Fallback auf Label empfohlen (Code + lesbare Objekt-ID), falls Scan mal ausfällt.
- Konkretes Layout/Material erst bei Umsetzung (Prompt 24) final festlegen, hier nur als Anforderung vermerkt.
## Umsetzungsstand (2026-09-04)
- Backend: `objektposition.code`-Feld, Lookup-/Vorschlag-Endpunkte, PDF-Label-Erzeugung (`app/services/label.py`) fertig.
- Frontend/Flutter: Kamera-Scan (Objekt-Code, Scan-First) fertig.
- **Offen: Label-Druck-Test mit echten Geräten** (physischer Schritt, nicht per Code erledigbar). Test-PDF erzeugen: `python -m scripts.test_label_erzeugen` im Backend-venv.
### Test-Checkliste (pro Labelgröße/-material einmal durchgehen)
1. Test-Label drucken (`test_label_erzeugen.py`, mind. eine Größe pro geplantes Labelformat).
2. Auf Ziel-Untergrund kleben/befestigen (Rucksack-Stoff, Fahrzeuglack o. Ä. reale Anbringung testen, nicht nur Tisch/Papier).
3. Mit jedem vorgesehenen Scan-Gerät testen (PWA im Handy-/Tablet-Browser, Flutter-App auf Android):
- Normalabstand (~1520 cm) und Winkel 0°
- Schräger Winkel (~30°)
- Schwaches Licht / Gegenlicht
4. Bei Fehlschlag: Modulbreite/Ruhezone in `_BARCODE_OPTIONEN` (`app/services/label.py`) erhöhen, neues Test-Label drucken, erneut testen.
5. Ergebnis (Gerät, Abstand/Winkel, Erfolg/Fehlschlag) hier oder in einer neuen Notiz festhalten, bevor Seriendruck freigegeben wird.
@@ -1,18 +0,0 @@
# Karte 11 Systemumfang: generisches Ressourcenmanagement
**Status:** entschieden, grundlegend (beeinflusst Benennung + Datenmodell)
## Entscheidung
System wird konzeptionell nicht als "Rettungsdienst-Materialverwaltung" gedacht, sondern als generisches **Ressourcen- und Materialmanagement**. Rettungsdienst/KatS sind ein Bereich davon, nicht der gesamte Scope.
Perspektivisch zu verwaltende Objekttypen (Beispiele, nicht abschließend):
Fahrzeuge, Rucksäcke, Zelte, Feldbetten, Stromerzeuger, Funkgeräte, Aggregate, Sanitätsmaterial, Betreuungsmaterial.
## Konsequenz für Datenmodell (Prompt 06/07)
- "Bereich" bzw. "Kategorie" wird eigene Dimension über dem Objekttyp nicht Rettungsdienst hartcodiert.
- Objekt-Entität (aktuell "Rucksack/Fahrzeug") sollte generisch als "Ressource"/"Ausrüstungsobjekt" modelliert werden, mit Typ als Attribut/Unterklasse statt eigener Tabelle je Objektart.
- Materialstamm (Prompt 07) muss über Sanitätsmaterial hinaus erweiterbar bleiben (z. B. Betreuungsmaterial, technisches Material).
## Auswirkung auf bestehende Prompts
- Prompt 01 (Anforderungsanalyse): Scope-Beschreibung entsprechend generisch formulieren, nicht auf Rettungsdienst verengen.
- Prompt 06 (Datenmodell): "Bereich" als Grunddimension explizit einführen.
-22
View File
@@ -1,22 +0,0 @@
# Karte 12 Eskalation offener Fehlbestände
**Status:** Roadmap-Feature, Datenmodell-Vorbereitung schon in V1 sinnvoll
## Entscheidung
Später gewünscht: automatische Eskalation bei lange offenen Fehlbeständen, z. B.:
- Erinnerung nach X Tagen (🟡)
- Eskalation an Leitungsverantwortlichen nach Y Tagen (🔴)
Zeitschwellen konfigurierbar, nicht fix.
## Konsequenz für V1
- Prompt 03 (Fehlbestandsmanagement): Fehlbestand-Entität muss Zeitstempel "entstanden am" führen, damit "Alter" später berechenbar ist, ohne Modelländerung.
- Kein Eskalationsmechanismus selbst in V1/MVP (Prompt 18) nur Datenbasis dafür vorhalten.
## Umsetzung
- Eskalationslogik (Jobs, Schwellenwerte, Empfängerlogik) → Prompt 24 (Roadmap).
## Umsetzungsstand (2026-09-04)
- `app/services/eskalation.py`: zwei Stufen (Erinnerung an Materialverantwortliche, Eskalation an Leitungsverantwortliche/Administration), Tracking-Zeitstempel je Stufe verhindert Mehrfachversand.
- Zeitschwellen in `eskalation_konfiguration` (DB, Singleton-Zeile) statt fix im Code - admin-editierbar über `GET/PUT /api/v1/eskalation/konfiguration`.
- Prüflauf selbst per `POST /api/v1/eskalation/pruefen` (admin-only) angestoßen - **Scheduling (Cron) ist weiterhin Betriebsaufgabe**, kein eigener Scheduler-Prozess im Code (Prompt 19 Deployment-Regel). Auf dem Zielserver z. B. per systemd-Timer/Cron, der diesen Endpunkt periodisch mit Admin-Token aufruft.
-39
View File
@@ -1,39 +0,0 @@
# Karte 13 Hauptserver mit Satelliten-Servern
**Status:** Entschieden (Architektur-Erweiterung), betrifft Prompt 17 (Offline) und Prompt 19 (Architektur).
## Entscheidung
Zusätzlich zum Hauptserver können **Satelliten-Server** existieren, die lokal (am Einsatzort/an einer Wache) laufen und temporär vom Hauptserver getrennt sind.
## Einsatzfälle
1. KatS-Einsatzlage (Zeltlager/Einsatzort ohne Internet) Satellit läuft autark vor Ort.
2. Wache mit dauerhaft schlechter Anbindung Satellit als Regelbetrieb, nicht nur Notfall.
3. Reiner Ausfallschutz Satellit übernimmt nur bei Komplettausfall Hauptserver/Internet.
## Autark-Dauer
Bewusst **nicht zeitlich begrenzt** System darf keine feste Obergrenze annehmen (z. B. "nach 3 Tagen zwingend Sync nötig"). Trennung kann Stunden bis mehrere Tage/unbestimmt dauern.
## Mehrbenutzerfähigkeit am Satelliten
Satellit ist funktional ein vollwertiger, kleiner Hauptserver-Klon (gleiche Software/API), kein reiner Cache. Mehrere Mitarbeiter können gleichzeitig am selben Satelliten arbeiten braucht keine eigene Konfliktlösung, da er wie der Hauptserver selbst funktioniert.
## Konfliktvermeidung (statt Konfliktlösung)
Zentrale Design-Entscheidung: Konflikte beim Zurücksynchronisieren **sollen strukturell nicht vorkommen**, nicht nachträglich aufgelöst werden.
- Jedes Objekt (Rucksack/Fahrzeug) ist während einer Trennung **fest genau einem Server zugeordnet** entweder Hauptserver oder ein bestimmter Satellit, nie beiden gleichzeitig.
- Objekte, die einem Satelliten zugeteilt sind, werden am Hauptserver für Schreibzugriffe gesperrt/als "ausgelagert" markiert, bis Rücksynchronisation erfolgt ist.
- Dadurch kein "wer gewinnt"-Problem es gibt pro Objekt nur eine schreibende Quelle zu jedem Zeitpunkt.
## Konsequenz für Datenmodell/Architektur (Vorbereitung, Details Prompt 19/20 zu vertiefen)
- Objekt braucht Feld "aktuell zugeordneter Server" (Hauptserver-ID oder Satelliten-ID).
- Zuordnung ändert sich nur durch bewussten Vorgang ("Objekt X an Satellit Y auslagern" / "Objekt X zurückholen"), nicht automatisch.
- Historie/Fehlbestände/Kontrollen, die am Satelliten entstehen, tragen von Anfang an die eindeutigen IDs des Gesamtsystems (nicht lokal generierte, kollisionsanfällige IDs) Voraussetzung für widerspruchsfreies Zusammenführen beim Sync.
- Synchronisation überträgt beim Reconnect neu entstandene Datensätze (Kontrollen, Nachfüllungen, Historie, neue Objektpositionen/Zuständigkeiten) per Insert **und** am Satelliten geänderte, bereits vorher existierende Zeilen (Objektpositionen, offene Fehlbestände, aktive Mindermengen-Genehmigungen) per Upsert an den Hauptserver kein reiner Append-Vorgang (konkretes SQL/Reihenfolge siehe [[20_datenbank_schema]] Punkt 10). Danach wird die Objekt-Zuordnung zurückgesetzt.
## Offene Punkte für weitere Ausarbeitung
- Wie wird eine Auslagerung technisch ausgelöst/verwaltet (manuell durch Administration vor einem Einsatz, oder automatisch bei Verbindungsverlust)?
- Muss der Satellit vorab mit den relevanten Stammdaten bestückt werden, bevor er getrennt wird? Dazu gehören: Materialstamm, Vorlagen, betroffene Objekte/Objektpositionen, **sowie deren offene Fehlbestände und aktive Mindermengen-Genehmigungen** (ohne diese kann am Satelliten weder korrekt nachgefüllt noch genehmigt werden).
- Was passiert, wenn beim Auslagern bereits eine Kontrolle am Hauptserver „in Bearbeitung" ist, bzw. wenn ein Objekt zurückgeholt werden soll, während am Satelliten noch eine Kontrolle läuft? noch keine Regel definiert, vor Umsetzung zu klären (Vorschlag: Auslagerung/Rückholung nur bei Kontrollstatus „nicht gestartet" oder „abgeschlossen" zulassen).
- Erzwingung von `objektposition.zuletzt_geaendert_am`: aktuell nur Spalten-Default, keine Garantie, dass jeder UPDATE-Pfad den Wert tatsächlich aktualisiert. Vorschlag: DB-Trigger `BEFORE UPDATE` statt Anwendungsdisziplin, um stillschweigend übersehene Änderungen beim Delta-Sync auszuschließen.
- Hardware-Anforderung an Satelliten-Server (kleiner lokaler Rechner/Mini-PC vor Ort, Prompt 19 zu ergänzen).
## Referenzen
Bezug: [[17_mobile_offline]], [[19_technische_architektur]]
-98
View File
@@ -1,98 +0,0 @@
# Karte 14 Prüf- und wartungspflichtige Geräte
**Status:** Konzeptphase, Datenmodell entschieden (2026-09-04), Umsetzung offen
## Entscheidung
Das Portal deckt nicht nur Bestandskontrolle (Soll/Ist-Mengen, Verbrauchsmaterial-
Nachschub) ab, sondern auch gesetzlich/betrieblich prüf- und wartungspflichtige
Geräte (z. B. Feuerlöscher, Defibrillatoren, Leitern, Atemschutzgeräte, Pulsoxymeter)
mit wiederkehrenden Prüfintervallen und Fristen. Das ist fachlich etwas anderes als
Ablaufdatum (einmaliges festes Datum) oder Charge (Identifikation) hier geht es
um einen wiederkehrenden Prüfzyklus mit Ergebnis pro Durchgang, UND um mehrere
Geräte-Exemplare desselben Materials im selben Objekt.
## Kernproblem im aktuellen Datenmodell
`objektposition.seriennummer` ist ein Einzelfeld kann nur EIN Gerät pro
Materialtyp pro Objekt erfassen. Bei z. B. 2 Pulsoxymetern im selben Rucksack
gibt es keine Möglichkeit, beide Seriennummern zu speichern. Das ist ein echtes
Datenmodell-Defizit, kein UI-Problem erfordert eine neue Entität.
## Datenmodell (entschieden)
Neue Tabelle `geraet_instanz` ersetzt `objektposition.seriennummer` für
`materialtyp='geraet_sn'`:
```sql
CREATE TABLE geraet_instanz (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
objektposition_id UUID NOT NULL REFERENCES objektposition(id),
seriennummer TEXT NOT NULL,
pruefdatum DATE, -- letzte Prüfung
naechste_pruefung DATE, -- fällige Prüfung
status TEXT NOT NULL DEFAULT 'einsatzbereit', -- einsatzbereit / defekt / in_reparatur
bemerkung TEXT,
UNIQUE (objektposition_id, seriennummer)
);
```
- `objektposition.seriennummer` entfällt (Migration: bestehende Werte nach
`geraet_instanz` überführen, dann Spalte droppen).
- Ist-Menge bei `geraet_sn` wird nicht mehr als Zahl geführt/eingegeben, sondern
als Anzahl der `geraet_instanz`-Zeilen mit `status='einsatzbereit'` berechnet.
- `objektposition`: neues Feld `pruefintervall_monate` (int, nullable)
**individuell überschreibbar** je Objektposition (wie `sollmenge_override`),
Vorlage/Material kann einen Standard vorgeben, einzelne Objektposition kann
abweichen (z. B. älteres Gerät mit kürzerer Frist).
- `naechste_pruefung` je `geraet_instanz` wird nach jeder erfassten Prüfung neu
berechnet (`pruefdatum + pruefintervall_monate`).
## "Nicht bestanden" / defekt → Fehlbestand (entschieden)
**Pro Gerät entscheidbar, nicht global fix.** Beim Setzen von
`status='defekt'` oder `status='in_reparatur'` an einer `geraet_instanz` wird
im selben Dialog gefragt/entschieden, ob daraus ein Fehlbestand entsteht (nutzt
die bestehende Fehlbestand-/Eskalations-Infrastruktur weiter, kein Parallel-
Konzept). Die ganze bestehende Fehlbestand-Logik (Kette Fehlbestand →
Nachfüllung/Mindermenge → Historie) wird dabei mitgenutzt, nicht neu gebaut
ein "defektes Gerät" ist fachlich einfach ein Fehlbestand mit Fehlmenge=1 an
dieser Position.
## Erfassungs-UI für `geraet_sn` (komplett neu, kein Mengenfeld mehr)
Statt Mengenfeld + "Passt"-Button: Instanz-Liste pro Position.
```
┌─────────────────────────────────────────┐
│ Pulsoxymeter Modell X (Soll: 2) │
├─────────────────────────────────────────┤
│ ✓ SN-001 [Prüfdatum: 2025-03-15] [OK] │
│ ✓ SN-002 [Prüfdatum: 2025-06-22] [OK] │
│ + Gerät hinzufügen (SN scannen/eingeben) │
└─────────────────────────────────────────┘
```
Buttons pro Instanz:
- **OK** Gerät ist da, einsatzbereit.
- **Fehlt/Defekt** Dialog: Grund (fehlt/defekt/in Reparatur), Bemerkung →
Instanz-Status ändern, bei "fehlt"/"defekt" optional Fehlbestand erzeugen
(siehe oben, pro Gerät entscheidbar).
`materialtyp='ablauf_charge'` und `'standard'` bleiben unverändert (Mengenfeld
+ Passt-Button wie bisher) nur `geraet_sn` bekommt diese neue Erfassungsart.
## Eskalation bei überfälliger Prüfung
Bestehende Zwei-Stufen-Mechanik (`app/services/eskalation.py`) um eine zweite
Datenquelle erweitern: überfällige `geraet_instanz.naechste_pruefung` statt
`fehlbestand.entstanden_am`. Eigene Konfigurationszeile/-spalten, damit
Prüf-Fristen unabhängig von Fehlbestand-Fristen einstellbar sind (TÜV-Fristen
unterscheiden sich je nach Gerätetyp).
## Umsetzungsschritte (grobe Reihenfolge)
1. Migration: `geraet_instanz`-Tabelle, `objektposition.pruefintervall_monate`,
Daten-Migration bestehender `seriennummer`-Werte, danach Spalte droppen.
2. Backend: `geraet_instanz`-Model + Service (CRUD, Status ändern inkl.
optionaler Fehlbestand-Erzeugung, Ist-Menge-Berechnung für `geraet_sn`).
3. Backend: Eskalation um Prüf-Fälligkeit erweitern.
4. Frontend: neue Instanz-Listen-UI für `geraet_sn` in der Kontroll-Erfassung
(`PositionCard.tsx`/`KontrollPage.tsx`), Scan-Integration (Karte 10) für
SN-Eingabe wiederverwenden.
5. Frontend: Admin-Pflege der Geräte-Instanzen (analog `ObjektPositionenPanel`).