Pular para conteúdo

Guia do código

Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-06-18

Audiência: dev que abriu o repositório e quer passar os olhos e entender como o código está organizado, sem ainda mergulhar no Javadoc classe a classe. Para o porquê das decisões, veja decisoes/; para rodar/testar, Como rodar; para o contrato externo, API REST.

A tabela de classes no fim desta página é gerada no build a partir da 1ª frase do Javadoc de cada tipo — então acompanha o código. A narrativa abaixo é autorada.

Como o código é organizado

O código segue package-by-feature (decisão 0022): cada funcionalidade é um pacote de topo sob br.com.vantroba.bi.transporte que carrega suas próprias camadas, em vez de pastas globais controller/, service/, repository/. A fundação transversal (erro RFC 7807, health, Sentry, motor de auth, object storage Garage, utilitários e infra de teste) vem das libs do xadm-commons — não é código local; ver decisões 0023/0024/0025. O pacote local comum guarda só o resto app-específico (o que não coube numa feature nem numa lib).

Pacote de topo É Responsabilidade
processamento feature o pipeline XLS ponta a ponta — a feature central do app
powersync feature reset da replicação PowerSync
configuracao feature configuração global de runtime (admin)
seguranca feature as duas portas de auth (Bearer + login Google) — view-glue sobre o motor da lib
comum resto app-específico: config typed, exception (503 XLS), dto, util (AnosVeiculoParser), notificacao (Telegram)

A fundação transversal (erros, health, Sentry, versão, auth, storage, util, teste) mora nas libs xadm-seguranca / xadm-comum-web / -storage / -util / -teste do xadm-commons — um bump de lib corrige todos os apps da casa de uma vez.

As camadas dentro de uma feature

O fluxo de uma requisição é Controller → Service → Repository:

  • Controller (@Controller): só HTTP. Em API retorna DTO (record + @Serdeable) → JSON; em view server-rendered alimenta o template JTE com um view-model. Zero regra de negócio.
  • Service (@Singleton): regra de negócio, orquestração, @Transactional, conversão entidade↔DTO. Injeção por construtor.
  • Repository (Micronaut Data JDBC, sem Hibernate — decisão 0001): só acesso a dado.
  • A entidade (@MappedEntity) nunca cruza o controller. A borda HTTP fala DTO (API) ou view-model (view); a entidade fica da camada de service para dentro.

Travas de arquitetura (ArchUnit)

O ArchitectureTest trava três invariantes do package-by-feature — rodam no ./gradlew check:

  1. sem ciclos entre as features de topo;
  2. nenhum subpacote de comum depende de feature (inclusive comum.notificacao: o Telegram é transporte puro, recebe texto pronto; a formatação que conhece o domínio vive no notificador de cada feature);
  3. processamento.processing (leitura do Excel) não depende da camada HTTP.

Referência completa

O Javadoc gerado (árvore de classes navegável, interna) fica em dev/api/ — gerado pelo CI de docs a cada publish. Use-o quando precisar do detalhe de uma classe; o inventário abaixo é o atalho para achá-la.

Inventário das classes

Processamento

Pipeline de processamento da planilha XLS — a feature central do app.

