246 lines
11 KiB
Python
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")
|