- 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).
68 lines
2.1 KiB
Python
68 lines
2.1 KiB
Python
"""
|
|
Log de ações do painel (LOG_PAINEL) — uma linha por ação que muda estado
|
|
(criar/editar/excluir cliente, adicionar/editar/excluir contato), sucesso
|
|
ou erro. Escrita feita pelos routers via `registrar(...)`, nunca
|
|
sobrescrita/editada depois — é histórico, não estado.
|
|
|
|
A tabela já existe no banco de dev. Em qualquer outro ambiente (produção),
|
|
crie-a primeiro com:
|
|
|
|
CREATE TABLE LOG_PAINEL (
|
|
ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
CRIADO_EM DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
USUARIO VARCHAR(60) NOT NULL,
|
|
ACAO VARCHAR(40) NOT NULL,
|
|
ENTIDADE VARCHAR(20) NOT NULL,
|
|
ENTIDADE_ID VARCHAR(20) DEFAULT NULL,
|
|
SUCESSO TINYINT(1) NOT NULL,
|
|
DETALHE VARCHAR(500) DEFAULT NULL,
|
|
PRIMARY KEY (ID),
|
|
KEY IDX_LOG_PAINEL_CRIADO_EM (CRIADO_EM)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
"""
|
|
from .connection import get_connection
|
|
|
|
|
|
def registrar(
|
|
usuario: str,
|
|
acao: str,
|
|
entidade: str,
|
|
entidade_id: str | None,
|
|
sucesso: bool,
|
|
detalhe: str | None = None,
|
|
) -> None:
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"INSERT INTO LOG_PAINEL (USUARIO, ACAO, ENTIDADE, ENTIDADE_ID, SUCESSO, DETALHE) "
|
|
"VALUES (%s, %s, %s, %s, %s, %s)",
|
|
(usuario, acao, entidade, entidade_id, 1 if sucesso else 0, detalhe),
|
|
)
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def listar(limite: int = 100, offset: int = 0) -> list[dict]:
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute(
|
|
"SELECT ID, CRIADO_EM, USUARIO, ACAO, ENTIDADE, ENTIDADE_ID, SUCESSO, DETALHE "
|
|
"FROM LOG_PAINEL ORDER BY CRIADO_EM DESC, ID DESC LIMIT %s OFFSET %s",
|
|
(limite, offset),
|
|
)
|
|
return cur.fetchall()
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
def contar() -> int:
|
|
conn = get_connection()
|
|
try:
|
|
with conn.cursor() as cur:
|
|
cur.execute("SELECT COUNT(*) AS total FROM LOG_PAINEL")
|
|
return cur.fetchone()["total"]
|
|
finally:
|
|
conn.close()
|