from datetime import datetime from sqlalchemy import Boolean, DateTime, ForeignKey, Integer, String, Text, func from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.base import Base class ChatSession(Base): __tablename__ = "chat_sessions" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) title: Mapped[str] = mapped_column(String(255), default="Новый чат") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now() ) messages: Mapped[list["Message"]] = relationship( back_populates="session", cascade="all, delete-orphan", order_by="Message.created_at" ) class Message(Base): __tablename__ = "messages" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) session_id: Mapped[int] = mapped_column(ForeignKey("chat_sessions.id", ondelete="CASCADE"), index=True) role: Mapped[str] = mapped_column(String(32)) content: Mapped[str] = mapped_column(Text, default="") tool_calls_json: Mapped[str | None] = mapped_column(Text, nullable=True) tool_call_id: Mapped[str | None] = mapped_column(String(64), nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) session: Mapped["ChatSession"] = relationship(back_populates="messages") class PomodoroCycle(Base): __tablename__ = "pomodoro_cycles" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) work_duration_min: Mapped[int] = mapped_column(Integer, default=25) short_break_min: Mapped[int] = mapped_column(Integer, default=5) long_break_min: Mapped[int] = mapped_column(Integer, default=15) sessions_until_long_break: Mapped[int] = mapped_column(Integer, default=4) completed_work_sessions: Mapped[int] = mapped_column(Integer, default=0) task_note: Mapped[str] = mapped_column(Text, default="") auto_advance: Mapped[bool] = mapped_column(Boolean, default=True) chat_notify_seq: Mapped[int] = mapped_column(Integer, default=0) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now() ) class PomodoroSession(Base): __tablename__ = "pomodoro_sessions" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) status: Mapped[str] = mapped_column(String(32), default="idle") phase: Mapped[str] = mapped_column(String(32), default="work") duration_min: Mapped[int] = mapped_column(Integer, default=25) task_note: Mapped[str] = mapped_column(Text, default="") result: Mapped[str | None] = mapped_column(Text, nullable=True) completed: Mapped[bool] = mapped_column(Boolean, default=False) completion_notified: Mapped[bool] = mapped_column(Boolean, default=False) started_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) paused_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) elapsed_seconds: Mapped[int] = mapped_column(Integer, default=0) finished_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) class TaigaProject(Base): __tablename__ = "taiga_projects" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) taiga_id: Mapped[int] = mapped_column(Integer, unique=True, index=True) name: Mapped[str] = mapped_column(String(255)) slug: Mapped[str] = mapped_column(String(255), unique=True, index=True) synced_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) class ProjectBinding(Base): __tablename__ = "project_bindings" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) taiga_slug: Mapped[str] = mapped_column(String(255), unique=True, index=True) gitea_owner: Mapped[str] = mapped_column(String(255), default="") gitea_repo: Mapped[str] = mapped_column(String(255), default="") default_branch: Mapped[str] = mapped_column(String(64), default="main") updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now() ) class WorkItem(Base): __tablename__ = "work_items" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) taiga_slug: Mapped[str] = mapped_column(String(255), index=True) taiga_project_id: Mapped[int] = mapped_column(Integer) taiga_story_id: Mapped[int] = mapped_column(Integer) taiga_story_ref: Mapped[int] = mapped_column(Integer, index=True) gitea_owner: Mapped[str] = mapped_column(String(255), default="") gitea_repo: Mapped[str] = mapped_column(String(255), default="") gitea_issue_number: Mapped[int | None] = mapped_column(Integer, nullable=True, index=True) suggested_branch: Mapped[str] = mapped_column(String(255), default="") raw_text: Mapped[str] = mapped_column(Text, default="") title: Mapped[str] = mapped_column(String(500), default="") status: Mapped[str] = mapped_column(String(32), default="open") created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) closed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)