-- v1.0.7 item A: add stripe_reversal_id column to seller_transfers. -- Prepares ground for item B (async reversal worker): when a refund-driven -- reversal succeeds, the worker persists the Stripe reversal id here so -- the operation is idempotent (a replayed webhook skips the reversal call -- if this column is populated) and auditable against the Stripe dashboard. -- -- This migration ships with item A because item B's worker is the next -- commit and we want the column in place before the code that writes it. -- Nullable — pre-v1.0.7 transfers will never have a reversal id. -- -- Companion column stripe_transfer_id already exists (pre-v1.0.7), but was -- never written to until item A: the TransferService.CreateTransfer -- signature changed to return the Stripe transfer id, which is now -- persisted by processSellerTransfers, TransferRetryWorker, and -- admin_transfer_handler. ALTER TABLE seller_transfers ADD COLUMN IF NOT EXISTS stripe_reversal_id VARCHAR(255); -- Partial UNIQUE index so a given Stripe reversal id cannot collide across -- rows, while still allowing many NULL/empty rows (the common case: only -- refunded transfers carry a reversal id). Mirrors the pattern landed in -- v1.0.6.1 for refunds.hyperswitch_refund_id. CREATE UNIQUE INDEX IF NOT EXISTS idx_seller_transfers_stripe_reversal_id ON seller_transfers(stripe_reversal_id) WHERE stripe_reversal_id IS NOT NULL AND stripe_reversal_id <> ''; -- Same pattern for stripe_transfer_id — previously declared without an -- index, now populated by item A so worth indexing for reconciliation -- lookups. Partial because pre-v1.0.7 rows carry empty values. CREATE UNIQUE INDEX IF NOT EXISTS idx_seller_transfers_stripe_transfer_id ON seller_transfers(stripe_transfer_id) WHERE stripe_transfer_id IS NOT NULL AND stripe_transfer_id <> ''; -- Visibility: how many historical rows lack a stripe_transfer_id? These -- are the rows that the backfill CLI (cmd/tools/backfill_stripe_transfer_ids) -- will target. Acceptable to leave NULL where Stripe has no match — see -- axis-1 P2.9 for the admin-triggered recovery path. DO $$ DECLARE v_count INTEGER; BEGIN SELECT COUNT(*) INTO v_count FROM seller_transfers WHERE status = 'completed' AND (stripe_transfer_id IS NULL OR stripe_transfer_id = ''); RAISE NOTICE 'v1.0.7 item A: % completed seller_transfer(s) have no stripe_transfer_id and need backfill (see cmd/tools/backfill_stripe_transfer_ids)', v_count; END $$;