TopSapp: Suporte: Função de fechar suporte
Signed-off-by: Rodrigo Bertoldo de Sousa Martins <rodrigo.sousa.577@gmail.com>
This commit is contained in:
1 parent
2a939def1d
commit
6dc11e1ffe
4 files changed
+400
-1
No files matched your search
+351
-1
@@ -265,6 +265,11 @@ class BotHandler {
|
||||
console.log(`🎫 Iniciando processo de abertura de suporte`);
|
||||
await this.iniciarProcessoSuporte(chatId, user.id, target);
|
||||
break;
|
||||
|
||||
case 'fechar_suporte':
|
||||
console.log(`🔒 Iniciando processo de fechamento de suporte`);
|
||||
await this.iniciarProcessoFecharSuporte(chatId, user.id, target);
|
||||
break;
|
||||
|
||||
case 'conectar':
|
||||
await this.handleConnect(chatId, target);
|
||||
@@ -531,7 +536,12 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
• "novo chamado"
|
||||
• "suporte cliente 123.456.789-10"
|
||||
|
||||
**🔄 PROCESSO INTERATIVO:**
|
||||
**� FECHAR SUPORTE:**
|
||||
• "fechar suporte"
|
||||
• "finalizar chamado"
|
||||
• "encerrar suporte João Silva"
|
||||
|
||||
**�🔄 PROCESSO INTERATIVO:**
|
||||
1️⃣ Busca do cliente (nome ou CPF)
|
||||
2️⃣ Seleção do serviço
|
||||
3️⃣ Escolha da categoria do problema
|
||||
@@ -2037,6 +2047,12 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
} else if (data.startsWith('suporte_servico_')) {
|
||||
console.log(`🔍 Condição suporte_servico_ atendida`);
|
||||
await this.handleSuporteServicoCallback(callbackQuery, data);
|
||||
} else if (data.startsWith('fechar_suporte_cli_')) {
|
||||
await this.bot.answerCallbackQuery(callbackQuery.id);
|
||||
await this.handleFecharSuporteClienteCallback(callbackQuery, data);
|
||||
} else if (data.startsWith('fechar_suporte_id_')) {
|
||||
await this.bot.answerCallbackQuery(callbackQuery.id);
|
||||
await this.handleFecharSuporteIdCallback(callbackQuery, data);
|
||||
} else if (data.startsWith('linha_')) {
|
||||
console.log(`🔍 Condição linha_ atendida`);
|
||||
await this.handleLinhaDigitavelCallback(callbackQuery, data);
|
||||
@@ -5862,6 +5878,23 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
case 'confirmar':
|
||||
await this.finalizarCriacaoSuporte(sessaoAtiva.id, text);
|
||||
break;
|
||||
|
||||
// Etapas para fechar suporte
|
||||
case 'fechar_buscar_cliente':
|
||||
await this.processarEtapaFecharBuscarCliente(sessaoAtiva.id, text);
|
||||
break;
|
||||
|
||||
case 'fechar_selecionar_cliente':
|
||||
await this.processarEtapaFecharSelecionarCliente(sessaoAtiva.id, text);
|
||||
break;
|
||||
|
||||
case 'fechar_selecionar_suporte':
|
||||
await this.processarEtapaFecharSelecionarSuporte(sessaoAtiva.id, text);
|
||||
break;
|
||||
|
||||
case 'fechar_aguardando_descricao':
|
||||
await this.processarEtapaFecharDescricao(sessaoAtiva.id, text);
|
||||
break;
|
||||
|
||||
default:
|
||||
await this.bot.sendMessage(chatId, '❌ Etapa desconhecida. Reiniciando processo...');
|
||||
@@ -6500,6 +6533,251 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
this.suporteSessions.delete(sessionId);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// Fechar Suporte
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Iniciar processo de fechamento de suporte
|
||||
*/
|
||||
async iniciarProcessoFecharSuporte(chatId, userId, target = '') {
|
||||
if (!this.topsapp.isReady()) {
|
||||
await this.bot.sendMessage(chatId,
|
||||
`❌ **TopSapp não configurado**\n\n` +
|
||||
`⚠️ O sistema TopSapp não está configurado. Entre em contato com o administrador.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const sessionId = `${userId}_${chatId}_${Date.now()}`;
|
||||
const suporteSession = {
|
||||
id: sessionId,
|
||||
chatId,
|
||||
userId,
|
||||
etapa: 'fechar_buscar_cliente',
|
||||
dados: {},
|
||||
iniciado: new Date()
|
||||
};
|
||||
|
||||
this.suporteSessions.set(sessionId, suporteSession);
|
||||
|
||||
await this.bot.sendMessage(chatId,
|
||||
`🔒 **Fechamento de Suporte**\n\n` +
|
||||
`🔍 Digite o **nome** ou **CPF** do cliente cujo suporte deseja fechar:`,
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
|
||||
if (target && target.trim()) {
|
||||
await this.processarEtapaFecharBuscarCliente(sessionId, target.trim());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Etapa 1 (fechar): Buscar cliente
|
||||
*/
|
||||
async processarEtapaFecharBuscarCliente(sessionId, query) {
|
||||
const session = this.suporteSessions.get(sessionId);
|
||||
if (!session) return;
|
||||
|
||||
await this.bot.sendMessage(session.chatId, `🔍 Buscando cliente: "${query}"...`);
|
||||
|
||||
try {
|
||||
const resultado = await this.topsapp.buscarCliente(query);
|
||||
|
||||
if (!resultado.success || !resultado.clientes || resultado.clientes.length === 0) {
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`❌ **Nenhum cliente encontrado**\n\n` +
|
||||
`🔍 Não foi encontrado nenhum cliente com: "${query}"\n\n` +
|
||||
`Por favor, tente novamente com outro nome ou CPF:`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
session.dados.clientesEncontrados = resultado.clientes;
|
||||
|
||||
if (resultado.clientes.length === 1) {
|
||||
session.dados.clienteSelecionado = resultado.clientes[0];
|
||||
session.dados.location = resultado.instancia || '';
|
||||
await this.processarEtapaFecharBuscarSuportes(sessionId);
|
||||
} else {
|
||||
session.etapa = 'fechar_selecionar_cliente';
|
||||
let message = `👥 **Clientes encontrados:**\n\n`;
|
||||
const buttons = [];
|
||||
resultado.clientes.forEach((cliente, index) => {
|
||||
message += `**${index + 1}.** ${cliente.nome} — CPF: ${cliente.cpf || 'N/A'}\n`;
|
||||
buttons.push([{ text: `${index + 1}. ${cliente.nome}`, callback_data: `fechar_suporte_cli_${sessionId}_${index}` }]);
|
||||
});
|
||||
message += `\nDigite o **número** do cliente:`;
|
||||
await this.bot.sendMessage(session.chatId, message, {
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: { inline_keyboard: buttons }
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
await this.bot.sendMessage(session.chatId, `❌ **Erro na busca**\n\n⚠️ ${error.message}\n\nTente novamente:`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Etapa 2 (fechar): Selecionar cliente quando há múltiplos
|
||||
*/
|
||||
async processarEtapaFecharSelecionarCliente(sessionId, input) {
|
||||
const session = this.suporteSessions.get(sessionId);
|
||||
if (!session) return;
|
||||
|
||||
const numero = parseInt(input.trim());
|
||||
if (isNaN(numero) || numero < 1 || numero > session.dados.clientesEncontrados.length) {
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`❌ Número inválido. Digite entre 1 e ${session.dados.clientesEncontrados.length}:`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
session.dados.clienteSelecionado = session.dados.clientesEncontrados[numero - 1];
|
||||
session.dados.location = '';
|
||||
await this.processarEtapaFecharBuscarSuportes(sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Buscar suportes abertos do cliente selecionado
|
||||
*/
|
||||
async processarEtapaFecharBuscarSuportes(sessionId) {
|
||||
const session = this.suporteSessions.get(sessionId);
|
||||
if (!session) return;
|
||||
|
||||
const cliente = session.dados.clienteSelecionado;
|
||||
await this.bot.sendMessage(session.chatId, `🔍 Buscando suportes abertos de **${cliente.nome}**...`, { parse_mode: 'Markdown' });
|
||||
|
||||
try {
|
||||
const resultado = await this.topsapp.obterSuportesAbertos(cliente.id, session.dados.location || '');
|
||||
|
||||
const suportes = resultado.success ? (resultado.data?.dados || []) : [];
|
||||
|
||||
if (suportes.length === 0) {
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`ℹ️ **Nenhum suporte aberto**\n\n` +
|
||||
`O cliente **${cliente.nome}** não possui suportes abertos no momento.`,
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
this.suporteSessions.delete(sessionId);
|
||||
return;
|
||||
}
|
||||
|
||||
session.dados.suportesAbertos = suportes;
|
||||
|
||||
if (suportes.length === 1) {
|
||||
session.dados.suporteSelecionado = suportes[0];
|
||||
session.etapa = 'fechar_aguardando_descricao';
|
||||
const s = suportes[0];
|
||||
const enderecoCompleto = [s.endereco, s.numero, s.bairro, s.cidade].filter(Boolean).join(', ');
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`🎫 **Suporte encontrado:**\n\n` +
|
||||
`🆔 ID: ${s.id}\n` +
|
||||
`📝 Problema: ${s.defeito || 'N/A'}\n` +
|
||||
`📍 Endereço: ${enderecoCompleto || 'N/A'}\n` +
|
||||
`📅 Data: ${s.data || 'N/A'}\n\n` +
|
||||
`✏️ Digite a **descrição do fechamento** do suporte:`,
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
} else {
|
||||
session.etapa = 'fechar_selecionar_suporte';
|
||||
let message = `🎫 **Suportes abertos de ${cliente.nome}:**\n\n`;
|
||||
const buttons = [];
|
||||
suportes.forEach((s, index) => {
|
||||
const enderecoCompleto = [s.endereco, s.numero, s.bairro].filter(Boolean).join(', ');
|
||||
message += `**${index + 1}.** ID #${s.id}\n`;
|
||||
message += ` 📝 ${s.defeito || 'Sem descrição'}\n`;
|
||||
if (enderecoCompleto) message += ` 📍 ${enderecoCompleto}\n`;
|
||||
message += ` 📅 ${s.data || ''}\n\n`;
|
||||
buttons.push([{ text: `${index + 1}. #${s.id} — ${(s.defeito || 'Sem descrição').substring(0, 40)}`, callback_data: `fechar_suporte_id_${sessionId}_${index}` }]);
|
||||
});
|
||||
message += `Selecione qual suporte deseja fechar:`;
|
||||
await this.bot.sendMessage(session.chatId, message, {
|
||||
parse_mode: 'Markdown',
|
||||
reply_markup: { inline_keyboard: buttons }
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
await this.bot.sendMessage(session.chatId, `❌ **Erro ao buscar suportes**\n\n⚠️ ${error.message}`);
|
||||
this.suporteSessions.delete(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Etapa 3 (fechar): Selecionar suporte quando há múltiplos
|
||||
*/
|
||||
async processarEtapaFecharSelecionarSuporte(sessionId, input) {
|
||||
const session = this.suporteSessions.get(sessionId);
|
||||
if (!session) return;
|
||||
|
||||
const numero = parseInt(input.trim());
|
||||
if (isNaN(numero) || numero < 1 || numero > session.dados.suportesAbertos.length) {
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`❌ Número inválido. Digite entre 1 e ${session.dados.suportesAbertos.length}:`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
session.dados.suporteSelecionado = session.dados.suportesAbertos[numero - 1];
|
||||
session.etapa = 'fechar_aguardando_descricao';
|
||||
|
||||
const s = session.dados.suporteSelecionado;
|
||||
const enderecoCompleto = [s.endereco, s.numero, s.bairro, s.cidade].filter(Boolean).join(', ');
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`🎫 **Suporte selecionado:**\n\n` +
|
||||
`🆔 ID: ${s.id}\n` +
|
||||
`📝 Problema: ${s.defeito || 'N/A'}\n` +
|
||||
`📍 Endereço: ${enderecoCompleto || 'N/A'}\n\n` +
|
||||
`✏️ Digite a **descrição do fechamento** do suporte:`,
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Etapa 4 (fechar): Receber descrição e executar fechamento
|
||||
*/
|
||||
async processarEtapaFecharDescricao(sessionId, descricao) {
|
||||
const session = this.suporteSessions.get(sessionId);
|
||||
if (!session) return;
|
||||
|
||||
if (!descricao || descricao.trim().length < 3) {
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`❌ A descrição é obrigatória e deve ter ao menos 3 caracteres.\n\nDigite a descrição do fechamento:`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const s = session.dados.suporteSelecionado;
|
||||
const cliente = session.dados.clienteSelecionado;
|
||||
|
||||
await this.bot.sendMessage(session.chatId, `⏳ Finalizando suporte #${s.id}...`);
|
||||
|
||||
try {
|
||||
const resultado = await this.topsapp.finalizarSuporte(s.id, descricao.trim(), session.dados.location || '');
|
||||
|
||||
if (resultado.success) {
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`✅ **Suporte finalizado com sucesso!**\n\n` +
|
||||
`🎫 ID do Suporte: #${s.id}\n` +
|
||||
`👤 Cliente: ${cliente.nome}\n` +
|
||||
`📝 Problema: ${s.defeito || 'N/A'}\n` +
|
||||
`✏️ Fechamento: ${descricao.trim()}`,
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
logger.info('Suporte finalizado via bot', { idSuporte: s.id, cliente: cliente.nome, usuario: session.userId });
|
||||
} else {
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`❌ **Erro ao finalizar suporte**\n\n⚠️ ${resultado.error}\n\nTente novamente mais tarde.`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Erro ao finalizar suporte:', error);
|
||||
await this.bot.sendMessage(session.chatId, `❌ **Erro ao finalizar suporte**\n\n⚠️ ${error.message}`);
|
||||
}
|
||||
|
||||
this.suporteSessions.delete(sessionId);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
// TopSapp — Vinculação de ONU após adição
|
||||
// ─────────────────────────────────────────────────────────────────────────
|
||||
@@ -6957,6 +7235,78 @@ Digite /help para ver todos os comandos disponíveis!
|
||||
await this.processarEtapaSelecionarCategoria(sessaoAtiva.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback: seleção de cliente no fluxo de fechar suporte
|
||||
* formato: fechar_suporte_cli_<sessionId>_<index>
|
||||
*/
|
||||
async handleFecharSuporteClienteCallback(callbackQuery, data) {
|
||||
const chatId = callbackQuery.message.chat.id;
|
||||
const userId = callbackQuery.from.id;
|
||||
|
||||
// fechar_suporte_cli_<sessionId>_<index>
|
||||
const withoutPrefix = data.replace('fechar_suporte_cli_', '');
|
||||
const lastUnder = withoutPrefix.lastIndexOf('_');
|
||||
const sessionId = withoutPrefix.substring(0, lastUnder);
|
||||
const index = parseInt(withoutPrefix.substring(lastUnder + 1));
|
||||
|
||||
const session = this.suporteSessions.get(sessionId);
|
||||
if (!session || session.chatId !== chatId || session.userId !== userId) {
|
||||
await this.bot.sendMessage(chatId, `❌ Sessão expirada. Use "fechar suporte" para iniciar novamente.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const clientes = session.dados.clientesEncontrados;
|
||||
if (!clientes || index < 0 || index >= clientes.length) {
|
||||
await this.bot.sendMessage(chatId, `❌ Seleção inválida. Tente novamente.`);
|
||||
return;
|
||||
}
|
||||
|
||||
session.dados.clienteSelecionado = clientes[index];
|
||||
session.dados.location = '';
|
||||
await this.processarEtapaFecharBuscarSuportes(sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback: seleção de suporte no fluxo de fechar suporte
|
||||
* formato: fechar_suporte_id_<sessionId>_<index>
|
||||
*/
|
||||
async handleFecharSuporteIdCallback(callbackQuery, data) {
|
||||
const chatId = callbackQuery.message.chat.id;
|
||||
const userId = callbackQuery.from.id;
|
||||
|
||||
// fechar_suporte_id_<sessionId>_<index>
|
||||
const withoutPrefix = data.replace('fechar_suporte_id_', '');
|
||||
const lastUnder = withoutPrefix.lastIndexOf('_');
|
||||
const sessionId = withoutPrefix.substring(0, lastUnder);
|
||||
const index = parseInt(withoutPrefix.substring(lastUnder + 1));
|
||||
|
||||
const session = this.suporteSessions.get(sessionId);
|
||||
if (!session || session.chatId !== chatId || session.userId !== userId) {
|
||||
await this.bot.sendMessage(chatId, `❌ Sessão expirada. Use "fechar suporte" para iniciar novamente.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const suportes = session.dados.suportesAbertos;
|
||||
if (!suportes || index < 0 || index >= suportes.length) {
|
||||
await this.bot.sendMessage(chatId, `❌ Seleção inválida. Tente novamente.`);
|
||||
return;
|
||||
}
|
||||
|
||||
session.dados.suporteSelecionado = suportes[index];
|
||||
session.etapa = 'fechar_aguardando_descricao';
|
||||
|
||||
const s = session.dados.suporteSelecionado;
|
||||
const enderecoCompleto = [s.endereco, s.numero, s.bairro, s.cidade].filter(Boolean).join(', ');
|
||||
await this.bot.sendMessage(session.chatId,
|
||||
`🎫 **Suporte selecionado:**\n\n` +
|
||||
`🆔 ID: ${s.id}\n` +
|
||||
`📝 Problema: ${s.defeito || 'N/A'}\n` +
|
||||
`📍 Endereço: ${enderecoCompleto || 'N/A'}\n\n` +
|
||||
`✏️ Digite a **descrição do fechamento** do suporte:`,
|
||||
{ parse_mode: 'Markdown' }
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exibe informações do roteador/CPE via GenieACS.
|
||||
* Uso: "ver roteador <serial>" ou "ver roteador <tag/login-topsapp>"
|
||||
|
||||
Reference in new issue
Block a user