Skip to content

Repository files navigation

SuperTixs

Novo gerador Borderô

Aplicação web para visualização, conferência e exportação de borderôs financeiros e operacionais.

Super eventos, mega experiências


Aplicação online

A aplicação também poderá ser acessada pela versão hospedada na Vercel:

Link da Vercel: será adicionado após a publicação e a validação do ambiente de produção.

A execução local continua disponível pelas instruções da seção Como executar.

Sobre o projeto

Este projeto foi desenvolvido para a SuperTixs. A aplicação consolida dados reais anonimizados de três eventos e gera um borderô completo, com informações financeiras, operacionais e detalhamento ingresso a ingresso.

Os arquivos JSON da pasta data/ são a única fonte de dados.

A solução permite:

  • selecionar um dos três eventos disponíveis;
  • consultar o borderô completo pela página web;
  • filtrar as vendas por data inicial e final;
  • navegar pelo detalhamento paginado dos ingressos;
  • exportar o mesmo relatório em PDF e XLSX;
  • manter o período selecionado nas exportações;
  • validar automaticamente os dados de entrada e os resultados consolidados.

Eventos disponíveis

Evento Perfil
evento-demo-a Evento corporativo, ingressos de valor elevado, grande quantidade de cortesias e formulário personalizado
evento-demo-b Evento cultural com cupons, cortesias, reembolsos, transferências e check-ins
evento-demo-c Festival de maior volume, com ingressos gratuitos e pagos, cupons e muitos check-ins

Cada evento possui os seguintes arquivos:

event.json
ticket-types.json
coupons.json
transactions.json
sold-tickets.json

O significado dos campos e as particularidades dos dados estão descritos em docs/dicionario-de-dados.md.

Seções do borderô

A página web, o PDF e o XLSX apresentam as oito seções exigidas em docs/requisitos-bordero.md:

  1. Resumo do evento — vendas brutas, taxas, vendas líquidas, repasse, ticket médio, percentual vendido e percentual de check-ins;
  2. Finanças gerais — composição dos valores brutos, taxas e valores líquidos;
  3. Formas de pagamento — quantidade, valor e participação por método;
  4. Tipos e lotes de ingresso — estoque, vendas, descontos, taxas e valores líquidos;
  5. Cupons de desconto — tipo, valor, utilizações, desconto concedido e receita associada;
  6. Cortesias — ingressos emitidos, cancelados, válidos e check-ins;
  7. Disponibilidade e check-ins — estoque, vendas e presença por tipo e lote;
  8. Detalhamento — listagem completa, ingresso a ingresso.

Regras financeiras implementadas

As regras foram centralizadas para manter os mesmos resultados na web, no PDF e no XLSX:

  • status são normalizados antes das comparações;
  • transações canceladas, inválidas ou reembolsadas não entram na receita;
  • pagamentos FREE e COMPLIMENTARY ficam fora da receita financeira;
  • a receita bruta utiliza o campo total das transações válidas;
  • as taxas utilizam o valor informado em platformFee, sem inferir ou recalcular valores ausentes;
  • a regra absorbFees define se a taxa é absorvida pelo organizador ou paga pelo comprador;
  • o ticket médio considera somente ingressos efetivamente pagos;
  • valores monetários são calculados com decimal.js e convertidos para centavos com arredondamento controlado;
  • descontos e taxas distribuídos por ingresso utilizam rateio de centavos para evitar diferenças de arredondamento;
  • o filtro de período considera transaction.createdAt;
  • o detalhamento mantém transações canceladas ou reembolsadas para rastreabilidade, mas identifica corretamente seu status.

Tecnologias utilizadas

Tecnologia Uso
Next.js 16 Aplicação web, rotas dinâmicas e endpoints de exportação
React 19 Componentes e interface
TypeScript 6 Tipagem e regras de domínio
Node.js Leitura dos arquivos, processamento e geração dos relatórios
Zod Validação estrutural dos JSONs
Decimal.js Cálculos monetários com precisão decimal
PDFKit Geração do relatório em PDF
ExcelJS Geração da planilha XLSX
ESLint Análise estática do código
TSX Execução dos validadores TypeScript

O desenvolvimento foi realizado e testado principalmente com:

Node.js 22.21.0
npm 10.9.4

Estrutura principal

assets/                         Logos e assinatura
data/                           Dados dos três eventos
docs/                           Requisitos, dicionário e validações
scripts/
  validate-data.ts              Validação dos arquivos de entrada
  validate-reports.ts           Validação dos resultados dos relatórios
src/
  app/                          Páginas e rotas da aplicação
  components/                   Tabelas e ações reutilizáveis
  lib/
    bordero/                    Regras de cálculo e consolidação
    data/                       Leitura e validação dos JSONs
    export/                     Geração de PDF e XLSX
    formatting/                 Formatação de datas, moedas e percentuais
    money/                      Operações monetárias
  types/                        Tipos do domínio

