""" Pydantic схемы для валидации данных API """ from pydantic import BaseModel, Field, ConfigDict from typing import Optional from datetime import datetime # Базовые схемы для пользователей class UserBase(BaseModel): """Базовая схема пользователя""" telegram_id: int = Field(..., description="Telegram ID пользователя") username: Optional[str] = Field(None, max_length=255, description="Username в Telegram") first_name: Optional[str] = Field(None, max_length=255, description="Имя пользователя") last_name: Optional[str] = Field(None, max_length=255, description="Фамилия пользователя") language_code: str = Field(default="ru", max_length=10, description="Код языка") class UserCreate(UserBase): """Схема для создания пользователя""" pass class UserUpdate(BaseModel): """Схема для обновления пользователя""" username: Optional[str] = Field(None, max_length=255) first_name: Optional[str] = Field(None, max_length=255) last_name: Optional[str] = Field(None, max_length=255) language_code: Optional[str] = Field(None, max_length=10) is_active: Optional[bool] = None class UserResponse(UserBase): """Схема ответа с данными пользователя""" model_config = ConfigDict(from_attributes=True) id: int is_active: bool is_admin: bool created_at: datetime updated_at: Optional[datetime] = None # Базовые схемы для сообщений class MessageBase(BaseModel): """Базовая схема сообщения""" telegram_message_id: int = Field(..., description="ID сообщения в Telegram") user_id: int = Field(..., description="ID пользователя в нашей БД") text: Optional[str] = Field(None, description="Текст сообщения") message_type: str = Field(default="text", max_length=50, description="Тип сообщения") class MessageCreate(MessageBase): """Схема для создания сообщения""" pass class MessageResponse(MessageBase): """Схема ответа с данными сообщения""" model_config = ConfigDict(from_attributes=True) id: int created_at: datetime # Базовые схемы для настроек бота class BotSettingBase(BaseModel): """Базовая схема настройки бота""" key: str = Field(..., max_length=255, description="Ключ настройки") value: Optional[str] = Field(None, description="Значение настройки") description: Optional[str] = Field(None, description="Описание настройки") class BotSettingCreate(BotSettingBase): """Схема для создания настройки""" pass class BotSettingUpdate(BaseModel): """Схема для обновления настройки""" value: Optional[str] = None description: Optional[str] = None class BotSettingResponse(BotSettingBase): """Схема ответа с данными настройки""" model_config = ConfigDict(from_attributes=True) id: int created_at: datetime updated_at: Optional[datetime] = None # Схемы для общих ответов API class MessageResponseModel(BaseModel): """Общая схема ответа с сообщением""" message: str status: str = "success" class ErrorResponse(BaseModel): """Схема ответа с ошибкой""" detail: str status: str = "error" class HealthCheckResponse(BaseModel): """Схема ответа проверки здоровья""" status: str database: str class RootResponse(BaseModel): """Схема корневого ответа""" message: str version: str status: str # Схемы для пагинации class PaginationParams(BaseModel): """Параметры пагинации""" limit: int = Field(default=100, ge=1, le=1000, description="Количество элементов на странице") offset: int = Field(default=0, ge=0, description="Смещение") class PaginatedResponse(BaseModel): """Схема ответа с пагинацией""" items: list total: int limit: int offset: int has_next: bool has_prev: bool # Схемы для работы с тестами class TestCategoryCreate(BaseModel): """Схема для создания категории тестов""" name: str = Field(..., max_length=100, description="Название категории") description: Optional[str] = Field(None, description="Описание категории") class TestCategoryResponse(BaseModel): """Схема ответа с категорией тестов""" model_config = ConfigDict(from_attributes=True) id: int name: str description: Optional[str] created_at: datetime class TestCreate(BaseModel): """Схема для создания теста""" title: str = Field(..., max_length=200, description="Название теста") description: Optional[str] = Field(None, description="Описание теста") category_id: Optional[int] = Field(None, description="ID категории") is_active: bool = Field(default=True, description="Активен ли тест") time_limit_minutes: Optional[int] = Field(None, ge=1, description="Лимит времени в минутах") class TestResponse(BaseModel): """Схема ответа с тестом""" model_config = ConfigDict(from_attributes=True) id: int title: str description: Optional[str] category_id: Optional[int] is_active: bool time_limit_minutes: Optional[int] created_at: datetime updated_at: Optional[datetime] class QuestionCreate(BaseModel): """Схема для создания вопроса""" test_id: int = Field(..., description="ID теста") question_text: str = Field(..., description="Текст вопроса") question_type: str = Field(default="single_choice", description="Тип вопроса") order_number: int = Field(..., ge=1, description="Порядковый номер вопроса") points: int = Field(default=1, ge=0, description="Количество баллов за правильный ответ") image_id: Optional[int] = Field(None, description="ID изображения к вопросу") class QuestionResponse(BaseModel): """Схема ответа с вопросом""" model_config = ConfigDict(from_attributes=True) id: int test_id: int question_text: str question_type: str order_number: int points: int image_id: Optional[int] created_at: datetime class AnswerOptionCreate(BaseModel): """Схема для создания варианта ответа""" question_id: int = Field(..., description="ID вопроса") option_text: str = Field(..., description="Текст варианта ответа") is_correct: bool = Field(..., description="Правильный ли этот вариант") order_number: int = Field(..., ge=1, description="Порядковый номер варианта") class AnswerOptionResponse(BaseModel): """Схема ответа с вариантом ответа""" model_config = ConfigDict(from_attributes=True) id: int question_id: int option_text: str is_correct: bool order_number: int created_at: datetime class ImageUploadResponse(BaseModel): """Схема ответа при загрузке изображения""" id: int filename: str content_type: str file_size: int message: str = "Изображение успешно загружено"