"""schema initial

Revision ID: 0001
Revises: 
Create Date: 2026-10-07 11:00:22.614739
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

revision = '0001'
down_revision = None
branch_labels = None
depends_on = None


def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('auth_throttle',
    sa.Column('key', sa.String(length=160), nullable=False),
    sa.Column('failures', sa.Integer(), nullable=False),
    sa.Column('first_failure_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('locked_until', sa.DateTime(timezone=True), nullable=True),
    sa.Column('lock_count', sa.Integer(), nullable=False),
    sa.PrimaryKeyConstraint('key')
    )
    op.create_table('indicator_categories',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('label', sa.String(length=120), nullable=False),
    sa.Column('position', sa.Integer(), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_table('jobs',
    sa.Column('id', sa.BigInteger(), nullable=False),
    sa.Column('kind', sa.String(length=32), nullable=False),
    sa.Column('payload', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('status', sa.String(length=16), nullable=False),
    sa.Column('progress', sa.Integer(), nullable=False),
    sa.Column('message', sa.Text(), nullable=True),
    sa.Column('attempts', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('started_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('finished_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint("status IN ('en_attente', 'en_cours', 'termine', 'echec')", name='ck_jobs_status'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_jobs_status'), 'jobs', ['status'], unique=False)
    op.create_table('permissions',
    sa.Column('code', sa.String(length=48), nullable=False),
    sa.Column('label', sa.String(length=160), nullable=False),
    sa.PrimaryKeyConstraint('code')
    )
    op.create_table('roles',
    sa.Column('code', sa.String(length=32), nullable=False),
    sa.Column('label', sa.String(length=80), nullable=False),
    sa.PrimaryKeyConstraint('code')
    )
    op.create_table('indicators',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('code', sa.String(length=48), nullable=False),
    sa.Column('label', sa.String(length=160), nullable=False),
    sa.Column('position', sa.Integer(), nullable=False),
    sa.Column('is_active', sa.Boolean(), nullable=False),
    sa.Column('category_id', sa.Integer(), nullable=True),
    sa.Column('detail_kind', sa.String(length=16), nullable=True),
    sa.Column('detail_unit', sa.String(length=32), nullable=False),
    sa.Column('direction', sa.String(length=24), nullable=True),
    sa.Column('warn_max', sa.Integer(), nullable=True),
    sa.Column('include_in_total', sa.Boolean(), nullable=False),
    sa.Column('aliases', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.CheckConstraint("detail_kind IS NULL OR detail_kind IN ('taux','vitesse')", name='ck_ind_detail'),
    sa.CheckConstraint("direction IS NULL OR direction IN ('hausse_favorable','baisse_favorable')", name='ck_ind_direction'),
    sa.ForeignKeyConstraint(['category_id'], ['indicator_categories.id'], ),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('code')
    )
    op.create_table('role_permissions',
    sa.Column('role_code', sa.String(length=32), nullable=False),
    sa.Column('permission_code', sa.String(length=48), nullable=False),
    sa.ForeignKeyConstraint(['permission_code'], ['permissions.code'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['role_code'], ['roles.code'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('role_code', 'permission_code')
    )
    op.create_table('users',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('username', sa.String(length=64), nullable=False),
    sa.Column('display_name', sa.String(length=120), nullable=False),
    sa.Column('role_code', sa.String(length=32), nullable=False),
    sa.Column('is_active', sa.Boolean(), nullable=False),
    sa.Column('can_export', sa.Boolean(), nullable=False),
    sa.Column('password_hash', sa.String(length=255), nullable=False),
    sa.Column('must_change_password', sa.Boolean(), nullable=False),
    sa.Column('password_changed_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('mfa_enabled', sa.Boolean(), nullable=False),
    sa.Column('mfa_secret_enc', sa.LargeBinary(), nullable=True),
    sa.Column('mfa_pending_secret_enc', sa.LargeBinary(), nullable=True),
    sa.Column('mfa_last_step', sa.BigInteger(), nullable=True),
    sa.Column('last_login_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('created_by', sa.Integer(), nullable=True),
    sa.Column('deactivated_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint('username = lower(username)', name='ck_users_username_lower'),
    sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
    sa.ForeignKeyConstraint(['role_code'], ['roles.code'], ),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('username')
    )
    op.create_table('audit_log',
    sa.Column('id', sa.BigInteger(), nullable=False),
    sa.Column('at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=True),
    sa.Column('username', sa.String(length=64), nullable=True),
    sa.Column('action', sa.String(length=64), nullable=False),
    sa.Column('target_type', sa.String(length=32), nullable=True),
    sa.Column('target_id', sa.String(length=64), nullable=True),
    sa.Column('ip', sa.String(length=64), nullable=True),
    sa.Column('details', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('prev_hash', sa.String(length=64), nullable=False),
    sa.Column('hash', sa.String(length=64), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_audit_log_action'), 'audit_log', ['action'], unique=False)
    op.create_table('bilans',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('iso_year', sa.Integer(), nullable=False),
    sa.Column('iso_week', sa.Integer(), nullable=False),
    sa.Column('period_start', sa.Date(), nullable=False),
    sa.Column('period_end', sa.Date(), nullable=False),
    sa.Column('status', sa.String(length=16), nullable=False),
    sa.Column('revision', sa.Integer(), nullable=False),
    sa.Column('current_version', sa.Integer(), nullable=False),
    sa.Column('is_demo', sa.Boolean(), nullable=False),
    sa.Column('created_by', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_by', sa.Integer(), nullable=True),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('validated_by', sa.Integer(), nullable=True),
    sa.Column('validated_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('reopened_by', sa.Integer(), nullable=True),
    sa.Column('reopened_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('reopen_reason', sa.Text(), nullable=True),
    sa.Column('archived_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint("status IN ('brouillon', 'a_verifier', 'valide', 'rouvert', 'archive')", name='ck_bilans_status'),
    sa.CheckConstraint('iso_week BETWEEN 1 AND 53', name='ck_bilans_week'),
    sa.CheckConstraint('period_end = period_start + 6', name='ck_bilans_period'),
    sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
    sa.ForeignKeyConstraint(['reopened_by'], ['users.id'], ),
    sa.ForeignKeyConstraint(['updated_by'], ['users.id'], ),
    sa.ForeignKeyConstraint(['validated_by'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('iso_year', 'iso_week', name='uq_bilans_week')
    )
    op.create_table('imports',
    sa.Column('id', sa.UUID(), nullable=False),
    sa.Column('original_name', sa.String(length=160), nullable=False),
    sa.Column('stored_name', sa.String(length=80), nullable=False),
    sa.Column('size', sa.Integer(), nullable=False),
    sa.Column('sha256', sa.String(length=64), nullable=False),
    sa.Column('detected_format', sa.String(length=16), nullable=False),
    sa.Column('detected_mime', sa.String(length=100), nullable=False),
    sa.Column('declared_mime', sa.String(length=100), nullable=True),
    sa.Column('status', sa.String(length=16), nullable=False),
    sa.Column('av_status', sa.String(length=16), nullable=False),
    sa.Column('error_message', sa.Text(), nullable=True),
    sa.Column('analysis', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('target_iso_year', sa.Integer(), nullable=True),
    sa.Column('target_iso_week', sa.Integer(), nullable=True),
    sa.Column('duplicate_of', sa.UUID(), nullable=True),
    sa.Column('uploaded_by', sa.Integer(), nullable=False),
    sa.Column('uploaded_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('finished_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('purged_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint("status IN ('en_attente', 'en_cours', 'analyse', 'echec', 'applique', 'annule', 'rejete')", name='ck_imports_status'),
    sa.ForeignKeyConstraint(['uploaded_by'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_imports_sha256'), 'imports', ['sha256'], unique=False)
    op.create_table('recovery_codes',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('code_hash', sa.String(length=64), nullable=False),
    sa.Column('used_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_recovery_codes_user_id'), 'recovery_codes', ['user_id'], unique=False)
    op.create_table('sessions',
    sa.Column('id', sa.String(length=64), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('csrf_token', sa.String(length=64), nullable=False),
    sa.Column('mfa_verified', sa.Boolean(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('last_seen_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('expires_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('revoked_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('revoked_reason', sa.String(length=80), nullable=True),
    sa.Column('ip', sa.String(length=64), nullable=True),
    sa.Column('user_agent', sa.String(length=200), nullable=True),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_sessions_user_id'), 'sessions', ['user_id'], unique=False)
    op.create_table('settings',
    sa.Column('key', sa.String(length=64), nullable=False),
    sa.Column('value', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('updated_by', sa.Integer(), nullable=True),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.ForeignKeyConstraint(['updated_by'], ['users.id'], ),
    sa.PrimaryKeyConstraint('key')
    )
    op.create_table('bilan_values',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('bilan_id', sa.Integer(), nullable=False),
    sa.Column('indicator_id', sa.Integer(), nullable=False),
    sa.Column('value', sa.Integer(), nullable=True),
    sa.Column('observation', sa.Text(), nullable=False),
    sa.Column('label_snapshot', sa.String(length=160), nullable=False),
    sa.Column('source_kind', sa.String(length=16), nullable=False),
    sa.Column('import_id', sa.UUID(), nullable=True),
    sa.Column('source_locator', sa.String(length=160), nullable=True),
    sa.Column('source_ref', sa.String(length=160), nullable=True),
    sa.Column('source_bbox', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
    sa.Column('confidence', sa.Float(), nullable=True),
    sa.Column('warnings', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('created_by', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('updated_by', sa.Integer(), nullable=True),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.CheckConstraint("source_kind IN ('manuel','collage','import','reprise','restauration','demo')", name='ck_values_source'),
    sa.CheckConstraint('value IS NULL OR (value >= 0 AND value <= 100000)', name='ck_values_value'),
    sa.ForeignKeyConstraint(['bilan_id'], ['bilans.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
    sa.ForeignKeyConstraint(['import_id'], ['imports.id'], ),
    sa.ForeignKeyConstraint(['indicator_id'], ['indicators.id'], ),
    sa.ForeignKeyConstraint(['updated_by'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('bilan_id', 'indicator_id', name='uq_values_bilan_indicator')
    )
    op.create_index(op.f('ix_bilan_values_bilan_id'), 'bilan_values', ['bilan_id'], unique=False)
    op.create_table('bilan_versions',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('bilan_id', sa.Integer(), nullable=False),
    sa.Column('version_no', sa.Integer(), nullable=False),
    sa.Column('snapshot', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('snapshot_sha256', sa.String(length=64), nullable=False),
    sa.Column('comment', sa.Text(), nullable=True),
    sa.Column('is_demo', sa.Boolean(), nullable=False),
    sa.Column('created_by', sa.Integer(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.ForeignKeyConstraint(['bilan_id'], ['bilans.id'], ),
    sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('bilan_id', 'version_no', name='uq_versions_no')
    )
    op.create_index(op.f('ix_bilan_versions_bilan_id'), 'bilan_versions', ['bilan_id'], unique=False)
    op.create_table('comments',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('bilan_id', sa.Integer(), nullable=False),
    sa.Column('user_id', sa.Integer(), nullable=False),
    sa.Column('body', sa.Text(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.ForeignKeyConstraint(['bilan_id'], ['bilans.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_comments_bilan_id'), 'comments', ['bilan_id'], unique=False)
    op.create_table('exports',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('bilan_id', sa.Integer(), nullable=True),
    sa.Column('kind', sa.String(length=8), nullable=False),
    sa.Column('options', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('pages', sa.Integer(), nullable=True),
    sa.Column('size', sa.Integer(), nullable=False),
    sa.Column('sha256', sa.String(length=64), nullable=False),
    sa.Column('created_by', sa.Integer(), nullable=False),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.ForeignKeyConstraint(['bilan_id'], ['bilans.id'], ondelete='SET NULL'),
    sa.ForeignKeyConstraint(['created_by'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_table('import_applications',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('import_id', sa.UUID(), nullable=False),
    sa.Column('bilan_id', sa.Integer(), nullable=False),
    sa.Column('before_snapshot', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('after_snapshot', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('report', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('applied_by', sa.Integer(), nullable=False),
    sa.Column('applied_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('reverted_by', sa.Integer(), nullable=True),
    sa.Column('reverted_at', sa.DateTime(timezone=True), nullable=True),
    sa.ForeignKeyConstraint(['applied_by'], ['users.id'], ),
    sa.ForeignKeyConstraint(['bilan_id'], ['bilans.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['import_id'], ['imports.id'], ),
    sa.ForeignKeyConstraint(['reverted_by'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_import_applications_import_id'), 'import_applications', ['import_id'], unique=False)
    op.create_table('import_sources',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('import_id', sa.UUID(), nullable=False),
    sa.Column('kind', sa.String(length=16), nullable=False),
    sa.Column('index', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=160), nullable=False),
    sa.Column('hidden', sa.Boolean(), nullable=False),
    sa.Column('width', sa.Integer(), nullable=True),
    sa.Column('height', sa.Integer(), nullable=True),
    sa.Column('image_name', sa.String(length=80), nullable=True),
    sa.Column('grid', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
    sa.Column('meta', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.ForeignKeyConstraint(['import_id'], ['imports.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_import_sources_import_id'), 'import_sources', ['import_id'], unique=False)
    op.create_table('value_history',
    sa.Column('id', sa.BigInteger(), nullable=False),
    sa.Column('bilan_id', sa.Integer(), nullable=False),
    sa.Column('indicator_id', sa.Integer(), nullable=False),
    sa.Column('field', sa.String(length=16), nullable=False),
    sa.Column('old_value', sa.Text(), nullable=True),
    sa.Column('new_value', sa.Text(), nullable=True),
    sa.Column('source_kind', sa.String(length=16), nullable=False),
    sa.Column('import_id', sa.UUID(), nullable=True),
    sa.Column('reason', sa.Text(), nullable=True),
    sa.Column('user_id', sa.Integer(), nullable=True),
    sa.Column('at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.Column('last_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
    sa.ForeignKeyConstraint(['bilan_id'], ['bilans.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['indicator_id'], ['indicators.id'], ),
    sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_value_history_bilan_id'), 'value_history', ['bilan_id'], unique=False)
    op.create_table('import_proposals',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('import_id', sa.UUID(), nullable=False),
    sa.Column('source_id', sa.Integer(), nullable=True),
    sa.Column('row_index', sa.Integer(), nullable=False),
    sa.Column('raw_label', sa.Text(), nullable=False),
    sa.Column('indicator_id', sa.Integer(), nullable=True),
    sa.Column('match_score', sa.Float(), nullable=False),
    sa.Column('raw_value', sa.String(length=200), nullable=False),
    sa.Column('value', sa.Integer(), nullable=True),
    sa.Column('value_error', sa.String(length=200), nullable=True),
    sa.Column('observation', sa.Text(), nullable=False),
    sa.Column('details', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('label_ref', sa.String(length=40), nullable=True),
    sa.Column('value_ref', sa.String(length=40), nullable=True),
    sa.Column('observation_ref', sa.String(length=40), nullable=True),
    sa.Column('bbox', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
    sa.Column('value_bbox', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
    sa.Column('confidence', sa.Float(), nullable=False),
    sa.Column('warnings', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
    sa.Column('decision', sa.String(length=16), nullable=False),
    sa.Column('edited', sa.Boolean(), nullable=False),
    sa.Column('updated_by', sa.Integer(), nullable=True),
    sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
    sa.CheckConstraint("decision IN ('a_verifier','accepte','ignore')", name='ck_proposals_decision'),
    sa.ForeignKeyConstraint(['import_id'], ['imports.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['indicator_id'], ['indicators.id'], ),
    sa.ForeignKeyConstraint(['source_id'], ['import_sources.id'], ondelete='CASCADE'),
    sa.ForeignKeyConstraint(['updated_by'], ['users.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_import_proposals_import_id'), 'import_proposals', ['import_id'], unique=False)
    op.create_table('value_details',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('value_id', sa.Integer(), nullable=False),
    sa.Column('kind', sa.String(length=16), nullable=False),
    sa.Column('amount', sa.Numeric(precision=10, scale=3), nullable=False),
    sa.Column('unit', sa.String(length=32), nullable=False),
    sa.Column('position', sa.Integer(), nullable=False),
    sa.CheckConstraint("kind IN ('taux','vitesse')", name='ck_details_kind'),
    sa.CheckConstraint('amount >= 0', name='ck_details_amount'),
    sa.ForeignKeyConstraint(['value_id'], ['bilan_values.id'], ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_value_details_value_id'), 'value_details', ['value_id'], unique=False)
    # ### end Alembic commands ###


def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_value_details_value_id'), table_name='value_details')
    op.drop_table('value_details')
    op.drop_index(op.f('ix_import_proposals_import_id'), table_name='import_proposals')
    op.drop_table('import_proposals')
    op.drop_index(op.f('ix_value_history_bilan_id'), table_name='value_history')
    op.drop_table('value_history')
    op.drop_index(op.f('ix_import_sources_import_id'), table_name='import_sources')
    op.drop_table('import_sources')
    op.drop_index(op.f('ix_import_applications_import_id'), table_name='import_applications')
    op.drop_table('import_applications')
    op.drop_table('exports')
    op.drop_index(op.f('ix_comments_bilan_id'), table_name='comments')
    op.drop_table('comments')
    op.drop_index(op.f('ix_bilan_versions_bilan_id'), table_name='bilan_versions')
    op.drop_table('bilan_versions')
    op.drop_index(op.f('ix_bilan_values_bilan_id'), table_name='bilan_values')
    op.drop_table('bilan_values')
    op.drop_table('settings')
    op.drop_index(op.f('ix_sessions_user_id'), table_name='sessions')
    op.drop_table('sessions')
    op.drop_index(op.f('ix_recovery_codes_user_id'), table_name='recovery_codes')
    op.drop_table('recovery_codes')
    op.drop_index(op.f('ix_imports_sha256'), table_name='imports')
    op.drop_table('imports')
    op.drop_table('bilans')
    op.drop_index(op.f('ix_audit_log_action'), table_name='audit_log')
    op.drop_table('audit_log')
    op.drop_table('users')
    op.drop_table('role_permissions')
    op.drop_table('indicators')
    op.drop_table('roles')
    op.drop_table('permissions')
    op.drop_index(op.f('ix_jobs_status'), table_name='jobs')
    op.drop_table('jobs')
    op.drop_table('indicator_categories')
    op.drop_table('auth_throttle')
    # ### end Alembic commands ###
