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
This commit is contained in:
2026-09-06 23:17:39 +02:00
co-authored by Claude Sonnet 5
parent d607a1101d
commit 2a4d391711
23 changed files with 1505 additions and 44 deletions
+13
View File
@@ -1,4 +1,6 @@
import uuid
from datetime import datetime
from decimal import Decimal
from pydantic import BaseModel, ConfigDict
@@ -17,6 +19,16 @@ class ZustaendigerBenutzer(BaseModel):
quelle: str # "standort" oder "objekt" (Vereinigungslogik Karte 04)
class BeladungsPosition(BaseModel):
objektposition_id: uuid.UUID
material_id: int
material_name: str
einheit: str
fach: str | None
sollmenge: Decimal
istmenge: Decimal
class AkteRead(BaseModel):
"""FILE-001..006: gebündelte Aggregations-Sicht über alle bereits existierenden
Teilbereiche einer Ressource (aktuell nur Objekttyp "objekt" - Prompt 24/Backlog-
@@ -36,3 +48,4 @@ class AkteRead(BaseModel):
dokumente: list[DokumentRead]
geraete: list[GeraetInstanzRead]
maengel: list[MangelRead]
beladung: list[BeladungsPosition]
+1 -1
View File
@@ -8,7 +8,7 @@ from pydantic import BaseModel, ConfigDict
# Validierung) - jeder Ressourcentyp, an den Dokumente angehängt werden dürfen,
# muss hier explizit freigeschaltet werden.
EntitaetTyp = Literal[
"objekt", "objektposition", "geraet_instanz", "mangel", "fahrzeugdetails", "benutzer"
"objekt", "objektposition", "geraet_instanz", "mangel", "fahrzeugdetails", "benutzer", "wartungsauftrag"
]
+101
View File
@@ -0,0 +1,101 @@
import uuid
from datetime import date, datetime
from decimal import Decimal
from pydantic import BaseModel, ConfigDict
from app.models.wartung import IntervallTyp, WartungsauftragStatus
class WartungsintervallCreate(BaseModel):
typ: IntervallTyp
wert: int
class WartungsintervallRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
wartungsplan_position_id: int
typ: IntervallTyp
wert: int
class WartungsplanPositionCreate(BaseModel):
wartungsart: str
beschreibung: str | None = None
intervalle: list[WartungsintervallCreate] = []
class WartungsplanPositionRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
wartungsplan_id: int
wartungsart: str
beschreibung: str | None
intervalle: list[WartungsintervallRead] = []
class WartungsplanCreate(BaseModel):
objekttyp_id: int
name: str
positionen: list[WartungsplanPositionCreate] = []
class WartungsplanRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: int
objekttyp_id: int
name: str
positionen: list[WartungsplanPositionRead] = []
class WartungsauftragCreate(BaseModel):
objekt_id: int
geraet_instanz_id: uuid.UUID | None = None
wartungsplan_position_id: int | None = None
wartungsart: str
beschreibung: str | None = None
werkstatt_intern: bool = True
werkstatt_name: str | None = None
faelligkeit_am: date | None = None
class WartungsauftragErledigen(BaseModel):
erledigt_am: date | None = None
kosten: Decimal | None = None
kilometerstand_bei_erledigung: int | None = None
betriebsstunden_bei_erledigung: Decimal | None = None
class WartungsauftragStatusUpdate(BaseModel):
status: WartungsauftragStatus
class WartungsauftragRead(BaseModel):
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
objekt_id: int
geraet_instanz_id: uuid.UUID | None
wartungsplan_position_id: int | None
wartungsart: str
beschreibung: str | None
status: WartungsauftragStatus
werkstatt_intern: bool
werkstatt_name: str | None
faelligkeit_am: date | None
erstellt_am: datetime
erledigt_am: datetime | None
durchgefuehrt_von: int | None
kosten: Decimal | None
kilometerstand_bei_erledigung: int | None
betriebsstunden_bei_erledigung: Decimal | None
class FaelligeWartungRead(BaseModel):
wartungsplan_position_id: int
wartungsart: str
objekt_id: int
faellig: bool
faellig_am: date | None
faellig_bei_km: int | None
faellig_bei_betriebsstunden: Decimal | None