Pacote Classe O que faz
processamento ArmazenamentoArquivoService Coordena o armazenamento do binário XLS entre o Postgres (coluna arquivo_bytes) e o object storage Garage, conforme o ArmazenamentoModo configurado em app.storage.modo.
processamento ArquivoBytesLegado Projeção de coluna única: o binário legado arquivo_bytes.
processamento ArquivoXlsDownload Conteúdo de um arquivo XLS recuperado do storage para download.
processamento BulkUpserter Caminho idempotente UPSERT diff-aware + DELETE seletivo (spec 004).
processamento ColunasConteudo Fonte de verdade única das colunas relevantes ao caminho idempotente UPSERT diff-aware (spec 004 — § 4.2 e § 5.4).
processamento ConjuntoLote Tabela xls_conjunto_lote: rastreia um lote de arquivos enviados juntos num .zip.
processamento ConjuntoLoteRepository Persistência de ConjuntoLote (lote por zip).
processamento ConjuntoLoteService Coordena o ciclo de vida de um lote (.zip).
processamento CopyTextWriter Builders para o formato TEXT do COPY FROM STDIN do PostgreSQL.
processamento Faturamento Linha de faturamento importada da aba 20 do Excel — tabela bi_faturamento.
processamento FaturamentoRepository Repositório CRUD de bi_faturamento.
processamento LoteRecebimentoBody Resposta do POST /api/xls/processar: id do lote, total e status por entrada.
processamento MesclaResumo Agregado das métricas de uma execução do orquestrador (spec 004 § 5.5): contém o UpsertResultado de cada tabela alvo.
processamento Movimento Linha de movimento contábil importada da aba 30 — tabela bi_movimento.
processamento MovimentoRepository Repositório CRUD de bi_movimento.
processamento ProcessamentoConsultaService Consultas de processamento: listagem paginada, detalhe, leitura do arquivo de log em disco e download do XLS original.
processamento ProcessamentoDetalheResponse Detalhe de um processamento para API e tela de detalhe (metadados, contagens e métricas de idempotência da spec 004; sem bytes do XLS).
processamento ProcessamentoListResponse Resposta paginada do endpoint de listagem de processamentos.
processamento ProcessamentoNotificador Formata e dispara as notificações Telegram do pipeline de processamento.
processamento ProcessamentoProcessador Execução assíncrona do processamento (fora do ProcessamentoService para o @Async ser aplicado via proxy).
processamento ProcessamentoRepository Persistência JDBC de ProcessamentoXls e atualizações de status.
processamento ProcessamentoResponse Resposta do recebimento síncrono (o controller HTTP mapeia httpStatus para o status da resposta).
processamento ProcessamentoResumoDto Linha da lista de processamentos (JTE e GET /api/transporte/processamentos).
processamento ProcessamentoService Orquestra recepção de arquivos, deduplicação por checksum e agendamento do processamento assíncrono.
processamento ProcessamentoStatus Estados de um processamento de XLS (xls_processamento.status).
processamento ProcessamentoTransactionalHelper Operações transacionais sobre os dados do BI por período (evita problemas de proxy com @Async).
processamento ProcessamentoXls Entidade da tabela xls_processamento: metadados do envio, referência ao objeto XLS no MinIO e resultado do job.
processamento StorageBackfillService Backfill dos blobs legados (arquivo_bytes) para o object storage Garage, dirigido pelo ArmazenamentoModo configurado em app.storage.modo: PSQL — não faz nada (tudo permanece no Postgres).
processamento TransporteController API REST de transporte: envio de XLS (Bearer), listagem e consulta pública de processamentos.
processamento UpsertResultado Métricas de uma operação UPSERT diff-aware + DELETE seletivo no caminho idempotente (spec 004 — § 4.7).
processamento ViewController Rotas HTML (JTE) para histórico e detalhe de processamentos — acesso anônimo conforme configuração de segurança.
processamento XlsController Porta única de envio de XLS — padrão da casa, idêntico entre todos os clientes.
processamento ZipXlsExtrator Desempacota o .zip de lote em suas entradas .xlsx (o zip É o lote).
processamento.processing ExcelProcessor Processa o byte[] do xlsx via FastExcel (StAX puro do JDK, sem XMLBeans/POI), em streaming.
processamento.processing PeriodoRelatorio Período do relatório extraído da aba "10" (células E1/F1).
processamento.processing ProcessamentoJsonExporter Serializa ResultadoProcessamento para JSON canônico conforme docs/dev/schema-processamento-xls.json.
processamento.processing VarcharLimits Trunca strings ao tamanho máximo da coluna no PostgreSQL (evita erro no insert).
processamento.processing VeiculoDadoFaltanteException Exception sintética usada pelo VeiculoDefesaCollector para envelopar um motivo+placa num evento Sentry (GlitchTip).
processamento.processing VeiculoDefesaAvaliador Inspeciona uma linha do XLS mensal (faturamento ou movimento) e produz a lista de motivos de defesa que se aplicam ao cadastro veicular daquela linha.
processamento.processing VeiculoDefesaCollector Coletor stateful per-processamento.

