12 Commits
Author SHA1 Message Date
patrickandClaude Sonnet 5 2a4d391711 feat(maintenance): MAINT-Epic (Wartungspläne/-aufträge, Werkstatt) + Akte-Redesign
CI / backend-tests (push) Failing after 2m4s
CI / frontend-build (push) Successful in 18s
Neues Wartungskonzept: Wartungsplan+Position+Intervall (zeit/km/
Betriebsstunden, kombinierbar - fällig sobald ein Kriterium erreicht
ist), Wartungsauftrag mit intern/externer Werkstatt, Status offen/
in_arbeit/erledigt, Kosten, Historie, Dokument-Anhang. Ad-hoc-Aufträge
ohne Plan möglich (z.B. kleinere Reparatur). Admin-Tab "Wartungspläne".

Objektakte-Redesign (Epic 21, Nutzer-Feedback "wirkt nicht modern"):
CSS-Grid statt Karten-Stapel, einspaltig mobil, zweispaltig ab 900px;
Fahrzeug-Objekte zeigen Wartung/Fahrzeugdaten prominent, Geräte/
Rucksäcke die Beladung. Dabei gefundene Lücke: Beladung (Soll/Ist je
Position) fehlte in der Akte komplett, nur über eine laufende
Kontrolle sichtbar - jetzt eigene Karte.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 23:17:39 +02:00
patrickandClaude Sonnet 5 b6ada2b5a1 feat(inventory): INV-007 Ausgabe/Rückgabe von Material und Leihgeräten
CI / backend-tests (push) Successful in 2m1s
CI / frontend-build (push) Successful in 18s
Personenbezogene Ausgabe ergänzt die reine Standort-/Lagerplatz-Sicht
um "wer hat das Ding gerade": neues Modell ausgabe (Material +
optional geraet_instanz_id), POST /ausgaben, GET /ausgaben (Filter
status/empfaenger), POST /ausgaben/{id}/rueckgabe mit Schutz vor
Doppel-Rueckgabe. Frontend als Admin-Tab "Ausgabe/Rückgabe" +
Command-Palette-Eintrag.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-06 13:19:31 +02:00
patrickandClaude Sonnet 5 f7367f6df3 feat(lager): Warehouse-Epic Kern (WH-001..004+007)
CI / backend-tests (push) Successful in 1m56s
CI / frontend-build (push) Successful in 18s
Lagerort-Hierarchie (organisation/standort/gebaeude/raum/lager, self-referenzierend),
Lagerplätze mit eindeutigem Code, Bestand je Lagerplatz+Material, Ein-/Auslagerung
mit lückenlosem Materialbewegungsprotokoll (append-only, analog Lagerbewegung
auf Objekt-Ebene, hier aber Material-/Lagerplatz-fein).

- Migration 0019: 4 neue Tabellen (lagerort, lagerplatz, bestand, materialbewegung)
- Backend: CRUD Lagerort/Lagerplatz, Bestandsabfrage, Ein-/Auslagern-Endpunkte,
  Negativbestand vorab abgefangen (kein DB-Constraint-Exception-Pfad, gleiches
  Muster wie objekte.py-Fix vom 2026-09-05)
- Frontend: neuer Admin-Tab "Lager" (Lagerort/-platz-Verwaltung, Bestand+Buchung
  je Lagerplatz)
- 2 neue Tests, 139 Tests weiterhin grün

WH-005 (Umlagerung) und WH-006 (Inventur) bewusst zurückgestellt - Kern zuerst,
laut Nutzer-Entscheidung.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-05 21:42:37 +02:00
patrickandClaude Sonnet 5 1afac3a797 fix(models): app/models/__init__.py fehlten 6 Module seit Personal-Modul
CI / backend-tests (push) Failing after 1m56s
CI / frontend-build (push) Successful in 17s
Nicht mitgezogen seit Migration 0012: personal, mangel, fahrzeugdetails,
lagerbewegung, dokument, permission. Live-Testlauf von scripts/create_admin.py
brach mit NoReferencedTableError ab (Benutzer.einheit_id -> einheit war nicht
registriert, da das Skript nur app.models.auth statt des vollständigen
Registry-Imports nutzt). App selbst lief nur zufällig fehlerfrei, weil
api.py alle Endpunkt-Module importiert und die dortigen Modell-Importe die
Lücke im Betrieb kaschiert haben.

