""" SNS 모듈 SQLAlchemy 모델 정의 SNS 업로드 작업 관리 모델입니다. """ from datetime import datetime from typing import TYPE_CHECKING, Optional from sqlalchemy import Boolean, DateTime, ForeignKey, Index, Integer, String, Text, func from sqlalchemy.orm import Mapped, mapped_column, relationship from app.database.session import Base if TYPE_CHECKING: from app.user.models import SocialAccount, User class SNSUploadTask(Base): """ SNS 업로드 작업 테이블 SNS 플랫폼에 콘텐츠를 업로드하는 작업을 관리합니다. 즉시 업로드 또는 예약 업로드를 지원합니다. Attributes: id: 고유 식별자 (자동 증가) user_uuid: 사용자 UUID (User.user_uuid 참조) task_id: 외부 작업 식별자 (비디오 생성 작업 등) is_scheduled: 예약 작업 여부 (True: 예약, False: 즉시) scheduled_at: 예약 발행 일시 (분 단위까지) social_account_id: 소셜 계정 외래키 (SocialAccount.id 참조) url: 업로드할 미디어 URL caption: 게시물 캡션/설명 status: 발행 상태 (pending: 예약 대기, completed: 완료, error: 에러) uploaded_at: 실제 업로드 완료 일시 created_at: 작업 생성 일시 발행 상태 (status): - pending: 예약 대기 중 (예약 작업이거나 처리 전) - processing: 처리 중 - completed: 발행 완료 - error: 에러 발생 Relationships: user: 작업 소유 사용자 (User 테이블 참조) social_account: 발행 대상 소셜 계정 (SocialAccount 테이블 참조) """ __tablename__ = "sns_upload_task" __table_args__ = ( Index("idx_sns_upload_task_user_uuid", "user_uuid"), Index("idx_sns_upload_task_task_id", "task_id"), Index("idx_sns_upload_task_social_account_id", "social_account_id"), Index("idx_sns_upload_task_status", "status"), Index("idx_sns_upload_task_is_scheduled", "is_scheduled"), Index("idx_sns_upload_task_scheduled_at", "scheduled_at"), Index("idx_sns_upload_task_created_at", "created_at"), { "mysql_engine": "InnoDB", "mysql_charset": "utf8mb4", "mysql_collate": "utf8mb4_unicode_ci", }, ) # ========================================================================== # 기본 식별자 # ========================================================================== id: Mapped[int] = mapped_column( Integer, primary_key=True, nullable=False, autoincrement=True, comment="고유 식별자", ) # ========================================================================== # 사용자 및 작업 식별 # ========================================================================== user_uuid: Mapped[str] = mapped_column( String(36), ForeignKey("user.user_uuid", ondelete="CASCADE"), nullable=False, comment="사용자 UUID (User.user_uuid 참조)", ) task_id: Mapped[Optional[str]] = mapped_column( String(100), nullable=True, comment="외부 작업 식별자 (비디오 생성 작업 ID 등)", ) # ========================================================================== # 예약 설정 # ========================================================================== is_scheduled: Mapped[bool] = mapped_column( Boolean, nullable=False, default=False, comment="예약 작업 여부 (True: 예약 발행, False: 즉시 발행)", ) scheduled_at: Mapped[Optional[datetime]] = mapped_column( DateTime, nullable=True, comment="예약 발행 일시 (분 단위까지 지정)", ) # ========================================================================== # 소셜 계정 연결 # ========================================================================== social_account_id: Mapped[int] = mapped_column( Integer, ForeignKey("social_account.id", ondelete="CASCADE"), nullable=False, comment="소셜 계정 외래키 (SocialAccount.id 참조)", ) # ========================================================================== # 업로드 콘텐츠 # ========================================================================== url: Mapped[str] = mapped_column( String(2048), nullable=False, comment="업로드할 미디어 URL", ) caption: Mapped[Optional[str]] = mapped_column( Text, nullable=True, comment="게시물 캡션/설명", ) # ========================================================================== # 발행 상태 # ========================================================================== status: Mapped[str] = mapped_column( String(20), nullable=False, default="pending", comment="발행 상태 (pending: 예약 대기, processing: 처리 중, completed: 완료, error: 에러)", ) # ========================================================================== # 시간 정보 # ========================================================================== uploaded_at: Mapped[Optional[datetime]] = mapped_column( DateTime, nullable=True, comment="실제 업로드 완료 일시", ) created_at: Mapped[datetime] = mapped_column( DateTime, nullable=False, server_default=func.now(), comment="작업 생성 일시", ) # ========================================================================== # Relationships # ========================================================================== user: Mapped["User"] = relationship( "User", foreign_keys=[user_uuid], primaryjoin="SNSUploadTask.user_uuid == User.user_uuid", ) social_account: Mapped["SocialAccount"] = relationship( "SocialAccount", foreign_keys=[social_account_id], ) def __repr__(self) -> str: return ( f"" )