Pular para o conteúdo principal

Marts do DW — Emplacamento (relatórios Vona/ABRACAF)

Pedido pro time de dados — o pipeline (Pentaho) fica fora deste repo, aqui só especifica como os marts devem ser. Cobre todos os relatórios do módulo de Emplacamento (produto Associação Digital): Por Marca, Por Ranking, Por Modelo, Por Território, Por Segmento, Por Invasão, Veículo, Duplo Emplacamento e o Dashboard KPI.

Validado direto contra o DW de produção em 2026-07-27 (conexão real, introspecção de information_schema + queries de contagem/distinct) — não é só levantamento de código.


Contexto

Hoje os relatórios montam JOIN no star schema cru (dw_emplacamento.fato_emplacamentos + dim_veiculo / dim_local / dim_concessionaria) a cada request. Queremos que passem a ler de marts pré-joinados em dw_emplacamento_mart, como o Monitor F&I (Belite) já faz.

Estado atual do dw_emplacamento_mart (3 marts, grão diário, materializados só pra 20262026-01-02 a 2026-07-24): emplacamento_kpi_fabricante_dia, emplacamento_kpi_local_dia, emplacamento_kpi_veiculos_dia.

Importante — a fato TEM histórico: dw_emplacamento.fato_emplacamentos está particionada e contém 2025 (ano cheio, ~2,55M linhas) e 2026 (parcial, ~1,38M). Os marts atuais é que só foram populados com 2026. Ou seja, comparações ano-a-ano são viáveis; falta materializar o histórico no mart (ver seção "Histórico / YoY").

Proposta: substituir os 3 marts atuais por 2 marts (agregado + detalhe) + avaliar 1 mart específico pro Duplo Emplacamento.


Convenções

  • Grão diário por data. ano/mes materializados; o resto do calendário (dia_util, feriado_nacional, nome_mes, etc.) o app resolve com JOIN em dw_emplacamento.dim_calendario por datanão precisa denormalizar o calendário. Média diária / "por dia útil" / "mesmo período" saem desse join.
  • tipo_pessoa ('PF' | 'PJ') derivado de fato.is_cpf_cliente (true → PF). Filtro em quase todos os relatórios; quando "Tipo de Pessoa = Todas", as telas mostram colunas Vol PF e Vol PJ lado a lado (pivot sobre essa coluna).
  • Colisão de nomes de região: dim_local e dim_concessionaria têm ambas regiao_abracaf/abcnissan/abrare. No mart usar prefixo: local_regiao_* e conc_regiao_*.
  • Medida: volume bigint = COUNT(*) de emplacamentos.

Mart 1 — emplacamento_kpi_dia (agregado)

Grão: dia × veículo × local × concessionária × modalidade × tipo_pessoa × grupo. Serve: Por Marca, Por Ranking, Por Modelo, Por Território, Por Segmento, Por Invasão, Dashboard KPI (cada um faz seu GROUP BY + SUM(volume)).

-- tempo
data date, ano int, mes int

-- veículo (filtro/agrupamento) — origem dim_veiculo
fabricante_codigo int, fabricante text, -- "Marca"
grupomodeloveiculo_codigo int, grupomodeloveiculo text, -- "Modelo" (família) no Por Modelo
modelo_codigo int, modelo text, -- "Versão" no Por Modelo
segmento_codigo int, segmento text, -- "Segmento" (esquema Mercado)
subsegmento_codigo int, subsegmento text, -- filtro "Segmentos"/"Tipo de Segmento"
combustivel_codigo int, combustivel text, -- filtro "Combustível" + KPI "novas energias" (Dashboard)
ano_fabricacao int
-- ⛔ categoria (ver perguntas) · ⛔ segmento_associacao (ver perguntas)

-- local (dim_local inteira + regiao_operacional) — "Área de Abrangência"
municipio_codigo int, municipio text, estado text,
local_regiao_abracaf text, local_regiao_abcnissan text, local_regiao_abrare text,
regiao_geografica text, regiao_metropolitana text, regiao_operacional text
-- ⛔ is_capital (ver perguntas)