Como executar

Pré-requisitos

  • Node.js 22 ou versão compatível;
  • npm;
  • Git, caso o projeto seja obtido pelo repositório.

Nenhuma variável de ambiente é obrigatória.

1. Instalar as dependências

Com o repositório clonado, abra um terminal na raiz do projeto e execute:

npm ci

O uso de npm ci é recomendado porque instala exatamente as versões registradas no package-lock.json.

2. Executar em desenvolvimento

npm run dev

A aplicação estará disponível em:

http://localhost:3000

O script de desenvolvimento utiliza Webpack:

next dev --webpack

Essa escolha foi feita por apresentar comportamento mais estável para o CSS e para os pacotes de geração de arquivos utilizados no projeto.

3. Executar a versão de produção local

npm run build
npm run start

4. Executar as validações

npm run lint
npm run validate:data
npm run validate:reports
npm run build

Função de cada comando:

Comando Finalidade
npm run lint Verifica problemas de estilo e código
npm run validate:data Confere a estrutura e características esperadas dos JSONs
npm run validate:reports Recalcula e valida os resultados consolidados dos três eventos
npm run build Valida a compilação de produção do Next.js

Rotas principais

/                                  Seleção dos eventos
/eventos/[slug]                    Borderô do evento
/api/eventos/[slug]/pdf            Exportação em PDF
/api/eventos/[slug]/xlsx           Exportação em XLSX

Os parâmetros de período utilizados na página também são enviados para as exportações:

?inicio=AAAA-MM-DD&fim=AAAA-MM-DD

Exportações

PDF

O PDF é gerado com PDFKit e inclui:

  • cabeçalho e identidade visual;
  • uma seção por conjunto de informações;
  • tabelas com quebras automáticas de página;
  • período aplicado;
  • data de emissão;
  • numeração de páginas.

As seções convencionais utilizam formato A4. A seção de detalhamento ingresso a ingresso utiliza A3, pois a quantidade de colunas tornava o conteúdo excessivamente pequeno e pouco legível em A4.

XLSX

A planilha é gerada com ExcelJS e possui uma aba para cada seção do borderô. As células recebem formatação de moeda, percentual, data, cabeçalhos, totais e dimensões adequadas para leitura.

Dificuldades encontradas e soluções

PDFKit não encontrava Helvetica.afm no Next.js

O PDFKit depende de arquivos internos de fonte. Quando empacotado diretamente pelo Next.js, o caminho desses arquivos podia ser perdido, resultando em erro ao localizar Helvetica.afm.

Solução: o pacote foi mantido como dependência externa do servidor em next.config.ts:

serverExternalPackages: ["pdfkit"]

Assim, o PDFKit é executado com a própria estrutura de arquivos disponível no ambiente Node.js.

Páginas em branco causadas pelo rodapé do PDF

Ao posicionar o rodapé abaixo da área útil, o PDFKit interpretava o texto como conteúdo adicional e criava novas páginas automaticamente.

Solução: o rodapé passou a ser desenhado dentro da margem útil da página, com altura limitada e lineBreak: false. As páginas também são mantidas em buffer para que a numeração seja inserida somente depois de o total ser conhecido.

Instabilidade do Turbopack e manifesto do React

Durante o desenvolvimento ocorreram falhas relacionadas ao manifesto do React e diferenças na aplicação do CSS com o Turbopack.

Solução: o servidor de desenvolvimento passou a usar Webpack por meio de next dev --webpack, que apresentou comportamento mais previsível neste projeto.

Precisão de valores monetários

O uso direto de number em JavaScript pode gerar imprecisões binárias, especialmente em somas, rateios e arredondamentos financeiros.

Solução: os cálculos foram implementados com decimal.js, com conversão controlada para centavos e arredondamento ROUND_HALF_UP.

Diferenças entre transactions.json e sold-tickets.json

Os arquivos representam perspectivas diferentes do mesmo processo: a transação contém o pedido consolidado, enquanto sold-tickets.json contém documentos individuais. Nem sempre os dados possuem correspondência direta perfeita.

Solução: as transações são usadas como fonte financeira e os ingressos emitidos como fonte de titularidade, check-in e identificação individual. O cruzamento é realizado por transactionId e, quando necessário, por tipo, título e lote.

Ingressos sem tid

Alguns registros de ingresso não possuem o identificador direto do tipo de ingresso.

Solução: foi implementada uma estratégia de resolução em etapas:

  1. tid ou ticketTypeId quando disponível;
  2. combinação exata de título e lote;
  3. correspondência pelo título;
  4. único item da transação, quando não há ambiguidade.

