from __future__ import annotations from typing import List from fastapi import APIRouter, Depends, HTTPException, status from dependencies import get_unit_of_work from models import Scenario from schemas.scenario import ScenarioCreate, ScenarioRead, ScenarioUpdate from services.exceptions import EntityConflictError, EntityNotFoundError from services.unit_of_work import UnitOfWork router = APIRouter(tags=["Scenarios"]) def _to_read_model(scenario: Scenario) -> ScenarioRead: return ScenarioRead.model_validate(scenario) @router.get( "/projects/{project_id}/scenarios", response_model=List[ScenarioRead], ) def list_scenarios_for_project( project_id: int, uow: UnitOfWork = Depends(get_unit_of_work) ) -> List[ScenarioRead]: try: uow.projects.get(project_id) except EntityNotFoundError as exc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc scenarios = uow.scenarios.list_for_project(project_id) return [_to_read_model(scenario) for scenario in scenarios] @router.post( "/projects/{project_id}/scenarios", response_model=ScenarioRead, status_code=status.HTTP_201_CREATED, ) def create_scenario_for_project( project_id: int, payload: ScenarioCreate, uow: UnitOfWork = Depends(get_unit_of_work), ) -> ScenarioRead: try: uow.projects.get(project_id) except EntityNotFoundError as exc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc scenario = Scenario(project_id=project_id, **payload.model_dump()) try: created = uow.scenarios.create(scenario) except EntityConflictError as exc: raise HTTPException( status_code=status.HTTP_409_CONFLICT, detail=str(exc)) from exc return _to_read_model(created) @router.get("/scenarios/{scenario_id}", response_model=ScenarioRead) def get_scenario( scenario_id: int, uow: UnitOfWork = Depends(get_unit_of_work) ) -> ScenarioRead: try: scenario = uow.scenarios.get(scenario_id) except EntityNotFoundError as exc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc return _to_read_model(scenario) @router.put("/scenarios/{scenario_id}", response_model=ScenarioRead) def update_scenario( scenario_id: int, payload: ScenarioUpdate, uow: UnitOfWork = Depends(get_unit_of_work), ) -> ScenarioRead: try: scenario = uow.scenarios.get(scenario_id) except EntityNotFoundError as exc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc update_data = payload.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(scenario, field, value) uow.flush() return _to_read_model(scenario) @router.delete("/scenarios/{scenario_id}", status_code=status.HTTP_204_NO_CONTENT) def delete_scenario( scenario_id: int, uow: UnitOfWork = Depends(get_unit_of_work) ) -> None: try: uow.scenarios.delete(scenario_id) except EntityNotFoundError as exc: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)) from exc