"""Reports: folder_id column for folder-based sorting Revision ID: 0139 Revises: 0138 Create Date: 2026-08-21 Adds folder_id to report_templates for folder-based organization. """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects.postgresql import UUID as PGUUID # revision identifiers, used by Alembic. revision = "0139" down_revision = "0138" branch_labels = None depends_on = None def _table_exists(conn, table_name: str) -> bool: """True when the table exists (dual-path convergence, Gate B). On a fresh install the report_generator plugin SQL migration has not run yet when Alembic reaches this revision — skip instead of failing. The plugin-side convergence migration adds the same column. """ row = conn.execute( sa.text("SELECT to_regclass(:tname) IS NOT NULL"), {"tname": f"public.{table_name}"}, ).scalar() return bool(row) def upgrade() -> None: conn = op.get_bind() if not _table_exists(conn, "report_templates"): return op.add_column("report_templates", sa.Column("folder_id", PGUUID(as_uuid=True), nullable=True)) op.create_index("ix_report_templates_folder", "report_templates", ["folder_id"]) def downgrade() -> None: conn = op.get_bind() if not _table_exists(conn, "report_templates"): return op.drop_index("ix_report_templates_folder", table_name="report_templates") op.drop_column("report_templates", "folder_id")