"""fiscal_idempotency_keys (Task 5): backs the `Idempotency-Key` contract of `POST /v1/emissoes` (design spec decision #6) -- a separate table so the Task 3 `fiscal_documents` migration stays untouched. See `documents.models.FiscalIdempotencyKey`'s docstring for the two-layer idempotency pattern this table's UNIQUE constraint exists for. Revision ID: 30a80fe36910 Revises: 523235d06bd5 Create Date: 2026-07-22 00:00:00.000000 """ from __future__ import annotations from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "30a80fe36910" down_revision: Union[str, Sequence[str], None] = "523235d06bd5" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.create_table( "fiscal_idempotency_keys", sa.Column("id", sa.UUID(), nullable=False), sa.Column("product_id", sa.UUID(), nullable=False), sa.Column("idempotency_key", sa.String(length=255), nullable=False), sa.Column("document_id", sa.UUID(), 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.ForeignKeyConstraint(["product_id"], ["products.id"]), sa.ForeignKeyConstraint(["document_id"], ["fiscal_documents.id"]), sa.PrimaryKeyConstraint("id"), sa.UniqueConstraint( "product_id", "idempotency_key", name="uq_fiscal_idempotency_key_product_key" ), ) def downgrade() -> None: op.drop_table("fiscal_idempotency_keys")