-- concessionária (dim_concessionaria inteira)
cnpj text, razao_social text, is_cpf_empresa bool, montadora bool,
conc_regiao_abracaf text, conc_regiao_abcnissan text, conc_regiao_abrare text,
area_influencia_codigo text, area_influencia_nome text
-- sigla da associação: derivável das regiões acima · ⛔ concessionaria_cadastrada (ver perguntas)

-- modalidade / pessoa / grupos
modalidade text, -- 'Varejo' | 'Direta'
tipo_pessoa text, -- 'PF' | 'PJ'
grupo_economico_codigo text, grupo_economico_nome text, -- ⛔ (= "grupo empresa")

-- medida
volume bigint -- COUNT(*)

Fora deste mart: numero_chassis, numero_placa (Mart 2) e atributos físicos de veículo sem uso (cor_veiculo, potencia, capacidade_carga, capacidade_passageiros).

Mart 2 — emplacamento_detalhe (grão do emplacamento)

Grão: 1 linha por emplacamento. Serve: o relatório Veículo (busca por chassi/placa), o drawer de drill-down por chassi (Por Marca, Por Modelo, Por Segmento, Por Território) e o export linha-a-linha.

data date,
numero_chassis text, numero_placa text,
fabricante text, modelo text, subsegmento text, -- "Versão"
segmento text, -- ⚠️ necessário pro relatório Veículo (14 colunas)
cilindradas text,
municipio text, estado text,
cnpj text, razao_social text, is_cpf_empresa bool,
modalidade text, tipo_pessoa text, ano_fabricacao int,
grupo_economico_codigo text, grupo_economico_nome text -- ⛔ (escopo/filtro; = "grupo empresa")
-- ⛔ categoria (relatório Veículo tem coluna "Categoria")

Mart 3 (avaliar) — emplacamento_duplo (grão: par de emplacamentos)

O Duplo Emplacamento é um relatório de auditoria: encontra o mesmo chassi emplacado 2x. Nenhum dos marts acima serve isso (o agregado não tem chassi; o detalhe é 1 linha por emplacamento, não por par). Precisa de uma detecção/mart próprio, 1 linha por par, com: chassi, empresa, data da 1ª e da 2ª ocorrência, dias entre elas, sigla (derivável das regiões) e tipo_pessoa (a coluna "Cliente" = PF/PJ). Confirmar com o time se fazem como mart ou como query sobre a fato.


⛔ Dimensões/campos que NÃO existem no DW — perguntas pro time de dados

Verificado em 2026-07-27: nenhum destes existe em dw_emplacamento*. São o que trava o fechamento dos relatórios.

  1. Grupo econômico (grupo_economico_codigo/nome) — filtros, agrupamento e controle de acesso em Por Marca (RF019/RF039), Por Ranking (RF010/RF020/RF022/RF041), Por Modelo (RF010), Por Território, Por Segmento e Duplo. Blocker. Existe cadastro na origem (DMS)? Qual o vínculo (grupo → N cnpj)? Conseguem expor uma dim_grupo_economico + a chave nos marts?

    • Nota: o spec do Por Ranking (Concessionárias) lista "Grupo Econômico" e "Grupo Empresa"/"Grupo de Concessionária" como filtros/colunas separados, mas são a mesma entidade — uma dimensão só resolve os dois rótulos.
  2. Categoria de veículo (categoria) — filtro/coluna em Por Marca (RF001), Por Ranking (RF005), Por Território, Por Segmento e Veículo. Atenção: no código legado do Por Marca "Categoria" era mapeado pra segmento. Precisamos confirmar: "Categoria" é sinônimo de segmento, ou é uma dimensão nova (ex.: Automóvel / Comercial Leve / Caminhão / Moto / Ônibus)? Se for nova, de onde vem?

  3. Segmentação "Associação" (segmento_associacao + código) — o Por Segmento tem filtro "Tipo de Segmento = Mercado | Associação". Hoje só existe um segmento (esquema Mercado). Existe o esquema da Associação? Precisa de uma 2ª coluna de segmento.

  4. Flag de capital (is_capital em dim_local) — Por Território, sub-aba "Capitais". Derivável de lista fixa das 27 capitais; confirmar se preferem materializar no mart ou o app resolve.

  5. "Incluir Não Cadastrados" (concessionaria_cadastrada bool) — filtro de Por Ranking → Concessionárias. Precisa de um flag distinguindo concessionária cadastrada vs. não cadastrada (ou um sentinela). Como está modelado na origem?

