- Erro BCB (dado não publicado): bloqueia retry por 15 min, não até EOD
- Sucesso BCB: cache válido até 23:59 como antes
- Garante que o CDI do dia seja calculado quando BCB publicar (~9h)
BCB retorna objeto de erro (não array) quando a taxa do dia ainda não foi
publicada. Antes: decode falhava, cache ficava vazio, BCB era chamado a cada
request. Agora: decode error → put(nil) no cache → requests seguintes servidas
do cache em <1ms até fim do dia
- Cache map[date]rate compartilhado entre chamadas do mesmo processo
- Expira às 23:59:59 do dia corrente (não TTL fixo de 24h)
- Double-checked locking evita múltiplas chamadas concorrentes ao BCB
- Cobre múltiplas contas com start dates diferentes sem chamadas redundantes
- GameRepo: EnsureCategoryAchievement, RemoveCategoryAchievementIfNotEarned, ListCategoriesWithBudget, GetMonthlySpendByCategory
- GameService: OnCategoryBudgetSet, CheckCategoryBudgets
- ListAchievements filtra conquistas por categorias do perfil (sem vazamento entre usuários)
- NotifyAction chama CheckCategoryBudgets em transaction_created e import_confirmed
- CategoryHandler injeta GameService e chama OnCategoryBudgetSet após Create/Update
- 5 novos testes unitários cobrindo todos os cenários de AC
- Migration 018: ADD COLUMN monthly_budget NUMERIC(12,2) em categories
- Migration 018: ADD COLUMN category_id INTEGER REFERENCES categories(id) ON DELETE CASCADE em achievements
- Remove conquistas hardcoded veleiro_under_500 e health_3months do banco
- Reset game state do profile_id=1
- Atualiza CategoryRepository, CategoryInput e Category model para incluir monthly_budget
- TransactionRepository.CategoryByDescription: busca a categoria mais
recente para cada descrição normalizada no histórico do perfil
- ImportService.Preview: pré-preenche category_id em linhas não-duplicatas
cuja descrição já foi categorizada antes (case-insensitive)
- Duplicatas não recebem sugestão
- 2 novos testes: auto-categorize + duplicate-not-categorized
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Nova tabela user_settings com savings_goal_pct (default 40%)
- API GET /api/settings, PUT /api/settings
- DashboardService inclui savings_goal_pct no payload
- DashboardHandler dispara savings_checked com goal configurado
- GameService.NotifyAction: checa pct >= goal (sem hardcode de 40%)
- SettingsView: painel META DE POUPANÇA com input configurável
- HomeView: widget mostra meta dinâmica (META: X%) e usa savingsGoal
- stores/settings.ts: store com fetch e update
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Nova tabela pending_bill_imports (migration 016)
- ImportHandler.Confirm: quando is_credit_card=true e payment_date > hoje,
salva como pending em vez de inserir transações
- Novos endpoints: GET /pending-bills, POST /pending-bills/:id/confirm,
DELETE /pending-bills/:id
- Dashboard inclui pending_bill_imports no payload
- Frontend: resultado "fatura salva como pendente" no ImportView
- AccountsView exibe widget de faturas pendentes com ações de confirmar/descartar
- dashboard_test: mock de PendingBillRepo + TransactionRepository
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Adiciona campo cdi_percentage (default 100%) na tabela accounts
- Cálculo CDI aplica proporção: balance × (compound-1) × (pct/100)
- Frontend exibe input de % quando yield_type=cdi e badge mostra valor
- Corrige mocks de teste desatualizados (DeleteByMonth, isTax)
- Corrige ConfirmIncome para rejeitar tipo expense (ErrRecurringNotIncome)
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Remove restrição que bloqueava delete de transações importadas.
Adiciona DELETE /transactions?month=YYYY-MM para exclusão em lote
e botão "EXCLUIR MÊS" na view de transações.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Botão CONFIRMAR para despesas pendentes, igual ao fluxo de receitas.
Backend remove guard income-only no ConfirmIncome.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Migration 011: closing_day/due_day em accounts + tabela credit_bills
- CreditBillService: cria/atualiza fatura corrente on-demand no GET /accounts
- Widget FATURA ATUAL no dashboard com total e botão PAGAR
- AccountsView: campos closing_day/due_day para contas credit + painel fatura
- Dashboard: current_bills lista faturas não pagas de todos os cartões
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Migration 009: coluna `type` em recurring_expenses + tabela recurring_late
- API Go: tipo income/expense em CRUD; endpoints POST /confirm e /late
- Dashboard: campo pending_income_recurrings na resposta
- Frontend: RecurringView com seções RECEITAS e DESPESAS separadas
- HomeView: widget de confirmação (dia 1-5) e badge SALÁRIO PENDENTE (pós dia 5)
- Testes unitários: 4 novos casos (income covered, late, confirm, reject expense)
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
CRUD de contas (corrente/poupança/investimento/cartão) com saldo calculado
automaticamente. account_id nullable em transactions. Widget patrimônio no
dashboard. Tela /contas. Seletor de conta nas transações manuais.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Adiciona CRUD manual de transações (income/expense) com filtro mensal, CRUD de
recorrências fixas com verificação mensal de cobertura (±10% por categoria),
endpoint de ignore/unignore e telas Vue para Transações e Configurações.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Parser OFX tolerante ao formato SGML de bancos brasileiros (sem closing tags, BOM,
timezone suffix). Parser CSV com separador de campo/decimal configurável. Dedup por
FITID (OFX) ou date+amount+desc normalizado. Fluxo: POST /preview → revisão na UI
→ POST /confirm salva e loga. Migration 002 adiciona external_id com unique index.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
API REST /api/categories (GET/POST/PUT/DELETE) com regras de negócio:
categorias padrão não podem ser excluídas; categorias com transações vinculadas
também bloqueadas. Tela Vue com formulário inline de criação/edição, indicador
visual de categorias padrão e botão de exclusão condicional.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>