""" 트리 구조 메모장 모델 """ from sqlalchemy import Column, String, Text, Integer, Boolean, DateTime, ForeignKey, ARRAY, JSON from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from sqlalchemy.sql import func import uuid from ..core.database import Base class MemoTree(Base): """메모 트리 (프로젝트/워크스페이스)""" __tablename__ = "memo_trees" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) title = Column(String(255), nullable=False) description = Column(Text) tree_type = Column(String(50), default="general") # 'novel', 'research', 'project', 'general' template_data = Column(JSON) # 템플릿별 메타데이터 settings = Column(JSON, default={}) # 트리별 설정 created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) is_public = Column(Boolean, default=False) is_archived = Column(Boolean, default=False) # 관계 user = relationship("User", back_populates="memo_trees") nodes = relationship("MemoNode", back_populates="tree", cascade="all, delete-orphan") shares = relationship("MemoTreeShare", back_populates="tree", cascade="all, delete-orphan") class MemoNode(Base): """메모 노드 (트리의 각 노드)""" __tablename__ = "memo_nodes" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) tree_id = Column(UUID(as_uuid=True), ForeignKey("memo_trees.id", ondelete="CASCADE"), nullable=False) parent_id = Column(UUID(as_uuid=True), ForeignKey("memo_nodes.id", ondelete="CASCADE")) user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) # 기본 정보 title = Column(String(500), nullable=False) content = Column(Text) # Markdown 형식 node_type = Column(String(50), default="memo") # 'folder', 'memo', 'chapter', 'character', 'plot' # 트리 구조 관리 sort_order = Column(Integer, default=0) depth_level = Column(Integer, default=0) path = Column(Text) # 경로 저장 (예: /1/3/7) # 메타데이터 tags = Column(ARRAY(String)) # 태그 배열 node_metadata = Column(JSON, default={}) # 노드별 메타데이터 # 상태 관리 status = Column(String(50), default="draft") # 'draft', 'writing', 'review', 'complete' word_count = Column(Integer, default=0) # 정사 경로 관련 필드 is_canonical = Column(Boolean, default=False) # 정사 경로 여부 canonical_order = Column(Integer, nullable=True) # 정사 경로 순서 story_path = Column(Text, nullable=True) # 정사 경로 문자열 # 시간 정보 created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) # 관계 tree = relationship("MemoTree", back_populates="nodes") user = relationship("User", back_populates="memo_nodes") parent = relationship("MemoNode", remote_side=[id], back_populates="children") children = relationship("MemoNode", back_populates="parent", cascade="all, delete-orphan") versions = relationship("MemoNodeVersion", back_populates="node", cascade="all, delete-orphan") class MemoNodeVersion(Base): """메모 노드 버전 관리""" __tablename__ = "memo_node_versions" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) node_id = Column(UUID(as_uuid=True), ForeignKey("memo_nodes.id", ondelete="CASCADE"), nullable=False) version_number = Column(Integer, nullable=False) title = Column(String(500), nullable=False) content = Column(Text) node_metadata = Column(JSON, default={}) created_at = Column(DateTime(timezone=True), server_default=func.now()) created_by = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) # 관계 node = relationship("MemoNode", back_populates="versions") creator = relationship("User") class MemoTreeShare(Base): """메모 트리 공유 (협업 기능)""" __tablename__ = "memo_tree_shares" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) tree_id = Column(UUID(as_uuid=True), ForeignKey("memo_trees.id", ondelete="CASCADE"), nullable=False) shared_with_user_id = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) permission_level = Column(String(20), default="read") # 'read', 'write', 'admin' created_at = Column(DateTime(timezone=True), server_default=func.now()) created_by = Column(UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), nullable=False) # 관계 tree = relationship("MemoTree", back_populates="shares") shared_with_user = relationship("User", foreign_keys=[shared_with_user_id]) creator = relationship("User", foreign_keys=[created_by])