freemium F2 polish: welcome email + plano gratuito na vitrine

- edge function send-welcome-email: e-mail de boas-vindas ao DONO do tenant
  recem-provisionado (destinatario do JWT, SMTP global/sistema, defaults Mailpit).
  Best-effort, disparada fire-and-forget no OnboardingPage so no provisionamento novo.
- vitrine: seed plan_public + bullets dos planos free (cartao "Gratis"); Landingpage
  passa a mostrar "Gratis para sempre" (isFreePlan) em vez de "—".
- build OK

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-06-13 20:36:33 -03:00
parent f6470718b7
commit 52c34cf63a
4 changed files with 212 additions and 3 deletions
@@ -0,0 +1,66 @@
-- =============================================================================
-- Freemium F2 (polish) — apresentação do plano gratuito na vitrine pública
--
-- Os planos free já eram is_visible em v_public_pricing, mas sem plan_public
-- (nome/descrição/bullets) e sem preço — renderizavam sem nome/valor. Este seed
-- dá um cartão "Grátis" decente. Referência por KEY (subquery), idempotente.
-- O preço "Grátis" é tratado no front (Landingpage isFreePlan).
-- =============================================================================
BEGIN;
INSERT INTO public.plan_public (plan_id, public_name, public_description, badge, is_featured, is_visible, sort_order)
SELECT id, 'Grátis',
'Comece sem custo: o essencial pra organizar sua agenda, pacientes e prontuário.',
'Grátis', false, true, 0
FROM public.plans WHERE key = 'clinic_free'
ON CONFLICT (plan_id) DO UPDATE
SET public_name = EXCLUDED.public_name,
public_description = EXCLUDED.public_description,
badge = EXCLUDED.badge,
is_visible = true,
sort_order = EXCLUDED.sort_order,
updated_at = now();
INSERT INTO public.plan_public (plan_id, public_name, public_description, badge, is_featured, is_visible, sort_order)
SELECT id, 'Grátis',
'Pra terapeutas individuais: agenda, pacientes e prontuário sem custo.',
'Grátis', false, true, 0
FROM public.plans WHERE key = 'therapist_free'
ON CONFLICT (plan_id) DO UPDATE
SET public_name = EXCLUDED.public_name,
public_description = EXCLUDED.public_description,
badge = EXCLUDED.badge,
is_visible = true,
sort_order = EXCLUDED.sort_order,
updated_at = now();
-- bullets (idempotente: limpa os dos free e re-insere)
DELETE FROM public.plan_public_bullets
WHERE plan_id IN (SELECT id FROM public.plans WHERE key IN ('clinic_free','therapist_free'));
INSERT INTO public.plan_public_bullets (plan_id, text, highlight, sort_order)
SELECT p.id, b.text, b.highlight, b.sort_order
FROM public.plans p
CROSS JOIN LATERAL (
VALUES
('Agenda completa e prontuário', true, 1),
('Até 30 pacientes ativos', false, 2),
('Documentos e lembretes básicos', false, 3),
('Agendamento online', false, 4)
) AS b(text, highlight, sort_order)
WHERE p.key = 'clinic_free';
INSERT INTO public.plan_public_bullets (plan_id, text, highlight, sort_order)
SELECT p.id, b.text, b.highlight, b.sort_order
FROM public.plans p
CROSS JOIN LATERAL (
VALUES
('Agenda completa e prontuário', true, 1),
('Até 20 pacientes ativos', false, 2),
('Documentos e lembretes básicos', false, 3),
('Agendamento online', false, 4)
) AS b(text, highlight, sort_order)
WHERE p.key = 'therapist_free';
COMMIT;