176:class SuppressionEntry(Base, TimestampMixin): 177- __tablename__ = "suppression_list" 178- id = Column(Integer, primary_key=True) 179- email = Column(String(320), unique=True, nullable=False, index=True) 180- reason = Column(String(50), default="unsubscribed") # unsubscribed|bounced|complaint|manual 181- source = Column(String(200), default="") 182- campaign_id = Column(Integer, ForeignKey("campaigns.id", ondelete="SET NULL")) 183- user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE")) 184- 185- 186-class SubjectLine(Base, TimestampMixin): 187- __tablename__ = "subject_lines" 188- id = Column(Integer, primary_key=True) 383:class ApplicationSettings(Base, TimestampMixin): 384- __tablename__ = "application_settings" 385- id = Column(Integer, primary_key=True) 386- key = Column(String(150), unique=True, nullable=False, index=True) 387- value = Column(JSON, nullable=False) 388- description = Column(String(300), default="") 389- category = Column(String(60), default="general") 357:class EmailEvent(Base, TimestampMixin): 358- __tablename__ = "email_events" 359- id = Column(Integer, primary_key=True) 360- campaign_id = Column(Integer, ForeignKey("campaigns.id", ondelete="CASCADE"), index=True) 361- campaign_recipient_id = Column(Integer, ForeignKey("campaign_recipients.id", ondelete="CASCADE"), index=True) 362- gmail_account_id = Column(Integer, ForeignKey("gmail_accounts.id", ondelete="SET NULL")) 363- event_type = Column(String(40), nullable=False) # sent|failed|bounced|suppressed|unsubscribed|complained 364- detail = Column(Text, default="") 365- message_id = Column(String(200), default="") 366- 367- __table_args__ = (Index("ix_email_events_campaign", "campaign_id", "event_type"),) 368- 369- 370-class AuditLog(Base, TimestampMixin): 371- __tablename__ = "audit_logs" 370:class AuditLog(Base, TimestampMixin): 371- __tablename__ = "audit_logs" 372- id = Column(Integer, primary_key=True) 373- user_id = Column(Integer, ForeignKey("users.id", ondelete="SET NULL"), index=True) 374- action = Column(String(120), nullable=False, index=True) 375- entity = Column(String(60), default="") 376- entity_id = Column(Integer) 377- detail = Column(JSON, default=dict) 378- ip_address = Column(String(64), default="") 379- 380- user = relationship("User") 381- 382- 383-class ApplicationSettings(Base, TimestampMixin): 384- __tablename__ = "application_settings"