"""Initial onboarding progress tables Revision ID: 001_initial_onboarding_tables Revises: Create Date: 2024-12-20 15:30:00.000000 """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. revision = '001_initial_onboarding_tables' down_revision = None # No previous migration branch_labels = None depends_on = None def upgrade() -> None: # Create users table first (if it doesn't exist) op.create_table( 'users', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False, primary_key=True), sa.Column('email', sa.String(length=255), nullable=False, unique=True, index=True), sa.Column('hashed_password', sa.String(length=255), nullable=False), sa.Column('full_name', sa.String(length=255), nullable=False), sa.Column('is_active', sa.Boolean(), nullable=False, default=True), sa.Column('is_verified', sa.Boolean(), nullable=False, default=False), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), sa.Column('last_login', sa.DateTime(timezone=True), nullable=True), sa.Column('phone', sa.String(length=20), nullable=True), sa.Column('language', sa.String(length=10), nullable=True, default='es'), sa.Column('timezone', sa.String(length=50), nullable=True, default='Europe/Madrid'), sa.Column('role', sa.String(length=20), nullable=False), ) # Create refresh_tokens table op.create_table( 'refresh_tokens', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False, primary_key=True), sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('token', sa.String(length=500), nullable=False, unique=True), sa.Column('expires_at', sa.DateTime(timezone=True), nullable=False), sa.Column('is_revoked', sa.Boolean(), nullable=False, default=False), 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), # Foreign key to users table sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'), ) # Create user_onboarding_progress table op.create_table( 'user_onboarding_progress', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False, primary_key=True), sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False, index=True), sa.Column('step_name', sa.String(length=50), nullable=False), sa.Column('completed', sa.Boolean(), nullable=False, default=False), sa.Column('completed_at', sa.DateTime(timezone=True), nullable=True), sa.Column('step_data', sa.JSON(), nullable=True, default=dict), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), # Foreign key to users table sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'), # Unique constraint to prevent duplicate steps per user sa.UniqueConstraint('user_id', 'step_name', name='uq_user_step'), # Indexes for performance sa.Index('ix_user_onboarding_progress_user_id', 'user_id'), sa.Index('ix_user_onboarding_progress_step_name', 'step_name'), sa.Index('ix_user_onboarding_progress_completed', 'completed'), ) # Create user_onboarding_summary table op.create_table( 'user_onboarding_summary', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False, primary_key=True), sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False, unique=True, index=True), sa.Column('current_step', sa.String(length=50), nullable=False, default='user_registered'), sa.Column('next_step', sa.String(length=50), nullable=True), sa.Column('completion_percentage', sa.String(length=10), nullable=True, default='0.0'), sa.Column('fully_completed', sa.Boolean(), nullable=False, default=False), sa.Column('steps_completed_count', sa.String(length=10), nullable=True, default='0'), sa.Column('created_at', sa.DateTime(timezone=True), nullable=False), sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False), sa.Column('last_activity_at', sa.DateTime(timezone=True), nullable=False), # Foreign key to users table sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'), # Indexes for performance sa.Index('ix_user_onboarding_summary_user_id', 'user_id'), sa.Index('ix_user_onboarding_summary_current_step', 'current_step'), sa.Index('ix_user_onboarding_summary_fully_completed', 'fully_completed'), ) def downgrade() -> None: # Drop tables in reverse order op.drop_table('user_onboarding_summary') op.drop_table('user_onboarding_progress') op.drop_table('refresh_tokens') op.drop_table('users')