npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@marcos_feitoza/personal-finance-frontend

v1.12.6

Published

Este repositório contém o frontend principal da aplicação de finanças pessoais. Ele é construído com Flutter e utiliza uma arquitetura modular para integrar funcionalidades de vários módulos de features.

Readme

Personal Finance - Aplicação Frontend (Flutter)

Este repositório contém o frontend principal da aplicação de finanças pessoais. Ele é construído com Flutter e utiliza uma arquitetura modular para integrar funcionalidades de vários módulos de features.

Visão Geral

O projeto utiliza uma arquitetura de microsserviços no backend e uma abordagem modular no frontend para separar as responsabilidades e permitir o desenvolvimento e a escalabilidade independentes de cada componente. O frontend, em Flutter, se comunica com o backend composto por vários serviços em Python.

Diagrama da Arquitetura

O diagrama abaixo ilustra a estrutura atual dos microsserviços e dos pacotes do frontend, e como eles se interconectam.

Arquitetura de Microsserviços

Diagrama futuro (visão de evolução)

Se a aplicação crescer (mais usuários, mais tráfego, integrações, jobs assíncronos), pode fazer sentido introduzir componentes como Redis (cache/rate limit) e mensageria/event streaming (RabbitMQ ou Pulsar).

Para gerar um PNG do diagrama futuro (via Python + Graphviz):

  • Script: ./generate_future_diagram.py
  • Output: ./architecture_future_diagram.png

Projetos

A aplicação é dividida nos seguintes projetos:

Frontend

O frontend é uma aplicação Flutter dividida em uma arquitetura de pacotes para máxima separação e manutenibilidade:

  • personal-finance-frontend: A aplicação "shell" que hospeda e integra todos os outros módulos de frontend.
  • personal-finance-frontend-core-ui: Um pacote de biblioteca contendo todos os widgets de UI reutilizáveis (formulários, diálogos, etc.).
  • personal-finance-frontend-core-services: Um pacote de biblioteca que lida com a comunicação com o backend, contendo todos os serviços e modelos de dados.
  • personal-finance-frontend-feature-dashboard: O módulo de feature que contém a tela principal do dashboard.
  • personal-finance-frontend-feature-reports: O módulo de feature para todas as telas de relatórios.
  • personal-finance-frontend-feature-charts: O módulo de feature para todas as telas de gráficos.
  • personal-finance-frontend-feature-investments: O módulo de feature para as telas de visualização e gerenciamento de investimentos.
  • personal-finance-frontend-feature-management: O módulo de feature para as telas de gerenciamento de transações e reconciliação.

Backend

  • personal-finance-backend-core: O microsserviço principal que lida com a lógica de negócios central, incluindo transações, contas e balanços.
  • personal-finance-backend-market-data: Um microsserviço dedicado a buscar dados de mercado em tempo real, como cotações de ações.
  • personal-finance-backend-trades-assets: Uma biblioteca de código para a lógica de criação e gerenciamento de trades (negociações) e ativos de investimento.
  • personal-finance-backend-shared: Uma biblioteca de código Python compartilhada contendo os modelos de banco de dados (SQLAlchemy), schemas (Pydantic) e utilitários comuns a todos os serviços de backend.

Cada projeto contém seu próprio README.md com detalhes específicos de sua função e configuração.


Como Começar

Pré-requisitos

  • Flutter SDK (instalação do Flutter)
  • Um editor de código com suporte a Flutter (VS Code, Android Studio, IntelliJ IDEA).

Instalação

  1. Navegue até o diretório raiz do projeto (personal-finance-frontend).
  2. Obtenha as dependências do Flutter:
    flutter pub get

Configuração

O aplicativo precisa se comunicar com o backend. A URL base da API do backend pode ser configurada via --dart-define durante o build ou run.

Auth: Após login, o app recebe um par access_token + refresh_token.

  • O access_token (JWT) é enviado em Authorization: Bearer <token> em chamadas protegidas.
  • O refresh_token é usado para renovar o access_token sem exigir relogin.

