npm package: @marcos_feitoza/personal-finance-frontend
Description: 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.
Latest version: 1.12.8

# 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](./architecture_diagram.png)

### 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).

- [Arquitetura futura: Redis + RabbitMQ/Pulsar](./Documentation/architecture_future.md)

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

## Atualizações recentes de UI/UX (Design System GenAI)

As telas foram alinhadas para um padrão visual dark-glass consistente (baseado no dashboard de referência), com foco em consistência, responsividade e usabilidade em telas grandes.

- Tema global centralizado com tokens de cor/radius/sombra no `core-ui`.
- Shell visual unificado nas principais features (`GenaiBackdrop`, cards/tabelas padronizados).
- Ações e filtros com estados consistentes (`active`, `hover`, `focus`, `disabled`).
- Tabelas normalizadas via componente base para reduzir variação entre módulos.

### Ajustes para telas 4K e ultrawide

Para evitar UI “gigante” e difícil de usar em resoluções altas:

- foi adicionado um wrapper adaptativo no app shell (`lib/main.dart`) que:
  - limita largura útil em telas muito largas,
  - controla escala de texto por breakpoint de viewport.

### Compatibilidade com tablet

- componentes de seleção e cards foram ajustados para evitar overflow de texto;
- ações do AI Chat e cards de plano foram normalizados para quebrar conteúdo corretamente em larguras menores.

### Login (layout novo)

`Login` agora usa layout de duas colunas em desktop/wide:

- esquerda: painel de boas-vindas (placeholder para imagem futura);
- direita: formulário;
- em mobile/tablet mantém layout em coluna única.

#### Imagem opcional no painel esquerdo (com fallback)

A tela de login suporta `Image.asset(...)` no painel esquerdo com fallback automático para texto quando a imagem não existir.

- Arquivo da tela: `lib/screens/login_screen.dart`
- Asset configurado: `assets/images/login_welcome.png`

Local para salvar a imagem:

- `personal-finance-frontend/assets/images/login_welcome.png`

Formato e especificação recomendada:

- Formato: `PNG` ou `WEBP` (preferível para web)
- Proporção: `4:3` ou `16:10`
- Resolução ideal: `1600x1200`
- Resolução mínima: `1200x900`
- Tamanho recomendado do arquivo: `<= 500 KB`

Observação:

- O `pubspec.yaml` já inclui `assets/images/`, então não é necessário adicionar uma entrada individual para esse arquivo.

### Pré-requisitos

-   Flutter SDK ([instalação do Flutter](https://flutter.dev/docs/get-started/install))
-   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:
    ```bash
    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.

```bash
# 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).

2) **Reports** (Expense Report / Salary Report)
- A coluna Date deve estar em `YYYY-MM-DD`.

3) **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:

```bash
flutter run
```

Para rodar para web (com a URL da API definida):
```bash
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)

```bash
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:

```bash
TOKEN="<access_token>"
```

### 2) Lista para dropdown (somente user-defined)

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

### 2.1) Template demo (read-only)

```bash
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)

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

### 4) CRUD: criar categoria

```bash
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

```bash
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

```bash
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

```bash
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

```bash
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)

```bash
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:

```bash
flutter build web --release --dart-define=BASE_API_URL=http://seuservico.com/api
```
Os arquivos gerados estarão na pasta `build/web`.

### Build/Push via Podman (arm64)

O script `podman.sh` foi ajustado para:

- build e push somente para arquitetura `arm64`;
- funcionar em monorepo (incluindo pacotes locais `../personal-finance-frontend-*` no contexto do Docker build);
- evitar problemas de manifest multi-arch quando não necessário.

Uso:

```bash
./podman.sh
```

---

## 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`.