diff --git a/backend/app/api/v1/endpoints/stammdaten.py b/backend/app/api/v1/endpoints/stammdaten.py index 88ca18b..d11cba1 100644 --- a/backend/app/api/v1/endpoints/stammdaten.py +++ b/backend/app/api/v1/endpoints/stammdaten.py @@ -1,6 +1,5 @@ from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import func, select -from sqlalchemy.exc import IntegrityError from sqlalchemy.ext.asyncio import AsyncSession from app.api.deps import get_current_user, require_roles, require_roles_or_permission @@ -96,12 +95,17 @@ async def erstelle_hersteller( db: AsyncSession = Depends(get_db), _=Depends(require_roles(RolleTyp.administration)), ) -> Hersteller: + # Explizit vorab prüfen statt sich auf den UNIQUE-Constraint zu verlassen: + # ein Flush-Fehlschlag hinterlässt die Session im Zustand DEACTIVE + # (SQLAlchemy 2.0), was in einer über mehrere Requests geteilten Session + # (z.B. Testsuite) jeden folgenden Request mit PendingRollbackError zum + # Absturz bringt (gleicher Fund wie bei geraet_instanz.py::erstelle). + bestehender = await db.execute(select(Hersteller).where(Hersteller.name == payload.name)) + if bestehender.scalar_one_or_none() is not None: + raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Hersteller existiert bereits") hersteller = Hersteller(**payload.model_dump()) db.add(hersteller) - try: - await db.flush() - except IntegrityError as exc: - raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Hersteller existiert bereits") from exc + await db.flush() return hersteller @@ -126,12 +130,14 @@ async def erstelle_modell( ) -> Modell: if await db.get(Hersteller, payload.hersteller_id) is None: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Hersteller nicht gefunden") + bestehendes = await db.execute( + select(Modell).where(Modell.hersteller_id == payload.hersteller_id, Modell.name == payload.name) + ) + if bestehendes.scalar_one_or_none() is not None: + raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Modell existiert bereits") modell = Modell(**payload.model_dump()) db.add(modell) - try: - await db.flush() - except IntegrityError as exc: - raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="Modell existiert bereits") from exc + await db.flush() return modell