inital commit
This commit is contained in:
45
server/alembic/env.py
Normal file
45
server/alembic/env.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from logging.config import fileConfig
|
||||
|
||||
from alembic import context
|
||||
from sqlalchemy import engine_from_config, pool
|
||||
|
||||
from app.db.base import Base
|
||||
from app.db import models # noqa: F401 - ensure models are imported
|
||||
from app.settings import settings
|
||||
|
||||
config = context.config
|
||||
config.set_main_option("sqlalchemy.url", settings.database_url)
|
||||
|
||||
if config.config_file_name is not None:
|
||||
fileConfig(config.config_file_name)
|
||||
|
||||
target_metadata = Base.metadata
|
||||
|
||||
|
||||
def run_migrations_offline() -> None:
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
context.configure(url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"})
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
def run_migrations_online() -> None:
|
||||
connectable = engine_from_config(
|
||||
config.get_section(config.config_ini_section, {}),
|
||||
prefix="sqlalchemy.",
|
||||
poolclass=pool.NullPool,
|
||||
)
|
||||
|
||||
with connectable.connect() as connection:
|
||||
context.configure(connection=connection, target_metadata=target_metadata)
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
||||
24
server/alembic/script.py.mako
Normal file
24
server/alembic/script.py.mako
Normal file
@@ -0,0 +1,24 @@
|
||||
"""${message}
|
||||
|
||||
Revision ID: ${up_revision}
|
||||
Revises: ${down_revision | comma,n}
|
||||
Create Date: ${create_date}
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
${imports if imports else ""}
|
||||
|
||||
revision = ${repr(up_revision)}
|
||||
down_revision = ${repr(down_revision)}
|
||||
branch_labels = ${repr(branch_labels)}
|
||||
depends_on = ${repr(depends_on)}
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
${downgrades if downgrades else "pass"}
|
||||
@@ -0,0 +1,58 @@
|
||||
"""editable campaign versions
|
||||
|
||||
Revision ID: 1f8d4c2a0b7e
|
||||
Revises: b57c5b216bce
|
||||
Create Date: 2026-06-08 08:00:00.000000
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision = "1f8d4c2a0b7e"
|
||||
down_revision = "b57c5b216bce"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
with op.batch_alter_table("campaign_versions") as batch_op:
|
||||
batch_op.add_column(sa.Column("source_base_path", sa.String(length=1000), nullable=True))
|
||||
batch_op.add_column(sa.Column("workflow_state", sa.String(length=50), nullable=False, server_default="editing"))
|
||||
batch_op.add_column(sa.Column("current_flow", sa.String(length=50), nullable=False, server_default="manual"))
|
||||
batch_op.add_column(sa.Column("current_step", sa.String(length=100), nullable=True))
|
||||
batch_op.add_column(sa.Column("is_complete", sa.Boolean(), nullable=False, server_default=sa.false()))
|
||||
batch_op.add_column(sa.Column("editor_state", sa.JSON(), nullable=False, server_default=sa.text("'{}'")))
|
||||
batch_op.add_column(sa.Column("autosaved_at", sa.DateTime(timezone=True), nullable=True))
|
||||
batch_op.add_column(sa.Column("published_at", sa.DateTime(timezone=True), nullable=True))
|
||||
batch_op.add_column(sa.Column("locked_at", sa.DateTime(timezone=True), nullable=True))
|
||||
batch_op.add_column(sa.Column("locked_by_user_id", sa.String(length=36), nullable=True))
|
||||
batch_op.create_foreign_key(
|
||||
op.f("fk_campaign_versions_locked_by_user_id_users"),
|
||||
"users",
|
||||
["locked_by_user_id"],
|
||||
["id"],
|
||||
ondelete="SET NULL",
|
||||
)
|
||||
batch_op.create_index(op.f("ix_campaign_versions_workflow_state"), ["workflow_state"], unique=False)
|
||||
batch_op.create_index(op.f("ix_campaign_versions_current_flow"), ["current_flow"], unique=False)
|
||||
batch_op.create_index(op.f("ix_campaign_versions_locked_by_user_id"), ["locked_by_user_id"], unique=False)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
with op.batch_alter_table("campaign_versions") as batch_op:
|
||||
batch_op.drop_index(op.f("ix_campaign_versions_locked_by_user_id"))
|
||||
batch_op.drop_index(op.f("ix_campaign_versions_current_flow"))
|
||||
batch_op.drop_index(op.f("ix_campaign_versions_workflow_state"))
|
||||
batch_op.drop_constraint(op.f("fk_campaign_versions_locked_by_user_id_users"), type_="foreignkey")
|
||||
batch_op.drop_column("locked_by_user_id")
|
||||
batch_op.drop_column("locked_at")
|
||||
batch_op.drop_column("published_at")
|
||||
batch_op.drop_column("autosaved_at")
|
||||
batch_op.drop_column("editor_state")
|
||||
batch_op.drop_column("is_complete")
|
||||
batch_op.drop_column("current_step")
|
||||
batch_op.drop_column("current_flow")
|
||||
batch_op.drop_column("workflow_state")
|
||||
batch_op.drop_column("source_base_path")
|
||||
@@ -0,0 +1,346 @@
|
||||
"""initial persistence models
|
||||
|
||||
Revision ID: b57c5b216bce
|
||||
Revises:
|
||||
Create Date: 2026-06-07 19:29:10.222504
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
revision = 'b57c5b216bce'
|
||||
down_revision = None
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('tenants',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('slug', sa.String(length=100), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_tenants'))
|
||||
)
|
||||
op.create_index(op.f('ix_tenants_slug'), 'tenants', ['slug'], unique=True)
|
||||
op.create_table('attachment_blobs',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('sha256', sa.String(length=64), nullable=False),
|
||||
sa.Column('size_bytes', sa.Integer(), nullable=False),
|
||||
sa.Column('mime_type', sa.String(length=255), nullable=True),
|
||||
sa.Column('storage_bucket', sa.String(length=255), nullable=False),
|
||||
sa.Column('storage_key', sa.String(length=1000), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_attachment_blobs_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_attachment_blobs')),
|
||||
sa.UniqueConstraint('tenant_id', 'sha256', name='uq_attachment_blobs_tenant_sha256')
|
||||
)
|
||||
op.create_index(op.f('ix_attachment_blobs_sha256'), 'attachment_blobs', ['sha256'], unique=False)
|
||||
op.create_index(op.f('ix_attachment_blobs_tenant_id'), 'attachment_blobs', ['tenant_id'], unique=False)
|
||||
op.create_table('groups',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('slug', sa.String(length=100), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_groups_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_groups')),
|
||||
sa.UniqueConstraint('tenant_id', 'slug', name='uq_groups_tenant_slug')
|
||||
)
|
||||
op.create_index(op.f('ix_groups_tenant_id'), 'groups', ['tenant_id'], unique=False)
|
||||
op.create_table('roles',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('slug', sa.String(length=100), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('permissions', sa.JSON(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_roles_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_roles')),
|
||||
sa.UniqueConstraint('tenant_id', 'slug', name='uq_roles_tenant_slug')
|
||||
)
|
||||
op.create_index(op.f('ix_roles_tenant_id'), 'roles', ['tenant_id'], unique=False)
|
||||
op.create_table('users',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('email', sa.String(length=320), nullable=False),
|
||||
sa.Column('display_name', sa.String(length=255), nullable=True),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('is_tenant_admin', sa.Boolean(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_users_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_users')),
|
||||
sa.UniqueConstraint('tenant_id', 'email', name='uq_users_tenant_email')
|
||||
)
|
||||
op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=False)
|
||||
op.create_index(op.f('ix_users_tenant_id'), 'users', ['tenant_id'], unique=False)
|
||||
op.create_table('api_keys',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('user_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('prefix', sa.String(length=16), nullable=False),
|
||||
sa.Column('key_hash', sa.String(length=128), nullable=False),
|
||||
sa.Column('scopes', sa.JSON(), nullable=False),
|
||||
sa.Column('expires_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('last_used_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('revoked_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_api_keys_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], name=op.f('fk_api_keys_user_id_users'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_api_keys'))
|
||||
)
|
||||
op.create_index(op.f('ix_api_keys_prefix'), 'api_keys', ['prefix'], unique=False)
|
||||
op.create_index(op.f('ix_api_keys_tenant_id'), 'api_keys', ['tenant_id'], unique=False)
|
||||
op.create_index(op.f('ix_api_keys_user_id'), 'api_keys', ['user_id'], unique=False)
|
||||
op.create_table('campaigns',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('created_by_user_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('external_id', sa.String(length=255), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('status', sa.String(length=50), nullable=False),
|
||||
sa.Column('current_version_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['created_by_user_id'], ['users.id'], name=op.f('fk_campaigns_created_by_user_id_users'), ondelete='SET NULL'),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_campaigns_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_campaigns')),
|
||||
sa.UniqueConstraint('tenant_id', 'external_id', name='uq_campaigns_tenant_external_id')
|
||||
)
|
||||
op.create_index(op.f('ix_campaigns_created_by_user_id'), 'campaigns', ['created_by_user_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaigns_external_id'), 'campaigns', ['external_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaigns_status'), 'campaigns', ['status'], unique=False)
|
||||
op.create_index(op.f('ix_campaigns_tenant_id'), 'campaigns', ['tenant_id'], unique=False)
|
||||
op.create_table('attachment_instances',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('owner_user_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('campaign_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('blob_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('logical_name', sa.String(length=500), nullable=True),
|
||||
sa.Column('filename', sa.String(length=500), nullable=False),
|
||||
sa.Column('tags', sa.JSON(), nullable=False),
|
||||
sa.Column('metadata', sa.JSON(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['blob_id'], ['attachment_blobs.id'], name=op.f('fk_attachment_instances_blob_id_attachment_blobs'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], name=op.f('fk_attachment_instances_campaign_id_campaigns'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['owner_user_id'], ['users.id'], name=op.f('fk_attachment_instances_owner_user_id_users'), ondelete='SET NULL'),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_attachment_instances_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_attachment_instances'))
|
||||
)
|
||||
op.create_index(op.f('ix_attachment_instances_blob_id'), 'attachment_instances', ['blob_id'], unique=False)
|
||||
op.create_index(op.f('ix_attachment_instances_campaign_id'), 'attachment_instances', ['campaign_id'], unique=False)
|
||||
op.create_index(op.f('ix_attachment_instances_owner_user_id'), 'attachment_instances', ['owner_user_id'], unique=False)
|
||||
op.create_index(op.f('ix_attachment_instances_tenant_id'), 'attachment_instances', ['tenant_id'], unique=False)
|
||||
op.create_table('audit_log',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('user_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('api_key_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('action', sa.String(length=100), nullable=False),
|
||||
sa.Column('object_type', sa.String(length=100), nullable=True),
|
||||
sa.Column('object_id', sa.String(length=100), nullable=True),
|
||||
sa.Column('details', sa.JSON(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['api_key_id'], ['api_keys.id'], name=op.f('fk_audit_log_api_key_id_api_keys'), ondelete='SET NULL'),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_audit_log_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], name=op.f('fk_audit_log_user_id_users'), ondelete='SET NULL'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_audit_log'))
|
||||
)
|
||||
op.create_index(op.f('ix_audit_log_action'), 'audit_log', ['action'], unique=False)
|
||||
op.create_index(op.f('ix_audit_log_api_key_id'), 'audit_log', ['api_key_id'], unique=False)
|
||||
op.create_index(op.f('ix_audit_log_object_id'), 'audit_log', ['object_id'], unique=False)
|
||||
op.create_index(op.f('ix_audit_log_object_type'), 'audit_log', ['object_type'], unique=False)
|
||||
op.create_index(op.f('ix_audit_log_tenant_id'), 'audit_log', ['tenant_id'], unique=False)
|
||||
op.create_index(op.f('ix_audit_log_user_id'), 'audit_log', ['user_id'], unique=False)
|
||||
op.create_table('campaign_versions',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('campaign_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('version_number', sa.Integer(), nullable=False),
|
||||
sa.Column('raw_json', sa.JSON(), nullable=False),
|
||||
sa.Column('schema_version', sa.String(length=50), nullable=False),
|
||||
sa.Column('source_filename', sa.String(length=500), nullable=True),
|
||||
sa.Column('validation_summary', sa.JSON(), nullable=True),
|
||||
sa.Column('build_summary', sa.JSON(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], name=op.f('fk_campaign_versions_campaign_id_campaigns'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_campaign_versions')),
|
||||
sa.UniqueConstraint('campaign_id', 'version_number', name='uq_campaign_versions_campaign_number')
|
||||
)
|
||||
op.create_index(op.f('ix_campaign_versions_campaign_id'), 'campaign_versions', ['campaign_id'], unique=False)
|
||||
op.create_table('campaign_jobs',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('campaign_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('campaign_version_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('entry_index', sa.Integer(), nullable=False),
|
||||
sa.Column('entry_id', sa.String(length=255), nullable=True),
|
||||
sa.Column('recipient_email', sa.String(length=320), nullable=True),
|
||||
sa.Column('subject', sa.String(length=998), nullable=True),
|
||||
sa.Column('message_id_header', sa.String(length=255), nullable=True),
|
||||
sa.Column('eml_storage_key', sa.String(length=1000), nullable=True),
|
||||
sa.Column('eml_local_path', sa.String(length=1000), nullable=True),
|
||||
sa.Column('eml_size_bytes', sa.Integer(), nullable=True),
|
||||
sa.Column('build_status', sa.String(length=50), nullable=False),
|
||||
sa.Column('validation_status', sa.String(length=50), nullable=False),
|
||||
sa.Column('queue_status', sa.String(length=50), nullable=False),
|
||||
sa.Column('send_status', sa.String(length=50), nullable=False),
|
||||
sa.Column('imap_status', sa.String(length=50), nullable=False),
|
||||
sa.Column('attempt_count', sa.Integer(), nullable=False),
|
||||
sa.Column('last_error', sa.Text(), nullable=True),
|
||||
sa.Column('queued_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('sent_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('resolved_recipients', sa.JSON(), nullable=True),
|
||||
sa.Column('resolved_attachments', sa.JSON(), nullable=False),
|
||||
sa.Column('issues_snapshot', sa.JSON(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], name=op.f('fk_campaign_jobs_campaign_id_campaigns'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['campaign_version_id'], ['campaign_versions.id'], name=op.f('fk_campaign_jobs_campaign_version_id_campaign_versions'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_campaign_jobs_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_campaign_jobs')),
|
||||
sa.UniqueConstraint('campaign_version_id', 'entry_index', name='uq_campaign_jobs_version_entry')
|
||||
)
|
||||
op.create_index(op.f('ix_campaign_jobs_build_status'), 'campaign_jobs', ['build_status'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_campaign_id'), 'campaign_jobs', ['campaign_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_campaign_version_id'), 'campaign_jobs', ['campaign_version_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_entry_id'), 'campaign_jobs', ['entry_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_imap_status'), 'campaign_jobs', ['imap_status'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_queue_status'), 'campaign_jobs', ['queue_status'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_recipient_email'), 'campaign_jobs', ['recipient_email'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_send_status'), 'campaign_jobs', ['send_status'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_tenant_id'), 'campaign_jobs', ['tenant_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_jobs_validation_status'), 'campaign_jobs', ['validation_status'], unique=False)
|
||||
op.create_table('campaign_issues',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('tenant_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('campaign_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('campaign_version_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('job_id', sa.String(length=36), nullable=True),
|
||||
sa.Column('severity', sa.String(length=20), nullable=False),
|
||||
sa.Column('code', sa.String(length=100), nullable=False),
|
||||
sa.Column('message', sa.Text(), nullable=False),
|
||||
sa.Column('source', sa.String(length=255), nullable=True),
|
||||
sa.Column('behavior', sa.String(length=50), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['campaign_id'], ['campaigns.id'], name=op.f('fk_campaign_issues_campaign_id_campaigns'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['campaign_version_id'], ['campaign_versions.id'], name=op.f('fk_campaign_issues_campaign_version_id_campaign_versions'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['job_id'], ['campaign_jobs.id'], name=op.f('fk_campaign_issues_job_id_campaign_jobs'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['tenant_id'], ['tenants.id'], name=op.f('fk_campaign_issues_tenant_id_tenants'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_campaign_issues'))
|
||||
)
|
||||
op.create_index(op.f('ix_campaign_issues_campaign_id'), 'campaign_issues', ['campaign_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_issues_campaign_version_id'), 'campaign_issues', ['campaign_version_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_issues_code'), 'campaign_issues', ['code'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_issues_job_id'), 'campaign_issues', ['job_id'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_issues_severity'), 'campaign_issues', ['severity'], unique=False)
|
||||
op.create_index(op.f('ix_campaign_issues_tenant_id'), 'campaign_issues', ['tenant_id'], unique=False)
|
||||
op.create_table('imap_append_attempts',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('job_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('attempt_number', sa.Integer(), nullable=False),
|
||||
sa.Column('folder', sa.String(length=500), nullable=True),
|
||||
sa.Column('status', sa.String(length=50), nullable=False),
|
||||
sa.Column('error_message', sa.Text(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['job_id'], ['campaign_jobs.id'], name=op.f('fk_imap_append_attempts_job_id_campaign_jobs'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_imap_append_attempts'))
|
||||
)
|
||||
op.create_index(op.f('ix_imap_append_attempts_job_id'), 'imap_append_attempts', ['job_id'], unique=False)
|
||||
op.create_table('send_attempts',
|
||||
sa.Column('id', sa.String(length=36), nullable=False),
|
||||
sa.Column('job_id', sa.String(length=36), nullable=False),
|
||||
sa.Column('attempt_number', sa.Integer(), nullable=False),
|
||||
sa.Column('smtp_status_code', sa.Integer(), nullable=True),
|
||||
sa.Column('smtp_response', sa.Text(), nullable=True),
|
||||
sa.Column('error_type', sa.String(length=255), nullable=True),
|
||||
sa.Column('error_message', sa.Text(), nullable=True),
|
||||
sa.Column('started_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('finished_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.ForeignKeyConstraint(['job_id'], ['campaign_jobs.id'], name=op.f('fk_send_attempts_job_id_campaign_jobs'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_send_attempts'))
|
||||
)
|
||||
op.create_index(op.f('ix_send_attempts_job_id'), 'send_attempts', ['job_id'], unique=False)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_index(op.f('ix_send_attempts_job_id'), table_name='send_attempts')
|
||||
op.drop_table('send_attempts')
|
||||
op.drop_index(op.f('ix_imap_append_attempts_job_id'), table_name='imap_append_attempts')
|
||||
op.drop_table('imap_append_attempts')
|
||||
op.drop_index(op.f('ix_campaign_issues_tenant_id'), table_name='campaign_issues')
|
||||
op.drop_index(op.f('ix_campaign_issues_severity'), table_name='campaign_issues')
|
||||
op.drop_index(op.f('ix_campaign_issues_job_id'), table_name='campaign_issues')
|
||||
op.drop_index(op.f('ix_campaign_issues_code'), table_name='campaign_issues')
|
||||
op.drop_index(op.f('ix_campaign_issues_campaign_version_id'), table_name='campaign_issues')
|
||||
op.drop_index(op.f('ix_campaign_issues_campaign_id'), table_name='campaign_issues')
|
||||
op.drop_table('campaign_issues')
|
||||
op.drop_index(op.f('ix_campaign_jobs_validation_status'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_tenant_id'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_send_status'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_recipient_email'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_queue_status'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_imap_status'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_entry_id'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_campaign_version_id'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_campaign_id'), table_name='campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_jobs_build_status'), table_name='campaign_jobs')
|
||||
op.drop_table('campaign_jobs')
|
||||
op.drop_index(op.f('ix_campaign_versions_campaign_id'), table_name='campaign_versions')
|
||||
op.drop_table('campaign_versions')
|
||||
op.drop_index(op.f('ix_audit_log_user_id'), table_name='audit_log')
|
||||
op.drop_index(op.f('ix_audit_log_tenant_id'), table_name='audit_log')
|
||||
op.drop_index(op.f('ix_audit_log_object_type'), table_name='audit_log')
|
||||
op.drop_index(op.f('ix_audit_log_object_id'), table_name='audit_log')
|
||||
op.drop_index(op.f('ix_audit_log_api_key_id'), table_name='audit_log')
|
||||
op.drop_index(op.f('ix_audit_log_action'), table_name='audit_log')
|
||||
op.drop_table('audit_log')
|
||||
op.drop_index(op.f('ix_attachment_instances_tenant_id'), table_name='attachment_instances')
|
||||
op.drop_index(op.f('ix_attachment_instances_owner_user_id'), table_name='attachment_instances')
|
||||
op.drop_index(op.f('ix_attachment_instances_campaign_id'), table_name='attachment_instances')
|
||||
op.drop_index(op.f('ix_attachment_instances_blob_id'), table_name='attachment_instances')
|
||||
op.drop_table('attachment_instances')
|
||||
op.drop_index(op.f('ix_campaigns_tenant_id'), table_name='campaigns')
|
||||
op.drop_index(op.f('ix_campaigns_status'), table_name='campaigns')
|
||||
op.drop_index(op.f('ix_campaigns_external_id'), table_name='campaigns')
|
||||
op.drop_index(op.f('ix_campaigns_created_by_user_id'), table_name='campaigns')
|
||||
op.drop_table('campaigns')
|
||||
op.drop_index(op.f('ix_api_keys_user_id'), table_name='api_keys')
|
||||
op.drop_index(op.f('ix_api_keys_tenant_id'), table_name='api_keys')
|
||||
op.drop_index(op.f('ix_api_keys_prefix'), table_name='api_keys')
|
||||
op.drop_table('api_keys')
|
||||
op.drop_index(op.f('ix_users_tenant_id'), table_name='users')
|
||||
op.drop_index(op.f('ix_users_email'), table_name='users')
|
||||
op.drop_table('users')
|
||||
op.drop_index(op.f('ix_roles_tenant_id'), table_name='roles')
|
||||
op.drop_table('roles')
|
||||
op.drop_index(op.f('ix_groups_tenant_id'), table_name='groups')
|
||||
op.drop_table('groups')
|
||||
op.drop_index(op.f('ix_attachment_blobs_tenant_id'), table_name='attachment_blobs')
|
||||
op.drop_index(op.f('ix_attachment_blobs_sha256'), table_name='attachment_blobs')
|
||||
op.drop_table('attachment_blobs')
|
||||
op.drop_index(op.f('ix_tenants_slug'), table_name='tenants')
|
||||
op.drop_table('tenants')
|
||||
# ### end Alembic commands ###
|
||||
Reference in New Issue
Block a user