diff --git a/scripts/migracoes.sql b/scripts/migracoes.sql new file mode 100644 index 0000000..7f393c9 --- /dev/null +++ b/scripts/migracoes.sql @@ -0,0 +1,411 @@ +-- ============================================================ +-- CHATC2 - MIGRAÇÕES DE BANCO DE DADOS (Firebird) +-- ============================================================ +-- Execute este arquivo no seu banco .FDB usando: +-- isql -user SYSDBA -pass masterkey localhost:SEU_BANCO.FDB -i migracoes.sql +-- Ou cole no IBExpert / FlameRobin e execute statement por statement. +-- +-- Cada bloco é idempotente: se a tabela/coluna já existe, o erro é ignorado. +-- ============================================================ + +-- ============================================================ +-- TABELA DE CONTROLE (deve ser a primeira) +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_CONTROLE_MIGRACOES')) THEN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_CONTROLE_MIGRACOES ( + MIG_ID INTEGER NOT NULL PRIMARY KEY, + MIG_DESCRICAO VARCHAR(200), + MIG_DATA_EXECUCAO TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + MIG_STATUS CHAR(1) DEFAULT ''A'' + )'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 1: Campo USU_TIPO_CHAT em USUARIOS +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'USUARIOS' AND RDB$FIELD_NAME = 'USU_TIPO_CHAT')) THEN + EXECUTE STATEMENT 'ALTER TABLE USUARIOS ADD USU_TIPO_CHAT CHAR(1) DEFAULT ''A'''; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 2: Tabela CHATC2_INSTANCIAS (WhatsApp / Evolution API) +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_INSTANCIAS')) THEN + BEGIN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_INSTANCIAS ( + INS_CODIGO_ID INTEGER NOT NULL PRIMARY KEY, + INS_EMPRESA_ID INTEGER NOT NULL, + INS_NOME VARCHAR(100), + INS_URL VARCHAR(500), + INS_API_KEY VARCHAR(500), + INS_INSTANCE_NAME VARCHAR(100), + INS_STATUS CHAR(1) DEFAULT ''D'', + INS_QR_CODE BLOB SUB_TYPE 0, + INS_DT_CONEXAO TIMESTAMP, + INS_DT_CADASTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INS_SITUACAO CHAR(1) DEFAULT ''A'' + )'; + EXECUTE STATEMENT 'CREATE SEQUENCE GEN_INSTANCIAS'; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 3: Tabela CHATC2_EQUIPES +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_EQUIPES')) THEN + BEGIN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_EQUIPES ( + EQU_CODIGO_ID INTEGER NOT NULL PRIMARY KEY, + EQU_EMPRESA_ID INTEGER NOT NULL, + EQU_NOME VARCHAR(100), + EQU_ORDEM INTEGER DEFAULT 0, + EQU_SITUACAO CHAR(1) DEFAULT ''A'' + )'; + EXECUTE STATEMENT 'CREATE SEQUENCE GEN_EQUIPES'; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 4: Tabela CHATC2_USU_EQUIPES (usuários x equipes) +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_USU_EQUIPES')) THEN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_USU_EQUIPES ( + EQU_EQUIPE_ID INTEGER NOT NULL, + EQU_USUARIO_ID INTEGER NOT NULL, + PRIMARY KEY (EQU_EQUIPE_ID, EQU_USUARIO_ID) + )'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 5: Tabela CHATC2_ETIQUETAS +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_ETIQUETAS')) THEN + BEGIN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_ETIQUETAS ( + ETI_CODIGO_ID INTEGER NOT NULL PRIMARY KEY, + ETI_EMPRESA_ID INTEGER NOT NULL, + ETI_NOME VARCHAR(50), + ETI_COR VARCHAR(7) DEFAULT ''#667eea'', + ETI_SITUACAO CHAR(1) DEFAULT ''A'' + )'; + EXECUTE STATEMENT 'CREATE SEQUENCE GEN_ETIQUETAS'; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 6: Tabela CHATC2_CONVERSAS +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_CONVERSAS')) THEN + BEGIN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_CONVERSAS ( + CON_CODIGO_ID INTEGER NOT NULL PRIMARY KEY, + CON_EMPRESA_ID INTEGER NOT NULL, + CON_INSTANCIA_ID INTEGER, + CON_CLIENTE_ID INTEGER, + CON_NUMERO VARCHAR(20), + CON_NOME_CONTATO VARCHAR(100), + CON_STATUS CHAR(1) DEFAULT ''E'', + CON_USUARIO_ID INTEGER, + CON_EQUIPE_ID INTEGER, + CON_DT_INICIO TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CON_DT_FINAL TIMESTAMP, + CON_DT_ULTIMA_MSG TIMESTAMP, + CON_SAUDACAO_ENVIADA CHAR(1) DEFAULT ''N'', + CON_CSAT_ENVIADO CHAR(1) DEFAULT ''N'', + CON_PRIMEIRA_MSG TIMESTAMP, + CON_ORIGEM VARCHAR(20) DEFAULT ''whatsapp'', + CON_SITUACAO CHAR(1) DEFAULT ''A'' + )'; + EXECUTE STATEMENT 'CREATE SEQUENCE GEN_CONVERSAS'; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 7: Tabela CHATC2_CONVERSAS_MENSAGENS +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_CONVERSAS_MENSAGENS')) THEN + BEGIN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_CONVERSAS_MENSAGENS ( + CME_CODIGO_ID INTEGER NOT NULL PRIMARY KEY, + CME_CONVERSA_ID INTEGER NOT NULL, + CME_REMETENTE CHAR(1) DEFAULT ''C'', + CME_USUARIO_ID INTEGER, + CME_MENSAGEM BLOB SUB_TYPE 1, + CME_TEXTO VARCHAR(4000), + CME_TIPO VARCHAR(20) DEFAULT ''text'', + CME_DT_ENVIO TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CME_PRIVADA CHAR(1) DEFAULT ''N'', + CME_LIDA CHAR(1) DEFAULT ''N'', + CME_MIDIA_ID INTEGER, + CME_SITUACAO CHAR(1) DEFAULT ''A'' + )'; + EXECUTE STATEMENT 'CREATE SEQUENCE GEN_CONVERSAS_MENSAGENS'; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 8: Tabela CHATC2_MENSAGENS_ATENDIMENTOS (mídias) +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_MENSAGENS_ATENDIMENTOS')) THEN + BEGIN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_MENSAGENS_ATENDIMENTOS ( + MAT_CODIGO_ID INTEGER NOT NULL PRIMARY KEY, + MAT_CONVERSA_ID INTEGER, + MAT_MENSAGEM_ID INTEGER, + MAT_NOME_ARQUIVO VARCHAR(255), + MAT_TIPO_ARQUIVO VARCHAR(50), + MAT_ARQUIVO BLOB SUB_TYPE 0, + MAT_DT_CADASTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + MAT_SITUACAO CHAR(1) DEFAULT ''A'' + )'; + EXECUTE STATEMENT 'CREATE SEQUENCE GEN_MENSAGENS_ATENDIMENTO'; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 9: Tabela CHATC2_CONVERSAS_ETIQUETAS +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_CONVERSAS_ETIQUETAS')) THEN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_CONVERSAS_ETIQUETAS ( + CET_CONVERSA_ID INTEGER NOT NULL, + CET_ETIQUETA_ID INTEGER NOT NULL, + PRIMARY KEY (CET_CONVERSA_ID, CET_ETIQUETA_ID) + )'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 10: Tabela CHATC2_CSAT_AVALIACOES +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_CSAT_AVALIACOES')) THEN + BEGIN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_CSAT_AVALIACOES ( + CSA_CODIGO_ID INTEGER NOT NULL PRIMARY KEY, + CSA_CONVERSA_ID INTEGER, + CSA_EMPRESA_ID INTEGER, + CSA_CLIENTE_ID INTEGER, + CSA_NOTA INTEGER, + CSA_COMENTARIO VARCHAR(500), + CSA_DT_AVALIACAO TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )'; + EXECUTE STATEMENT 'CREATE SEQUENCE GEN_CSAT_AVALIACOES'; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 11: Tabela CHATC2_CONFIGURACOES_EMPRESA +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_CONFIGURACOES_EMPRESA')) THEN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_CONFIGURACOES_EMPRESA ( + CFE_EMPRESA_ID INTEGER NOT NULL PRIMARY KEY, + CFE_INSTANCIA_PADRAO_ID INTEGER, + CFE_FOTO_CELULAR CHAR(1) DEFAULT ''N'', + CFE_SAUDACAO_ATIVA CHAR(1) DEFAULT ''S'', + CFE_SAUDACAO_MENSAGEM VARCHAR(500), + CFE_CSAT_ATIVO CHAR(1) DEFAULT ''N'', + CFE_CSAT_MENSAGEM VARCHAR(500) DEFAULT ''Avalie seu atendimento de 1 a 5 estrelas'' + )'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 12: EQU_ORDEM em CHATC2_EQUIPES +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'CHATC2_EQUIPES' AND RDB$FIELD_NAME = 'EQU_ORDEM')) THEN + EXECUTE STATEMENT 'ALTER TABLE CHATC2_EQUIPES ADD EQU_ORDEM INTEGER DEFAULT 0'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 13: Campos de triagem em CHATC2_CONFIGURACOES_EMPRESA +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'CHATC2_CONFIGURACOES_EMPRESA' AND RDB$FIELD_NAME = 'CFE_TRIAGEM_ATIVA')) THEN + BEGIN + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_ENVIAR_NOME_USUARIO CHAR(1) DEFAULT ''N'''; + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_TRIAGEM_ATIVA CHAR(1) DEFAULT ''N'''; + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_TRIAGEM_MSG_WELCOME VARCHAR(500)'; + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_TRIAGEM_MSG_AFTER VARCHAR(500)'; + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONFIGURACOES_EMPRESA ADD CFE_TRIAGEM_BOLETO_NUMERO VARCHAR(10) DEFAULT ''0'''; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 14: CON_MENU_ESTADO em CHATC2_CONVERSAS +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'CHATC2_CONVERSAS' AND RDB$FIELD_NAME = 'CON_MENU_ESTADO')) THEN + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONVERSAS ADD CON_MENU_ESTADO VARCHAR(100)'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 15: CON_ETIQUETAS_DESC em CHATC2_CONVERSAS +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'CHATC2_CONVERSAS' AND RDB$FIELD_NAME = 'CON_ETIQUETAS_DESC')) THEN + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONVERSAS ADD CON_ETIQUETAS_DESC VARCHAR(500)'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 16: Tabela CHATC2_MENUS_EMPRESA (fluxo de atendimento) +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = 'CHATC2_MENUS_EMPRESA')) THEN + EXECUTE STATEMENT 'CREATE TABLE CHATC2_MENUS_EMPRESA ( + MNE_CODIGO_ID INTEGER NOT NULL PRIMARY KEY, + MNE_EMPRESA_ID INTEGER, + MNE_EQUIPE_ID INTEGER, + MNE_MENU_PAI_ID INTEGER, + MNE_ORDEM INTEGER DEFAULT 0, + MNE_TITULO VARCHAR(100), + MNE_TIPO CHAR(1) DEFAULT ''M'', + MNE_TEXTO BLOB SUB_TYPE TEXT, + MNE_ACAO_ROTA VARCHAR(100), + MNE_ACAO_METODO VARCHAR(10), + MNE_ACAO_PROMPT VARCHAR(300), + MNE_SITUACAO CHAR(1) DEFAULT ''A'' + )'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 17: Novos campos em CHATC2_CONVERSAS +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'CHATC2_CONVERSAS' AND RDB$FIELD_NAME = 'CON_USUARIO_NOME')) THEN + BEGIN + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONVERSAS ADD CON_USUARIO_NOME VARCHAR(100)'; + EXECUTE STATEMENT 'ALTER TABLE CHATC2_CONVERSAS ADD CON_EQUIPE_NOME VARCHAR(100)'; + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 18: Etiquetas nos menus de fluxo +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'CHATC2_MENUS_EMPRESA' AND RDB$FIELD_NAME = 'MNE_ETIQUETA_IDS')) THEN + EXECUTE STATEMENT 'ALTER TABLE CHATC2_MENUS_EMPRESA ADD MNE_ETIQUETA_IDS VARCHAR(200)'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- MIGRAÇÃO 19: Transcrição de áudio +-- ============================================================ +EXECUTE BLOCK AS BEGIN + IF (NOT EXISTS(SELECT 1 FROM RDB$RELATION_FIELDS WHERE RDB$RELATION_NAME = 'CHATC2_MENSAGENS_ATENDIMENTOS' AND RDB$FIELD_NAME = 'MAT_TRANSCRICAO')) THEN + EXECUTE STATEMENT 'ALTER TABLE CHATC2_MENSAGENS_ATENDIMENTOS ADD MAT_TRANSCRICAO BLOB SUB_TYPE TEXT'; +END; +^ +COMMIT; +^ + +-- ============================================================ +-- REGISTRO DAS MIGRAÇÕES (marca como executadas) +-- ============================================================ +EXECUTE BLOCK AS + DECLARE mig_id INTEGER; + DECLARE mig_desc VARCHAR(200); +BEGIN + -- Só insere se não existir (idempotente) + FOR SELECT MIG_ID, MIG_DESCRICAO FROM ( + SELECT 1 AS MIG_ID, 'Campo USU_TIPO_CHAT em USUARIOS' AS MIG_DESCRICAO FROM RDB$DATABASE UNION ALL + SELECT 2, 'Tabela CHATC2_INSTANCIAS' FROM RDB$DATABASE UNION ALL + SELECT 3, 'Tabela CHATC2_EQUIPES' FROM RDB$DATABASE UNION ALL + SELECT 4, 'Tabela CHATC2_USU_EQUIPES' FROM RDB$DATABASE UNION ALL + SELECT 5, 'Tabela CHATC2_ETIQUETAS' FROM RDB$DATABASE UNION ALL + SELECT 6, 'Tabela CHATC2_CONVERSAS' FROM RDB$DATABASE UNION ALL + SELECT 7, 'Tabela CHATC2_CONVERSAS_MENSAGENS' FROM RDB$DATABASE UNION ALL + SELECT 8, 'Tabela CHATC2_MENSAGENS_ATENDIMENTOS' FROM RDB$DATABASE UNION ALL + SELECT 9, 'Tabela CHATC2_CONVERSAS_ETIQUETAS' FROM RDB$DATABASE UNION ALL + SELECT 10, 'Tabela CHATC2_CSAT_AVALIACOES' FROM RDB$DATABASE UNION ALL + SELECT 11, 'Tabela CHATC2_CONFIGURACOES_EMPRESA' FROM RDB$DATABASE UNION ALL + SELECT 12, 'EQU_ORDEM em CHATC2_EQUIPES' FROM RDB$DATABASE UNION ALL + SELECT 13, 'Campos de triagem em config' FROM RDB$DATABASE UNION ALL + SELECT 14, 'CON_MENU_ESTADO em conversas' FROM RDB$DATABASE UNION ALL + SELECT 15, 'CON_ETIQUETAS_DESC em conversas' FROM RDB$DATABASE UNION ALL + SELECT 16, 'Tabela CHATC2_MENUS_EMPRESA' FROM RDB$DATABASE UNION ALL + SELECT 17, 'CON_USUARIO_NOME e CON_EQUIPE_NOME' FROM RDB$DATABASE UNION ALL + SELECT 18, 'MNE_ETIQUETA_IDS nos menus' FROM RDB$DATABASE UNION ALL + SELECT 19, 'MAT_TRANSCRICAO nas mídias' FROM RDB$DATABASE + ) AS migracoes + INTO :mig_id, :mig_desc + DO BEGIN + IF (NOT EXISTS(SELECT 1 FROM CHATC2_CONTROLE_MIGRACOES WHERE MIG_ID = :mig_id)) THEN + INSERT INTO CHATC2_CONTROLE_MIGRACOES (MIG_ID, MIG_DESCRICAO) VALUES (:mig_id, :mig_desc); + END +END; +^ +COMMIT; +^ + +-- ============================================================ +-- FIM +-- ============================================================ +-- Após executar, verifique com: +-- SELECT * FROM CHATC2_CONTROLE_MIGRACOES ORDER BY MIG_ID; +-- Deve mostrar 19 migrações registradas. diff --git a/src/controllers/evolutionController.js b/src/controllers/evolutionController.js index e10eaab..5eb793f 100644 --- a/src/controllers/evolutionController.js +++ b/src/controllers/evolutionController.js @@ -650,6 +650,75 @@ class EvolutionController { } } +/** + * Busca um cliente pelo número de telefone em TODOS os aliases disponíveis. + * Tenta primeiro o alias principal (mais rápido), depois os demais. + * Retorna { cliente, alias } ou null se não encontrado em nenhum banco. + */ +async function buscarClienteGlobal(numero, empresaId, aliasPrincipal) { + const todosAliases = db.listAliases(); + const termo1 = numero; + const termo2 = numero.startsWith('55') ? numero.substring(2) : numero; + const ultimosDigitos = numero.slice(-8); + + // Busca primeiro no alias principal (cache quente), depois nos outros + const aliasesOrdenados = [aliasPrincipal]; + for (const a of todosAliases) { + if (a !== aliasPrincipal) aliasesOrdenados.push(a); + } + + for (const aliasAtual of aliasesOrdenados) { + try { + // Tenta com número completo (DDI 55) + let clientes = await db.query(aliasAtual, + `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES + WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' + OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' + OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') + AND CLI_EMPRESA_ID = ?`, + [termo1, termo1, termo1, empresaId] + ); + + // Tenta sem DDI + if (clientes.length === 0 && termo2 !== termo1) { + clientes = await db.query(aliasAtual, + `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES + WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' + OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' + OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') + AND CLI_EMPRESA_ID = ?`, + [termo2, termo2, termo2, empresaId] + ); + } + + // Último recurso: últimos 8 dígitos + if (clientes.length === 0) { + clientes = await db.query(aliasAtual, + `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES + WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' + OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' + OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') + AND CLI_EMPRESA_ID = ?`, + [ultimosDigitos, ultimosDigitos, ultimosDigitos, empresaId] + ); + } + + if (clientes.length > 0) { + console.log('[Webhook] Cliente encontrado no alias:', aliasAtual, '| ID:', clientes[0].CLI_CODIGO_ID); + return { cliente: clientes[0], alias: aliasAtual }; + } + } catch (e) { + // Alias offline ou com erro — pula para o próximo + if (e.message && !e.message.includes('não encontrado')) { + console.log('[Webhook] Alias', aliasAtual, 'indisponível:', e.message.substring(0, 60)); + } + } + } + + console.log('[Webhook] Cliente NÃO encontrado em nenhum alias para número:', numero); + return null; +} + async function processWebhook(alias, body) { try { const data = body.data || body; @@ -724,75 +793,34 @@ async function processWebhook(alias, body) { const newId = (maxId[0]?.ID || 0) + 1; const nomeContato = data.pushName || data.notifyName || sender || ''; - // Busca cliente pelo número em múltiplos campos de telefone - // Tenta com o número completo (com DDI 55) e também sem o DDI + // Busca cliente pelo número em TODOS os aliases (multi-banco) let clienteId = null; let nomeCliente = null; - - // Atualiza foto do contato se configurado (usa metodo estatico) - // A funcao local foi movida para EvolutionController.atualizarFotoContato - const termo1 = numero; // 5582996258669 - const termo2 = numero.startsWith('55') ? numero.substring(2) : numero; // 8299625869 + var aliasEfetivo = alias; // alias onde o cliente foi encontrado (pode ser diferente) - const clientes = await db.query(alias, - `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES - WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') - AND CLI_EMPRESA_ID = ?`, - [termo1, termo1, termo1, empresaId] - ); - - // Se não achou com DDI, tenta sem DDI - if (clientes.length === 0 && termo2 !== termo1) { - const clientes2 = await db.query(alias, - `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES - WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') - AND CLI_EMPRESA_ID = ?`, - [termo2, termo2, termo2, empresaId] - ); - if (clientes2.length > 0) { - clientes.push(...clientes2); - } - } - - // Último recurso: tenta os últimos 8 dígitos - if (clientes.length === 0) { - const ultimosDigitos = numero.slice(-8); - const clientes3 = await db.query(alias, - `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES - WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') - AND CLI_EMPRESA_ID = ?`, - [ultimosDigitos, ultimosDigitos, ultimosDigitos, empresaId] - ); - if (clientes3.length > 0) { - clientes.push(...clientes3); - } - } - if (clientes.length > 0) { - clienteId = clientes[0].CLI_CODIGO_ID; - nomeCliente = (clientes[0].CLI_NOME || '').trim(); + const resultadoGlobal = await buscarClienteGlobal(numero, empresaId, alias); + if (resultadoGlobal) { + clienteId = resultadoGlobal.cliente.CLI_CODIGO_ID; + nomeCliente = (resultadoGlobal.cliente.CLI_NOME || '').trim(); + aliasEfetivo = resultadoGlobal.alias; // Atualiza foto do contato - EvolutionController.atualizarFotoContato(alias, clienteId, numero, empresaId).catch(function() {}); + EvolutionController.atualizarFotoContato(aliasEfetivo, clienteId, numero, empresaId).catch(function() {}); } // Usa nome do cliente do BD se encontrado, senão usa o nome do WhatsApp const nomeFinal = nomeCliente || nomeContato; - await db.execute(alias, ` + await db.execute(aliasEfetivo, ` INSERT INTO CHATC2_CONVERSAS (CON_CODIGO_ID, CON_EMPRESA_ID, CON_INSTANCIA_ID, CON_NUMERO, CON_NOME_CONTATO, CON_CLIENTE_ID, CON_STATUS, CON_SITUACAO, CON_PRIMEIRA_MSG, CON_DT_ULTIMA_MSG) VALUES (?, ?, ?, ?, ?, ?, 'E', 'A', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) `, [newId, empresaId, instanciaId, numero, nomeFinal, clienteId]); + console.log('[Webhook] Conversa criada no alias:', aliasEfetivo, '| ID:', newId); - conversa = await db.query(alias, 'SELECT * FROM CHATC2_CONVERSAS WHERE CON_CODIGO_ID = ?', [newId]); + conversa = await db.query(aliasEfetivo, 'SELECT * FROM CHATC2_CONVERSAS WHERE CON_CODIGO_ID = ?', [newId]); conversa = conversa[0]; - const config = await db.query(alias, + const config = await db.query(aliasEfetivo, 'SELECT CFE_SAUDACAO_ATIVA, CFE_SAUDACAO_MENSAGEM FROM CHATC2_CONFIGURACOES_EMPRESA WHERE CFE_EMPRESA_ID = ?', [empresaId] ); @@ -800,16 +828,16 @@ async function processWebhook(alias, body) { if (config.length > 0 && config[0].CFE_SAUDACAO_ATIVA === 'S') { const msgSaudacao = (config[0].CFE_SAUDACAO_MENSAGEM || '').trim(); if (msgSaudacao) { - const maxMsgId = await db.query(alias, 'SELECT MAX(CME_CODIGO_ID) AS ID FROM CHATC2_CONVERSAS_MENSAGENS'); - await db.execute(alias, ` + const maxMsgId = await db.query(aliasEfetivo, 'SELECT MAX(CME_CODIGO_ID) AS ID FROM CHATC2_CONVERSAS_MENSAGENS'); + await db.execute(aliasEfetivo, ` INSERT INTO CHATC2_CONVERSAS_MENSAGENS (CME_CODIGO_ID, CME_CONVERSA_ID, CME_REMETENTE, CME_TEXTO, CME_TIPO, CME_SITUACAO, CME_DT_ENVIO) VALUES (?, ?, 'S', ?, 'text', 'A', CURRENT_TIMESTAMP) `, [(maxMsgId[0]?.ID || 0) + 1, conversa.CON_CODIGO_ID, msgSaudacao]); - await db.execute(alias, "UPDATE CHATC2_CONVERSAS SET CON_SAUDACAO_ENVIADA = 'S' WHERE CON_CODIGO_ID = ?", [conversa.CON_CODIGO_ID]); + await db.execute(aliasEfetivo, "UPDATE CHATC2_CONVERSAS SET CON_SAUDACAO_ENVIADA = 'S' WHERE CON_CODIGO_ID = ?", [conversa.CON_CODIGO_ID]); // Envia saudação via Evolution API try { - const inst = await db.query(alias, + const inst = await db.query(aliasEfetivo, "SELECT * FROM CHATC2_INSTANCIAS WHERE INS_CODIGO_ID = ? AND INS_SITUACAO = 'A'", [instanciaId]); if (inst.length > 0) { await evolutionRequest( @@ -827,10 +855,10 @@ async function processWebhook(alias, body) { // Envia menu de triagem SEMPRE que for conversa nova // (sendMenu internamente verifica se CFE_TRIAGEM_ATIVA = 'S') try { - const triagemInst = await db.query(alias, + const triagemInst = await db.query(aliasEfetivo, "SELECT * FROM CHATC2_INSTANCIAS WHERE INS_CODIGO_ID = ? AND INS_SITUACAO = 'A'", [instanciaId]); if (triagemInst.length > 0) { - await TriageController.sendMenu(alias, conversa.CON_CODIGO_ID, empresaId, instanciaId, numero); + await TriageController.sendMenu(aliasEfetivo, conversa.CON_CODIGO_ID, empresaId, instanciaId, numero); } } catch(e) { console.error('[Webhook] Erro ao enviar triagem:', e.message); } } else { @@ -838,53 +866,18 @@ async function processWebhook(alias, body) { // Se a conversa existente não tem cliente vinculado, tenta vincular agora if (!conversa.CON_CLIENTE_ID) { - const termo1 = numero; - const termo2 = numero.startsWith('55') ? numero.substring(2) : numero; - - const clientes = await db.query(alias, - `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES - WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') - AND CLI_EMPRESA_ID = ?`, - [termo1, termo1, termo1, empresaId] - ); - - if (clientes.length === 0 && termo2 !== termo1) { - const clientes2 = await db.query(alias, - `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES - WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') - AND CLI_EMPRESA_ID = ?`, - [termo2, termo2, termo2, empresaId] - ); - if (clientes2.length > 0) clientes.push(...clientes2); - } - - // Último recurso: tenta os últimos 8 dígitos - if (clientes.length === 0) { - const ultimosDigitos = numero.slice(-8); - const clientes3 = await db.query(alias, - `SELECT CLI_CODIGO_ID, CLI_NOME FROM CLIENTES - WHERE (REPLACE(REPLACE(REPLACE(COALESCE(CLI_CELULAR,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE1,''),'-',''),'(',''),')','') LIKE '%' || ? || '%' - OR REPLACE(REPLACE(REPLACE(COALESCE(CLI_FONE2,''),'-',''),'(',''),')','') LIKE '%' || ? || '%') - AND CLI_EMPRESA_ID = ?`, - [ultimosDigitos, ultimosDigitos, ultimosDigitos, empresaId] - ); - if (clientes3.length > 0) clientes.push(...clientes3); - } - - if (clientes.length > 0) { - var cliId = clientes[0].CLI_CODIGO_ID; - const nomeCliente = (clientes[0].CLI_NOME || '').trim(); - await db.execute(alias, + // Busca cliente em TODOS os aliases (multi-banco) + const resultadoGlobal = await buscarClienteGlobal(numero, empresaId, alias); + if (resultadoGlobal) { + var cliId = resultadoGlobal.cliente.CLI_CODIGO_ID; + const nomeCliente = (resultadoGlobal.cliente.CLI_NOME || '').trim(); + var aliasEfetivo = resultadoGlobal.alias; + await db.execute(aliasEfetivo, 'UPDATE CHATC2_CONVERSAS SET CON_CLIENTE_ID = ?, CON_NOME_CONTATO = ? WHERE CON_CODIGO_ID = ?', [cliId, nomeCliente, conversa.CON_CODIGO_ID]); conversa.CON_CLIENTE_ID = cliId; // Atualiza foto do contato - EvolutionController.atualizarFotoContato(alias, cliId, numero, empresaId).catch(function() {}); + EvolutionController.atualizarFotoContato(aliasEfetivo, cliId, numero, empresaId).catch(function() {}); } } else { // Mesmo ja tendo cliente vinculado, tenta atualizar a foto