"""API schemas (Pydantic) for PreschoolPlanningDays. Schemas are the API boundary — they validate request bodies and shape responses, kept separate from the domain entity so the wire format can evolve independently. `PreschoolPlanningDaysResponse.default_for` builds a response for a (child, year) with no persisted row, using `Child.preschool_planning_days_per_year` as the planned figure and `taken_days=None` ("not recorded"). `is_default` tells the caller (frontend, or later the allocation engine) whether the figures are a real record or just the child's fallback default. """ from datetime import datetime from uuid import UUID from pydantic import BaseModel, Field from app.entities.child import Child from app.entities.preschool_planning_days import PreschoolPlanningDays class PreschoolPlanningDaysPlannedUpdate(BaseModel): planned_days: int = Field(ge=0, le=30) class PreschoolPlanningDaysTakenUpdate(BaseModel): taken_days: int = Field(ge=0, le=30) class PreschoolPlanningDaysResponse(BaseModel): id: UUID | None child_id: UUID year: int planned_days: int taken_days: int | None is_default: bool created_at: datetime | None updated_at: datetime | None @classmethod def from_entity(cls, entity: PreschoolPlanningDays) -> "PreschoolPlanningDaysResponse": return cls( id=entity.id, child_id=entity.child_id, year=entity.year, planned_days=entity.planned_days, taken_days=entity.taken_days, is_default=False, created_at=entity.created_at, updated_at=entity.updated_at, ) @classmethod def default_for(cls, child: Child, year: int) -> "PreschoolPlanningDaysResponse": """A (child, year) with no persisted row: fall back to the child's default.""" return cls( id=None, child_id=child.id, year=year, planned_days=child.preschool_planning_days_per_year, taken_days=None, is_default=True, created_at=None, updated_at=None, )