from typing import Annotated from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession from app.core.deps import get_session, get_tenant_context, require_min_role from app.crud.bed import crud_bed from app.crud.planting import crud_planting from app.models.user import TenantRole from app.schemas.planting import PlantingCreate, PlantingRead, PlantingUpdate router = APIRouter(tags=["Bepflanzungen"]) TenantCtx = Annotated[tuple, Depends(get_tenant_context)] WriteCtx = Annotated[tuple, Depends(require_min_role(TenantRole.READ_WRITE))] async def _get_bed_or_404(db: AsyncSession, bed_id: UUID, tenant_id: UUID): bed = await crud_bed.get(db, id=bed_id) if not bed or bed.tenant_id != tenant_id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Beet nicht gefunden.") return bed @router.get("/beds/{bed_id}/plantings", response_model=list[PlantingRead]) async def list_plantings( bed_id: UUID, db: Annotated[AsyncSession, Depends(get_session)], ctx: TenantCtx, ) -> list[PlantingRead]: _, tenant_id = ctx await _get_bed_or_404(db, bed_id, tenant_id) plantings = await crud_planting.get_multi_for_bed(db, bed_id=bed_id) return [PlantingRead.model_validate(p) for p in plantings] @router.post("/beds/{bed_id}/plantings", response_model=PlantingRead, status_code=status.HTTP_201_CREATED) async def create_planting( bed_id: UUID, body: PlantingCreate, db: Annotated[AsyncSession, Depends(get_session)], ctx: WriteCtx, ) -> PlantingRead: _, tenant_id, _ = ctx await _get_bed_or_404(db, bed_id, tenant_id) planting = await crud_planting.create_for_bed(db, obj_in=body, bed_id=bed_id) return PlantingRead.model_validate(planting) @router.put("/plantings/{planting_id}", response_model=PlantingRead) async def update_planting( planting_id: UUID, body: PlantingUpdate, db: Annotated[AsyncSession, Depends(get_session)], ctx: WriteCtx, ) -> PlantingRead: _, tenant_id, _ = ctx planting = await crud_planting.get(db, id=planting_id) if not planting: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bepflanzung nicht gefunden.") await _get_bed_or_404(db, planting.bed_id, tenant_id) updated = await crud_planting.update(db, db_obj=planting, obj_in=body) return PlantingRead.model_validate(updated) @router.delete("/plantings/{planting_id}", status_code=status.HTTP_204_NO_CONTENT) async def delete_planting( planting_id: UUID, db: Annotated[AsyncSession, Depends(get_session)], ctx: WriteCtx, ) -> None: _, tenant_id, _ = ctx planting = await crud_planting.get(db, id=planting_id) if not planting: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Bepflanzung nicht gefunden.") await _get_bed_or_404(db, planting.bed_id, tenant_id) await crud_planting.remove(db, id=planting_id)