from sqlalchemy import String, Integer, Text, ForeignKey, DateTime, DECIMAL, Enum from sqlalchemy.orm import Mapped, mapped_column, relationship from datetime import datetime from .base import Base, TimestampMixin, MYSQL_TABLE_ARGS class Meeting(Base, TimestampMixin): __tablename__ = "biz_meeting" __table_args__ = MYSQL_TABLE_ARGS meeting_id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) user_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("sys_user.user_id"), nullable=True) title: Mapped[str] = mapped_column(String(255), nullable=False) tags: Mapped[str | None] = mapped_column(String(255)) meeting_time: Mapped[datetime | None] = mapped_column(DateTime) access_password: Mapped[str | None] = mapped_column(String(10)) status: Mapped[str] = mapped_column(String(20), default="draft") # draft, transcribing, summarizing, completed summary: Mapped[str | None] = mapped_column(Text) creator = relationship("User", backref="created_meetings") attendees = relationship("MeetingAttendee", back_populates="meeting", cascade="all, delete-orphan") audios = relationship("MeetingAudio", back_populates="meeting", cascade="all, delete-orphan") segments = relationship("TranscriptSegment", back_populates="meeting", cascade="all, delete-orphan") class MeetingAttendee(Base): __tablename__ = "biz_meeting_attendees" __table_args__ = MYSQL_TABLE_ARGS attendee_id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) meeting_id: Mapped[int] = mapped_column(Integer, ForeignKey("biz_meeting.meeting_id", ondelete="CASCADE"), index=True) user_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("sys_user.user_id")) meeting = relationship("Meeting", back_populates="attendees") user = relationship("User") class MeetingAudio(Base): __tablename__ = "biz_meeting_audio" __table_args__ = MYSQL_TABLE_ARGS audio_id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) meeting_id: Mapped[int] = mapped_column(Integer, ForeignKey("biz_meeting.meeting_id", ondelete="CASCADE")) file_path: Mapped[str] = mapped_column(String(512), nullable=False) file_name: Mapped[str | None] = mapped_column(String(200)) file_size: Mapped[float | None] = mapped_column(DECIMAL(10, 0)) duration: Mapped[int] = mapped_column(Integer, default=0) processing_status: Mapped[str] = mapped_column(String(20), default="uploaded") upload_time: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow) error_message: Mapped[str | None] = mapped_column(Text) meeting = relationship("Meeting", back_populates="audios") class TranscriptTask(Base): __tablename__ = "biz_transcript_task" __table_args__ = MYSQL_TABLE_ARGS task_id: Mapped[str] = mapped_column(String(255), primary_key=True) meeting_id: Mapped[int] = mapped_column(Integer, ForeignKey("biz_meeting.meeting_id", ondelete="CASCADE"), index=True) model_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("biz_ai_model.model_id")) language: Mapped[str] = mapped_column(String(10), default="auto") status: Mapped[str] = mapped_column(String(20), default="pending") # pending, processing, completed, failed progress: Mapped[int] = mapped_column(Integer, default=0) completed_at: Mapped[datetime | None] = mapped_column(DateTime) error_message: Mapped[str | None] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True) class TranscriptSegment(Base): __tablename__ = "biz_transcript_segment" __table_args__ = MYSQL_TABLE_ARGS segment_id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) meeting_id: Mapped[int] = mapped_column(Integer, ForeignKey("biz_meeting.meeting_id", ondelete="CASCADE")) audio_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("biz_meeting_audio.audio_id", ondelete="CASCADE")) speaker_id: Mapped[int | None] = mapped_column(Integer) speaker_tag: Mapped[str | None] = mapped_column(String(50)) start_time_ms: Mapped[int] = mapped_column(Integer, nullable=False) end_time_ms: Mapped[int] = mapped_column(Integer, nullable=False) text_content: Mapped[str] = mapped_column(Text, nullable=False) meeting = relationship("Meeting", back_populates="segments") class SummarizeTask(Base): __tablename__ = "biz_summarize_task" __table_args__ = MYSQL_TABLE_ARGS task_id: Mapped[str] = mapped_column(String(100), primary_key=True) meeting_id: Mapped[int] = mapped_column(Integer, ForeignKey("biz_meeting.meeting_id", ondelete="CASCADE"), index=True) prompt_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("biz_prompt_template.id")) model_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("biz_ai_model.model_id")) user_prompt: Mapped[str | None] = mapped_column(Text) status: Mapped[str] = mapped_column(String(50), default="pending", index=True) progress: Mapped[int] = mapped_column(Integer, default=0) result: Mapped[str | None] = mapped_column(Text) error_message: Mapped[str | None] = mapped_column(Text) created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True) completed_at: Mapped[datetime | None] = mapped_column(DateTime)