# alembic/versions/v0a1b2c3d4e5_add_vendor_email_settings.py """Add vendor email settings table. Revision ID: v0a1b2c3d4e5 Revises: u9c0d1e2f3g4 Create Date: 2026-01-05 Changes: - Create vendor_email_settings table for vendor SMTP/email provider configuration - Vendors must configure this to send transactional emails - Premium providers (SendGrid, Mailgun, SES) are tier-gated (Business+) """ from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision = "v0a1b2c3d4e5" down_revision = "u9c0d1e2f3g4" branch_labels = None depends_on = None def upgrade() -> None: # Create vendor_email_settings table op.create_table( "vendor_email_settings", sa.Column("id", sa.Integer(), nullable=False), sa.Column("vendor_id", sa.Integer(), nullable=False), # Sender Identity sa.Column("from_email", sa.String(255), nullable=False), sa.Column("from_name", sa.String(100), nullable=False), sa.Column("reply_to_email", sa.String(255), nullable=True), # Signature/Footer sa.Column("signature_text", sa.Text(), nullable=True), sa.Column("signature_html", sa.Text(), nullable=True), # Provider Configuration sa.Column("provider", sa.String(20), nullable=False, default="smtp"), # SMTP Settings sa.Column("smtp_host", sa.String(255), nullable=True), sa.Column("smtp_port", sa.Integer(), nullable=True, default=587), sa.Column("smtp_username", sa.String(255), nullable=True), sa.Column("smtp_password", sa.String(500), nullable=True), sa.Column("smtp_use_tls", sa.Boolean(), nullable=False, default=True), sa.Column("smtp_use_ssl", sa.Boolean(), nullable=False, default=False), # SendGrid Settings sa.Column("sendgrid_api_key", sa.String(500), nullable=True), # Mailgun Settings sa.Column("mailgun_api_key", sa.String(500), nullable=True), sa.Column("mailgun_domain", sa.String(255), nullable=True), # Amazon SES Settings sa.Column("ses_access_key_id", sa.String(100), nullable=True), sa.Column("ses_secret_access_key", sa.String(500), nullable=True), sa.Column("ses_region", sa.String(50), nullable=True, default="eu-west-1"), # Status & Verification sa.Column("is_configured", sa.Boolean(), nullable=False, default=False), sa.Column("is_verified", sa.Boolean(), nullable=False, default=False), sa.Column("last_verified_at", sa.DateTime(timezone=True), nullable=True), sa.Column("verification_error", sa.Text(), nullable=True), # Timestamps sa.Column("created_at", sa.DateTime(), nullable=False), sa.Column("updated_at", sa.DateTime(), nullable=False), # Constraints sa.PrimaryKeyConstraint("id"), sa.ForeignKeyConstraint( ["vendor_id"], ["vendors.id"], name="fk_vendor_email_settings_vendor_id", ondelete="CASCADE", ), sa.UniqueConstraint("vendor_id", name="uq_vendor_email_settings_vendor_id"), ) # Create indexes op.create_index( "ix_vendor_email_settings_id", "vendor_email_settings", ["id"], unique=False, ) op.create_index( "ix_vendor_email_settings_vendor_id", "vendor_email_settings", ["vendor_id"], unique=True, ) op.create_index( "idx_vendor_email_settings_configured", "vendor_email_settings", ["vendor_id", "is_configured"], ) def downgrade() -> None: # Drop indexes op.drop_index("idx_vendor_email_settings_configured", table_name="vendor_email_settings") op.drop_index("ix_vendor_email_settings_vendor_id", table_name="vendor_email_settings") op.drop_index("ix_vendor_email_settings_id", table_name="vendor_email_settings") # Drop table op.drop_table("vendor_email_settings")