MicroFish/backend/app/models/db_models.py

246 lines
11 KiB
Python

# backend/app/models/db_models.py
"""Models SQLAlchemy per a tota la persistència de MiroFish."""
import uuid
from datetime import datetime, timezone
from typing import Optional
from sqlalchemy import (
String, Integer, Text, Boolean, DateTime, JSON,
ForeignKey
)
from sqlalchemy.orm import Mapped, mapped_column, relationship
from ..db import Base
def _uuid() -> str:
return str(uuid.uuid4())
def _now() -> datetime:
return datetime.now(timezone.utc)
class UserModel(Base):
__tablename__ = "users"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
email: Mapped[str] = mapped_column(String(255), unique=True, nullable=False)
name: Mapped[str] = mapped_column(String(255), nullable=False, default="")
password_hash: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
role: Mapped[str] = mapped_column(String(20), nullable=False, default="user")
status: Mapped[str] = mapped_column(String(20), nullable=False, default="pending")
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=_now, onupdate=_now)
projects: Mapped[list["ProjectModel"]] = relationship(
back_populates="owner", cascade="all, delete-orphan"
)
invitation_tokens: Mapped[list["InvitationTokenModel"]] = relationship(
back_populates="user", cascade="all, delete-orphan"
)
password_reset_tokens: Mapped[list["PasswordResetTokenModel"]] = relationship(
back_populates="user", cascade="all, delete-orphan"
)
class ProjectModel(Base):
__tablename__ = "projects"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
user_id: Mapped[Optional[str]] = mapped_column(
String(36), ForeignKey("users.id", ondelete="CASCADE"), nullable=True
)
name: Mapped[str] = mapped_column(String(255), nullable=False, default="Unnamed Project")
status: Mapped[str] = mapped_column(String(50), nullable=False, default="created")
analysis_summary: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
simulation_requirement: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
chunk_size: Mapped[int] = mapped_column(Integer, default=500)
chunk_overlap: Mapped[int] = mapped_column(Integer, default=50)
active_task_id: Mapped[Optional[str]] = mapped_column(
String(36), ForeignKey("tasks.id", ondelete="SET NULL"), nullable=True
)
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=_now, onupdate=_now)
owner: Mapped[Optional["UserModel"]] = relationship(back_populates="projects")
files: Mapped[list["ProjectFileModel"]] = relationship(
back_populates="project", cascade="all, delete-orphan"
)
ontologies: Mapped[list["OntologyModel"]] = relationship(
back_populates="project", cascade="all, delete-orphan"
)
graphs: Mapped[list["GraphModel"]] = relationship(
back_populates="project", cascade="all, delete-orphan"
)
simulations: Mapped[list["SimulationModel"]] = relationship(
back_populates="project", cascade="all, delete-orphan"
)
reports: Mapped[list["ReportModel"]] = relationship(
back_populates="project", cascade="all, delete-orphan"
)
class ProjectFileModel(Base):
__tablename__ = "project_files"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
project_id: Mapped[str] = mapped_column(
String(36), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False
)
original_name: Mapped[str] = mapped_column(String(255), nullable=False)
storage_path: Mapped[str] = mapped_column(Text, nullable=False)
size: Mapped[int] = mapped_column(Integer, default=0)
mime_type: Mapped[str] = mapped_column(String(100), default="application/octet-stream")
file_type: Mapped[str] = mapped_column(String(30), default="upload") # upload | extracted_text
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
project: Mapped["ProjectModel"] = relationship(back_populates="files")
class OntologyModel(Base):
__tablename__ = "ontologies"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
project_id: Mapped[str] = mapped_column(
String(36), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False
)
version: Mapped[int] = mapped_column(Integer, default=1)
entity_types: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
edge_types: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
project: Mapped["ProjectModel"] = relationship(back_populates="ontologies")
graphs: Mapped[list["GraphModel"]] = relationship(back_populates="ontology")
class GraphModel(Base):
__tablename__ = "graphs"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
project_id: Mapped[str] = mapped_column(
String(36), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False
)
ontology_id: Mapped[Optional[str]] = mapped_column(
String(36), ForeignKey("ontologies.id", ondelete="SET NULL"), nullable=True
)
backend: Mapped[str] = mapped_column(String(20), default="zep") # zep | graphiti
external_id: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
status: Mapped[str] = mapped_column(String(20), default="building") # building | ready | failed
node_count: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
edge_count: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=_now, onupdate=_now)
project: Mapped["ProjectModel"] = relationship(back_populates="graphs")
ontology: Mapped[Optional["OntologyModel"]] = relationship(back_populates="graphs")
simulations: Mapped[list["SimulationModel"]] = relationship(back_populates="graph")
reports: Mapped[list["ReportModel"]] = relationship(back_populates="graph")
class SimulationModel(Base):
__tablename__ = "simulations"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
project_id: Mapped[str] = mapped_column(
String(36), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False
)
graph_id: Mapped[Optional[str]] = mapped_column(
String(36), ForeignKey("graphs.id", ondelete="SET NULL"), nullable=True
)
status: Mapped[str] = mapped_column(String(30), default="prepared")
platform: Mapped[str] = mapped_column(String(20), default="twitter") # twitter | reddit | both
config: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
profiles_path: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
db_path: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
actions_path: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
rounds_total: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
rounds_completed: Mapped[int] = mapped_column(Integer, default=0)
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=_now, onupdate=_now)
project: Mapped["ProjectModel"] = relationship(back_populates="simulations")
graph: Mapped[Optional["GraphModel"]] = relationship(back_populates="simulations")
reports: Mapped[list["ReportModel"]] = relationship(back_populates="simulation")
class ReportModel(Base):
__tablename__ = "reports"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
project_id: Mapped[str] = mapped_column(
String(36), ForeignKey("projects.id", ondelete="CASCADE"), nullable=False
)
simulation_id: Mapped[Optional[str]] = mapped_column(
String(36), ForeignKey("simulations.id", ondelete="SET NULL"), nullable=True
)
graph_id: Mapped[Optional[str]] = mapped_column(
String(36), ForeignKey("graphs.id", ondelete="SET NULL"), nullable=True
)
status: Mapped[str] = mapped_column(String(30), default="generating")
outline: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
storage_prefix: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=_now, onupdate=_now)
project: Mapped["ProjectModel"] = relationship(back_populates="reports")
simulation: Mapped[Optional["SimulationModel"]] = relationship(back_populates="reports")
graph: Mapped[Optional["GraphModel"]] = relationship(back_populates="reports")
class TaskModel(Base):
__tablename__ = "tasks"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
task_type: Mapped[str] = mapped_column(String(100), nullable=False)
entity_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
entity_id: Mapped[Optional[str]] = mapped_column(String(36), nullable=True)
status: Mapped[str] = mapped_column(String(20), default="pending")
progress: Mapped[int] = mapped_column(Integer, default=0)
message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
result: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
error: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
progress_detail: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=_now)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=_now, onupdate=_now)
class SystemConfigModel(Base):
__tablename__ = "system_config"
key: Mapped[str] = mapped_column(String(100), primary_key=True)
value: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
value_type: Mapped[str] = mapped_column(String(20), default="string")
group: Mapped[str] = mapped_column(String(50), default="general")
label: Mapped[str] = mapped_column(String(255), default="")
description: Mapped[str] = mapped_column(Text, default="")
is_secret: Mapped[bool] = mapped_column(Boolean, default=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=_now, onupdate=_now)
updated_by: Mapped[Optional[str]] = mapped_column(
String(36), ForeignKey("users.id", ondelete="SET NULL"), nullable=True
)
class InvitationTokenModel(Base):
__tablename__ = "invitation_tokens"
token: Mapped[str] = mapped_column(String(36), primary_key=True)
user_id: Mapped[str] = mapped_column(
String(36), ForeignKey("users.id", ondelete="CASCADE"), nullable=False
)
expires_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
used_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
user: Mapped["UserModel"] = relationship(back_populates="invitation_tokens")
class PasswordResetTokenModel(Base):
__tablename__ = "password_reset_tokens"
token: Mapped[str] = mapped_column(String(36), primary_key=True)
user_id: Mapped[str] = mapped_column(
String(36), ForeignKey("users.id", ondelete="CASCADE"), nullable=False
)
expires_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
used_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
user: Mapped["UserModel"] = relationship(back_populates="password_reset_tokens")