Pular para o conteúdo
jpaulos.dev

MoneyLens

Um app de finanças pessoais, feito de ponta a ponta e usado de verdade, com leitura de faturas, previsão de gastos e alertas.

2026 · 5 min de leitura
  • Python
  • FastAPI
  • PostgreSQL
  • React
Código no GitHub (abre em nova aba)
Nesta página
Tour pelo app: todos os dados são inventados.

O problema

O controle financeiro começou numa planilha. Ela servia para anotar gastos, mas não dava conta do resto: faturas de cartão com parcelas que atravessam meses, contas fixas que precisam ser confirmadas, extratos de bancos diferentes e a pergunta que mais importa no meio do mês: quanto ainda dá para gastar?

Cada fatura era digitada à mão, e um erro só aparecia no fechamento. O MoneyLens troca essa digitação por leitura automática, com conferência, e responde àquela pergunta com números.

O que o app faz

  • Painel do mês: receitas, gastos, saldo previsto, orçamento 50/30/20 e o que ainda falta confirmar.
  • Lançamentos, parcelas e fixas: compras parceladas no cartão, no Pix ou no boleto geram as parcelas futuras; as contas fixas entram como previstas e são confirmadas com um clique.
  • Importação de PDF: faturas do Inter e extratos do Nubank e do PicPay. O app confere a soma com os totais impressos, reconhece as categorias e deixa em standby o que não reconhece. Ao resolver um item com “lembrar”, ele aprende a regra.
  • Cartões: faturas de cada mês, limite usado e pagamento.
  • Previsão: quanto cada categoria deve fechar no mês, com um valor provável e um máximo provável.
  • Tetos de gasto: por valor ou por porcentagem da renda, com alertas em 50%, 90% e 100% e sugestão a partir do histórico.
  • Vários usuários: cada pessoa só enxerga os próprios dados.
Painel do mêsPainel do mês
Painel do mês
LançamentosLançamentos
Lançamentos
Cartões e faturasCartões e faturas
Cartões e faturas
Revisão de uma fatura importadaRevisão de uma fatura importada
Revisão de uma fatura importada
Previsão por categoriaPrevisão por categoria
Previsão por categoria
Tetos de gastoTetos de gasto
Tetos de gasto

Arquitetura

O front-end é um app React servido por um Cloudflare Worker, que também repassa as chamadas de API para o back-end. A API em FastAPI roda num container no Render e guarda tudo num PostgreSQL no Supabase.

NO ARNavegadorReact + TanStack QueryCloudflareWorker + site estáticoAPI FastAPIno RenderPostgreSQLSupabase, com RLSPREVISÃOTreino localPyTorchModelo ONNXgravado no bancoPrevisãoonnxruntime na API

A previsão tem um caminho separado: o treino roda fora do servidor, em PyTorch, e o modelo exportado em ONNX vai para o banco, um por usuário. Na API, quem executa o modelo é o onnxruntime.

Decisões técnicas

Decisão

PyTorch só no treino; a API roda o modelo em ONNX

A imagem de produção não instala o PyTorch. O modelo é treinado fora do servidor, exportado para ONNX e gravado no banco; a API só carrega e executa. O container fica pequeno e a previsão continua rápida.

Decisão

Leitores de PDF que conferem os totais

Cada leitor soma o que leu e compara com os totais que o próprio banco imprime: o total da fatura, o saldo de cada dia, o saldo final. Se não bater, nada é importado. É melhor recusar um PDF do que gravar um número errado em silêncio.

Decisão

Isolamento entre usuários e banco fechado ao público

Toda consulta filtra pelo dono, e um teste confere que nenhuma rota da API fica de fora: o item de outra pessoa responde como se não existisse. No Supabase, o RLS fica ligado sem políticas e os papéis da API pública perdem o acesso, então o banco só atende o back-end.

Decisão

Migração publicada não se edita

O app é publicado a cada push na main, e as migrações rodam na subida. Uma migração que já foi para produção nunca é alterada: qualquer mudança vira uma migração nova, testada no SQLite e no PostgreSQL.

Decisão

Um fuso só em todo o teste

Um teste de ponta a ponta falhava só na CI, entre 21h e meia-noite: o servidor estava em UTC, o navegador em São Paulo, e os dois discordavam sobre que dia era. Hoje o servidor de testes e o navegador rodam no mesmo fuso, o de São Paulo.

Qualidade e testes

testes no back-end
550
testes no front-end
196
testes de ponta a ponta
33
bancos na CI
2
  • Back-end: Pytest cobre regras de negócio, API, segurança, migrações e os leitores de PDF. Na CI, a suíte roda no SQLite e no PostgreSQL.
  • Front-end: Vitest nos formulários, nos utilitários e no Worker do Cloudflare.
  • Ponta a ponta: o Playwright sobe o app com um banco temporário e percorre os fluxos no computador e no celular.
  • Dados reais nunca entram: as faturas e os extratos dos testes são sintéticos, gerados por código.

O que aprendi

  • Conferir é mais barato que corrigir. A regra de “só importa se o total bater” evitou mais problemas do que qualquer revisão manual.
  • Um modelo precisa de uma régua. Cada treino mede o erro da rede neural ao lado do erro de uma estatística simples, no mesmo mês de teste. Com essa referência, fica claro quando o modelo realmente ajuda.
  • Fuso horário é requisito. Datas aparecem em faturas, parcelas e alertas; tratar o fuso desde o começo evita bugs que só aparecem à noite.
  • Testes de ponta a ponta se pagam. Eles pegaram problemas que nenhum teste de unidade pegaria, como um clique caindo na página anterior durante a troca de rota.