"""Create hmrc_sync.tax_year_snapshot + hmrc_sync.fetch_log. These two tables hold everything hmrc-sync persists. The snapshot table keeps HMRC's `hmrc-held` PAYE/NI view per (tax_year, employer, day); fetch_log is the audit trail of every outbound API call (for fraud-header compliance reviews HMRC may trigger). """ import sqlalchemy as sa from sqlalchemy.dialects import postgresql from alembic import op revision = "0001" down_revision = None branch_labels = None depends_on = None SCHEMA = "hmrc_sync" def upgrade() -> None: op.create_table( "tax_year_snapshot", sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True), sa.Column("tax_year", sa.String(), nullable=False), sa.Column("employer_paye_ref", sa.String(), nullable=False), sa.Column("snapshot_date", sa.TIMESTAMP(timezone=True), nullable=False), sa.Column("gross_pay", sa.Numeric(12, 2), nullable=False), sa.Column("income_tax", sa.Numeric(12, 2), nullable=False), sa.Column("ni_contributions", sa.Numeric(12, 2), nullable=False), sa.Column("source", sa.String(), nullable=False, server_default="hmrc-held"), sa.Column( "raw_response", postgresql.JSONB().with_variant(sa.JSON(), "sqlite"), nullable=False, ), sa.Column( "fetched_at", sa.TIMESTAMP(timezone=True), nullable=False, server_default=sa.text("now()"), ), sa.UniqueConstraint( "tax_year", "employer_paye_ref", "snapshot_date", name="uq_tax_year_snapshot", ), schema=SCHEMA, ) op.create_index( "ix_tax_year_snapshot_tax_year", "tax_year_snapshot", ["tax_year"], schema=SCHEMA, ) op.create_table( "fetch_log", sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True), sa.Column("endpoint", sa.String(), nullable=False), sa.Column("status_code", sa.Integer(), nullable=False), sa.Column("request_id", sa.String(), nullable=True), sa.Column("correlation_id", sa.String(), nullable=True), sa.Column( "fraud_headers_sent", postgresql.JSONB().with_variant(sa.JSON(), "sqlite"), nullable=False, ), sa.Column("response_snippet", sa.String(), nullable=True), sa.Column("duration_ms", sa.Integer(), nullable=False), sa.Column( "fetched_at", sa.TIMESTAMP(timezone=True), nullable=False, server_default=sa.text("now()"), ), schema=SCHEMA, ) def downgrade() -> None: op.drop_table("fetch_log", schema=SCHEMA) op.drop_index("ix_tax_year_snapshot_tax_year", table_name="tax_year_snapshot", schema=SCHEMA) op.drop_table("tax_year_snapshot", schema=SCHEMA)