"""Note model: free-text notes attached polymorphically to accounts/contacts/deals.""" from __future__ import annotations from enum import Enum from typing import TYPE_CHECKING from sqlalchemy import ForeignKey, Integer, String, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from app.models.base import Base, OrgScopedMixin, SoftDeleteMixin, TimestampMixin if TYPE_CHECKING: from app.models.user import User class NoteParentType(str, Enum): """Polymorphic parent type for notes (no DB FK, validated in service layer).""" account = "account" contact = "contact" deal = "deal" class Note(Base, TimestampMixin, SoftDeleteMixin, OrgScopedMixin): __tablename__ = "notes" id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) body: Mapped[str] = mapped_column(Text, nullable=False) author_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False, index=True) parent_type: Mapped[NoteParentType] = mapped_column(String(32), nullable=False, index=True) # parent_id is intentionally NOT a DB FK because of polymorphic parent. # Service layer (note_service.create_note) validates existence. parent_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True) author: Mapped[User] = relationship("User", foreign_keys=[author_id], lazy="joined") def __repr__(self) -> str: return f"" __all__ = ["Note", "NoteParentType"]