Gift-card rolling expiry, SvelteDate→Date purge, strict DST tests, UTC scan-location + settings legal floor
Gift-card rolling expiry (setting-driven, was dead config): - GetGiftCardExpiryMonths(): single source of truth (business_settings gift_card_expiry_months, fallback 24) shared by payment handlers and the CleanupExpiredGiftCards job (was hardcoded 24). - expiry_date now maintained on ALL 9 gift-card write sites (buy, topup, transfer, redeem, terminal payment, refund credit, till) so the refund-time guard at refunds.go actually fires. Schema default 12->24 + migration note; test-DB seed aligned. Stale "expiry_date IS NULL" test rewritten; new expired-card-rejected regression test. Frontend SvelteDate purge (docs' stated convention, wide): - All 180+ raw `new SvelteDate(...)` uses across routes/components replaced with parseWallClockDate (backend UTC ISO) or new Date (wall-clock constructors). SvelteDate imports removed. timeSlots.ts getDayWithOrdinal fixed. Zero SvelteDate references remain; svelte-check clean. Strict timezone/DST testing + QA fixes: - 8 new hermetic boundary tests: clock.DST transitions (both 2026 folds), closing-hours GMT vs BST, booking date-window midnight, refund-tier elapsed-time independence, deposit-window UTC-instant, scheduling LondonDateString midnight, today AT TIME ZONE window + UTC round-trip. - today.go summary date labels fixed to London wall-clock (were showing the previous UTC day during BST) + regression test. - pgx ScanLocation fixed to UTC via AfterConnect (was host-local -> JSON offsets depended on deployment TZ, contradicting the documented UTC invariant) + regression test. Registered as a new *Type to avoid a data race on the shared type map (caught by -race). Admin Business Settings (setting now functional => legal floor): - gift_card_expiry_months validation floor raised 1 -> 12 months (CMA/ Consumer Rights Act 2015 unfair-contract-term guidance) in endpoint + UI, with rolling-expiry semantics shown in both display and edit form. - 3 new expiry validation tests; 2 pre-existing message assertions updated. Full suite 25/25 + race clean via run-tests.sh lockfile; svelte-check 0 errors/warnings; production build succeeds.
This commit is contained in:
@@ -790,7 +790,7 @@ CREATE TABLE business_settings (
|
||||
default_vat_rate NUMERIC(5,2) NOT NULL DEFAULT 20.00,
|
||||
currency_code CHAR(3) NOT NULL DEFAULT 'GBP',
|
||||
website_url TEXT,
|
||||
gift_card_expiry_months INT NOT NULL DEFAULT 12,
|
||||
gift_card_expiry_months INT NOT NULL DEFAULT 24,
|
||||
voucher_type VARCHAR(3) NOT NULL DEFAULT 'SPV',
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
@@ -824,7 +824,8 @@ INSERT INTO business_settings (
|
||||
is_vat_registered,
|
||||
default_vat_rate,
|
||||
currency_code,
|
||||
website_url
|
||||
website_url,
|
||||
gift_card_expiry_months
|
||||
) VALUES (
|
||||
'Crussell Nail Art Studio',
|
||||
'Address',
|
||||
@@ -834,7 +835,8 @@ INSERT INTO business_settings (
|
||||
FALSE, -- Set to TRUE when we register for VAT
|
||||
20.00,
|
||||
'GBP',
|
||||
'https://www.website.co.uk'
|
||||
'https://www.website.co.uk',
|
||||
24
|
||||
);
|
||||
|
||||
-- 'critical_payment_log' surfaces unresolved money events (stale pending
|
||||
@@ -2152,7 +2154,10 @@ CREATE INDEX idx_affiliate_payouts_affiliate ON affiliate_payouts(affiliate_id);
|
||||
-- Gift cards are Single-Purpose Vouchers (SPVs) under UK VAT law.
|
||||
-- VAT is charged at point of sale, NOT at redemption.
|
||||
--
|
||||
-- Expiry: 24 months rolling from last usage (industry standard per CMA guidance).
|
||||
-- Expiry: rolling from last usage (industry standard per CMA guidance),
|
||||
-- default 24 months. The window is configurable via
|
||||
-- business_settings.gift_card_expiry_months (admin settings) — the SINGLE
|
||||
-- source of truth read by the expiry job and every expiry_date write.
|
||||
-- UK Consumer Rights Act 2015 requires expiry terms to be "fair and transparent".
|
||||
-- 24 months matches premium retailers (John Lewis, M&S, Sainsbury's) and is
|
||||
-- widely considered reasonable by the CMA. Under 12 months risks being challenged
|
||||
|
||||
Reference in New Issue
Block a user