feat: implement scenario comparison validation and API endpoint with comprehensive unit tests
This commit is contained in:
@@ -9,8 +9,18 @@ from fastapi.templating import Jinja2Templates
|
||||
|
||||
from dependencies import get_unit_of_work
|
||||
from models import ResourceType, Scenario, ScenarioStatus
|
||||
from schemas.scenario import ScenarioCreate, ScenarioRead, ScenarioUpdate
|
||||
from services.exceptions import EntityConflictError, EntityNotFoundError
|
||||
from schemas.scenario import (
|
||||
ScenarioComparisonRequest,
|
||||
ScenarioComparisonResponse,
|
||||
ScenarioCreate,
|
||||
ScenarioRead,
|
||||
ScenarioUpdate,
|
||||
)
|
||||
from services.exceptions import (
|
||||
EntityConflictError,
|
||||
EntityNotFoundError,
|
||||
ScenarioValidationError,
|
||||
)
|
||||
from services.unit_of_work import UnitOfWork
|
||||
|
||||
router = APIRouter(tags=["Scenarios"])
|
||||
@@ -51,6 +61,53 @@ def list_scenarios_for_project(
|
||||
return [_to_read_model(scenario) for scenario in scenarios]
|
||||
|
||||
|
||||
@router.post(
|
||||
"/projects/{project_id}/scenarios/compare",
|
||||
response_model=ScenarioComparisonResponse,
|
||||
status_code=status.HTTP_200_OK,
|
||||
)
|
||||
def compare_scenarios(
|
||||
project_id: int,
|
||||
payload: ScenarioComparisonRequest,
|
||||
uow: UnitOfWork = Depends(get_unit_of_work),
|
||||
) -> ScenarioComparisonResponse:
|
||||
try:
|
||||
uow.projects.get(project_id)
|
||||
except EntityNotFoundError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
|
||||
) from exc
|
||||
|
||||
try:
|
||||
scenarios = uow.validate_scenarios_for_comparison(payload.scenario_ids)
|
||||
if any(scenario.project_id != project_id for scenario in scenarios):
|
||||
raise ScenarioValidationError(
|
||||
code="SCENARIO_PROJECT_MISMATCH",
|
||||
message="Selected scenarios do not belong to the same project.",
|
||||
scenario_ids=[
|
||||
scenario.id for scenario in scenarios if scenario.id is not None
|
||||
],
|
||||
)
|
||||
except EntityNotFoundError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_404_NOT_FOUND, detail=str(exc)
|
||||
) from exc
|
||||
except ScenarioValidationError as exc:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_422_UNPROCESSABLE_CONTENT,
|
||||
detail={
|
||||
"code": exc.code,
|
||||
"message": exc.message,
|
||||
"scenario_ids": list(exc.scenario_ids or []),
|
||||
},
|
||||
) from exc
|
||||
|
||||
return ScenarioComparisonResponse(
|
||||
project_id=project_id,
|
||||
scenarios=[_to_read_model(scenario) for scenario in scenarios],
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/projects/{project_id}/scenarios",
|
||||
response_model=ScenarioRead,
|
||||
|
||||
Reference in New Issue
Block a user