fix: corrige validação e salvamento do formulário de edição de militante - Corrige validação do email, ajusta conversão de datas, corrige CSRF token e melhora feedback visual

This commit is contained in:
andersonid
2025-04-07 03:42:01 -03:00
committed by LS
parent 179ea3cad0
commit 3f2e6e3022
3 changed files with 116 additions and 115 deletions

164
app.py
View File

@@ -940,146 +940,112 @@ def create_app():
db.close()
# Rota para editar militante
@app.route("/militantes/editar/<int:militante_id>", methods=["POST"])
@require_login
@app.route('/militantes/editar/<int:militante_id>', methods=['POST'])
@login_required
@require_permission('gerenciar_militantes')
def editar_militante(militante_id):
"""Edita um militante existente"""
# Verificar token CSRF manualmente
csrf_token = request.headers.get('X-CSRFToken') or request.form.get('csrf_token')
if not csrf_token or not csrf.validate_csrf(csrf_token):
return jsonify({
'status': 'error',
'message': 'Token CSRF inválido'
}), 400
db = get_db_connection()
try:
militante = db.query(Militante).get(militante_id)
# Verificar se o militante existe
militante = db_session.query(Militante).get(militante_id)
if not militante:
return jsonify({
'status': 'error',
'message': 'Militante não encontrado'
}), 404
# Dados Básicos
militante.nome = request.form.get('nome')
militante.cpf = request.form.get('cpf')
militante.titulo_eleitoral = request.form.get('titulo_eleitoral')
militante.data_nascimento = datetime.strptime(request.form.get('data_nascimento'), '%Y-%m-%d') if request.form.get('data_nascimento') else None
militante.data_entrada_oci = datetime.strptime(request.form.get('data_entrada_oci'), '%Y-%m-%d') if request.form.get('data_entrada_oci') else None
militante.data_efetivacao_oci = datetime.strptime(request.form.get('data_efetivacao_oci'), '%Y-%m-%d') if request.form.get('data_efetivacao_oci') else None
# Contato
militante.telefone1 = request.form.get('telefone1')
militante.telefone2 = request.form.get('telefone2')
# Email (atualizar o principal)
# Obter dados do formulário
nome = request.form.get('nome')
cpf = request.form.get('cpf')
titulo_eleitoral = request.form.get('titulo_eleitoral')
data_nascimento = request.form.get('data_nascimento')
data_entrada_oci = request.form.get('data_entrada_oci')
data_efetivacao_oci = request.form.get('data_efetivacao_oci')
telefone1 = request.form.get('telefone1')
telefone2 = request.form.get('telefone2')
email = request.form.get('email')
# Converter datas para objetos date
data_nascimento = datetime.strptime(data_nascimento, '%Y-%m-%d').date() if data_nascimento else None
data_entrada_oci = datetime.strptime(data_entrada_oci, '%Y-%m-%d').date() if data_entrada_oci else None
data_efetivacao_oci = datetime.strptime(data_efetivacao_oci, '%Y-%m-%d').date() if data_efetivacao_oci else None
# Atualizar dados básicos
militante.nome = nome
militante.cpf = cpf
militante.titulo_eleitoral = titulo_eleitoral
militante.data_nascimento = data_nascimento
militante.data_entrada_oci = data_entrada_oci
militante.data_efetivacao_oci = data_efetivacao_oci
militante.telefone1 = telefone1
militante.telefone2 = telefone2
# Atualizar email
if email:
if militante.emails:
militante.emails[0].endereco_email = email
# Verificar se já existe um email para este militante
email_existente = db_session.query(EmailMilitante).filter_by(militante_id=militante_id).first()
if email_existente:
email_existente.endereco_email = email
else:
novo_email = EmailMilitante(
endereco_email=email,
militante_id=militante.id
)
db.add(novo_email)
militante.emails.append(novo_email)
novo_email = EmailMilitante(endereco_email=email, militante_id=militante_id)
db_session.add(novo_email)
# Atualizar endereço
endereco = militante.endereco or Endereco(militante_id=militante_id)
endereco.cep = request.form.get('cep')
endereco.estado = request.form.get('estado')
endereco.cidade = request.form.get('cidade')
endereco.bairro = request.form.get('bairro')
endereco.rua = request.form.get('rua')
endereco.numero = request.form.get('numero')
endereco.complemento = request.form.get('complemento')
# Endereço
if not militante.endereco:
militante.endereco = Endereco()
db.add(militante.endereco)
militante.endereco = endereco
db_session.add(endereco)
militante.endereco.cep = request.form.get('cep')
militante.endereco.estado = request.form.get('estado')
militante.endereco.cidade = request.form.get('cidade')
militante.endereco.bairro = request.form.get('bairro')
militante.endereco.rua = request.form.get('rua')
militante.endereco.numero = request.form.get('numero')
militante.endereco.complemento = request.form.get('complemento')
# Profissional
militante.profissao = request.form.get('profissao')
militante.regime_trabalho = request.form.get('regime_trabalho')
# Atualizar dados profissionais
militante.empresa = request.form.get('empresa')
militante.contratante = request.form.get('contratante')
# Acadêmico
militante.instituicao_ensino = request.form.get('instituicao_ensino')
militante.tipo_instituicao = request.form.get('tipo_instituicao')
# Sindical
# Atualizar dados sindicais
militante.sindicato = request.form.get('sindicato')
militante.cargo_sindical = request.form.get('cargo_sindical')
militante.central_sindical = request.form.get('central_sindical')
militante.dirigente_sindical = request.form.get('dirigente_sindical') == 'on'
militante.dirigente_sindical = request.form.get('dirigente_sindical') == 'true'
# Organização
estado_str = request.form.get('estado', 'ATIVO').lower()
print(f"Estado recebido: {estado_str}")
# Converter o estado para o enum
try:
militante.estado = EstadoMilitante[estado_str.upper()]
print(f"Estado convertido: {militante.estado}")
except (KeyError, ValueError) as e:
print(f"Erro ao converter estado: {str(e)}")
return jsonify({
'status': 'error',
'message': f'Estado inválido: {estado_str}'
}), 400
# Tratar celula_id corretamente
celula_id = request.form.get('celula_id')
if celula_id:
try:
militante.celula_id = int(celula_id)
except (ValueError, TypeError):
militante.celula_id = None
else:
militante.celula_id = None
# Tratar responsabilidades corretamente
# Atualizar responsabilidades
try:
responsabilidades_valor = request.form.get('responsabilidades_valor')
if responsabilidades_valor:
militante.responsabilidades = int(responsabilidades_valor)
print(f"Responsabilidades atualizadas: {militante.responsabilidades}")
print(f"Responsabilidades atualizadas para: {militante.responsabilidades}")
else:
militante.responsabilidades = 0
print("Responsabilidades zeradas")
print("Nenhuma responsabilidade definida")
except (ValueError, TypeError) as e:
print(f"Erro ao processar responsabilidades: {str(e)}")
print(f"Erro ao processar responsabilidades: {e}")
militante.responsabilidades = 0
# Se o estado mudou para DESLIGADO, registrar data e motivo
if militante.estado == EstadoMilitante.DESLIGADO:
militante.data_desligamento = datetime.now()
militante.motivo_desligamento = request.form.get('motivo_desligamento')
db.commit()
print("Alterações salvas com sucesso")
# Retornar as responsabilidades atualizadas
responsabilidades = militante.get_responsabilidades()
# Salvar alterações
db_session.commit()
print("Alterações salvas com sucesso!")
# Retornar resposta
return jsonify({
'status': 'success',
'message': f'Militante {militante.nome} atualizado com sucesso!',
'responsabilidades': responsabilidades,
'responsabilidades_valor': militante.responsabilidades
'message': 'Militante atualizado com sucesso!',
'responsabilidades': militante.get_responsabilidades()
})
except Exception as e:
print(f"Erro ao atualizar militante: {str(e)}")
db.rollback()
db_session.rollback()
print(f"Erro ao salvar alterações: {e}")
return jsonify({
'status': 'error',
'message': f'Erro ao atualizar militante: {str(e)}'
'message': str(e)
}), 500
finally:
db.close()
# Rota para criar um novo usuário
@app.route("/usuarios/novo", methods=["GET", "POST"])