Vocabulário legado e variações de status

Os dados possuem status em diferentes caixas e campos auxiliares de cancelamento ou reembolso.

Solução: os valores são normalizados com remoção de espaços e conversão para minúsculas. A decisão final também considera flags e datas como isCancelled, cancelledAt, isRefunded e refundedAt.

Transações reembolsadas com status aparentemente pago

Foram encontrados registros marcados como RECEIVED, mas também sinalizados como reembolsados ou cancelados.

Solução: as flags e datas de invalidação têm prioridade sobre o status de pagamento. A operação continua visível no detalhamento, mas deixa de compor receitas, taxas, vendas e ticket médio.

Ticket médio com ingressos gratuitos em pedidos mistos

Pedidos podiam conter simultaneamente itens pagos e gratuitos. Contar todos os itens no denominador reduzia incorretamente o ticket médio.

Solução: o denominador passou a considerar apenas itens cujo preço original, preço ou desconto aplicado demonstre que o ingresso possuía valor financeiro.

Paginação do detalhamento

A quantidade de ingressos tornava inviável exibir todos os registros de uma só vez na página web.

Solução: o detalhamento foi dividido em páginas de 50 registros, com navegação que preserva o evento e o período selecionado.

Preservação dos filtros nas exportações

Inicialmente, a página podia estar filtrada, mas os downloads eram gerados com todo o período.

Solução: os parâmetros inicio e fim passaram a ser adicionados às URLs de PDF e XLSX e são processados novamente pelas rotas de exportação.

Leitura e interpretação dos arquivos JSON

Erros de leitura, JSON incompleto ou dados fora do formato esperado podiam produzir mensagens pouco informativas.

Solução: o carregador passou a separar as etapas de leitura, JSON.parse e validação com Zod. Cada etapa gera uma mensagem contextual contendo o arquivo e a causa do problema.

Divergências de arredondamento por ingresso

A distribuição direta de descontos e taxas entre vários ingressos podia produzir diferenças de um ou mais centavos em relação ao total da transação.

Solução: foi criado um rateio em centavos que distribui os resíduos de arredondamento sem alterar o total consolidado.

Limitações e bugs conhecidos

Os itens abaixo não impedem as funções principais da aplicação, mas devem ser considerados durante a avaliação:

Centralização horizontal da logo no XLSX

O ExcelJS posiciona imagens como objetos flutuantes por coordenadas fracionárias. A renderização pode variar conforme o Excel, o LibreOffice, as células mescladas e a largura calculada das colunas.

A logo é inserida e dimensionada corretamente, mas pode apresentar um pequeno desalinhamento horizontal em algumas abas ou programas. As tentativas de correção por deslocamento manual não produziram comportamento consistente em todos os casos.

Erro intermitente Unexpected end of JSON input

Foi observado, de forma não determinística durante o desenvolvimento, o erro:

SyntaxError: Unexpected end of JSON input

O carregador possui tratamento explícito para falhas de leitura, interpretação e validação. Ainda assim, o erro pode surgir esporadicamente em situações de atualização do servidor de desenvolvimento ou leitura interrompida. Não foi encontrada uma reprodução estável que permitisse uma correção definitiva.

Limitações dos dados de origem

Existem divergências naturais entre arquivos, campos opcionais e transações sem platformFee. Nesses casos, a aplicação segue literalmente o dicionário de dados e não inventa valores ausentes.

Por esse motivo, algumas reconciliações entre seções podem apresentar pequenas diferenças que refletem os dados fornecidos, não um recálculo inferido pela aplicação.

Decisões de projeto 5.0

  • Os JSONs permanecem imutáveis e são tratados como fonte oficial.
  • As regras de negócio ficam em src/lib/bordero, separadas da interface.
  • A web e as duas exportações recebem o mesmo objeto consolidado para reduzir divergências.
  • O detalhamento permanece completo nos arquivos exportados, embora seja paginado na web.
  • Campos ausentes recebem tratamentos seguros quando o requisito permite, sem criar dados financeiros inexistentes.
  • O layout foi desenvolvido originalmente para a identidade da SuperTixs, sem copiar relatórios de outras plataformas.

Documentação complementar

Versão anonimizada para demonstração

Esta cópia contém dados sintéticos/pseudonimizados para publicação demonstrativa. Foram substituídos nomes de eventos, produtores e participantes, e-mails, telefones, documentos, endereços, respostas de formulários, cupons, URLs, identificadores internos e datas. Valores monetários também foram transformados por fatores distintos por evento, mantendo a estrutura e os relacionamentos necessários ao funcionamento do relatório.

Os arquivos originais não devem ser reintroduzidos nesta versão pública.

About

New borderô generator for Supertixs website

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages