Schema: purge ALTERs per pre-launch recreate policy; nullable account_id for unredeemed gift-card expiries

The project is pre-launch with no production DB — all dev starts from a fresh
volume recreated from init-scripts/init-script.sql. All ALTER statements are
removed and their effects expressed directly in the CREATE statements:
name_history now lives after bookings with its booking_id FK inlined (no
ALTER TABLE ADD CONSTRAINT), the critical_payment_log enum value is in the
CREATE TYPE (no ALTER TYPE ADD VALUE), and voucher_type_at_purchase is in the
CREATE TABLE gift_cards (no ADD COLUMN).

gift_card_expired_balances.account_id is now nullable: CleanupExpiredGiftCards
inserts NULL for unredeemed gift cards (bought for non-account-holders, never
claimed) — a NOT NULL column made that expiry fail at runtime. The three tests
that papered over this with ALTER TABLE DROP NOT NULL now rely on the schema
directly.
This commit is contained in:
2026-08-22 00:34:49 +01:00
parent 3f6250ea81
commit d9c2c5ac2c
2 changed files with 29 additions and 56 deletions
@@ -2688,16 +2688,12 @@ func TestCleanupExpiredGiftCards(t *testing.T) {
t.Parallel()
ctx, tx := resetTestData(t)
// Make account_id nullable for this test — CleanupExpiredGiftCards inserts NULL
// account_id is nullable in the schema — CleanupExpiredGiftCards inserts NULL
// for unredeemed gift cards (no user account to reference).
_, err := tx.Exec(ctx, `ALTER TABLE gift_card_expired_balances ALTER COLUMN account_id DROP NOT NULL`)
if err != nil {
t.Fatalf("failed to alter gift_card_expired_balances: %v", err)
}
// Create expired gift card (unused for 25 months)
var expiredCardID string
err = tx.QueryRow(ctx, `
err := tx.QueryRow(ctx, `
INSERT INTO gift_cards (total_funds_added, amount_remaining, last_used_at)
VALUES (100.00, 50.00, NOW() - INTERVAL '25 months')
RETURNING id
@@ -2759,16 +2755,9 @@ func TestCleanupExpiredGiftCards_SkipRecentlyUsed(t *testing.T) {
t.Parallel()
ctx, tx := resetTestData(t)
// Make account_id nullable for this test — CleanupExpiredGiftCards inserts NULL
// for unredeemed gift cards (no user account to reference).
_, err := tx.Exec(ctx, `ALTER TABLE gift_card_expired_balances ALTER COLUMN account_id DROP NOT NULL`)
if err != nil {
t.Fatalf("failed to alter gift_card_expired_balances: %v", err)
}
// Create recently used gift card
var recentCardID string
err = tx.QueryRow(ctx, `
err := tx.QueryRow(ctx, `
INSERT INTO gift_cards (total_funds_added, amount_remaining, last_used_at)
VALUES (100.00, 75.00, NOW())
RETURNING id
@@ -2810,14 +2799,6 @@ func TestCleanupExpiredGiftCards_SkipRedeemed(t *testing.T) {
t.Parallel()
ctx, tx := resetTestData(t)
// Make account_id nullable for this test — CleanupExpiredGiftCards inserts NULL
// for unredeemed gift cards (no user account to reference). Even though this
// card is redeemed, the function may also match other cards; ensure schema allows it.
_, err := tx.Exec(ctx, `ALTER TABLE gift_card_expired_balances ALTER COLUMN account_id DROP NOT NULL`)
if err != nil {
t.Fatalf("failed to alter gift_card_expired_balances: %v", err)
}
// Create a user to be the redeemer
userID, err := fixtures.CreateTestUser(tx)
if err != nil {