Gustavo 9ed0bf57c2 feat: log de acoes/envios, ordenacao/filtro, codigo sequencial, campos opcionais
- 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).
2026-08-13 14:04:24 -03:00
2026-08-13 09:39:28 -03:00
2026-08-13 09:39:28 -03:00
2026-08-13 09:39:28 -03:00

painel-clientes-web

Painel administrativo (FastAPI + Jinja2) para gestão de CLIENTE, CLIENTE_CONTATO e geração manual de chave de licenciamento no MySQL do sistema legado.

Proteções: login HTTP Basic em toda rota, CSRF via cookie de duplo envio (app/csrf.py — todo formulário que muda estado embute o mesmo token do cookie csrf_token, definido pelo middleware em app/main.py) e a lista de clientes é paginada (100 por página), com busca e ordenação por código/razão/fantasia/CNPJ.

CODIGO de cliente não aceita duplicado (bloqueio duro, sem bypass) e o formulário de novo cliente já sugere o próximo código sequencial (editável). Só CODIGO, CNPJ, RAZAO e FANTASIA são obrigatórios — os campos de contrato (implantação, mensalidade, juros, datas) podem ficar em branco e recebem default (0,00 / data de hoje).

A rota /log mostra o histórico de ações do painel (tabela LOG_PAINEL, criada no banco de dev — precisa ser criada manualmente em produção também, DDL no início de app/db/log.py) e, se N8N_API_URL/N8N_API_KEY estiverem configuradas (.env.example), os últimos envios automáticos de chave via WhatsApp (lidos da Data Table pagamentos_processados do n8n, somente leitura).

Rodando localmente (sem Docker)

  1. Instale as dependências de desenvolvimento:
    pip install -r requirements-dev.txt
    
  2. Defina as variáveis de ambiente necessárias (ADMIN_USER, ADMIN_PASSWORD, DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD — veja .env.example) diretamente no shell antes de subir a aplicação. Importante: apesar de python-dotenv estar nas dependências, nada no código chama load_dotenv() hoje — um arquivo .env sozinho NÃO é lido automaticamente fora do Docker. Exporte as variáveis manualmente (ex.: set -a; source .env; set +a no bash, ou $env:... no PowerShell) ou defina-as por outro meio.
  3. Rode a aplicação:
    uvicorn app.main:app --reload
    
  4. Rodando direto na máquina (fora de container), use DB_HOST=127.0.0.1 (porta 3307, a mesma do container de dev licenciamento-mysql-dev).

Rodando os testes

pytest -v

Os testes usam defaults definidos em tests/conftest.py (equivalentes ao .env.example) e incluem testes de integração que precisam do container MySQL de dev (licenciamento-mysql-dev, 127.0.0.1:3307) rodando.

Rodando via Docker

  1. Copie o arquivo de exemplo de variáveis de ambiente e edite ADMIN_PASSWORD (e demais valores, se necessário):
    cp .env.example .env
    
  2. Suba o container:
    docker compose up -d --build
    
    O docker-compose.yml já usa env_file: .env e mapeia host.docker.internal para o host (via extra_hosts), então o valor padrão DB_HOST=host.docker.internal do .env.example funciona também em hosts Docker Linux, não só no Docker Desktop (Windows/Mac).
  3. A aplicação fica disponível em http://localhost:8010.
S
Description
GTI GERENCIADOR / FISCAL
Readme
11 MiB
Languages
Python 82%
HTML 15.8%
CSS 1.2%
PowerShell 0.6%
Shell 0.2%
Other 0.1%