modcomms/backend/alembic/versions/001_initial_schema.py
2025-12-18 16:51:27 +00:00

160 lines
7.8 KiB
Python
Executable file

"""Initial schema
Revision ID: 001_initial
Revises:
Create Date: 2024-12-16
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision: str = '001_initial'
down_revision: Union[str, None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
# Create agencies table
op.create_table(
'agencies',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('name', sa.String(255), nullable=False, unique=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
)
# Create users table
op.create_table(
'users',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('azure_ad_oid', sa.String(255), nullable=False, unique=True),
sa.Column('email', sa.String(255), nullable=False),
sa.Column('name', sa.String(255), nullable=False),
sa.Column('role', sa.String(50), nullable=False, server_default='basic_user'),
sa.Column('agency_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('agencies.id'), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
)
# Create campaigns table
op.create_table(
'campaigns',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('name', sa.String(255), nullable=False),
sa.Column('workfront_id', sa.String(100), nullable=True),
sa.Column('client_lead', sa.String(255), nullable=True),
sa.Column('agency_lead', sa.String(255), nullable=True),
sa.Column('brand_guidelines', sa.String(50), nullable=True),
sa.Column('status', sa.String(50), server_default='In Progress'),
sa.Column('agency_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('agencies.id'), nullable=True),
sa.Column('created_by', postgresql.UUID(as_uuid=True), sa.ForeignKey('users.id'), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
)
# Create proofs table
op.create_table(
'proofs',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('campaign_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('campaigns.id', ondelete='CASCADE'), nullable=False),
sa.Column('proof_name', sa.String(255), nullable=False),
sa.Column('channel', sa.String(100), nullable=True),
sa.Column('sub_channel', sa.String(100), nullable=True),
sa.Column('proof_type', sa.String(100), nullable=True),
sa.Column('workfront_id', sa.String(100), nullable=True),
sa.Column('created_by', postgresql.UUID(as_uuid=True), sa.ForeignKey('users.id'), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.UniqueConstraint('campaign_id', 'proof_name', name='uq_campaign_proof_name'),
)
# Create proof_versions table
op.create_table(
'proof_versions',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('proof_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('proofs.id', ondelete='CASCADE'), nullable=False),
sa.Column('version', sa.Integer, nullable=False),
sa.Column('file_storage_key', sa.String(500), nullable=True),
sa.Column('thumbnail_url', sa.Text, nullable=True),
sa.Column('agent_review', postgresql.JSONB, nullable=True),
sa.Column('overall_status', sa.String(50), nullable=True),
sa.Column('workfront_id', sa.String(100), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.UniqueConstraint('proof_id', 'version', name='uq_proof_version'),
)
# Create flagged_items table
op.create_table(
'flagged_items',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('proof_version_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('proof_versions.id'), nullable=False),
sa.Column('agent_flagged', sa.String(100), nullable=False),
sa.Column('comments', sa.Text, nullable=True),
sa.Column('submitter_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('users.id'), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
)
# Create resolved_items table
op.create_table(
'resolved_items',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('proof_version_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('proof_versions.id'), nullable=False),
sa.Column('agent', sa.String(100), nullable=False),
sa.Column('issue', sa.Text, nullable=True),
sa.Column('resolution', sa.Text, nullable=True),
sa.Column('submitter_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('users.id'), nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
)
# Create error_items table
op.create_table(
'error_items',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('proof_version_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('proof_versions.id'), nullable=False),
sa.Column('error_summary', sa.Text, nullable=True),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
)
# Create dropdown_options table for configurable options
op.create_table(
'dropdown_options',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, server_default=sa.text('gen_random_uuid()')),
sa.Column('option_type', sa.String(50), nullable=False),
sa.Column('parent_id', postgresql.UUID(as_uuid=True), sa.ForeignKey('dropdown_options.id'), nullable=True),
sa.Column('value', sa.String(255), nullable=False),
sa.Column('display_order', sa.Integer, server_default='0'),
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.func.now()),
)
# Create indexes for common queries
op.create_index('idx_campaigns_agency', 'campaigns', ['agency_id'])
op.create_index('idx_proofs_campaign', 'proofs', ['campaign_id'])
op.create_index('idx_proof_versions_proof', 'proof_versions', ['proof_id'])
op.create_index('idx_proof_versions_status', 'proof_versions', ['overall_status'])
op.create_index('idx_users_agency', 'users', ['agency_id'])
op.create_index('idx_flagged_items_version', 'flagged_items', ['proof_version_id'])
op.create_index('idx_resolved_items_version', 'resolved_items', ['proof_version_id'])
def downgrade() -> None:
# Drop indexes
op.drop_index('idx_resolved_items_version')
op.drop_index('idx_flagged_items_version')
op.drop_index('idx_users_agency')
op.drop_index('idx_proof_versions_status')
op.drop_index('idx_proof_versions_proof')
op.drop_index('idx_proofs_campaign')
op.drop_index('idx_campaigns_agency')
# Drop tables in reverse order
op.drop_table('dropdown_options')
op.drop_table('error_items')
op.drop_table('resolved_items')
op.drop_table('flagged_items')
op.drop_table('proof_versions')
op.drop_table('proofs')
op.drop_table('campaigns')
op.drop_table('users')
op.drop_table('agencies')