from fastapi import APIRouter, Depends, Header, HTTPException, Query, status from sqlalchemy.orm import Session from starlette.requests import Request from typing import cast from app.core.config import settings from app.core.rbac import require_permission from app.db.database import get_db from app.models.repair import Repair from app.models.user import User from app.repositories.repair_repository import RepairRepository from app.schemas.repair import ( RepairCreate, RepairIntakePayload, RepairIntakeResponse, RepairListResponse, RepairResponse, RepairStatus, RepairStatusHistoryResponse, RepairStatusUpdate, RepairUpdate, ) from app.services.repair_service import RepairService router = APIRouter(tags=["Repairs"]) def get_repair_or_404(db: Session, repair_id: int) -> Repair: repair = RepairRepository.get_by_id(db, repair_id) if repair is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Reparatur nicht gefunden") return repair @router.get("/repairs", response_model=RepairListResponse) @router.get("/repairs/", response_model=RepairListResponse, include_in_schema=False) def get_repairs( status_filter: str | None = Query(default=None, alias="status"), q: str | None = None, customer_id: int | None = None, source: str | None = None, priority: str | None = None, limit: int = Query(default=50, ge=1, le=100), offset: int = Query(default=0, ge=0), db: Session = Depends(get_db), current_user: User = Depends(require_permission("repairs.read")), ): items, total = RepairRepository.list( db, status=status_filter, q=q, customer_id=customer_id, source=source, priority=priority, limit=limit, offset=offset, ) return RepairListResponse(items=items, total=total, limit=limit, offset=offset) @router.get("/repairs/{repair_id}", response_model=RepairResponse) def get_repair( repair_id: int, db: Session = Depends(get_db), current_user: User = Depends(require_permission("repairs.read")), ): return get_repair_or_404(db, repair_id) @router.post("/repairs", response_model=RepairResponse, status_code=status.HTTP_201_CREATED) @router.post("/repairs/", response_model=RepairResponse, status_code=status.HTTP_201_CREATED, include_in_schema=False) def create_repair( repair: RepairCreate, request: Request, db: Session = Depends(get_db), current_user: User = Depends(require_permission("repairs.create")), ): return RepairService.create(db, repair, actor=current_user, request=request) @router.put("/repairs/{repair_id}", response_model=RepairResponse) def update_repair( repair_id: int, repair: RepairUpdate, request: Request, db: Session = Depends(get_db), current_user: User = Depends(require_permission("repairs.update")), ): db_repair = get_repair_or_404(db, repair_id) return RepairService.update(db, db_repair, repair, actor=current_user, request=request) @router.delete("/repairs/{repair_id}", response_model=RepairResponse) def delete_repair( repair_id: int, request: Request, db: Session = Depends(get_db), current_user: User = Depends(require_permission("repairs.delete")), ): db_repair = get_repair_or_404(db, repair_id) return RepairService.cancel(db, db_repair, actor=current_user, request=request) @router.put("/repairs/{repair_id}/status", response_model=RepairResponse) def update_repair_status( repair_id: int, payload: RepairStatusUpdate, request: Request, db: Session = Depends(get_db), current_user: User = Depends(require_permission("repairs.status.update")), ): db_repair = get_repair_or_404(db, repair_id) return RepairService.update_status(db, db_repair, payload, actor=current_user, request=request) @router.get("/repairs/{repair_id}/history", response_model=list[RepairStatusHistoryResponse]) def get_repair_history( repair_id: int, db: Session = Depends(get_db), current_user: User = Depends(require_permission("repairs.read")), ): get_repair_or_404(db, repair_id) return RepairRepository.get_history(db, repair_id) @router.post("/public/repair-intake", response_model=RepairIntakeResponse, status_code=status.HTTP_201_CREATED) def create_repair_intake( payload: RepairIntakePayload, request: Request, x_olympus_intake_token: str | None = Header(default=None, alias="X-Olympus-Intake-Token"), db: Session = Depends(get_db), ): expected_token = settings.olympus_repair_intake_token if not expected_token or not x_olympus_intake_token or x_olympus_intake_token != expected_token: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Nicht autorisiert") repair = RepairService.create_from_intake(db, payload, request=request) return RepairIntakeResponse( repair_number=repair.repair_number, status=cast(RepairStatus, repair.status), message="Reparaturanfrage übernommen", )