Fora de escopo / resolvidos (não são gaps):

  • Sigla da associação (Duplo, RF005) — é a sigla da associação (não a UF; "Estados" é filtro separado). Derivável no app de qual regiao_abracaf/regiao_abcnissan/regiao_abrare a concessionária tem preenchida — confirmar a regra, mas não é campo novo no DW.
  • Código BIR da concessionária — fora de escopo por ora (a coluna "Código" do Por Ranking / Duplo fica sem BIR; se precisar de identificação, usa cnpj).
  • Data NF (Duplo) — fora de escopo.
  • "Cliente" (Duplo) é o tipo do cliente (PF/PJ) → usa tipo_pessoa, que já temos (sem nome/documento, evita LGPD).
  • "Novas energias" (Dashboard) é derivado do combustivel do veículo (já no mart agregado), não de classificação de marca.

Histórico / YoY

Vários relatórios comparam com anos anteriores — Por Ranking (Δ% ano anterior, MS ant., Δ% mesmo mês ano ant.), Por Modelo (aba "Ano a Ano" é multi-ano por definição; "Mês a Mês" tem coluna do ano anterior), Por Segmento (2025 vs 2026 + DIF%).

A fato já tem 2025 + 2026 e vamos carregar os dois. Pedido: materializar emplacamento_kpi_dia (e o detalhe, se necessário) com 2025 e 2026 — e manter os anos seguintes conforme entram. Com isso o YoY (ano vigente vs. anterior) fica habilitado desde o início.

Limitação conhecida: a sub-aba Capitais Anual (Por Território) pede 4 anos anteriores + o vigente (5 anos). O DW só tem 2025 e 2026 — dá pra mostrar 2 anos; os demais só quando houver histórico na origem. Confirmar até onde vai o histórico disponível.


Notas de grão / volumetria

  • Denormalizar dim_local inteira + tipo_pessoa + modalidade + concessionária + ano_fabricacao no agregado multiplica linhas — é o custo de permitir filtrar por qualquer atributo. Se pesar, priorizar estado + regiões + tipo_pessoa; ano_fabricacao e municipio_codigo podem vir numa 2ª fase.
  • Confirmar se os 3 marts atuais (*_fabricante_dia, *_local_dia, *_veiculos_dia) são consumidos por outro produto (ex.: Belite) antes de descontinuá-los.

Apêndice — relatório × o que precisa (resumo)

RelatórioMartDimensões-chaveGaps que dependem do time de dados
Por Marcaagregado + detalhefabricante, modelo, local, modalidade, tipo_pessoagrupo_economico, categoria(?)
Por Rankingagregadofabricante/modelo/cidade/concessionária, regiões, tipo_pessoagrupo_economico, não-cadastrados, YoY
Por Modeloagregado + detalhefabricante>grupomodelo>modelo, segmento/subsegmentogrupo_economico, YoY (aba Ano a Ano)
Por Territórioagregado + detalhelocal completo, area_influencia, montadora, capitaisgrupo_economico, is_capital, categoria(?), YoY (Capitais)
Por Segmentoagregado + detalhesegmento>marca>modelo>versão, tipo_pessoasegmento_associacao, categoria(?), grupo_economico, YoY
Por Invasãoagregadoarea_influencia vs município, empresa(nenhum novo — usa area_influencia)
Veículodetalhechassi/placa + 14 colunascategoria, segmento no mart de detalhe
Duplo Emplacamentoduplo (novo)par por chassigrupo_economico (sigla derivável)
Dashboard KPIagregadovolume, modalidade, tipo_pessoa, combustivel, mêssem gap — "novas energias" = combustivel; dia_util via calendário