import enum from datetime import date, datetime, timezone from sqlalchemy import Date, DateTime, ForeignKey, Index, Integer, Text from sqlalchemy.dialects.postgresql import ARRAY from sqlalchemy.orm import Mapped, mapped_column from fabledassistant.models import Base class TaskStatus(str, enum.Enum): todo = "todo" in_progress = "in_progress" done = "done" class TaskPriority(str, enum.Enum): none = "none" low = "low" medium = "medium" high = "high" class Note(Base): __tablename__ = "notes" id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int | None] = mapped_column( Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=True ) title: Mapped[str] = mapped_column(Text, default="") body: Mapped[str] = mapped_column(Text, default="") tags: Mapped[list[str]] = mapped_column(ARRAY(Text), default=list) parent_id: Mapped[int | None] = mapped_column( nullable=True ) status: Mapped[str | None] = mapped_column(Text, nullable=True) priority: Mapped[str | None] = mapped_column(Text, nullable=True) due_date: Mapped[date | None] = mapped_column(Date, nullable=True) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(timezone.utc) ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), ) __table_args__ = ( Index("ix_notes_tags", "tags", postgresql_using="gin"), Index("ix_notes_status", "status"), Index("ix_notes_title", "title"), Index("ix_notes_user_id", "user_id"), ) @property def is_task(self) -> bool: return self.status is not None def to_dict(self) -> dict: return { "id": self.id, "title": self.title, "body": self.body, "tags": self.tags or [], "parent_id": self.parent_id, "status": self.status, "priority": self.priority, "due_date": self.due_date.isoformat() if self.due_date else None, "is_task": self.is_task, "created_at": self.created_at.isoformat(), "updated_at": self.updated_at.isoformat(), }