Pular para o conteúdo
← Projetos

Backend

Controle Financeiro API

Controle de gastos com resumo mensal. O Postgres soma, não o Java, e todo valor é BigDecimal para não perder centavo.

2consultas JPQL agregam no banco

O problema

Resumo mensal parece a tela mais boba do app. Ela quebra em dois lugares: somar dinheiro com double, que perde centavo, e trazer todas as transações do banco para somar no Java.

Arquitetura

Categoria 1—N Transação, com o tipo da transação derivado da categoria. O resumo é uma consulta JPQL com sum e group by — a agregação acontece no banco. Valores em BigDecimal com escala fixa. PostgreSQL via Docker Compose; H2 isolado nos testes.

O contrato

Copiei do controller. É isto que a API responde.

GET/api/resumo?ano=2026&mes=7200 OK

Resposta

{
  "ano": 2026,
  "mes": 7,
  "totalReceitas": 8400.00,
  "totalDespesas": 5231.47,
  "saldo": 3168.53,
  "porCategoria": [
    { "categoria": "Salário",   "tipo": "RECEITA", "total": 8400.00 },
    { "categoria": "Aluguel",   "tipo": "DESPESA", "total": 2600.00 },
    { "categoria": "Mercado",   "tipo": "DESPESA", "total": 1487.32 }
  ]
}

Os totais já vêm somados do banco. A aplicação não percorre transação nenhuma.

SQLTransacaoRepository, a consulta que faz o trabalhoJPQL

Consulta

select c.nome as categoria, t.tipo as tipo, sum(t.valor) as total
from Transacao t join t.categoria c
where t.data between :inicio and :fim
group by c.nome, t.tipo
order by sum(t.valor) desc

O group by roda no Postgres. Mil ou cem mil transações custam quase o mesmo.

Decisões

  1. 01

    Agregar no banco, não em laço

    O banco devolve o total já somado. Quem tem dez mil lançamentos abre a tela na mesma velocidade de quem tem dez.

  2. 02

    BigDecimal com escala fixa

    double erra centavo, e erro de centavo em app de dinheiro aparece no extrato do usuário.

  3. 03

    Tipo derivado da categoria

    Não existe jeito de cadastrar despesa marcada como receita, porque o tipo vem da categoria. O modelo impede, então não depende de eu lembrar de validar.

O que ficou de pé

  • 5 testes cobrindo o fluxo de categorias, transações e resumo
  • Banco de teste isolado para evitar teste intermitente por estado compartilhado
  • Subida local em um comando com Docker Compose