Prepare ERP source for Gitea deployment

This commit is contained in:
A R R R Associates
2026-06-20 15:01:44 +05:30
commit 5c75eb6bd9
450 changed files with 67698 additions and 0 deletions
@@ -0,0 +1,111 @@
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")