Dashboard SaaS ganha seção de receita de créditos WhatsApp (Asaas)

Fecha o gap de analytics que faltava: MRR/ARR de assinatura já existia,
mas não havia visão de receita dos créditos WhatsApp comprados via Asaas.

Banco (migration 20260423000011) — 4 RPCs saas_admin only:
- saas_wa_credits_revenue_stats(from, to): total arrecadado, count de
  compras, tenants únicos, créditos vendidos, ticket médio.
- saas_wa_credits_top_packages(from, to): ranking top 10 pacotes por
  revenue, consolida nome atual se pacote foi renomeado.
- saas_wa_credits_usage_summary(): snapshot atual de lifetime_purchased
  vs lifetime_used vs current_balance + taxa de consumo.
- saas_wa_credits_revenue_evolution(from, to, bucket_days): série
  temporal pra sparkline.

Todas com check is_saas_admin() no início + SECURITY DEFINER.

Frontend:
- useSaasCreditsAnalytics composable orquestra as 4 RPCs em paralelo
  com seleção de período (30d/90d/6m/12m) que ajusta bucket_days
  automaticamente.
- SaasCreditsRevenueCard.vue: 4 KPIs (receita + ticket médio, compras +
  tenants, créditos vendidos, % consumo global), sparkline SVG com
  indicador de tendência, ranking top 5 pacotes.
- Integrado no SaasDashboard logo antes da tabela "Distribuição por plano".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-04-23 22:31:15 -03:00
parent b8ea292ef1
commit f1c97ee906
4 changed files with 448 additions and 0 deletions
+4
View File
@@ -23,6 +23,7 @@ import { useToast } from 'primevue/usetoast';
import { useConfirm } from 'primevue/useconfirm';
import Chart from 'primevue/chart';
import SaasCreditsRevenueCard from '@/components/dashboard/SaasCreditsRevenueCard.vue';
const router = useRouter();
const toast = useToast();
@@ -604,6 +605,9 @@ onBeforeUnmount(() => {
</div>
</div>
<!-- Receita de créditos WhatsApp (Asaas) -->
<SaasCreditsRevenueCard />
<!-- Breakdown table (com ações) -->
<div class="rounded-md border border-[var(--surface-border)] bg-[var(--surface-card)] p-5">
<div class="text-[1rem] font-semibold text-[var(--text-color)] mb-3">Distribuição por plano</div>