Admin: Rotas /api/admin/* exigem um usuário com role=admin ou role=support_admin. O app do usuário comum não expõe funções administrativas.

# Exemplo de uso para definir a URL da API
flutter run --dart-define=BASE_API_URL=http://localhost:8000

Se BASE_API_URL não for definida, um valor padrão será usado (ver transaction_service.dart ou auth_service.dart em personal-finance-frontend-core-services).

Conceito atual de Admin Console

A experiência administrativa é centralizada em uma tela dedicada com abas:

  • Users: gestão de plano, role, status, segurança e créditos AI
  • Audit Logs: trilha de ações administrativas (quem fez, quando, antes/depois, ip/request_id)
  • AI Observability: visão operacional de AI por usuário (centralizada no admin)

Importante:

  • a opção AI Observability foi removida do menu de usuário comum
  • observability operacional agora é consumida no Admin Console

Padrões de Formatação (UI)

Para reduzir duplicação e evitar inconsistências entre telas, as formatações principais foram centralizadas no pacote core-ui.

Datas (padrão único)

Decisão do projeto: toda data exibida ao usuário e enviada para a API usa o formato:

  • yyyy-MM-dd

Helpers:

  • personal-finance-frontend-core-ui/lib/utils/dates.dart
    • Dates.formatUi(date)
    • Dates.formatApi(date)
    • (quando precisar em listas) Dates.formatCompactDate(date)

Dinheiro

Para exibir valores monetários com consistência (separador de milhar, 2 casas, etc.), use:

  • personal-finance-frontend-core-ui/lib/utils/money.dart
    • Money.format(value, currency: CurrencyCode.cad)
    • Money.fixed(value)

Nota: a conversão CAD/USD está preparada no util, mas o fetch automático de cotação (API grátis) fica como próximo passo.


Como validar rapidamente na UI

Checklist de smoke-test (2–5 minutos):

  1. Forms (Expense/Salary/Move Money/RRSP/Dividend/Trade/Crypto Trade)
  • Campo Date deve estar como YYYY-MM-DD.
  • Selecionar uma data no calendário deve manter YYYY-MM-DD.
  • Salvar deve funcionar (payload segue o mesmo formato).
  1. Reports (Expense Report / Salary Report)
  • A coluna Date deve estar em YYYY-MM-DD.
  1. Tabelas de investimentos (ex.: TFSA)
  • Valores devem estar formatados (ex.: $1,234.50).

Sessão, expiração e logout automático

Expiração de tokens (backend)

  • Access token: expira em 30 minutos.
  • Refresh token: expira por padrão em 30 dias (configurável no backend).

Renovação automática (frontend)

O frontend possui um ApiClient centralizado (no pacote personal-finance-frontend-core-services) que:

  • injeta o header Authorization automaticamente
  • ao receber 401, tenta /api/auth/refresh e reexecuta a request uma vez

Idle timeout (segurança/UX)

O app aplica logout automático após 30 minutos sem interação (touch/mouse/scroll).

  • Arquivo: personal-finance-frontend/lib/widgets/idle_timeout_wrapper.dart
  • No Web, timers podem ser reduzidos/pausados em abas em background; por isso o app também reavalia o idle ao voltar para a aba.

Como Executar

Localmente para Desenvolvimento

A partir do diretório raiz do projeto (personal-finance-frontend), execute:

flutter run

Para rodar para web (com a URL da API definida):

flutter run -d chrome --web-hostname localhost --web-port 5000 --dart-define=BASE_API_URL=http://localhost:8000/api

Metadata (Categories/Subcategories) — testes via curl

Alguns endpoints de metadata exigem autenticação. No ambiente personal-finance.casa, seu curl pode precisar do -k (certificado).

Decisão de produto (modo "clean"):

  • Dropdowns do app (ex.: Add Expense) mostram somente categorias/subcategorias explicitamente salvas pelo usuário.
  • O sistema não aprende/mergeia categorias a partir do histórico de transações (isso evitou poluição com itens como pagamentos de cartão gerados pela reconciliação).

Por isso, o endpoint /api/metadata/categories hoje retorna somente user-defined categories. A tela de Settings usa /api/metadata/user-categories (mesma lista, em endpoint separado).

1) Login (gera token)

curl -k -s -X POST https://personal-finance.casa/api/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=SEU_EMAIL" \
  -d "password=SUA_SENHA" \
  | jq

Depois:

TOKEN="<access_token>"

2) Lista para dropdown (somente user-defined)

curl -k -s -H "Authorization: Bearer $TOKEN" \
  https://personal-finance.casa/api/metadata/categories | jq

2.1) Template demo (read-only)

curl -k -s -H "Authorization: Bearer $TOKEN" \
  https://personal-finance.casa/api/metadata/demo-categories | jq

3) Lista do usuário (somente o que ele criou)

curl -k -s -H "Authorization: Bearer $TOKEN" \
  https://personal-finance.casa/api/metadata/user-categories | jq

4) CRUD: criar categoria

curl -k -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"house test"}' \
  https://personal-finance.casa/api/metadata/categories | jq

5) CRUD: criar subcategoria

curl -k -s -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Rent X"}' \
  https://personal-finance.casa/api/metadata/categories/HOUSE%20TEST/subcategories | jq

6) CRUD: deletar subcategoria

curl -k -s -X DELETE -H "Authorization: Bearer $TOKEN" \
  https://personal-finance.casa/api/metadata/categories/HOUSE%20TEST/subcategories/Rent%20X

7) CRUD: deletar categoria

curl -k -s -X DELETE -H "Authorization: Bearer $TOKEN" \
  https://personal-finance.casa/api/metadata/categories/HOUSE%20TEST

8) Importar categorias demo para o usuário

curl -k -s -X POST -H "Authorization: Bearer $TOKEN" \
  https://personal-finance.casa/api/metadata/user-categories/import-defaults | jq

Observação importante:

  • Escolher uma categoria/subcategoria no Add Expense NÃO grava isso na sua lista custom automaticamente.
  • Para que vire parte da sua lista custom (aparecer em /user-categories), você precisa:
    • importar o demo, ou
    • criar manualmente no Settings, ou
    • criar durante o Import Statement (CSV) (o botão Create item salva na sua lista).

Comportamento (decisão de produto):

  • Para evitar poluição com itens que você nunca usa, o app não mostra a lista demo automaticamente nos dropdowns.
  • O demo é apenas um template para importar quando fizer sentido.

Nota importante sobre cache e multi-user

Os resultados de metadata são cacheados no SharedPreferences.

  • As chaves de cache para categories/user-categories/payment-methods são escopadas por usuário (ex.: metadata.categories.v2.uid_123).
  • Isso evita que ao fazer logout/login com outro usuário, a UI reutilize a lista do usuário anterior.

9) Ver categorias usadas em transações (somente "aprendido" do histórico — diagnóstico)

curl -k -s -H "Authorization: Bearer $TOKEN" \
  https://personal-finance.casa/api/metadata/transaction-categories | jq

> Nota: este endpoint é útil para diagnóstico/insights, mas **não** é usado para alimentar dropdowns.

Build para Produção (Web)

Para gerar uma build otimizada para web:

flutter build web --release --dart-define=BASE_API_URL=http://seuservico.com/api

Os arquivos gerados estarão na pasta build/web.


Estrutura de Pacotes

Este aplicativo Flutter é construído sobre uma arquitetura de pacotes modulares, com a aplicação principal (personal-finance-frontend) orquestrando o carregamento de funcionalidades fornecidas por pacotes de features.

Arquitetura de Cálculos Financeiros

Este documento esclarece como os principais valores financeiros são calculados no sistema. Aderir a esta lógica é crucial para manter a consistência dos dados.

1. Balanço de Caixa (Cash Balance)

O balanço de caixa é a representação do dinheiro "em mãos" do usuário. O cálculo correto e completo é:

Balanço de Caixa = (Renda Total) - (Despesas Pagas com Caixa) + (Transferências para o Caixa) - (Transferências para Fora do Caixa)

  • Renda Total: A soma de todas as transações com type = 'credit' na tabela transactions.
  • Despesas Pagas com Caixa: A soma de todas as transações com type = 'debit' E payment_method = 'CASH' na tabela transactions.
  • Transferências para o Caixa: A soma de todos os registros na tabela investments onde destination_account = 'CASH'.
  • Transferências para Fora do Caixa: A soma de todos os registros na tabela investments onde source_account = 'CASH'.

2. Relatório de Despesas

O relatório de despesas deve refletir todos os gastos operacionais do usuário. Ele é calculado como:

Total de Despesas do Relatório = (Soma de todos os débitos) - (Soma dos débitos de investimento/capital)

  • Lógica: Soma todas as transações com type = 'debit' na tabela transactions, excluindo aquelas cujas categorias são INVESTMENTS, PENT HAUS, Da Vince, e Acores, pois estas representam uma transferência de capital e não uma despesa operacional.

3. Relatório de Salário (Renda)

O relatório de salário deve refletir a renda principal do usuário.

Total de Salário do Relatório = Soma de todos os créditos das categorias de renda

  • Lógica: Soma todas as transações com type = 'credit' E cuja category seja Salary 1, Salary 2, ou Extra.