PowerSync

Reset da replicação PowerSync — orquestra os steps que pausam a replicação, derrubam o estado no MongoDB do PowerSync, recriam o slot no PostgreSQL e sinalizam os clientes Dart a refazerem o bootstrap (disconnectAndClear).

Pacote Classe O que faz
powersync AdminController Endpoints administrativos: hoje, apenas o "reset" da replicação PowerSync.
powersync AdminViewController Tela de administração JTE do reset da replicação PowerSync.
powersync CoolifyClient Wrapper fino sobre HttpClient para a API REST do Coolify — apenas as chamadas que a estratégia coolify de PowerSyncProcessControl precisa.
powersync MongoAdminService Operações administrativas no MongoDB do PowerSync.
powersync MongoAdminServiceImpl Implementação real de MongoAdminService usando mongodb-driver-sync.
powersync MongoAdminServiceStub Stub de MongoAdminService ativo quando powersync.mongodb.uri está vazio (default em dev).
powersync PostgresReplicationAdmin Operações administrativas em slots de replicação lógica do PostgreSQL.
powersync PowerSyncProcessControl Controla pause/resume do PowerSync Service durante o reset.
powersync PowerSyncProcessControlCoolify Estratégia coolify de PowerSyncProcessControl: reinicia o recurso PowerSync pela API REST do Coolify ao final do reset.
powersync PowerSyncProcessControlNone Implementação no-op de PowerSyncProcessControl: loga warning e reporta no progresso que o restart do PowerSync é manual.
powersync ResetStatus Estados de uma execução de reset da replicação (xls_resetar_powersync.status).
powersync ResetarPowersync Auditoria de execuções do "reset" da replicação PowerSync.
powersync ResetarPowersyncAlreadyInProgressException Sinal do ResetarPowersyncRepository#iniciar de que já existe um reset EM_ANDAMENTO (violação do partial unique index).
powersync ResetarPowersyncDetalheView View-model do reset para a tela de detalhe (admin/resetar-powersync-detalhe) — projeção dos campos que o template exibe.
powersync ResetarPowersyncNotificador Formata e dispara as notificações Telegram do reset da replicação.
powersync ResetarPowersyncRecovery Instruções de recuperação manual por step do reset — espelha a matriz de recovery do runbook (docs/resetar-powersync.md).
powersync ResetarPowersyncRepository Persistência da auditoria de resets em xls_resetar_powersync.
powersync ResetarPowersyncRequest Body opcional do POST /api/transporte/admin/resetar-powersync.
powersync ResetarPowersyncResponse Resposta 202 do POST /api/transporte/admin/resetar-powersync.
powersync ResetarPowersyncResumo View-model do reset para a listagem da tela admin — projeção dos campos que o template admin/powersync exibe.
powersync ResetarPowersyncService Orquestra os 9 steps do reset da replicação PowerSync.
powersync ResetarPowersyncStatusResponse Resposta 200 do GET /api/transporte/admin/resetar-powersync/{id}.
powersync StartupRecoveryService Recuperação ao subir a aplicação: Processamentos órfãos em PROCESSANDO viram ERRO; Processamentos em PENDENTE são re-enfileirados; Resets órfãos em EM_ANDAMENTO (pool reset- morreu junto com a JVM) viram ERRO — desbloqueia o partial unique index pra novos resets.

Configuração

Configuração global de runtime do app, editável pelo admin e persistida em banco — distinta da configuração estática de deploy (application.yml/env).

