企業內部新聞彙整與分析系統 - 自動新聞抓取 (Digitimes, 經濟日報, 工商時報) - AI 智慧摘要 (OpenAI/Claude/Ollama) - 群組管理與訂閱通知 - 已清理 Python 快取檔案 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
104 lines
4.2 KiB
Python
104 lines
4.2 KiB
Python
"""
|
|
系統設定與日誌資料模型
|
|
"""
|
|
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")
|