Files
MABEA/arbeitskarten/14_pruef_wartungspflicht.md
T
patrickandClaude Sonnet 5 d61aabadf3
CI / backend-tests (push) Successful in 1m13s
CI / frontend-build (push) Successful in 23s
Karte 14 Schritt 1: geraet_instanz-Tabelle (additiv)
objektposition.seriennummer war ein Einzelfeld, konnte nur EIN Gerät pro
Materialtyp/Objekt abbilden (z.B. 2 Pulsoxymeter im selben Rucksack nicht
darstellbar). Neue Tabelle geraet_instanz erlaubt beliebig viele Exemplare
pro Position (Seriennummer, Prüfdatum, nächste Prüfung, Status). Zusätzlich
objektposition.pruefintervall_monate (individuell überschreibbar).

Bewusst additiv: seriennummer-Spalte bleibt vorerst stehen (Service/
Endpunkte/Frontend hängen noch daran), bestehende Werte werden per
INSERT...SELECT nach geraet_instanz kopiert. Drop + Umbau der abhängigen
Schichten folgt in Umsetzungsschritt 2 (siehe arbeitskarten/14_...).

Migration von postgres-expert gegengeprüft (ON CONFLICT DO NOTHING als
Sicherheitsnetz, DROP TYPE IF EXISTS ergänzt), Tests decken Mehrfach-
Instanzen, UNIQUE-Constraint je Position, gleiche SN an verschiedenen
Positionen und pruefintervall_monate ab.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-04 20:45:04 +02:00

5.2 KiB
Raw Blame History

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':

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).