-- ========================================================================== -- Agencia PSI — Migracao: Alerta de saldo baixo WhatsApp -- ========================================================================== -- Criado por: Leonardo Nohama -- Data: 2026-04-23 · Sao Carlos/SP — Brasil -- -- Fecha o loop do Marco B: tenant compra creditos → usa → saldo zera sem -- aviso → PIX recusado surpresa. Agora o tenant e admins recebem -- notificacao quando saldo cai abaixo do threshold configurado. -- -- Modelo: -- - whatsapp_credits_balance ja tem: -- low_balance_threshold (default 20) -- low_balance_alerted_at (anti-spam; reset via add_whatsapp_credits) -- - Falta so o trigger que dispara a notificacao. -- -- Fluxo: -- 1. UPDATE em whatsapp_credits_balance (via deduct/adjust) -- 2. Trigger BEFORE UPDATE detecta balance < threshold E alerted_at IS NULL -- 3. Insere system_alert pros stakeholders (owner do canal WhatsApp -- ativo + clinic_admin + tenant_admin do tenant, deduplicado) -- 4. Seta NEW.low_balance_alerted_at = now() pra nao realertar -- 5. Reset do alerted_at acontece em add_whatsapp_credits / topup -- (ja existe: "low_balance_alerted_at = NULL" na RPC) -- ========================================================================== CREATE OR REPLACE FUNCTION public.fn_whatsapp_low_balance_notify() RETURNS TRIGGER LANGUAGE plpgsql SECURITY DEFINER SET search_path = public AS $$ DECLARE v_detail TEXT; BEGIN -- So alerta na transicao (alerted_at NULL) E se esta abaixo do threshold IF NEW.balance < NEW.low_balance_threshold AND NEW.low_balance_alerted_at IS NULL THEN v_detail := format( 'Saldo atual: %s credito(s). Alerta configurado em %s. ' 'Compre mais na loja para nao interromper envios via WhatsApp Oficial.', NEW.balance, NEW.low_balance_threshold ); -- Stakeholders: owner do canal WhatsApp ativo + admins ativos do tenant INSERT INTO public.notifications (owner_id, tenant_id, type, ref_id, ref_table, payload) SELECT u.user_id, NEW.tenant_id, 'system_alert', NEW.tenant_id, 'whatsapp_credits_balance', jsonb_build_object( 'title', 'Saldo de WhatsApp baixo', 'detail', v_detail, 'severity', 'warn', 'deeplink', '/configuracoes/creditos-whatsapp' ) FROM ( SELECT owner_id AS user_id FROM public.notification_channels WHERE tenant_id = NEW.tenant_id AND channel = 'whatsapp' AND is_active = true AND deleted_at IS NULL UNION SELECT user_id FROM public.tenant_members WHERE tenant_id = NEW.tenant_id AND role IN ('clinic_admin', 'tenant_admin') AND status = 'active' ) u WHERE u.user_id IS NOT NULL; -- Anti-spam: so alerta de novo depois que add_whatsapp_credits -- reseta alerted_at pra NULL (acontece em purchase/topup) NEW.low_balance_alerted_at := now(); END IF; RETURN NEW; END; $$; COMMENT ON FUNCTION public.fn_whatsapp_low_balance_notify() IS 'Trigger BEFORE UPDATE em whatsapp_credits_balance. Dispara notificacao system_alert quando saldo cruza low_balance_threshold pra baixo. Anti-spam via low_balance_alerted_at (resetado pelo add_whatsapp_credits).'; DROP TRIGGER IF EXISTS trg_whatsapp_low_balance_notify ON public.whatsapp_credits_balance; CREATE TRIGGER trg_whatsapp_low_balance_notify BEFORE UPDATE ON public.whatsapp_credits_balance FOR EACH ROW EXECUTE FUNCTION public.fn_whatsapp_low_balance_notify();