Files
accounted/supabase/migrations/20260818170000_trial_seed_all_paid_capabilities.sql
Jakob Wennberg b07a4a4bca fix(entitlements): trial seeding grants every paid capability, not the launch four (#1698)
seed_trial_capability_grants() still hardcoded ai/bank_sync/skatteverket/
email_send while PAID_CAPABILITIES grew to seven keys. Payers got all seven
via the Stripe webhook; every company created since 2026-07-12 was trialing
without stripe_payments (and later woocommerce_sync/shopify_sync). Redefine
the trigger with the full set, backfill existing trial grants by mirroring
bank_sync, and pin the pg test to PAID_CAPABILITIES so the lists cannot
drift again.

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 11:09:10 +02:00

61 lines
2.3 KiB
PL/PgSQL

-- Trial seeding must grant every PAID capability, not the 2026-06-29 four.
--
-- lib/entitlements/keys.ts PAID_CAPABILITIES grew to seven keys
-- (stripe_payments 2026-07-12, woocommerce_sync 2026-08-06, shopify_sync
-- 2026-08-08). The Stripe webhook writes grants from that constant, so
-- payers have all seven; the trial trigger seed_trial_capability_grants()
-- (20260629120000) still hardcodes ('ai','bank_sync','skatteverket',
-- 'email_send'), and each key's backfill only mirrored the grants that
-- existed on its day. Every company created since is trialing without the
-- newer keys: on 2026-08-18, 226 of 230 active trialers lacked
-- stripe_payments, 146 woocommerce_sync, 131 shopify_sync.
--
-- 1. Redefine the trigger function with the full PAID set. Keep this VALUES
-- list in step with PAID_CAPABILITIES whenever a key is added (and add a
-- backfill like part 2 for the companies already seeded).
-- 2. Backfill: mirror every existing trial bank_sync grant (same company,
-- same expiry) for the three missing keys. Idempotent via the unique
-- index; expired trials are mirrored too so state stays aligned, exactly
-- as the earlier backfills did.
CREATE OR REPLACE FUNCTION public.seed_trial_capability_grants()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = public
AS $$
BEGIN
INSERT INTO public.capability_grants (company_id, capability_key, source, expires_at)
SELECT NEW.id, k.key, 'trial', NEW.created_at + interval '30 days'
FROM (VALUES
('ai'),
('bank_sync'),
('skatteverket'),
('email_send'),
('stripe_payments'),
('woocommerce_sync'),
('shopify_sync')
) AS k(key)
ON CONFLICT (company_id, team_id, capability_key, source) DO NOTHING;
RETURN NEW;
END;
$$;
INSERT INTO public.capability_grants
(company_id, team_id, capability_key, source, granted_at, expires_at, metadata)
SELECT
g.company_id,
g.team_id,
k.key,
g.source,
g.granted_at,
g.expires_at,
jsonb_build_object(
'backfilled_from', 'bank_sync',
'backfill_migration', '20260818170000'
)
FROM public.capability_grants g
CROSS JOIN (VALUES ('stripe_payments'), ('woocommerce_sync'), ('shopify_sync')) AS k(key)
WHERE g.capability_key = 'bank_sync' AND g.source = 'trial'
ON CONFLICT (company_id, team_id, capability_key, source) DO NOTHING;