diff --git a/app/schemas/calendar.py b/app/schemas/calendar.py index 7bd166b..7d5c08e 100644 --- a/app/schemas/calendar.py +++ b/app/schemas/calendar.py @@ -9,10 +9,10 @@ BE-CAL-API-004: TimeSlot cancel schemas. from __future__ import annotations -from datetime import date, time, datetime +from datetime import date as dt_date, time as dt_time, datetime as dt_datetime from enum import Enum from pydantic import BaseModel, Field, model_validator, field_validator -from typing import Any, Optional +from typing import Optional # --------------------------------------------------------------------------- @@ -102,17 +102,17 @@ class SlotStatusEnum(str, Enum): class TimeSlotCreate(BaseModel): """Request body for creating a single calendar slot.""" - date: Optional[date] = Field(None, description="Target date (defaults to today)") + date: Optional[dt_date] = Field(None, description="Target date (defaults to today)") slot_type: SlotTypeEnum = Field(..., description="work | on_call | entertainment | system") - scheduled_at: time = Field(..., description="Planned start time HH:MM (00:00-23:00)") + scheduled_at: dt_time = Field(..., description="Planned start time HH:MM (00:00-23:00)") estimated_duration: int = Field(..., ge=1, le=50, description="Duration in minutes (1-50)") event_type: Optional[EventTypeEnum] = Field(None, description="job | entertainment | system_event") - event_data: Optional[dict[str, Any]] = Field(None, description="Event details JSON") + event_data: Optional[dict] = Field(None, description="Event details JSON") priority: int = Field(0, ge=0, le=99, description="Priority 0-99") @field_validator("scheduled_at") @classmethod - def _validate_scheduled_at(cls, v: time) -> time: + def _validate_scheduled_at(cls, v: dt_time) -> dt_time: if v.hour > 23: raise ValueError("scheduled_at hour must be between 00 and 23") return v @@ -132,7 +132,7 @@ class TimeSlotResponse(BaseModel): """Response for a single TimeSlot.""" id: int user_id: int - date: date + date: dt_date slot_type: str estimated_duration: int scheduled_at: str # HH:MM:SS ISO format @@ -140,12 +140,12 @@ class TimeSlotResponse(BaseModel): attended: bool actual_duration: Optional[int] = None event_type: Optional[str] = None - event_data: Optional[dict[str, Any]] = None + event_data: Optional[dict] = None priority: int status: str plan_id: Optional[int] = None - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None + created_at: Optional[dt_datetime] = None + updated_at: Optional[dt_datetime] = None class Config: from_attributes = True @@ -169,15 +169,15 @@ class TimeSlotEdit(BaseModel): ``virtual_id`` (for plan-generated virtual slots) in the URL path. """ slot_type: Optional[SlotTypeEnum] = Field(None, description="New slot type") - scheduled_at: Optional[time] = Field(None, description="New start time HH:MM") + scheduled_at: Optional[dt_time] = Field(None, description="New start time HH:MM") estimated_duration: Optional[int] = Field(None, ge=1, le=50, description="New duration in minutes (1-50)") event_type: Optional[EventTypeEnum] = Field(None, description="New event type") - event_data: Optional[dict[str, Any]] = Field(None, description="New event details JSON") + event_data: Optional[dict] = Field(None, description="New event details JSON") priority: Optional[int] = Field(None, ge=0, le=99, description="New priority 0-99") @field_validator("scheduled_at") @classmethod - def _validate_scheduled_at(cls, v: Optional[time]) -> Optional[time]: + def _validate_scheduled_at(cls, v: Optional[dt_time]) -> Optional[dt_time]: if v is not None and v.hour > 23: raise ValueError("scheduled_at hour must be between 00 and 23") return v @@ -214,7 +214,7 @@ class CalendarSlotItem(BaseModel): id: Optional[int] = Field(None, description="Real slot DB id (None for virtual)") virtual_id: Optional[str] = Field(None, description="Virtual slot id (None for real)") user_id: int - date: date + date: dt_date slot_type: str estimated_duration: int scheduled_at: str # HH:MM:SS ISO format @@ -222,12 +222,12 @@ class CalendarSlotItem(BaseModel): attended: bool actual_duration: Optional[int] = None event_type: Optional[str] = None - event_data: Optional[dict[str, Any]] = None + event_data: Optional[dict] = None priority: int status: str plan_id: Optional[int] = None - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None + created_at: Optional[dt_datetime] = None + updated_at: Optional[dt_datetime] = None class Config: from_attributes = True @@ -235,7 +235,7 @@ class CalendarSlotItem(BaseModel): class CalendarDayResponse(BaseModel): """Response for a single-day calendar query.""" - date: date + date: dt_date user_id: int slots: list[CalendarSlotItem] = Field( default_factory=list, @@ -290,16 +290,16 @@ class SchedulePlanCreate(BaseModel): """Request body for creating a recurring schedule plan.""" slot_type: SlotTypeEnum = Field(..., description="work | on_call | entertainment | system") estimated_duration: int = Field(..., ge=1, le=50, description="Duration in minutes (1-50)") - at_time: time = Field(..., description="Daily scheduled time (HH:MM)") + at_time: dt_time = Field(..., description="Daily scheduled time (HH:MM)") on_day: Optional[DayOfWeekEnum] = Field(None, description="Day of week (sun-sat)") on_week: Optional[int] = Field(None, ge=1, le=4, description="Week of month (1-4)") on_month: Optional[MonthOfYearEnum] = Field(None, description="Month (jan-dec)") event_type: Optional[EventTypeEnum] = Field(None, description="job | entertainment | system_event") - event_data: Optional[dict[str, Any]] = Field(None, description="Event details JSON") + event_data: Optional[dict] = Field(None, description="Event details JSON") @field_validator("at_time") @classmethod - def _validate_at_time(cls, v: time) -> time: + def _validate_at_time(cls, v: dt_time) -> dt_time: if v.hour > 23: raise ValueError("at_time hour must be between 00 and 23") return v @@ -325,10 +325,10 @@ class SchedulePlanResponse(BaseModel): on_week: Optional[int] = None on_month: Optional[str] = None event_type: Optional[str] = None - event_data: Optional[dict[str, Any]] = None + event_data: Optional[dict] = None is_active: bool - created_at: Optional[datetime] = None - updated_at: Optional[datetime] = None + created_at: Optional[dt_datetime] = None + updated_at: Optional[dt_datetime] = None class Config: from_attributes = True @@ -352,19 +352,19 @@ class SchedulePlanEdit(BaseModel): """ slot_type: Optional[SlotTypeEnum] = Field(None, description="New slot type") estimated_duration: Optional[int] = Field(None, ge=1, le=50, description="New duration in minutes (1-50)") - at_time: Optional[time] = Field(None, description="New daily time (HH:MM)") + at_time: Optional[dt_time] = Field(None, description="New daily time (HH:MM)") on_day: Optional[DayOfWeekEnum] = Field(None, description="New day of week (sun-sat), use 'clear' param to remove") on_week: Optional[int] = Field(None, ge=1, le=4, description="New week of month (1-4), use 'clear' param to remove") on_month: Optional[MonthOfYearEnum] = Field(None, description="New month (jan-dec), use 'clear' param to remove") event_type: Optional[EventTypeEnum] = Field(None, description="New event type") - event_data: Optional[dict[str, Any]] = Field(None, description="New event details JSON") + event_data: Optional[dict] = Field(None, description="New event details JSON") clear_on_day: bool = Field(False, description="Clear on_day (set to NULL)") clear_on_week: bool = Field(False, description="Clear on_week (set to NULL)") clear_on_month: bool = Field(False, description="Clear on_month (set to NULL)") @field_validator("at_time") @classmethod - def _validate_at_time(cls, v: Optional[time]) -> Optional[time]: + def _validate_at_time(cls, v: Optional[dt_time]) -> Optional[dt_time]: if v is not None and v.hour > 23: raise ValueError("at_time hour must be between 00 and 23") return v @@ -403,7 +403,7 @@ class DateListResponse(BaseModel): Returns only dates that have at least one materialized (real) future slot. Pure plan-generated (virtual) dates are excluded. """ - dates: list[date] = Field( + dates: list[dt_date] = Field( default_factory=list, description="Sorted list of future dates with materialized slots", )