-- 013_payment_surcharges.sql -- Payment method surcharge tracking. -- Phase 1 (Stripe): ACH 0%, Card 3%, Klarna 4.5%, Crypto 0%. No PayPal at launch. -- Phase 2 (Adyen): Klarna drops to ~4.3% effective; PayPal added via Adyen. BEGIN; -- Add payment method and surcharge columns to all order tables ALTER TABLE formation_orders ADD COLUMN IF NOT EXISTS payment_method TEXT CHECK (payment_method IN ('ach', 'card', 'klarna', 'crypto')); ALTER TABLE formation_orders ADD COLUMN IF NOT EXISTS surcharge_pct NUMERIC(5,2) DEFAULT 0; ALTER TABLE formation_orders ADD COLUMN IF NOT EXISTS surcharge_cents INTEGER DEFAULT 0; ALTER TABLE formation_orders ADD COLUMN IF NOT EXISTS stripe_payment_id TEXT; ALTER TABLE formation_orders ADD COLUMN IF NOT EXISTS stripe_session_id TEXT; ALTER TABLE canada_crtc_orders ADD COLUMN IF NOT EXISTS payment_method TEXT CHECK (payment_method IN ('ach', 'card', 'klarna', 'crypto')); ALTER TABLE canada_crtc_orders ADD COLUMN IF NOT EXISTS surcharge_pct NUMERIC(5,2) DEFAULT 0; ALTER TABLE canada_crtc_orders ADD COLUMN IF NOT EXISTS surcharge_cents INTEGER DEFAULT 0; ALTER TABLE canada_crtc_orders ADD COLUMN IF NOT EXISTS stripe_payment_id TEXT; ALTER TABLE canada_crtc_orders ADD COLUMN IF NOT EXISTS stripe_session_id TEXT; ALTER TABLE canada_crtc_orders ADD COLUMN IF NOT EXISTS payment_status TEXT DEFAULT 'pending_payment'; ALTER TABLE orders ADD COLUMN IF NOT EXISTS payment_method TEXT CHECK (payment_method IN ('ach', 'card', 'klarna', 'crypto')); ALTER TABLE orders ADD COLUMN IF NOT EXISTS surcharge_pct NUMERIC(5,2) DEFAULT 0; ALTER TABLE orders ADD COLUMN IF NOT EXISTS surcharge_cents INTEGER DEFAULT 0; ALTER TABLE orders ADD COLUMN IF NOT EXISTS stripe_payment_id TEXT; ALTER TABLE orders ADD COLUMN IF NOT EXISTS stripe_session_id TEXT; ALTER TABLE bundle_orders ADD COLUMN IF NOT EXISTS payment_method TEXT CHECK (payment_method IN ('ach', 'card', 'klarna', 'crypto')); ALTER TABLE bundle_orders ADD COLUMN IF NOT EXISTS surcharge_pct NUMERIC(5,2) DEFAULT 0; ALTER TABLE bundle_orders ADD COLUMN IF NOT EXISTS surcharge_cents INTEGER DEFAULT 0; ALTER TABLE bundle_orders ADD COLUMN IF NOT EXISTS stripe_payment_id TEXT; ALTER TABLE bundle_orders ADD COLUMN IF NOT EXISTS stripe_session_id TEXT; -- Payment surcharge configuration (editable by admin) CREATE TABLE IF NOT EXISTS payment_surcharges ( id SERIAL PRIMARY KEY, method TEXT NOT NULL UNIQUE, label TEXT NOT NULL, surcharge_pct NUMERIC(5,2) NOT NULL DEFAULT 0, -- Stripe's actual cost so we can track margin processor_pct NUMERIC(5,2) NOT NULL DEFAULT 0, processor_cents INTEGER NOT NULL DEFAULT 0, -- fixed fee component in cents description TEXT, active BOOLEAN DEFAULT TRUE, display_order INTEGER DEFAULT 0 ); INSERT INTO payment_surcharges (method, label, surcharge_pct, processor_pct, processor_cents, description, display_order) VALUES ('ach', 'Bank Transfer (ACH) via Stripe Link', 0.00, 0.80, 0, 'No surcharge. We absorb the ACH fee (0.8%, capped at $5).', 1), ('card', 'Credit or Debit Card', 3.00, 2.90, 30, '3% processing surcharge added at checkout.', 2), ('klarna', 'Klarna — Pay in 4 or Monthly', 4.50, 5.99, 30, '4.5% surcharge. Split into 4 interest-free payments or monthly financing.', 3), ('crypto', 'Cryptocurrency (BTC, ETH, USDC)', 0.00, 0.00, 0, 'No processing fee. Paid via BTCPay Server.', 4) ON CONFLICT (method) DO UPDATE SET label = EXCLUDED.label, surcharge_pct = EXCLUDED.surcharge_pct, processor_pct = EXCLUDED.processor_pct, processor_cents = EXCLUDED.processor_cents, description = EXCLUDED.description, display_order = EXCLUDED.display_order; -- Remove stale PayPal rows if upgrading from earlier schema DELETE FROM payment_surcharges WHERE method IN ('paypal', 'paypal_bnpl'); COMMIT;