112 lines
7.0 KiB
Python
112 lines
7.0 KiB
Python
from __future__ import annotations
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision = "20260608_phase_7s1_email_notifications"
|
|
down_revision = "20260607_phase_7r6a_cashfree"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def _has_table(bind, table_name: str) -> bool:
|
|
return sa.inspect(bind).has_table(table_name)
|
|
|
|
|
|
def upgrade() -> None:
|
|
bind = op.get_bind()
|
|
|
|
if not _has_table(bind, "email_settings"):
|
|
op.create_table(
|
|
"email_settings",
|
|
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
|
|
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False),
|
|
sa.Column("branch_id", sa.Integer(), sa.ForeignKey("branches.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("smtp_host", sa.String(length=255), nullable=True),
|
|
sa.Column("smtp_port", sa.Integer(), nullable=True),
|
|
sa.Column("smtp_username", sa.String(length=255), nullable=True),
|
|
sa.Column("smtp_password", sa.String(length=500), nullable=True),
|
|
sa.Column("smtp_security", sa.String(length=20), nullable=False, server_default="SSL"),
|
|
sa.Column("smtp_timeout_seconds", sa.Integer(), nullable=False, server_default="20"),
|
|
sa.Column("from_email", sa.String(length=255), nullable=True),
|
|
sa.Column("from_name", sa.String(length=255), nullable=True),
|
|
sa.Column("reply_to_email", sa.String(length=255), nullable=True),
|
|
sa.Column("imap_host", sa.String(length=255), nullable=True),
|
|
sa.Column("imap_port", sa.Integer(), nullable=True),
|
|
sa.Column("imap_username", sa.String(length=255), nullable=True),
|
|
sa.Column("imap_password", sa.String(length=500), nullable=True),
|
|
sa.Column("imap_security", sa.String(length=20), nullable=False, server_default="SSL"),
|
|
sa.Column("send_auth_emails", sa.Boolean(), nullable=False, server_default=sa.true()),
|
|
sa.Column("send_alert_emails", sa.Boolean(), nullable=False, server_default=sa.false()),
|
|
sa.Column("send_billing_emails", sa.Boolean(), nullable=False, server_default=sa.true()),
|
|
sa.Column("send_task_emails", sa.Boolean(), nullable=False, server_default=sa.true()),
|
|
sa.Column("is_active", sa.Boolean(), nullable=False, server_default=sa.true()),
|
|
sa.Column("created_by_user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("updated_by_user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("created_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
|
|
sa.Column("updated_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
|
|
sa.UniqueConstraint("tenant_id", "branch_id", name="uq_email_settings_tenant_branch"),
|
|
)
|
|
op.create_index("ix_email_settings_tenant_id", "email_settings", ["tenant_id"])
|
|
op.create_index("ix_email_settings_branch_id", "email_settings", ["branch_id"])
|
|
op.create_index("ix_email_settings_is_active", "email_settings", ["is_active"])
|
|
|
|
if not _has_table(bind, "email_templates"):
|
|
op.create_table(
|
|
"email_templates",
|
|
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
|
|
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=True),
|
|
sa.Column("branch_id", sa.Integer(), sa.ForeignKey("branches.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("template_code", sa.String(length=80), nullable=False),
|
|
sa.Column("template_name", sa.String(length=160), nullable=False),
|
|
sa.Column("subject_template", sa.String(length=500), nullable=False),
|
|
sa.Column("body_template", sa.Text(), nullable=False),
|
|
sa.Column("is_html", sa.Boolean(), nullable=False, server_default=sa.false()),
|
|
sa.Column("is_active", sa.Boolean(), nullable=False, server_default=sa.true()),
|
|
sa.Column("created_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
|
|
sa.Column("updated_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
|
|
sa.UniqueConstraint("tenant_id", "branch_id", "template_code", name="uq_email_templates_scope_code"),
|
|
)
|
|
op.create_index("ix_email_templates_tenant_id", "email_templates", ["tenant_id"])
|
|
op.create_index("ix_email_templates_branch_id", "email_templates", ["branch_id"])
|
|
op.create_index("ix_email_templates_template_code", "email_templates", ["template_code"])
|
|
op.create_index("ix_email_templates_is_active", "email_templates", ["is_active"])
|
|
|
|
if not _has_table(bind, "email_logs"):
|
|
op.create_table(
|
|
"email_logs",
|
|
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
|
|
sa.Column("tenant_id", sa.Integer(), sa.ForeignKey("tenants.id", ondelete="CASCADE"), nullable=True),
|
|
sa.Column("branch_id", sa.Integer(), sa.ForeignKey("branches.id", ondelete="SET NULL"), nullable=True),
|
|
sa.Column("recipient_email", sa.String(length=255), nullable=False),
|
|
sa.Column("subject", sa.String(length=500), nullable=False),
|
|
sa.Column("body", sa.Text(), nullable=True),
|
|
sa.Column("status", sa.String(length=30), nullable=False, server_default="PENDING"),
|
|
sa.Column("error_message", sa.Text(), nullable=True),
|
|
sa.Column("sent_at", sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column("related_module", sa.String(length=80), nullable=True),
|
|
sa.Column("related_id", sa.Integer(), nullable=True),
|
|
sa.Column("template_code", sa.String(length=80), nullable=True),
|
|
sa.Column("provider_message_id", sa.String(length=255), nullable=True),
|
|
sa.Column("created_at_utc", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()),
|
|
)
|
|
op.create_index("ix_email_logs_tenant_id", "email_logs", ["tenant_id"])
|
|
op.create_index("ix_email_logs_branch_id", "email_logs", ["branch_id"])
|
|
op.create_index("ix_email_logs_recipient_email", "email_logs", ["recipient_email"])
|
|
op.create_index("ix_email_logs_status", "email_logs", ["status"])
|
|
op.create_index("ix_email_logs_sent_at", "email_logs", ["sent_at"])
|
|
op.create_index("ix_email_logs_related_module", "email_logs", ["related_module"])
|
|
op.create_index("ix_email_logs_related_id", "email_logs", ["related_id"])
|
|
op.create_index("ix_email_logs_template_code", "email_logs", ["template_code"])
|
|
op.create_index("ix_email_logs_created_at_utc", "email_logs", ["created_at_utc"])
|
|
|
|
|
|
def downgrade() -> None:
|
|
bind = op.get_bind()
|
|
if _has_table(bind, "email_logs"):
|
|
op.drop_table("email_logs")
|
|
if _has_table(bind, "email_templates"):
|
|
op.drop_table("email_templates")
|
|
if _has_table(bind, "email_settings"):
|
|
op.drop_table("email_settings")
|