""" 報告資料模型 """ from datetime import datetime, date from sqlalchemy import String, Boolean, ForeignKey, Text, Date, Enum as SQLEnum, UniqueConstraint, Index from sqlalchemy.orm import Mapped, mapped_column, relationship from typing import Optional, List import enum from app.db.session import Base class ReportStatus(str, enum.Enum): """報告狀態""" DRAFT = "draft" PENDING = "pending" PUBLISHED = "published" DELAYED = "delayed" class Report(Base): """報告表""" __tablename__ = "reports" __table_args__ = ( UniqueConstraint("group_id", "report_date", name="uk_group_date"), Index("idx_reports_status", "status"), Index("idx_reports_date", "report_date"), ) id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) group_id: Mapped[int] = mapped_column(ForeignKey("groups.id"), nullable=False, comment="所屬群組ID") title: Mapped[str] = mapped_column(String(200), nullable=False, comment="報告標題") report_date: Mapped[date] = mapped_column(Date, nullable=False, comment="報告日期") ai_summary: Mapped[Optional[str]] = mapped_column(Text, comment="AI綜合摘要") edited_summary: Mapped[Optional[str]] = mapped_column(Text, comment="編輯後摘要") status: Mapped[ReportStatus] = mapped_column(SQLEnum(ReportStatus), default=ReportStatus.DRAFT, comment="狀態") published_at: Mapped[Optional[datetime]] = mapped_column(comment="發布時間") published_by: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id"), comment="發布者ID") created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow) updated_at: Mapped[datetime] = mapped_column(default=datetime.utcnow, onupdate=datetime.utcnow) # 關聯 group: Mapped["Group"] = relationship(back_populates="reports") report_articles: Mapped[List["ReportArticle"]] = relationship(back_populates="report", cascade="all, delete-orphan") favorites: Mapped[List["Favorite"]] = relationship(back_populates="report", cascade="all, delete-orphan") comments: Mapped[List["Comment"]] = relationship(back_populates="report", cascade="all, delete-orphan") notes: Mapped[List["Note"]] = relationship(back_populates="report", cascade="all, delete-orphan") notifications: Mapped[List["NotificationLog"]] = relationship(back_populates="report") @property def final_summary(self) -> str: """取得最終摘要(優先使用編輯後版本)""" return self.edited_summary or self.ai_summary or "" class ReportArticle(Base): """報告-新聞關聯表""" __tablename__ = "report_articles" __table_args__ = ( UniqueConstraint("report_id", "article_id", name="uk_report_article"), ) id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) report_id: Mapped[int] = mapped_column(ForeignKey("reports.id", ondelete="CASCADE"), nullable=False) article_id: Mapped[int] = mapped_column(ForeignKey("news_articles.id"), nullable=False) is_included: Mapped[bool] = mapped_column(Boolean, default=True, comment="是否納入報告") display_order: Mapped[int] = mapped_column(default=0, comment="顯示順序") created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow) # 關聯 report: Mapped["Report"] = relationship(back_populates="report_articles") article: Mapped["NewsArticle"] = relationship(back_populates="report_articles") # 避免循環引入 from app.models.group import Group from app.models.news import NewsArticle from app.models.interaction import Favorite, Comment, Note from app.models.system import NotificationLog