"""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')