from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Enum, Index, Text from sqlalchemy.sql import func from app.db.base import Base import enum class CampaignStatus(str, enum.Enum): DRAFT = "draft" SCHEDULED = "scheduled" SENDING = "sending" DONE = "done" FAILED = "failed" class RecipientStatus(str, enum.Enum): PENDING = "pending" SENT = "sent" DELIVERED = "delivered" READ = "read" FAILED = "failed" class Campaign(Base): __tablename__ = "campaigns" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True) name = Column(String, nullable=False) template_id = Column(Integer, ForeignKey("templates.id", ondelete="SET NULL"), nullable=True) list_id = Column(Integer, ForeignKey("lists.id", ondelete="SET NULL"), nullable=True) status = Column(Enum(CampaignStatus), default=CampaignStatus.DRAFT, nullable=False, index=True) scheduled_at = Column(DateTime(timezone=True), nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) class CampaignRecipient(Base): __tablename__ = "campaign_recipients" __table_args__ = ( Index('ix_campaign_recipients_campaign_status', 'campaign_id', 'status'), ) id = Column(Integer, primary_key=True, index=True) campaign_id = Column(Integer, ForeignKey("campaigns.id", ondelete="CASCADE"), nullable=False, index=True) contact_id = Column(Integer, ForeignKey("contacts.id", ondelete="CASCADE"), nullable=False, index=True) status = Column(Enum(RecipientStatus), default=RecipientStatus.PENDING, nullable=False) provider_message_id = Column(String, nullable=True) last_error = Column(Text, nullable=True) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())