View File

@@ -317,7 +317,7 @@ async function carregarDadosMilitante(militanteId) {
const emailElement = document.getElementById('edit_email');
if (emailElement) {
if (data.emails && data.emails.length > 0) {
emailElement.value = data.emails[0].endereco_email;
emailElement.value = data.emails[0]; // O email já vem como string
} else {
emailElement.value = '';
}
@@ -568,7 +568,7 @@ document.addEventListener('DOMContentLoaded', function() {
const emailElement = document.getElementById('edit_email');
if (emailElement) {
if (data.emails && data.emails.length > 0) {
emailElement.value = data.emails[0].endereco_email;
emailElement.value = data.emails[0]; // O email já vem como string
} else {
emailElement.value = '';
}
@@ -667,10 +667,41 @@ document.addEventListener('DOMContentLoaded', function() {
formEditarMilitante.addEventListener('submit', async function(event) {
event.preventDefault();
console.log('Formulário de edição enviado');
// Validar todos os campos antes do envio
const form = this;
form.classList.add('was-validated');
// Verificar se o formulário é válido
if (!form.checkValidity()) {
event.stopPropagation();
// Encontrar o primeiro campo inválido
const invalidField = form.querySelector(':invalid');
if (invalidField) {
// Encontrar a aba que contém o campo inválido
const tabPane = invalidField.closest('.tab-pane');
if (tabPane) {
// Ativar a aba
const tabId = tabPane.id;
const tab = document.querySelector(`button[data-bs-target="#${tabId}"]`);
if (tab) {
const bsTab = new bootstrap.Tab(tab);
bsTab.show();
// Focar no campo inválido após a aba ser exibida
setTimeout(() => {
invalidField.focus();
}, 200);
}
}
}
return;
}
// Se chegou aqui, o formulário é válido
// Obter ID do militante
const militanteId = document.getElementById('edit_militante_id').value;
console.log('ID do militante:', militanteId);
if (!militanteId) {
console.error('ID do militante não encontrado');
@@ -679,24 +710,21 @@ document.addEventListener('DOMContentLoaded', function() {
}
// Criar FormData com todos os campos
const formData = new FormData(this);
const formData = new FormData(form);
// Garantir que o valor das responsabilidades seja enviado
const responsabilidadesValue = document.getElementById('responsabilidades_values').value;
formData.set('responsabilidades_valor', responsabilidadesValue);
console.log('Valor das responsabilidades sendo enviado:', responsabilidadesValue);
try {
// Construir URL
const url = `/militantes/editar/${militanteId}`;
console.log('URL da requisição:', url);
const csrfToken = document.querySelector('input[name="csrf_token"]').value;
// Enviar requisição
const response = await fetch(url, {
method: 'POST',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': getCsrfToken()
'X-CSRF-Token': csrfToken
},
body: formData
});
@@ -706,17 +734,11 @@ document.addEventListener('DOMContentLoaded', function() {
}
const data = await response.json();
console.log('Resposta do servidor:', data);
if (data.status === 'success') {
// Fechar modal
const modal = bootstrap.Modal.getInstance(document.getElementById('modalEditarMilitante'));
modal.hide();
// Mostrar mensagem de sucesso
mostrarAlerta('Militante atualizado com sucesso!', 'success');
// Recarregar página após um pequeno delay para a mensagem ser vista
setTimeout(() => {
location.reload();
}, 1000);

View File

@@ -44,10 +44,16 @@
<div class="col-md-6 mb-3">
<label for="edit_nome" class="form-label">Nome</label>
<input type="text" class="form-control" id="edit_nome" name="nome" required>
<div class="invalid-feedback">
Por favor, insira o nome do militante.
</div>
</div>
<div class="col-md-6 mb-3">
<label for="edit_cpf" class="form-label">CPF</label>
<input type="text" class="form-control" id="edit_cpf" name="cpf" required>
<div class="invalid-feedback">
Por favor, insira um CPF válido.
</div>
</div>
</div>
<div class="row">
@@ -91,7 +97,14 @@
<!-- Email Principal -->
<div class="mb-3">
<label for="edit_email" class="form-label">Email Principal</label>
<input type="email" class="form-control" id="edit_email" name="email" required>
<input type="email"
class="form-control"
id="edit_email"
name="email"
required>
<div class="invalid-feedback">
Por favor, insira um email válido.
</div>
</div>
<!-- Endereço -->