"""Database models for enhanced export functionality.""" from sqlalchemy import Column, String, Integer, Text, DateTime, Float, Boolean, ForeignKey, JSON from sqlalchemy.orm import relationship from sqlalchemy.sql import func from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.types import TypeDecorator, CHAR import uuid from datetime import datetime from backend.models.base import Model class GUID(TypeDecorator): """Platform-independent GUID type for SQLite and PostgreSQL compatibility.""" impl = CHAR cache_ok = True def load_dialect_impl(self, dialect): if dialect.name == 'postgresql': return dialect.type_descriptor(UUID()) else: return dialect.type_descriptor(CHAR(32)) def process_bind_param(self, value, dialect): if value is None: return value elif dialect.name == 'postgresql': return str(value) else: if not isinstance(value, uuid.UUID): return "%.32x" % uuid.UUID(value).int else: return "%.32x" % value.int def process_result_value(self, value, dialect): if value is None: return value else: if not isinstance(value, uuid.UUID): return uuid.UUID(value) return value class EnhancedExport(Model): """Enhanced export configurations and results.""" __tablename__ = "enhanced_exports" __table_args__ = {'extend_existing': True} id = Column(GUID, primary_key=True, default=uuid.uuid4) user_id = Column(GUID, ForeignKey("users.id"), nullable=True) summary_id = Column(GUID, ForeignKey("summaries.id"), nullable=True) playlist_id = Column(GUID, ForeignKey("playlists.id"), nullable=True) # Export configuration export_type = Column(String(50), nullable=False) # single_video, playlist, multi_agent, comparison format = Column(String(20), nullable=False) # pdf, markdown, json, csv, docx template_id = Column(GUID, ForeignKey("prompt_templates.id"), nullable=True) # Multi-agent export options include_technical_analysis = Column(Boolean, default=True) include_business_analysis = Column(Boolean, default=True) include_ux_analysis = Column(Boolean, default=True) include_synthesis = Column(Boolean, default=True) # Export customization custom_sections = Column(JSON) styling_options = Column(JSON) metadata_options = Column(JSON) # Export results file_path = Column(String(500)) file_size_bytes = Column(Integer) generation_time_seconds = Column(Float) status = Column(String(20), default="pending") # pending, processing, completed, failed error_message = Column(Text) # Timestamps created_at = Column(DateTime, server_default=func.now()) completed_at = Column(DateTime) # Relationships user = relationship("backend.models.user.User") summary = relationship("backend.models.summary.Summary") template = relationship("backend.models.prompt_models.PromptTemplate") sections = relationship("backend.models.export_models.ExportSection", back_populates="export", cascade="all, delete-orphan") def __repr__(self): return f"" class ExportSection(Model): """Individual sections within an enhanced export.""" __tablename__ = "export_sections" __table_args__ = {'extend_existing': True} id = Column(GUID, primary_key=True, default=uuid.uuid4) export_id = Column(GUID, ForeignKey("enhanced_exports.id", ondelete="CASCADE"), nullable=False) # Section metadata section_type = Column(String(50), nullable=False) # summary, technical, business, ux, synthesis, custom title = Column(String(200), nullable=False) order_index = Column(Integer, nullable=False) # Section content content = Column(Text) raw_data = Column(JSON) # Structured data for the section agent_type = Column(String(20)) # For multi-agent sections: technical, business, user, synthesis # Section configuration styling = Column(JSON) include_in_toc = Column(Boolean, default=True) is_collapsible = Column(Boolean, default=False) # Processing metadata generated_at = Column(DateTime, server_default=func.now()) processing_time_ms = Column(Integer) token_count = Column(Integer) # For AI-generated sections confidence_score = Column(Float) # Relationships export = relationship("backend.models.export_models.EnhancedExport", back_populates="sections") def __repr__(self): return f""