Fix: __init__.py vervollständigt + create_admin.py/eskalation_pruefen.py
(täglicher Timer!) bekommen zusätzlich ein explizites "import app.models" als
Schutz, unabhängig davon ob die Registry künftig wieder unvollständig wird.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KC8HYvv6UkCVYheYiTw9DD
2026-09-05 14:09:30 +02:00
patrickandClaude Sonnet 5 d61aabadf3 Karte 14 Schritt 1: geraet_instanz-Tabelle (additiv)
CI / backend-tests (push) Successful in 1m13s
CI / frontend-build (push) Successful in 23s
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
patrickandClaude Sonnet 5 fb676a4a0b Karte 12: Eskalationslogik für lange offene Fehlbestände
CI / backend-tests (push) Successful in 1m6s
CI / frontend-build (push) Successful in 21s
Zwei Stufen (Erinnerung an Materialverantwortliche, Eskalation an
Leitungsverantwortliche/Administration) mit Tracking-Zeitstempel je Stufe
gegen Mehrfachversand. Zeitschwellen in eskalation_konfiguration (DB,
Singleton), admin-editierbar über GET/PUT /eskalation/konfiguration - bewusst
nicht fix im Code. Prüflauf per POST /eskalation/pruefen angestoßen,
Scheduling (Cron/systemd-Timer) bleibt Betriebsaufgabe.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CVgbozhYmuEhiEJHffRXCV
2026-09-04 18:04:52 +02:00
patrickandClaude Sonnet 5 1e9012cba3 Sprint 5: Mindermengen-Genehmigung + automatischer Ablauf, Historie für Kernkette
CI / backend-tests (push) Successful in 47s
- MindermengenGenehmigung-Modell/Service (Prompt 04): reine fachliche Bewertung,
  ändert NIEMALS Ist-Menge/Fehlmenge/Fehlbestand-Status (Leitplanke, U2)
- Automatischer Ablauf bei Start der nächsten Kontrolle desselben Objekts (Karte 08,
  U6) - kein Zeit-Trigger, der Kontrollstart selbst ist der Ablauf-Zeitpunkt
- Genehmigung endet gemeinsam mit dem Fehlbestand, wenn dieser durch Nachfüllung
  erledigt wird (U7), unabhängig davon ob vorher eine neue Kontrolle stattfand
- Historie-Service (app/services/historie.py) + Verdrahtung in die komplette
  Kernkette: kontrolle_gestartet/-abgeschlossen/-abgebrochen/-uebernommen,
  istmenge_erfasst, fehlbestand_entstanden/-erledigt, nachfuellung_erfasst,
  mindermenge_genehmigt/-abgelaufen/-beendet_durch_erledigung (U14)
  Hinweis: Stammdaten-/Vorlagen-/Benutzerverwaltung noch nicht retrofittet -
  Sprint 5 deckt bewusst die im Testkonzept referenzierte Kernkette ab, keine
  flächendeckende Audit-Abdeckung aller CRUD-Endpunkte.
- Tests: U2, U6, U7, vollständige Historie-Kette nach Prompt-13.3-Beispiel (U14)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
2026-09-03 23:53:14 +02:00
patrickandClaude Sonnet 5 18fba28eae Sprint 4: Fehlbestand-Statusmaschine komplett, Nachfüllung sofort/später/teilweise
CI / backend-tests (push) Successful in 40s
- Nachfuellung-Modell: einzige Aktion, die Objektposition.istmenge tatsächlich
  ändert (Vier-Kernbegriffe). Deckt Sofort-Nachfüllung während Kontrolle (Karte 07)
  und spätere/externe Nachfüllung (Prompt 02.5) mit derselben Logik ab
- Wichtiger Fix vor dem ersten Testlauf: Objektposition.istmenge wird bei Nachfüllung
  auf den neuen Wert GESETZT (fehlbestand.istmenge + menge), nicht unabhängig
  inkrementiert - sonst bliebe sie beim initialen "nicht kontrolliert"-Stand (0)
  stehen, obwohl die Kontrolle bereits einen realen Zählwert kennt
- Statusübergänge: offen -> nachgefuellt_teilweise (Fehlmenge>0) -> erledigt
  (Fehlmenge=0), ausschließlich automatisch bei Ist=Soll (U3)
- Überbestand durch Nachfüllung erlaubt, als Info gekennzeichnet, kein Fehler (E4)
- KontrollpositionRead liefert jetzt fehlbestand_id mit, damit die UI direkt eine
  Sofort-Nachfüllung anbieten kann, ohne separat nachzufragen
- Tests: U3, U4 (Sofort-Nachfüllung ohne Zwischenstatus), U5 (Teilnachfüllung),
  Überbestand-Fall, Nachfüllung auf bereits erledigten Fehlbestand -> 409

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
2026-09-03 23:46:21 +02:00
patrickandClaude Sonnet 5 8fd507cc5d Sprint 3: Kontroll-Kern (Statusmaschine, Objekt-Sperre, automatische Fehlbestand-Erzeugung)
CI / backend-tests (push) Successful in 38s
- Kontrolle/Kontrollposition-Modelle: Kontrolle ändert NIEMALS Objektposition.istmenge
  (Vier-Kernbegriffe-Tabelle, Prompt 02.9) - reine Erfassung/Snapshot
- Objekt-Sperre (Prompt 02.8): Kontrolle.status='in_bearbeitung' + benutzer_id IST die
  Sperre, kein separates Sperr-Modell. Zweiter Zugriff -> 409 mit wer/seit; Übernahme
  bricht alte Kontrolle ab (Datensatz bleibt, Prompt 16.6-Analogie) und protokolliert
  das Ereignis in einer neuen, minimalen Historie-Tabelle (volle Ausbaustufe Sprint 5)
