import uuid from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.api.deps import get_current_user, require_roles from app.db.session import get_db from app.models.auth import Benutzer, RolleTyp from app.models.objekt import Objekt from app.models.wartung import Wartungsauftrag, Wartungsplan, WartungsauftragStatus from app.schemas.wartung import ( FaelligeWartungRead, WartungsauftragCreate, WartungsauftragErledigen, WartungsauftragRead, WartungsauftragStatusUpdate, WartungsplanCreate, WartungsplanPositionRead, WartungsplanRead, ) from app.services.wartung import ( aendere_status, erledige_wartungsauftrag, erstelle_wartungsauftrag, erstelle_wartungsplan, faellige_wartungen_fuer_objekt, hole_intervalle, hole_positionen_mit_intervallen, liste_wartungsauftraege, ) router = APIRouter() _verantwortliche = require_roles( RolleTyp.administration, RolleTyp.materialverantwortlicher, RolleTyp.leitungsverantwortlicher ) async def _wartungsplan_read(db: AsyncSession, plan: Wartungsplan) -> WartungsplanRead: positionen = await hole_positionen_mit_intervallen(db, plan.id) positionen_read = [] for position in positionen: intervalle = await hole_intervalle(db, position.id) positionen_read.append( WartungsplanPositionRead( id=position.id, wartungsplan_id=position.wartungsplan_id, wartungsart=position.wartungsart, beschreibung=position.beschreibung, intervalle=list(intervalle), ) ) return WartungsplanRead( id=plan.id, objekttyp_id=plan.objekttyp_id, name=plan.name, positionen=positionen_read ) @router.get("/wartungsplaene", response_model=list[WartungsplanRead]) async def liste_wartungsplaene( objekttyp_id: int | None = None, db: AsyncSession = Depends(get_db), _=Depends(get_current_user), ) -> list[WartungsplanRead]: stmt = select(Wartungsplan) if objekttyp_id is not None: stmt = stmt.where(Wartungsplan.objekttyp_id == objekttyp_id) result = await db.execute(stmt) return [await _wartungsplan_read(db, p) for p in result.scalars().all()] @router.post("/wartungsplaene", response_model=WartungsplanRead, status_code=status.HTTP_201_CREATED) async def erstelle_neuer_wartungsplan( payload: WartungsplanCreate, db: AsyncSession = Depends(get_db), _=Depends(_verantwortliche) ) -> WartungsplanRead: plan = await erstelle_wartungsplan( db, objekttyp_id=payload.objekttyp_id, name=payload.name, positionen=payload.positionen ) return await _wartungsplan_read(db, plan) @router.get("/objekte/{objekt_id}/faellige-wartungen", response_model=list[FaelligeWartungRead]) async def hole_faellige_wartungen( objekt_id: int, db: AsyncSession = Depends(get_db), _=Depends(get_current_user) ) -> list[dict]: objekt = await db.get(Objekt, objekt_id) if objekt is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Objekt nicht gefunden") return await faellige_wartungen_fuer_objekt(db, objekt) @router.get("/wartungsauftraege", response_model=list[WartungsauftragRead]) async def liste_auftraege( objekt_id: int | None = None, status_filter: WartungsauftragStatus | None = None, db: AsyncSession = Depends(get_db), _=Depends(get_current_user), ) -> list[Wartungsauftrag]: return await liste_wartungsauftraege(db, objekt_id=objekt_id, status=status_filter) @router.post("/wartungsauftraege", response_model=WartungsauftragRead, status_code=status.HTTP_201_CREATED) async def erstelle_auftrag( payload: WartungsauftragCreate, db: AsyncSession = Depends(get_db), _=Depends(_verantwortliche) ) -> Wartungsauftrag: objekt = await db.get(Objekt, payload.objekt_id) if objekt is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Objekt nicht gefunden") return await erstelle_wartungsauftrag( db, objekt_id=payload.objekt_id, geraet_instanz_id=payload.geraet_instanz_id, wartungsplan_position_id=payload.wartungsplan_position_id, wartungsart=payload.wartungsart, beschreibung=payload.beschreibung, werkstatt_intern=payload.werkstatt_intern, werkstatt_name=payload.werkstatt_name, faelligkeit_am=payload.faelligkeit_am, ) @router.patch("/wartungsauftraege/{auftrag_id}/status", response_model=WartungsauftragRead) async def route_status_aendern( auftrag_id: uuid.UUID, payload: WartungsauftragStatusUpdate, db: AsyncSession = Depends(get_db), _=Depends(_verantwortliche), ) -> Wartungsauftrag: auftrag = await db.get(Wartungsauftrag, auftrag_id) if auftrag is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Wartungsauftrag nicht gefunden") return await aendere_status(db, auftrag=auftrag, status=payload.status) @router.post("/wartungsauftraege/{auftrag_id}/erledigen", response_model=WartungsauftragRead) async def route_erledigen( auftrag_id: uuid.UUID, payload: WartungsauftragErledigen, db: AsyncSession = Depends(get_db), current_user: Benutzer = Depends(_verantwortliche), ) -> Wartungsauftrag: auftrag = await db.get(Wartungsauftrag, auftrag_id) if auftrag is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Wartungsauftrag nicht gefunden") return await erledige_wartungsauftrag( db, auftrag=auftrag, benutzer_id=current_user.id, erledigt_am=payload.erledigt_am, kosten=payload.kosten, kilometerstand_bei_erledigung=payload.kilometerstand_bei_erledigung, betriebsstunden_bei_erledigung=payload.betriebsstunden_bei_erledigung, )