Multi-Tenant - 15 - Exemplo de NFSe para o Ambiente Nacional em Golang

Boa, vamos fechar com a parte “observabilidade” da NFSe. Vou montar:

  1. Uma view principal diária por tenant.

  2. Uma view filtrando últimos 30 dias.

  3. Alguns exemplos de consultas pra dashboard.

Vou assumir que sua tabela nfse tem pelo menos:


1. View principal: vw_nfse_dashboard_diario

Essa view consolida por dia, tenant, situação e substatus técnico:

CREATE OR REPLACE VIEW public.vw_nfse_dashboard_diario AS
SELECT
    n.tenant_id,
    date_trunc('day', n.data_emissao)::date AS dia,
    n.situacao,
    COALESCE(n.substatus_tecnico, '') AS substatus_tecnico,

    COUNT(*)                             AS total_notas,
    SUM(n.valor_servicos)                AS total_servicos,

    -- métricas auxiliares por estado
    COUNT(*) FILTER (WHERE n.situacao = 'autorizada')          AS qtd_autorizadas,
    COUNT(*) FILTER (WHERE n.situacao = 'rejeitada')           AS qtd_rejeitadas,
    COUNT(*) FILTER (WHERE n.situacao = 'erro_interno')        AS qtd_erro_interno,
    COUNT(*) FILTER (WHERE n.situacao = 'pendente_transmissao') AS qtd_pendente_transmissao,

    -- taxa de erro (rejeitada + erro_interno) / total
    CASE
      WHEN COUNT(*) = 0 THEN 0
      ELSE ROUND(
        (COUNT(*) FILTER (WHERE n.situacao IN ('rejeitada','erro_interno'))::numeric
         / COUNTnumeric * 100
      , 2)
    END AS taxa_erro_percent
FROM
    public.nfse n
GROUP BY
    n.tenant_id,
    date_trunc('day', n.data_emissao)::date,
    n.situacao,
    COALESCE(n.substatus_tecnico, '');

O que você ganha aqui:

No dashboard você pode:


2. View de “últimos 30 dias”: vw_nfse_dashboard_30d

Se quiser algo já pronto pra painel de monitoramento:

CREATE OR REPLACE VIEW public.vw_nfse_dashboard_30d AS
SELECT *
FROM public.vw_nfse_dashboard_diario
WHERE dia >= (current_date - INTERVAL '30 days');

Você pode trocar para 7 dias, 90 dias, etc. Ou criar múltiplas views (_7d, _30d).


3. Exemplos de consultas pro dashboard

3.1. Resumo por dia (todas as situações somadas)

SELECT
  dia,
  tenant_id,
  SUM(total_notas)        AS total_notas,
  SUM(total_servicos)     AS total_servicos,
  SUM(qtd_autorizadas)    AS qtd_autorizadas,
  SUM(qtd_rejeitadas)     AS qtd_rejeitadas,
  SUM(qtd_erro_interno)   AS qtd_erro_interno,
  SUM(qtd_pendente_transmissao) AS qtd_pendentes,
  ROUND(
    (SUM(qtd_rejeitadas + qtd_erro_interno)::numeric
     / NULLIFnumeric * 100
  , 2) AS taxa_erro_percent
FROM public.vw_nfse_dashboard_30d
GROUP BY dia, tenant_id
ORDER BY dia, tenant_id;

Esse é ótimo pra gráfico de linha/barra por dia no Grafana/Metabase.


3.2. Top tenants com mais erro técnico nos últimos 30 dias

SELECT
  tenant_id,
  SUM(qtd_erro_interno)                         AS erros_internos,
  SUM(qtd_rejeitadas)                           AS rejeitadas,
  SUM(total_notas)                              AS total_notas,
  ROUND(
    (SUM(qtd_erro_interno + qtd_rejeitadas)::numeric
     / NULLIFnumeric * 100
  , 2) AS taxa_erro_percent
FROM public.vw_nfse_dashboard_30d
GROUP BY tenant_id
ORDER BY taxa_erro_percent DESC
LIMIT 10;

3.3. Quebra por substatus_tecnico (para investigar integração)

SELECT
  tenant_id,
  substatus_tecnico,
  SUM(total_notas)        AS total_notas,
  SUM(qtd_erro_interno)   AS erros_internos
FROM public.vw_nfse_dashboard_30d
WHERE situacao = 'erro_interno'
GROUP BY tenant_id, substatus_tecnico
ORDER BY erros_internos DESC;

Aqui você vê, por exemplo: