"""Модель пользователя.""" from datetime import datetime from typing import TYPE_CHECKING from sqlalchemy import String, func from sqlalchemy.orm import Mapped, mapped_column, relationship from app.database import Base if TYPE_CHECKING: from app.models.document import UsageLog from app.models.task import Task class User(Base): """Пользователь системы.""" __tablename__ = "users" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) email: Mapped[str] = mapped_column(String(255), unique=True, index=True, nullable=False) # Nullable: пользователи, вошедшие через OAuth, пароля не заводят hashed_password: Mapped[str | None] = mapped_column(String(255), nullable=True) name: Mapped[str] = mapped_column(String(255), nullable=False) # OAuth-провайдер ("google" / "yandex") и id пользователя у провайдера. # Пара уникальна (см. миграцию 004) — один аккаунт провайдера не привязать дважды. oauth_provider: Mapped[str | None] = mapped_column(String(20), nullable=True) oauth_id: Mapped[str | None] = mapped_column(String(255), nullable=True) is_verified: Mapped[bool] = mapped_column(default=False) # Администратор системы (доступ к админ-панели) is_admin: Mapped[bool] = mapped_column(default=False) # Тарифный план: free / student / premium / science plan: Mapped[str] = mapped_column(String(20), default="free") verification_token: Mapped[str | None] = mapped_column(String(255), nullable=True) created_at: Mapped[datetime] = mapped_column(server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( server_default=func.now(), onupdate=func.now(), ) # Связи tasks: Mapped[list["Task"]] = relationship(back_populates="user", lazy="select") usage: Mapped[list["UsageLog"]] = relationship(back_populates="user", lazy="select") def __repr__(self) -> str: return f""