280 lines
13 KiB
Python
280 lines
13 KiB
Python
from datetime import datetime
|
|
|
|
from sqlalchemy import Boolean, DateTime, Float, 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 UserProfile(Base):
|
|
__tablename__ = "user_profile"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
data_json: Mapped[str] = mapped_column(Text, default="{}")
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
|
|
|
|
class MemoryFact(Base):
|
|
__tablename__ = "memory_facts"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
category: Mapped[str] = mapped_column(String(64), default="fact", index=True)
|
|
content: Mapped[str] = mapped_column(Text)
|
|
source: Mapped[str] = mapped_column(String(32), default="user")
|
|
session_id: Mapped[int | None] = mapped_column(
|
|
ForeignKey("chat_sessions.id", ondelete="SET NULL"), nullable=True, index=True
|
|
)
|
|
importance: Mapped[int] = mapped_column(Integer, default=3)
|
|
active: Mapped[bool] = mapped_column(Boolean, default=True, index=True)
|
|
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()
|
|
)
|
|
|
|
|
|
class SessionSummary(Base):
|
|
__tablename__ = "session_summaries"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
session_id: Mapped[int] = mapped_column(
|
|
ForeignKey("chat_sessions.id", ondelete="CASCADE"), unique=True, index=True
|
|
)
|
|
summary: Mapped[str] = mapped_column(Text, default="")
|
|
message_count: Mapped[int] = mapped_column(Integer, default=0)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
|
|
|
|
class FitnessProfile(Base):
|
|
__tablename__ = "fitness_profiles"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
sex: Mapped[str] = mapped_column(String(16), default="male")
|
|
age: Mapped[int] = mapped_column(Integer, default=30)
|
|
height_cm: Mapped[float] = mapped_column(Float, default=170.0)
|
|
weight_kg: Mapped[float] = mapped_column(Float, default=70.0)
|
|
activity_level: Mapped[str] = mapped_column(String(32), default="moderate")
|
|
goal: Mapped[str] = mapped_column(String(32), default="maintain")
|
|
target_weight_kg: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
weekly_workouts: Mapped[int] = mapped_column(Integer, default=3)
|
|
calorie_target: Mapped[float] = mapped_column(Float, default=2000.0)
|
|
protein_g: Mapped[float] = mapped_column(Float, default=140.0)
|
|
fat_g: Mapped[float] = mapped_column(Float, default=65.0)
|
|
carbs_g: Mapped[float] = mapped_column(Float, default=200.0)
|
|
water_l: Mapped[float] = mapped_column(Float, default=2.5)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
|
|
)
|
|
|
|
|
|
class BodyMetric(Base):
|
|
__tablename__ = "body_metrics"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
recorded_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
weight_kg: Mapped[float] = mapped_column(Float)
|
|
body_fat_pct: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
chest_cm: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
waist_cm: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
notes: Mapped[str] = mapped_column(Text, default="")
|
|
|
|
|
|
class FoodLog(Base):
|
|
__tablename__ = "food_logs"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
logged_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
meal_type: Mapped[str] = mapped_column(String(32), default="snack")
|
|
description: Mapped[str] = mapped_column(Text, default="")
|
|
calories: Mapped[float] = mapped_column(Float, default=0)
|
|
protein_g: Mapped[float] = mapped_column(Float, default=0)
|
|
fat_g: Mapped[float] = mapped_column(Float, default=0)
|
|
carbs_g: Mapped[float] = mapped_column(Float, default=0)
|
|
source: Mapped[str] = mapped_column(String(32), default="llm")
|
|
estimated: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
|
|
|
|
class WaterLog(Base):
|
|
__tablename__ = "water_logs"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
logged_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
amount_ml: Mapped[int] = mapped_column(Integer)
|
|
|
|
|
|
class WorkoutLog(Base):
|
|
__tablename__ = "workout_logs"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
logged_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
title: Mapped[str] = mapped_column(String(255), default="Тренировка")
|
|
notes: Mapped[str] = mapped_column(Text, default="")
|
|
duration_min: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
exercises_json: Mapped[str] = mapped_column(Text, default="[]")
|
|
|
|
|
|
class FitnessReminder(Base):
|
|
__tablename__ = "fitness_reminders"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
kind: Mapped[str] = mapped_column(String(32))
|
|
hour: Mapped[int] = mapped_column(Integer, default=12)
|
|
minute: Mapped[int] = mapped_column(Integer, default=0)
|
|
interval_hours: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
enabled: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
last_fired_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
|
|
|
|
class ShoppingList(Base):
|
|
__tablename__ = "shopping_lists"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
name: Mapped[str] = mapped_column(String(255), unique=True, index=True)
|
|
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
|
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()
|
|
)
|
|
|
|
items: Mapped[list["ShoppingListItem"]] = relationship(
|
|
back_populates="shopping_list",
|
|
cascade="all, delete-orphan",
|
|
order_by="ShoppingListItem.sort_order, ShoppingListItem.id",
|
|
)
|
|
|
|
|
|
class ShoppingListItem(Base):
|
|
__tablename__ = "shopping_list_items"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
list_id: Mapped[int] = mapped_column(
|
|
ForeignKey("shopping_lists.id", ondelete="CASCADE"), index=True
|
|
)
|
|
text: Mapped[str] = mapped_column(String(500))
|
|
quantity: Mapped[float | None] = mapped_column(Float, nullable=True)
|
|
unit: Mapped[str] = mapped_column(String(64), default="")
|
|
checked: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
|
|
sort_order: Mapped[int] = mapped_column(Integer, default=0)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
shopping_list: Mapped["ShoppingList"] = relationship(back_populates="items")
|
|
|
|
|
|
class AssistantState(Base):
|
|
__tablename__ = "assistant_state"
|
|
|
|
key: Mapped[str] = mapped_column(String(128), primary_key=True)
|
|
value: Mapped[str] = mapped_column(Text, default="")
|
|
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)
|