- Tabela LOG_PAINEL (nova, ja criada no banco de dev) + app/db/log.py:
toda criacao/edicao/exclusao de cliente e contato fica registrada
(usuario, acao, sucesso/erro, detalhe). Tela /log mostra esse
historico.
- app/n8n_client.py: leitura opcional (N8N_API_URL/N8N_API_KEY) da
Data Table pagamentos_processados do n8n, mostrando os envios
automaticos de chave na mesma tela /log. Degrada de forma segura
(lista vazia) se nao configurado ou se a chamada falhar.
- Lista de clientes ganha ordenacao configuravel (codigo/razao/
fantasia/CNPJ) via whitelist, alem da busca que ja existia.
- CODIGO duplicado agora BLOQUEIA de verdade na criacao/edicao (sem
bypass) — antes so avisava com opcao de confirmar mesmo assim.
- Formulario de novo cliente sugere o proximo CODIGO sequencial
(editavel), ignorando a faixa reservada para dados de teste
(>= 900000) para nao ser contaminado por sobra de teste no banco.
- IMPLANTACAO/MENSALIDADE/JUROS_MORA/JUROS_MULTA/DATA_CONTRATO/
VENCIMENTO_CONTRATO deixam de ser obrigatorios — em branco, gravam
default (0,00 / hoje) em vez de bloquear o cadastro. Só CODIGO/CNPJ/
RAZAO/FANTASIA continuam obrigatorios.
- Limpeza: removidas 10 linhas de teste vazadas (CODIGO 999902) que
ficaram no banco de dev por sessoes de teste interrompidas.
69/69 testes passando (16 novos).
CSRF: novo app/csrf.py + middleware em app/main.py garantem um cookie
csrf_token por navegador; todo formulario que muda estado (criar/editar/
excluir cliente, adicionar/editar/excluir contato) embute esse valor
como campo oculto, e Depends(exigir_csrf) confere no POST que o valor
enviado bate com o cookie antes de deixar a rota executar. Verificado
ponta a ponta com o app real rodando (curl): token errado -> 403,
token correto -> 303.
Paginacao: db_clientes.listar_clientes ganha offset, nova
contar_clientes(); GET /clientes aceita ?pagina=N (100 clientes por
pagina), template mostra Anterior/Proxima e o total.
53/53 testes passando (8 novos).
Adiciona UI (details/summary, sem JS) para editar nome/telefone/email
de um contato existente, usando a rota POST /clientes/{id}/contatos/{id}/editar
que ja existia no router e no db mas nunca tinha formulario associado.
Cobre com testes de rota (sucesso + telefone duplicado) e um teste
verificando que a tela de detalhe realmente renderiza o formulario.