From 40d5a0f3fc3a158cfcb70b30c61d1086fd60baef Mon Sep 17 00:00:00 2001 From: Tiago Date: Tue, 13 Oct 2026 10:10:14 -0300 Subject: [PATCH] fix(cliente): exibir qrcode e acoes de whatsapp apenas apos aprovacao da conexao --- .../tenant/http/ClienteHandlers.java | 14 +++++- src/main/webapp/cliente/configuracoes.js | 44 +++++++++++++------ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/seconectai/condocontab/tenant/http/ClienteHandlers.java b/src/main/java/com/seconectai/condocontab/tenant/http/ClienteHandlers.java index 96001ce..adfdbca 100644 --- a/src/main/java/com/seconectai/condocontab/tenant/http/ClienteHandlers.java +++ b/src/main/java/com/seconectai/condocontab/tenant/http/ClienteHandlers.java @@ -457,7 +457,7 @@ public final class ClienteHandlers implements HttpHandler { } private boolean adminEmpresa(String cargo){return "admin_empresa".equals(cargo);} - private void conectarEvolution(HttpExchange ex,long empresaId)throws Exception{Mapb=body(ex);String url=b.getOrDefault("instance_url","");String numero=EvolutionApiClient.onlyDigits(req(b,"numero_whatsapp"));if(numero.length()<10){HttpResponses.json(ex,400,Map.of("erro","numero_whatsapp_invalido","mensagem","Informe o número com DDD e código do país."));return;}try(Connection m=masterDs.getMasterConnection()){liberarCadastrosEvolutionOrfaos(m,numero);Map existente=one(m,"SELECT id,empresa_id,status FROM evolution_instancias WHERE numero_whatsapp=? ORDER BY id DESC LIMIT 1",Arrays.asList(numero));if(existente!=null){HttpResponses.json(ex,409,Map.of("erro","numero_whatsapp_ja_cadastrado","mensagem","Este número de WhatsApp já está cadastrado em uma conexão."));return;}}String instance="empresa"+empresaId+"_"+System.currentTimeMillis();String token=UUID.randomUUID().toString().replace("-","");var criada=evolutionApiClient.criarInstancia(url,instance,token,numero);try(Connection m=masterDs.getMasterConnection();PreparedStatement ps=m.prepareStatement("INSERT INTO evolution_instancias (empresa_id,instance_url,instance_token_enc,numero_whatsapp,status) VALUES (?,?,?,?, 'pendente') RETURNING id")){ps.setLong(1,empresaId);ps.setString(2,url);ps.setString(3,criada.instanceName()+":"+criada.token());ps.setString(4,numero);try(ResultSet rs=ps.executeQuery()){rs.next();Map resp=new LinkedHashMap<>();resp.put("id",rs.getLong(1));resp.put("instance_name",criada.instanceName());resp.put("status","pendente");resp.put("qrcode_base64",criada.qrcodeBase64());resp.put("mock",criada.mock());HttpResponses.json(ex,201,resp);}}} + private void conectarEvolution(HttpExchange ex,long empresaId)throws Exception{Mapb=body(ex);String url=b.getOrDefault("instance_url","");String numero=EvolutionApiClient.onlyDigits(req(b,"numero_whatsapp"));if(numero.length()<10){HttpResponses.json(ex,400,Map.of("erro","numero_whatsapp_invalido","mensagem","Informe o número com DDD e código do país."));return;}try(Connection m=masterDs.getMasterConnection()){liberarCadastrosEvolutionOrfaos(m,numero);Map existente=one(m,"SELECT id,empresa_id,status FROM evolution_instancias WHERE numero_whatsapp=? ORDER BY id DESC LIMIT 1",Arrays.asList(numero));if(existente!=null){HttpResponses.json(ex,409,Map.of("erro","numero_whatsapp_ja_cadastrado","mensagem","Este número de WhatsApp já está cadastrado em uma conexão."));return;}}String instance="empresa"+empresaId+"_"+System.currentTimeMillis();String token=UUID.randomUUID().toString().replace("-","");var criada=evolutionApiClient.criarInstancia(url,instance,token,numero);try(Connection m=masterDs.getMasterConnection();PreparedStatement ps=m.prepareStatement("INSERT INTO evolution_instancias (empresa_id,instance_url,instance_token_enc,numero_whatsapp,status) VALUES (?,?,?,?, 'pendente') RETURNING id")){ps.setLong(1,empresaId);ps.setString(2,url);ps.setString(3,criada.instanceName()+":"+criada.token());ps.setString(4,numero);try(ResultSet rs=ps.executeQuery()){rs.next();Map resp=new LinkedHashMap<>();resp.put("id",rs.getLong(1));resp.put("instance_name",criada.instanceName());resp.put("status","pendente");resp.put("mock",criada.mock());HttpResponses.json(ex,201,resp);}}} private void liberarCadastrosEvolutionOrfaos(Connection m,String numero)throws Exception{List> existentes=rows(m,"SELECT id,instance_url,instance_token_enc FROM evolution_instancias WHERE numero_whatsapp=? ORDER BY id",Arrays.asList(numero));for(Map inst:existentes){String token=str(inst.get("instance_token_enc"));String instanceName=token.split(":",2)[0];if(instanceName.isBlank())continue;try{evolutionApiClient.estado(str(inst.get("instance_url")),instanceName);}catch(Exception err){if(!evolutionNaoEncontrada(err))throw err;try(PreparedStatement ps=m.prepareStatement("DELETE FROM evolution_instancias WHERE id=?")){ps.setLong(1,((Number)inst.get("id")).longValue());ps.executeUpdate();}}}} private boolean evolutionNaoEncontrada(Exception err){String msg=err.getMessage()==null?"":err.getMessage().toLowerCase(Locale.ROOT);return msg.contains("404")||msg.contains("not found")||msg.contains("instance not found")||msg.contains("nao encontrada")||msg.contains("não encontrada");} private void statusEvolution(HttpExchange ex,long empresaId)throws Exception{ @@ -494,6 +494,10 @@ public final class ClienteHandlers implements HttpHandler { Long id=optLong(b.get("id")); Map inst=id!=null?evolutionInstanciaPorId(empresaId,id):evolutionInstancia(empresaId); if(inst==null){HttpResponses.json(ex,404,Map.of("erro","instancia_nao_configurada"));return;} + if(!"aprovada".equalsIgnoreCase(str(inst.get("status")))){ + HttpResponses.json(ex,403,Map.of("erro","instancia_pendente_aprovacao","mensagem","Esta conexão está pendente de aprovação pelo administrador.")); + return; + } String[] parts=String.valueOf(inst.get("instance_token_enc")).split(":",2); Map qr=evolutionApiClient.conectar(str(inst.get("instance_url")),parts[0],str(inst.get("numero_whatsapp"))); HttpResponses.json(ex,200,qr); @@ -503,6 +507,10 @@ public final class ClienteHandlers implements HttpHandler { Long id=optLong(b.get("id")); Map inst=id!=null?evolutionInstanciaPorId(empresaId,id):evolutionInstancia(empresaId); if(inst==null){HttpResponses.json(ex,404,Map.of("erro","instancia_nao_configurada"));return;} + if(!"aprovada".equalsIgnoreCase(str(inst.get("status")))){ + HttpResponses.json(ex,403,Map.of("erro","instancia_pendente_aprovacao","mensagem","Esta conexão está pendente de aprovação pelo administrador.")); + return; + } String[] parts=String.valueOf(inst.get("instance_token_enc")).split(":",2); HttpResponses.json(ex,200,evolutionApiClient.logout(str(inst.get("instance_url")),parts[0])); } @@ -511,6 +519,10 @@ public final class ClienteHandlers implements HttpHandler { Long id=optLong(b.get("id")); Map inst=id!=null?evolutionInstanciaPorId(empresaId,id):evolutionInstancia(empresaId); if(inst==null){HttpResponses.json(ex,404,Map.of("erro","instancia_nao_configurada"));return;} + if(!"aprovada".equalsIgnoreCase(str(inst.get("status")))){ + HttpResponses.json(ex,403,Map.of("erro","instancia_pendente_aprovacao","mensagem","Esta conexão está pendente de aprovação pelo administrador.")); + return; + } String[] parts=String.valueOf(inst.get("instance_token_enc")).split(":",2); HttpResponses.json(ex,200,evolutionApiClient.reiniciar(str(inst.get("instance_url")),parts[0])); } diff --git a/src/main/webapp/cliente/configuracoes.js b/src/main/webapp/cliente/configuracoes.js index 3405dc9..088bcf8 100644 --- a/src/main/webapp/cliente/configuracoes.js +++ b/src/main/webapp/cliente/configuracoes.js @@ -90,6 +90,7 @@ function renderCards(list) { const evoState = evo.state || 'close'; const instName = inst.instance_name || ('instancia_' + inst.id); const phoneFormatted = formatPhone(inst.numero_whatsapp); + const isAprovada = String(inst.status || '').toLowerCase() === 'aprovada'; return ` @@ -200,6 +205,10 @@ async function requisitarQrCode() { function abrirModalQr(id, initialData = null) { selectedInstanciaId = id; const inst = conexoes.find(c => c.id === id); + if (inst && String(inst.status || '').toLowerCase() !== 'aprovada') { + Util.toast('Esta conexão ainda está pendente de aprovação pelo administrador.', true); + return; + } if (inst && inst.numero_whatsapp) { qrModalTitle.textContent = `Conectar ${formatPhonePlain(inst.numero_whatsapp)}`; } else { @@ -220,6 +229,11 @@ function fecharModalQr() { function abrirModalReconectar(id) { selectedInstanciaId = id; + const inst = conexoes.find(c => c.id === id); + if (inst && String(inst.status || '').toLowerCase() !== 'aprovada') { + Util.toast('Esta conexão ainda está pendente de aprovação pelo administrador.', true); + return; + } reconectarStepConfirm.classList.remove('hidden'); reconectarStepLoading.classList.add('hidden'); reconectarModal.classList.remove('hidden'); @@ -251,6 +265,11 @@ async function executarReconectar() { function abrirModalDesconectar(id) { selectedInstanciaId = id; + const inst = conexoes.find(c => c.id === id); + if (inst && String(inst.status || '').toLowerCase() !== 'aprovada') { + Util.toast('Esta conexão ainda está pendente de aprovação pelo administrador.', true); + return; + } desconectarStepConfirm.classList.remove('hidden'); desconectarStepLoading.classList.add('hidden'); desconectarModal.classList.remove('hidden'); @@ -286,13 +305,10 @@ form.onsubmit = async (e) => { try { if (submitBtn) submitBtn.disabled = true; const body = Util.formData(form); - const d = await Api.post('/api/config/evolution-instancia/conectar', body); + await Api.post('/api/config/evolution-instancia/conectar', body); form.reset(); - Util.toast('WhatsApp cadastrado com sucesso!'); + Util.toast('WhatsApp cadastrado com sucesso! Aguarde a aprovação do administrador para conectar via QR Code.'); await load(); - if (d.id) { - abrirModalQr(d.id, d); - } } catch (err) { Util.toast(err.message, true); } finally {