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>
This commit is contained in:
103
app/models/system.py
Normal file
103
app/models/system.py
Normal file
@@ -0,0 +1,103 @@
|
||||
"""
|
||||
系統設定與日誌資料模型
|
||||
"""
|
||||
from datetime import datetime
|
||||
from sqlalchemy import String, ForeignKey, Text, JSON, Enum as SQLEnum, Index
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from typing import Optional, TYPE_CHECKING
|
||||
import enum
|
||||
|
||||
from app.db.session import Base
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.models.user import User
|
||||
from app.models.report import Report
|
||||
|
||||
|
||||
class SettingType(str, enum.Enum):
|
||||
"""設定值類型"""
|
||||
STRING = "string"
|
||||
NUMBER = "number"
|
||||
BOOLEAN = "boolean"
|
||||
JSON = "json"
|
||||
|
||||
|
||||
class NotificationType(str, enum.Enum):
|
||||
"""通知類型"""
|
||||
EMAIL = "email"
|
||||
SYSTEM = "system"
|
||||
|
||||
|
||||
class NotificationStatus(str, enum.Enum):
|
||||
"""通知狀態"""
|
||||
PENDING = "pending"
|
||||
SENT = "sent"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
class SystemSetting(Base):
|
||||
"""系統設定表"""
|
||||
__tablename__ = "system_settings"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
setting_key: Mapped[str] = mapped_column(String(50), unique=True, nullable=False, comment="設定鍵")
|
||||
setting_value: Mapped[Optional[str]] = mapped_column(Text, comment="設定值")
|
||||
setting_type: Mapped[SettingType] = mapped_column(SQLEnum(SettingType), default=SettingType.STRING)
|
||||
description: Mapped[Optional[str]] = mapped_column(String(200), comment="設定描述")
|
||||
updated_by: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id"), comment="更新者ID")
|
||||
updated_at: Mapped[datetime] = mapped_column(default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
def get_value(self):
|
||||
"""取得轉換後的設定值"""
|
||||
if self.setting_value is None:
|
||||
return None
|
||||
if self.setting_type == SettingType.NUMBER:
|
||||
return float(self.setting_value) if '.' in self.setting_value else int(self.setting_value)
|
||||
if self.setting_type == SettingType.BOOLEAN:
|
||||
return self.setting_value.lower() in ('true', '1', 'yes')
|
||||
if self.setting_type == SettingType.JSON:
|
||||
import json
|
||||
return json.loads(self.setting_value)
|
||||
return self.setting_value
|
||||
|
||||
|
||||
class AuditLog(Base):
|
||||
"""操作日誌表"""
|
||||
__tablename__ = "audit_logs"
|
||||
__table_args__ = (
|
||||
Index("idx_audit_user", "user_id"),
|
||||
Index("idx_audit_action", "action"),
|
||||
Index("idx_audit_created", "created_at"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id"), comment="操作用戶ID")
|
||||
action: Mapped[str] = mapped_column(String(50), nullable=False, comment="操作類型")
|
||||
target_type: Mapped[Optional[str]] = mapped_column(String(50), comment="目標類型")
|
||||
target_id: Mapped[Optional[str]] = mapped_column(String(50), comment="目標ID")
|
||||
details: Mapped[Optional[dict]] = mapped_column(JSON, comment="操作詳情")
|
||||
ip_address: Mapped[Optional[str]] = mapped_column(String(45), comment="IP地址")
|
||||
user_agent: Mapped[Optional[str]] = mapped_column(String(500), comment="User Agent")
|
||||
created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)
|
||||
|
||||
|
||||
class NotificationLog(Base):
|
||||
"""通知記錄表"""
|
||||
__tablename__ = "notification_logs"
|
||||
__table_args__ = (
|
||||
Index("idx_notification_status", "status"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
|
||||
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"), nullable=False)
|
||||
report_id: Mapped[Optional[int]] = mapped_column(ForeignKey("reports.id"), comment="關聯報告ID")
|
||||
notification_type: Mapped[NotificationType] = mapped_column(SQLEnum(NotificationType), default=NotificationType.EMAIL)
|
||||
subject: Mapped[Optional[str]] = mapped_column(String(200), comment="通知標題")
|
||||
content: Mapped[Optional[str]] = mapped_column(Text, comment="通知內容")
|
||||
status: Mapped[NotificationStatus] = mapped_column(SQLEnum(NotificationStatus), default=NotificationStatus.PENDING)
|
||||
sent_at: Mapped[Optional[datetime]] = mapped_column()
|
||||
error_message: Mapped[Optional[str]] = mapped_column(Text)
|
||||
created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)
|
||||
|
||||
# 關聯
|
||||
report: Mapped[Optional["Report"]] = relationship(back_populates="notifications")
|
||||
Reference in New Issue
Block a user