e409ba64ef
Fecha o loop do Marco B — tenant não zera mais saldo sem aviso. Nova função fn_whatsapp_low_balance_notify + trigger BEFORE UPDATE em whatsapp_credits_balance: - Dispara quando NEW.balance < NEW.low_balance_threshold e NEW.low_balance_alerted_at IS NULL - Insere system_alert pros stakeholders do tenant (owner do canal WhatsApp ativo + clinic_admin + tenant_admin, deduplicado via UNION) - Deeplink direto pra /configuracoes/creditos-whatsapp - Seta NEW.low_balance_alerted_at = now() pra anti-spam Reset do anti-spam já existia: add_whatsapp_credits seta low_balance_alerted_at=NULL ao creditar (purchase/topup/refund). Assim o ciclo completo funciona: cai abaixo → alerta → compra recrédita → cai de novo futuramente → alerta de novo. Toast no frontend já é sticky vermelho pra type='system_alert' (commit anterior). Config de threshold já existia na UI em /configuracoes/creditos-whatsapp. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
97 lines
3.8 KiB
PL/PgSQL
97 lines
3.8 KiB
PL/PgSQL
-- ==========================================================================
|
|
-- 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();
|