from __future__ import annotations from datetime import date, datetime from pydantic import BaseModel, ConfigDict, field_validator, model_validator from models import ResourceType, ScenarioStatus class ScenarioBase(BaseModel): name: str description: str | None = None status: ScenarioStatus = ScenarioStatus.DRAFT start_date: date | None = None end_date: date | None = None discount_rate: float | None = None currency: str | None = None primary_resource: ResourceType | None = None model_config = ConfigDict(extra="forbid") @field_validator("currency") @classmethod def normalise_currency(cls, value: str | None) -> str | None: if value is None: return value value = value.upper() if len(value) != 3: raise ValueError("Currency code must be a 3-letter ISO value") return value class ScenarioCreate(ScenarioBase): pass class ScenarioUpdate(BaseModel): name: str | None = None description: str | None = None status: ScenarioStatus | None = None start_date: date | None = None end_date: date | None = None discount_rate: float | None = None currency: str | None = None primary_resource: ResourceType | None = None model_config = ConfigDict(extra="forbid") @field_validator("currency") @classmethod def normalise_currency(cls, value: str | None) -> str | None: if value is None: return value value = value.upper() if len(value) != 3: raise ValueError("Currency code must be a 3-letter ISO value") return value class ScenarioRead(ScenarioBase): id: int project_id: int created_at: datetime updated_at: datetime model_config = ConfigDict(from_attributes=True) class ScenarioComparisonRequest(BaseModel): scenario_ids: list[int] model_config = ConfigDict(extra="forbid") @model_validator(mode="after") def ensure_minimum_ids(self) -> "ScenarioComparisonRequest": unique_ids: list[int] = list(dict.fromkeys(self.scenario_ids)) if len(unique_ids) < 2: raise ValueError("At least two unique scenario identifiers are required for comparison.") self.scenario_ids = unique_ids return self class ScenarioComparisonResponse(BaseModel): project_id: int scenarios: list[ScenarioRead] model_config = ConfigDict(from_attributes=True)