- Automatische Fehlbestand-Erzeugung bei Ist < Soll (U1), Überbestand erzeugt
  ausdrücklich KEINEN Fehlbestand (Prompt 02.4); Korrektur vor Abschluss möglich
  (von derselben Kontrolle erzeugter Fehlbestand ist bis zum Abschluss nicht final)
- Abschluss verweigert bei unbestätigten Positionen, liefert deren IDs (U11)
- Abbruch verwirft Kontrollpositionen UND von dieser Kontrolle erzeugte Fehlbestände,
  Kontrolle selbst bleibt als Datensatz mit Status "abgebrochen" erhalten (U12)
- Tests: U1, U11, U12, Sperre/409, Übernahme, Fremdzugriff/403, parallele Objekte

Mitarbeiter-UI (PWA-Frontend) ist bewusst noch nicht Teil dieses Commits - eigenes
Techstack-Setup, wird als nächster Schritt separat angegangen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
2026-09-03 23:40:26 +02:00
patrickandClaude Sonnet 5 fdcac2f160 Sprint 2: Beladungsvorlagen (Versionierung), Objekte anlegen/duplizieren, Override-Logik
CI / backend-tests (push) Successful in 29s
- Beladungsvorlage/Vorlagenposition-Modelle + Endpunkte: erstellen, neue Version
  (Prompt 08 Punkt 4 - alte Version bleibt unverändert lesbar statt überschrieben)
- Objekt-Anlage aus Vorlage: Objektpositionen werden initialisiert, Ist-Menge startet
  bei 0 ("nicht kontrolliert", Prompt 09)
- Duplizieren: Struktur/Sollmengen-Override kopiert, Ist-Menge/SN/Ablauf/Charge NICHT,
  neuer Code Pflicht (409 bei Kollision)
- Sollmengen-Auflösung (Prompt 10): Override schlägt Vorlagenwert, sonst dynamisch aus
  aktueller Vorlagenposition des Objekts
- GET /objekte/code/{code} bewusst vor /objekte/{id} registriert (Routing-Reihenfolge)
- Bugfix: app.models muss vollständig importiert werden (main.py + conftest.py), sonst
  schlägt FK-Auflösung zwischen Modellen fehl, die noch von keinem Endpoint berührt
  werden (Fund im dritten echten CI-Lauf)
- Tests: U8 (Override schlägt Vorlage), U9 (Duplizieren-Kopierregeln + Code-Konflikt),
  U10 (neue Version, alte bleibt lesbar), Rollenrechte

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
2026-09-03 23:31:14 +02:00
patrickandClaude Sonnet 5 b9cf195a63 Sprint 1: Stammdaten-Modelle/-Endpunkte, Admin-Benutzerverwaltung, Zuständigkeits-Vererbung (E2)
CI / backend-tests (push) Failing after 0s
- ORM-Modelle: Bereich, Kategorie, Standort, Objekttyp, Material (Prompt 06/07),
  minimales Objekt-Modell (voll ausgebaut erst Sprint 2), Zustaendigkeit/
  Kontrollverantwortung
- Admin-API 7a: GET/POST Stammdaten-Endpunkte, PATCH Material, Benutzerverwaltung
  (anlegen/Rollen ändern), Zuständigkeits-/Kontrollverantwortungs-CRUD
- Vererbungslogik E2 als eigener Service (app/services/zustaendigkeit.py):
  Standort-Zuordnung vererbt sich auf alle Objekte, Objekt-Zeile ist Vereinigung
  statt Ersatz - GET /zustaendigkeiten/benutzer/{id}/objekte exponiert das
- Tests: Stammdaten-CRUD + Rollenrechte, Benutzerverwaltung (inkl. 409 bei
  Login-Duplikat), E2-Vererbungslogik (Standort-only, Standort+Objekt-Vereinigung,
  End-to-End über den Endpunkt)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
2026-09-03 23:12:49 +02:00
patrickandClaude Sonnet 5 48b6d6a5be Sprint 0: FastAPI-Skeleton, vollständiges DB-Schema (Alembic), Auth (JWT/bcrypt), Rollen-Dependency, CI
CI / backend-tests (push) Failing after 1s
- Vollständiges Ziel-Schema aus Prompt 20 als initiale Migration (inkl. Karte-13-Vorbereitung: UUID-PKs, systemknoten)
- Seed-Migration für Hauptserver-Datensatz (Sprintplan E6)
- JWT-Login + /auth/me, require_roles-Dependency (Prompt 05 Berechtigungsmatrix)
- Tests: health, login/me, Rollen-Ablehnung/-Zulassung (S0-Abnahmekriterien)
- Gitea-Actions-CI: install -> migrate -> pytest mit Coverage-Gate 50%

Nur Code/Config erzeugt, nicht lokal installiert oder ausgeführt (Deployment-Regel).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L85hmKbvX7Cqkq47KnQhFt
2026-09-03 22:32:54 +02:00