"""add_missing_user_fields Revision ID: 002_add_missing_user_fields Revises: 001_initial_baseline Create Date: 2026-01-04 Adds missing user fields to sync models.py with database: - scholarship_reason - directory_* fields (email, bio, address, phone, dob, partner_name) - profile_photo_url (rename from profile_image_url) - social_media_* fields (facebook, instagram, twitter, linkedin) - email_verification_expires """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision: str = '002_add_missing_user_fields' down_revision: Union[str, None] = '001_initial_baseline' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: """Add missing user fields (skip if already exists)""" from sqlalchemy import inspect conn = op.get_bind() inspector = inspect(conn) existing_columns = {col['name'] for col in inspector.get_columns('users')} # Add scholarship_reason if 'scholarship_reason' not in existing_columns: op.add_column('users', sa.Column('scholarship_reason', sa.Text(), nullable=True)) # Add directory fields if 'directory_email' not in existing_columns: op.add_column('users', sa.Column('directory_email', sa.String(), nullable=True)) if 'directory_bio' not in existing_columns: op.add_column('users', sa.Column('directory_bio', sa.Text(), nullable=True)) if 'directory_address' not in existing_columns: op.add_column('users', sa.Column('directory_address', sa.String(), nullable=True)) if 'directory_phone' not in existing_columns: op.add_column('users', sa.Column('directory_phone', sa.String(), nullable=True)) if 'directory_dob' not in existing_columns: op.add_column('users', sa.Column('directory_dob', sa.DateTime(), nullable=True)) if 'directory_partner_name' not in existing_columns: op.add_column('users', sa.Column('directory_partner_name', sa.String(), nullable=True)) # Rename profile_image_url to profile_photo_url (skip if already renamed) if 'profile_image_url' in existing_columns and 'profile_photo_url' not in existing_columns: op.alter_column('users', 'profile_image_url', new_column_name='profile_photo_url') # Add social media fields if 'social_media_facebook' not in existing_columns: op.add_column('users', sa.Column('social_media_facebook', sa.String(), nullable=True)) if 'social_media_instagram' not in existing_columns: op.add_column('users', sa.Column('social_media_instagram', sa.String(), nullable=True)) if 'social_media_twitter' not in existing_columns: op.add_column('users', sa.Column('social_media_twitter', sa.String(), nullable=True)) if 'social_media_linkedin' not in existing_columns: op.add_column('users', sa.Column('social_media_linkedin', sa.String(), nullable=True)) # Add email_verification_expires if missing if 'email_verification_expires' not in existing_columns: op.add_column('users', sa.Column('email_verification_expires', sa.DateTime(), nullable=True)) def downgrade() -> None: """Remove added fields (rollback)""" # Remove social media fields op.drop_column('users', 'social_media_linkedin') op.drop_column('users', 'social_media_twitter') op.drop_column('users', 'social_media_instagram') op.drop_column('users', 'social_media_facebook') # Rename profile_photo_url back to profile_image_url op.alter_column('users', 'profile_photo_url', new_column_name='profile_image_url') # Remove directory fields op.drop_column('users', 'directory_partner_name') op.drop_column('users', 'directory_dob') op.drop_column('users', 'directory_phone') op.drop_column('users', 'directory_address') op.drop_column('users', 'directory_bio') op.drop_column('users', 'directory_email') # Remove scholarship_reason op.drop_column('users', 'scholarship_reason')