Files
daily-news-app/app/models/report.py
donald db0f0bbfe7 Initial commit: Daily News App
企業內部新聞彙整與分析系統
- 自動新聞抓取 (Digitimes, 經濟日報, 工商時報)
- AI 智慧摘要 (OpenAI/Claude/Ollama)
- 群組管理與訂閱通知
- 已清理 Python 快取檔案

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 23:53:24 +08:00

80 lines
3.6 KiB
Python

"""
報告資料模型
"""
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