"""prd012: add fee_settlement_run_id FK column to transactions.

Links each platform-fee-bearing transaction to the fee_settlement_runs row
that claimed it during the daily sweep.  NULL means the transaction has not
yet been swept (the expected state for the vast majority of rows).

A partial index (WHERE fee_settlement_run_id IS NOT NULL) is used instead of
a full-table index because:
  - Most rows in `transactions` will be unsettled (NULL) at any given time.
  - The daily sweep query filters WHERE fee_settlement_run_id IS NULL to find
    unclaimed transactions — this query does NOT benefit from the partial index
    and uses a seqscan + platform_fee_amount IS NOT NULL filter instead.
  - The admin detail query "show me all transactions in run X" hits the partial
    index directly, giving fast lookups without bloating the index with NULLs.

Revision ID: prd012_add_fee_settlement_run_id_to_transactions
Revises: prd012_add_fee_settlement_tables
Create Date: 2026-05-14
"""
from typing import Union, Sequence

import sqlalchemy as sa
from alembic import op

revision: str = "prd012_add_fee_settlement_run_id_to_transactions"
down_revision: Union[str, Sequence[str], None] = "prd012_add_fee_settlement_tables"
branch_labels = None
depends_on = None


def upgrade() -> None:
    # ------------------------------------------------------------------
    # Add fee_settlement_run_id column to transactions
    # ------------------------------------------------------------------
    op.add_column(
        "transactions",
        sa.Column(
            "fee_settlement_run_id",
            sa.Integer(),
            sa.ForeignKey(
                "fee_settlement_runs.id",
                name="fk_transactions_fee_settlement_run",
                ondelete="SET NULL",
            ),
            nullable=True,
        ),
    )

    # ------------------------------------------------------------------
    # Partial index: only index rows that have been assigned to a run.
    # Used by: "SELECT * FROM transactions WHERE fee_settlement_run_id = :run_id"
    # ------------------------------------------------------------------
    op.create_index(
        "ix_transactions_fee_settlement_run_id",
        "transactions",
        ["fee_settlement_run_id"],
        postgresql_where=sa.text("fee_settlement_run_id IS NOT NULL"),
    )


def downgrade() -> None:
    op.drop_index(
        "ix_transactions_fee_settlement_run_id",
        table_name="transactions",
    )
    op.drop_column("transactions", "fee_settlement_run_id")