Pacote Classe O que faz
configuracao BiConfiguracao Configuração global do app em formato chave/valor.
configuracao BiConfiguracaoRepository Persistência de configurações globais em bi_configuracao (V12).
configuracao BiConfiguracaoView View-model de configuração para a tela admin/configuracoes — projeção dos campos que o template exibe.
configuracao ConfigService Leitura de configurações globais (bi_configuracao) em runtime, com cache curto.
configuracao ConfiguracaoAdminService Operações da tela admin de configurações (/admin/configuracoes).
configuracao ConfiguracaoAdminViewController } (exige sessão; gate de email @xadm.com.br no login).

Segurança

Camada de segurança específica do app (decisão 0011 / etapa 07): a policy de proteção das views e o fluxo de login Google.

Pacote Classe O que faz
seguranca AuthExceptionHandler Rede de segurança para AuthException que escape sem tratamento inline (o LoginController traduz as suas próprias no fluxo normal).
seguranca ViewRejectionHandler Tradução das rejeições do micronaut-security (5.x lança AuthorizationException) preservando o comportamento do antigo AuthFilter: autenticado sem permissão (AuthorizationException#isForbidden()) → 403; view anônima, browser (Accept: text/html) → 302 /login?from=…; view anônima, script (JSON) → 401; view em fail-closed (prod sem envs de auth) → 503; path whitelisted (ex.: /api sem Bearer) → 401.
seguranca ViewSecurityRule Regra de segurança das views, replicando o tri-estado do antigo AuthFilter: enabled (envs de auth completas): path de view exige Authentication — autenticado → ALLOWED, anônimo → REJECTED (o ViewRejectionHandler faz 302/401); bypass (dev/test sem envs): view liberada (ALLOWED) — views públicas; fail-closed (prod sem envs): view rejeitada (REJECTED) — o handler responde 503.
seguranca ViewWhitelist Whitelist da CAMADA DE VIEWS — os paths que a ViewSecurityRule dispensa de sessão.

Comum — base transversal

Base transversal — não é feature e, por trava de arquitetura (decisão 0022), não depende de nenhuma.

Pacote Classe O que faz
comum.config AppConfig Configuração de nível app.* compartilhada entre beans — prefixo app.
comum.config CoolifyConfig Configuração do restart automático do PowerSync via API do Coolify — prefixo powersync.admin.coolify.*.
comum.config LogsConfig Configuração do diretório de logs de execução — prefixo app.logs.*.
comum.config PowersyncMongoConfig Configuração do MongoDB do PowerSync usada no reset da replicação — prefixo powersync.mongodb.*.
comum.config PowersyncNukeConfig Configuração da confirmação e do bootstrap do reset destrutivo — prefixo powersync.nuke.* (contrato preservado do rename Nuke→ResetarPowersync; lido por integrações).
comum.config PowersyncPostgresConfig Configuração da replicação Postgres do PowerSync usada no reset — prefixo powersync.postgres.*.
comum.config TelegramConfig Configuração do bot Telegram — prefixo telegram.*.
comum.exception StorageIndisponivelException Storage de arquivos (Garage) indisponível ao receber o XLS — HTTP 503.
comum.notificacao TelegramApi Cliente HTTP declarativo da Telegram Bot API — só o sendMessage que o TelegramService usa.
comum.notificacao TelegramService Transporte de notificações via Telegram Bot API: recebe um texto já pronto e o posta.
comum.util AnosVeiculoParser Parseia o texto de ano do Excel no formato AAAA/AAAA (ex.: 2007/2007): à esquerda da barra = ano de construção; à direita = ano do modelo.

Raiz

Raiz do bi-transporte-xls: serviço Micronaut que recebe a planilha XLS de transporte, processa as abas em registros bi_/xls_ no PostgreSQL e expõe o resultado por API REST e views server-rendered, sincronizando para clientes Dart via PowerSync.

Pacote Classe O que faz
transporte Application Ponto de entrada da aplicação Micronaut e definição global OpenAPI (Bearer).
transporte BearerTokenEnv —