Files

38 lines
5.0 KiB
Markdown

## Why
Hoje o LerNotaFiscal extrai fornecedor, data e valor de cada nota fiscal, mas não classifica a despesa por categoria (ex.: Alimentação, Transporte, Saúde). Sem categoria, o usuário não consegue entender para onde o dinheiro está indo pelo Dashboard, apenas por fornecedor ou período. Precisamos categorizar automaticamente cada nota no momento da extração, com uma regra de negócio clara (AI primeiro, palavra-chave como fallback) e sem risco de gerar custo descontrolado de tokens de IA.
## What Changes
- Criar tabela `categoria` (`id`, `categoria`, `palavra_chave`) para mapear palavras-chave a categorias, usada como fallback e administrável pelo usuário. O registro `id = 1` é reservado pelo sistema para a categoria "Não Encontrado" e é garantido automaticamente na inicialização do schema; o usuário é responsável por cadastrar as demais categorias/palavras-chave pela tela de CRUD.
- Adicionar coluna `categoria_id` (FK para `categoria`) em `fiscal_documents` para persistir a classificação. Documentos processados pelo novo fluxo sempre recebem um `categoria_id` válido (nunca ficam nulos); apenas documentos já existentes antes desta mudança (não reprocessados) permanecem com `categoria_id` nulo ("Sem categoria").
- Implementar fluxo de categorização automática:
1. Ao processar uma nota, pedir à IA (mesma chamada de extração ou chamada dedicada) para sugerir a categoria a partir do nome do fornecedor.
2. Se a IA não retornar uma categoria válida/reconhecida, buscar na tabela `categoria` por correspondência de `palavra_chave` no `supplier_name` e usar a `categoria` encontrada.
3. Se a IA não conseguir categorizar **e** nenhuma `palavra_chave` corresponder, gravar `categoria_id = 1` ("Não Encontrado") sem bloquear o processamento.
- Ajustar o Dashboard (`app/templates/dashboard.html` + `dashboard_routes.py`) para exibir gastos agrupados por categoria (gráfico/lista) e permitir filtrar os dados exibidos por categoria, na mesma linha dos filtros de fornecedor/período já existentes na tela de documentos.
- Criar tela administrativa de CRUD (Create, Read, Update, Delete) para a tabela `categoria`, seguindo exatamente o mesmo layout/padrão já usado em "Documentos" (`documents_list.html` + `document_form.html`, mesmo `base.html`, mesmas classes CSS de `app/static/styles.css`, mesmo padrão de rotas `GET/POST /categorias`, `/categorias/new`, `/categorias/{id}/edit`, `POST /categorias/{id}/delete` com CSRF), para que o usuário possa cadastrar/editar/remover categorias e palavras-chave sem precisar de acesso direto ao banco.
- Criar mecanismo de segurança contra loop infinito / consumo excessivo de tokens ao acionar a IA para categorização:
- Limite de tentativas de chamada de IA por nota (ex.: no máximo 1 tentativa de categorização por nota, sem retry automático).
- Cache/memória de categorização por fornecedor (se já categorizamos "Fornecedor X" antes, não chamar a IA de novo — reusar resultado ou usar a tabela `categoria`).
- Circuit breaker/limite global (ex.: máximo de N chamadas de categorização por lote de importação ou por janela de tempo), com log e interrupção segura (fallback para palavra-chave) ao atingir o limite.
## Capabilities
### New Capabilities
- `expense-categorization`: Classificação automática de notas fiscais por categoria, com IA como fonte primária e a tabela `categoria` (palavra-chave) como fallback determinístico.
- `categorization-safety-limits`: Limites e proteções (retries, cache, circuit breaker) para chamadas de IA usadas na categorização, evitando loops e consumo excessivo de tokens.
### Modified Capabilities
- (nenhuma capability existente com spec.md hoje — projeto ainda não possui specs em `openspec/specs/`)
## Impact
- **Banco de dados** (`app/database.py`): nova tabela `categoria`; nova coluna `categoria_id` em `fiscal_documents` (e possivelmente `detected_documents`); nova migração aditiva no `SCHEMA`/`executescript`.
- **IA** (`app/ai_extraction.py` ou novo módulo `app/categorization.py`): nova função/chamada para sugerir categoria a partir do `supplier_name`; ajuste no fluxo de `extract_with_ai` ou chamada adicional pós-extração.
- **Ingestão** (`ingestion.py`): aplicar a lógica de categorização (IA → palavra-chave → `categoria_id = 1` "Não Encontrado") ao confirmar/criar `fiscal_documents`.
- **Rotas/Dashboard** (`app/routes/dashboard_routes.py`, `app/templates/dashboard.html`): novo agrupamento e filtro por categoria.
- **Nova rota de administração** (`app/routes/categoria_routes.py`, registrada em `app/main.py`; novos templates `app/templates/categorias_list.html` e `app/templates/categoria_form.html`, reaproveitando `base.html`): CRUD completo da tabela `categoria`, no mesmo padrão das rotas/telas de "Documentos".
- **Rotas de documentos** (`app/routes/documents_routes.py`): opcionalmente permitir filtrar/editar categoria manualmente por nota.
- **Configuração** (`app/config.py`): novos parâmetros para limites de segurança (ex.: `CATEGORIZATION_MAX_CALLS_PER_BATCH`, cache TTL).