Pular para o conteúdo principal

Services de Relatório — Vona

Os relatórios do Vona expõem três services de servidor, todos seguindo o padrão factory (createXService()):

ServiceRelatórioFonte de dados
RankingServicePor RankingData Warehouse (dw_emplacamento)
TerritoryServicePor TerritórioData Warehouse (dw_emplacamento)
AccessServiceDe AcessosSupabase (report_access_events)

Os services de DW (RankingService e TerritoryService) são documentados nesta página. O AccessService está documentado em Relatório De Acessos.

Todos são usados exclusivamente em Server Components e nunca exportam código para o cliente.

Criar a instância do service

Ambos os services usam o padrão factory — crie a instância no início do Server Component ou Route Handler.

import { createRankingService } from './_lib/server/ranking-service';
import { createTerritoryService } from './_lib/server/territory-service';

// Por Ranking
const rankingService = createRankingService();

// Por Território
const territoryService = createTerritoryService();
Apenas no servidor

Os services importam server-only no topo. Importar em Client Components causa erro de build. Use sempre em page.tsx, layout.tsx ou Route Handlers.

Buscar os dados com getReportData

RankingService

const data = await rankingService.getReportData(tab, filters);
// data: RankingPageData

Parâmetros:

ParâmetroTipoDescrição
tabRankingTabAba ativa: 'por-marcas' | 'cidades' | 'concessionarias' | 'modelos'
filtersRankingFiltersFiltros aplicados pelo usuário

Tipo RankingFilters:

interface RankingFilters {
intervalStart?: string; // YYYY-MM-DD — mês/ano de referência
state?: string; // Sigla do estado (ex: 'SP')
group?: string; // Região ABRACAF (ex: 'ABRACAF')
personType?: string; // 'fisica' | 'juridica' | undefined (= todos)
}

Retorno RankingPageData:

interface RankingPageData {
card: { variant: 'pivot'; data: PivotCard }
| { variant: 'standard'; data: StandardCard }
| null; // null quando não há dados no DW para o período
lastUpdated: string | null; // Data mais recente com dados (ISO)
}

Abas e seu retorno:

TabVarianteDescrição
por-marcaspivotRanking anual por fabricante com acumulados e últimos 5 dias úteis
cidadesstandardTop 100 cidades por volume de emplacamento
concessionariasstandardTop 100 concessionárias por volume
modelosstandardTop 100 modelos com pivot mensal (últimos 12 meses)

TerritoryService

const data = await territoryService.getReportData(grupoId, tab, subtab, filters);
// data: TerritoryPageData

Parâmetros:

ParâmetroTipoDescrição
grupoIdstringID do grupo concessionário (reservado — não usado nas queries ainda)
tabTerritoryTabAba principal
subtabCapitalsSubTabSub-aba de capitais
filtersTerritoryFiltersFiltros aplicados

Tipo TerritoryFilters:

interface TerritoryFilters {
intervalStart?: string; // YYYY-MM-DD — mês/ano de referência
state?: string; // Sigla do estado
group?: string; // Região ABRACAF
dealerships?: string; // CNPJ da concessionária
}

Abas disponíveis (TerritoryTab):

TabDescrição
da-sua-concessionariaEmplacamentos dentro e fora da área de influência da concessionária
por-area-influenciaMarket share por fabricante × área de influência
por-capitaisDados das 27 capitais brasileiras (3 sub-abas)
por-cidade-concessionariaMarket share por fabricante × cidade/concessionária
por-regioesMarket share por fabricante × região ABRACAF

Sub-abas de capitais (CapitalsSubTab):

SubtabDescrição
anualAcumulado anual por capital, colunas = meses
mensalEmplacamentos do mês selecionado por capital, colunas = dias
e-marcasEmplacamentos do mês por capital × fabricante

Retorno TerritoryPageData:

interface TerritoryPageData {
cards: PivotCard[]; // Um ou mais cards pivot, dependendo da aba
lastUpdated: string | null;
}

Buscar opções de filtro com getFilterOptions

Ambos os services expõem getFilterOptions() para popular os selects do modal de filtros. Deve ser chamado no Server Component da página e passado como props para o header da página.

RankingService

const { stateOptions, groupOptions } = await rankingService.getFilterOptions();
// stateOptions: FilterOption[] — estados distintos do DW
// groupOptions: FilterOption[] — regiões ABRACAF distintas

TerritoryService

const { stateOptions, groupOptions, dealershipOptions } = await territoryService.getFilterOptions();
// dealershipOptions: FilterOption[] — { value: cnpj, label: razao_social }

Referência ao Data Warehouse

Os services se conectam ao DW via getSupabaseDwClient(), uma conexão tagged-template SQL para o schema dw_emplacamento. As queries sempre usam a coluna _ano_particao como filtro de partição para performance.

Tabelas consultadas:

TabelaAliasDescrição
fato_emplacamentosfTabela fato central — uma linha por emplacamento
dim_veiculodvDimensão veículo (fabricante, modelo)
dim_localdlDimensão local (município, estado, região ABRACAF)
dim_concessionariadcDimensão concessionária (razão social, CNPJ, região)
Capitais brasileiras — IDs do DW

O TerritoryService usa a constante CAPITAIS_CODIGOS_DW (array de 27 inteiros) para filtrar as capitais estaduais. Esses IDs são do DW interno e não correspondem a códigos IBGE. Para adicionar ou corrigir uma capital, edite CAPITAIS_CODIGOS_DW em territory-service.ts consultando dw_emplacamento.dim_local diretamente.

Exportar dados de tabela

Todos os cards de relatório (StandardCard e AccessCard) suportam exportação via o utilitário compartilhado exportCardData, localizado em reports/_lib/export-utils.ts.

import { exportCardData } from '../../_lib/export-utils';

// Dentro de um componente cliente:
exportCardData(card, 'csv'); // CSV com separador vírgula
exportCardData(card, 'xlsx'); // CSV com BOM + separador ponto-e-vírgula (compatível com Excel)

Interface aceita pelo utilitário:

interface ExportableCard {
id: string; // Usado como nome do arquivo: `${id}.csv`
title: string; // Primeira coluna do cabeçalho
columns: ReportColumn[];
rows: ReportRow[];
}
Exportação de XLSX

O formato 'xlsx' na verdade gera um arquivo .csv com BOM UTF-8 e separador ponto-e-vírgula. Isso faz o Excel abrir o arquivo diretamente sem precisar configurar a importação — o nome do botão é "Excel (CSV)" por conveniência.

O StandardTableCard e o AccessTableCard já incluem os botões de exportação pré-configurados; não é necessário nenhum código adicional para ativar essa funcionalidade ao criar um novo relatório baseado nesses componentes.