2025-10-07 17:57:23 -03:00
|
|
|
// controller/processController.js
|
|
|
|
|
const hubsoftModel = require('../model/hubsoftModel.js');
|
|
|
|
|
const hubglpiModel = require('../model/hubglpiModel.js');
|
2025-10-08 18:55:29 -03:00
|
|
|
const glpiModel = require('../model/glpiModel.js');
|
|
|
|
|
const { logError, logInfo } = require('../utils/logger');
|
2025-10-07 17:57:23 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
// ================================================================================
|
|
|
|
|
// Constantes e Configurações
|
|
|
|
|
// ================================================================================
|
2025-10-07 17:57:23 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
const statusAtendimentoHubGlpi = {
|
|
|
|
|
1: 'Pendente',
|
|
|
|
|
2: 'Em atendimento',
|
|
|
|
|
3: 'Resolvido',
|
|
|
|
|
31: 'Pendente',
|
|
|
|
|
32: 'Pendente',
|
|
|
|
|
33: 'Novo'
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const statusAtendimentoGLPI = {
|
|
|
|
|
'Novo': 1,
|
|
|
|
|
'Pendente': 4,
|
|
|
|
|
'Em atendimento': 2,
|
|
|
|
|
'Resolvido': 5
|
|
|
|
|
};
|
|
|
|
|
|
2025-10-13 16:20:11 -03:00
|
|
|
const categoriaGLPI = {
|
|
|
|
|
'Lan-to-Lan 100 Mbps' : 5708 ,
|
|
|
|
|
'Link de Internet Dedicado 2 Gbps Full Duplex' : 5707 ,
|
|
|
|
|
'Lan-to-Lan' : 5707 ,
|
|
|
|
|
'Lan-to-Lan 500 Mbps' : 5708 ,
|
|
|
|
|
'Link de internet - Banda Larga' : 5708 ,
|
|
|
|
|
'Lan-to-Lan 700 Mbps' : 5708 ,
|
|
|
|
|
'Link de Internet Dedicado 20 Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'Lan-to-Lan 300 Mbps' : 5708 ,
|
|
|
|
|
'Link de Internet Dedicado 5Gbs + Burst 5Gbs Burs Full Duplex Anti DDOS' : 5707 ,
|
|
|
|
|
'Link de Internet - Banda Larga - 500 Mbps' : 5708 ,
|
|
|
|
|
'Link de Internet Dedicado 600Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'Link de Internet - Banda Larga - 1Gbps' : 5707 ,
|
|
|
|
|
'Link de Internet Dedicado 1Gbps Full Duplex' : 5707 ,
|
|
|
|
|
'Link de Internet Dedicado Full Duplex' : 5707 ,
|
|
|
|
|
'Fibra Apagada' : 5706 ,
|
|
|
|
|
'Link de Internet - Banda Larga - 100 Mbps' : 5708 ,
|
|
|
|
|
'Canal de Voz IP' : 5715 ,
|
|
|
|
|
'Link de Internet Dedicado 500Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'Lan-to-Lan 200 Mbps' : 5708 ,
|
|
|
|
|
'Lan-to-Lan 50 Mbps' : 5708 ,
|
|
|
|
|
'Linha IP - Limitado' : 5715 ,
|
|
|
|
|
'PABX IP Cloud' : 5717 ,
|
|
|
|
|
'Link de Internet Dedicado 100 Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'Link de Internet Dedicado 200 Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'Link de Internet - Banda Larga - 200 Mbps' : 5708 ,
|
|
|
|
|
'Link de Internet - Banda Larga - 300 Mbps' : 5708 ,
|
|
|
|
|
'Link de Internet - Banda Larga - 700 Mbps' : 5708 ,
|
|
|
|
|
'Link de Internet Dedicado 300 Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'Link de Internet Dedicado 50Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'Link de Internet Dedicado 10 Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'Link de Internet Dedicado 30 Mbps Full Duplex' : 5707 ,
|
|
|
|
|
'PABX IP - Até 30 ramais com telefones IPs (CAOA ESTADO DE SP)' : 5717 ,
|
|
|
|
|
'Lan-to-Lan 1GB' : 5707 ,
|
|
|
|
|
'PABX IP - Até 30 ramais com telefones IPs (CAOA OUTROS ESTADOS)' : 5717 ,
|
|
|
|
|
'Link de Internet Dedicado 700MB Full Duplex' : 5707 ,
|
|
|
|
|
'Link de Internet Dedicado - Temporário' : 5707
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
// ================================================================================
|
|
|
|
|
// Funções Utilitárias
|
|
|
|
|
// ================================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Formata a descrição do ticket em HTML
|
|
|
|
|
const formatDescription = (ticketData) => {
|
|
|
|
|
|
2025-10-10 09:06:44 -03:00
|
|
|
let htmlDescription = `
|
|
|
|
|
<table style="width:100%; border-collapse: collapse;">
|
|
|
|
|
<tr style="background-color:#f2f2f2;">
|
|
|
|
|
<th style="padding: 8px; border: 1px solid #ddd; text-align: left;">Campo</th>
|
|
|
|
|
<th style="padding: 8px; border: 1px solid #ddd; text-align: left;">Valor</th>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Nome:</strong></td>
|
|
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.cliente_nome}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Codigo:</strong></td>
|
|
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.codigo_cliente}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Serviço:</strong></td>
|
|
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.servico_nome}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Ticket Mundiale</strong></td>
|
|
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.ticket_mundiale}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
2025-10-10 15:05:05 -03:00
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Protocolo Hub:</strong></td>
|
2025-10-10 09:06:44 -03:00
|
|
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.protocolo_hub || 'N/A'}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
`;
|
2025-10-08 18:55:29 -03:00
|
|
|
|
|
|
|
|
return htmlDescription;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Formata os dados do ticket para o GLPI
|
|
|
|
|
const formatTicketDataForGlpi = async (ticketData) => {
|
|
|
|
|
const formattedData = {
|
|
|
|
|
...ticketData,
|
|
|
|
|
status_atendimento: statusAtendimentoGLPI[ticketData.status_atendimento] || 1,
|
|
|
|
|
date_mod: new Date(),
|
2025-10-14 15:38:16 -03:00
|
|
|
user_id_recipient: 1100,
|
2025-10-10 09:06:44 -03:00
|
|
|
descricao_abertura: formatDescription(ticketData),
|
2025-10-08 18:55:29 -03:00
|
|
|
urgency: 3,
|
|
|
|
|
impact: 3,
|
|
|
|
|
priority: 3,
|
|
|
|
|
type: 1,
|
2025-10-13 16:20:11 -03:00
|
|
|
itilcategories_id: categoriaGLPI[ticketData.servico_nome] || 1,
|
2025-10-08 18:55:29 -03:00
|
|
|
date_creation: new Date(),
|
2025-10-10 09:06:44 -03:00
|
|
|
// entidades_id: 0 //await glpiModel.selectEntityId() //TODO: Implementar a busca da entidade
|
2025-10-08 18:55:29 -03:00
|
|
|
};
|
|
|
|
|
return formattedData;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ================================================================================
|
|
|
|
|
// Funções de Integração
|
|
|
|
|
// ================================================================================
|
|
|
|
|
|
|
|
|
|
const createGlpiTicket = async (ticketData) => {
|
2025-10-07 17:57:23 -03:00
|
|
|
try {
|
2025-10-08 18:55:29 -03:00
|
|
|
|
2025-10-13 00:42:38 -03:00
|
|
|
|
|
|
|
|
const formattedTicketData = await formatTicketDataForGlpi(ticketData);
|
2025-10-10 09:06:44 -03:00
|
|
|
const glpiTicket = await glpiModel.insertTicket(formattedTicketData);
|
2025-10-13 00:42:38 -03:00
|
|
|
logInfo(`Ticket criado no GLPI: ${glpiTicket.insertId} `);
|
2025-10-10 15:05:05 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
|
2025-10-13 00:42:38 -03:00
|
|
|
//Atualiza que ticket foi criado
|
2025-10-10 16:28:06 -03:00
|
|
|
ticketData.status_sync = 'created_glpi';
|
2025-10-13 00:42:38 -03:00
|
|
|
ticketData.glpi_ticket_id = glpiTicket.insertId;
|
|
|
|
|
ticketData.created_at = new Date();
|
|
|
|
|
ticketData.updated_at = new Date();
|
|
|
|
|
|
2025-10-10 10:28:32 -03:00
|
|
|
|
2025-10-10 16:28:06 -03:00
|
|
|
const updateSyncData = await hubglpiModel.update_syncData(ticketData);
|
2025-10-13 00:42:38 -03:00
|
|
|
logInfo(`Sync Data atualizado com o ID do ticket do GLPI: ${updateSyncData.glpi_ticket_id}`);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2025-10-14 15:47:51 -03:00
|
|
|
//Insetindo ao grupo Operacao NOC
|
2025-10-13 00:42:38 -03:00
|
|
|
await glpiModel.insertGroupTickets(glpiTicket.insertId);
|
|
|
|
|
logInfo(`Atribuido grupo Operação NOC ao ticket no GLPI: ${glpiTicket.insertId} `)
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
const updateSyncDataError = await hubglpiModel.update_syncaDataError(error.message, ticketData.id_atendimento)
|
|
|
|
|
logError(`Erro ao criar ticket no GLPI. Sync Data atualizado com a mensagem de erro: ${error}`);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
|
|
|
|
|
} catch (error) {
|
2025-10-13 00:42:38 -03:00
|
|
|
|
|
|
|
|
const updateSyncDataError = await hubglpiModel.update_syncaDataError(error.message, ticketData.id_atendimento)
|
|
|
|
|
logError(`Erro ao criar ticket no GLPI. Sync Data atualizado com a mensagem de erro: ${error}`);
|
2025-10-08 18:55:29 -03:00
|
|
|
}
|
|
|
|
|
};
|
2025-10-07 17:57:23 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
const processTicketFromHubSoft = async (atendimento) => {
|
|
|
|
|
const ticketData = {
|
|
|
|
|
id_atendimento: atendimento.id_atendimento,
|
|
|
|
|
id_atendimento_status: atendimento.id_atendimento_status,
|
|
|
|
|
codigo_servico: String(atendimento.id_cliente_servico || ''), // Garante que seja uma string
|
|
|
|
|
protocolo_hub: atendimento.protocolo,
|
|
|
|
|
servico_nome: atendimento.descricao,
|
|
|
|
|
descricao_abertura: atendimento.descricao_abertura,
|
|
|
|
|
data_cadastro: atendimento.data_cadastro,
|
|
|
|
|
cliente_nome: atendimento.nome_contato,
|
|
|
|
|
codigo_cliente: atendimento.codigo_cliente,
|
|
|
|
|
descricao: atendimento.descricao
|
|
|
|
|
};
|
2025-10-07 17:57:23 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
ticketData.status_atendimento = statusAtendimentoHubGlpi[ticketData.id_atendimento_status] || ticketData.id_atendimento_status;
|
2025-10-07 17:57:23 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
ticketData.descricao_abertura = ticketData.descricao_abertura.replace(/[^0-9]/g, '');
|
|
|
|
|
ticketData.ticket_mundiale = parseInt(ticketData.descricao_abertura) || null;
|
2025-10-07 17:57:23 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
return ticketData;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const saveTicketToHubGlpi = async (ticketData) => {
|
|
|
|
|
try {
|
|
|
|
|
const insertedTicket = await hubglpiModel.insertTicket(ticketData);
|
2025-10-13 00:42:38 -03:00
|
|
|
logInfo(`Ticket inserido/atualizado na tabela hubsoft_tickets: ${insertedTicket.protocolo_hub}`);
|
2025-10-08 18:55:29 -03:00
|
|
|
|
2025-10-13 00:42:38 -03:00
|
|
|
await hubglpiModel.insertSyncData(ticketData.id_atendimento);
|
|
|
|
|
logInfo('Dados inseridos/atualizados na tabela sync_data');
|
2025-10-08 18:55:29 -03:00
|
|
|
|
|
|
|
|
return insertedTicket;
|
|
|
|
|
} catch (error) {
|
2025-10-13 00:42:38 -03:00
|
|
|
logError(`Erro ao salvar ticket no hubglpi: ${error}`);
|
2025-10-08 18:55:29 -03:00
|
|
|
throw error; // Rejeita a promise para que o erro seja tratado no nível superior
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-10-07 17:57:23 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
const processAtendimento = async (ticketData) => {
|
2025-10-13 00:42:38 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
try {
|
2025-10-13 00:42:38 -03:00
|
|
|
const glpiTicketId = await hubglpiModel.getGlpiTicketIdByAtendimentoId(ticketData.id_atendimento);
|
|
|
|
|
if (glpiTicketId) {
|
|
|
|
|
logInfo(`Ticket já inserido no GLPI para id_atendimento ${ticketData.id_atendimento}, pulando criação.`);
|
|
|
|
|
ticketData.status_sync = 'created_glpi';
|
|
|
|
|
ticketData.glpi_ticket_id = glpiTicketId;
|
|
|
|
|
await hubglpiModel.update_syncData(ticketData);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2025-10-08 18:55:29 -03:00
|
|
|
|
2025-10-10 09:06:44 -03:00
|
|
|
const titulo = `Mundiale - Protocolo: ${ticketData.ticket_mundiale} - ${ticketData.cliente_nome}`;
|
|
|
|
|
ticketData.titulo = titulo;
|
|
|
|
|
|
|
|
|
|
const selectedEntityCodServico = await glpiModel.selectEntityId(ticketData.codigo_servico);
|
2025-10-14 15:47:51 -03:00
|
|
|
// Prioriza a entidade do serviço; se não existir tenta pelo cliente; fallback para 0
|
2025-10-15 08:05:35 -03:00
|
|
|
if (selectedEntityCodServico.include(ticketData.codigo_cliente)) {
|
2025-10-10 09:06:44 -03:00
|
|
|
ticketData.entidades_id = selectedEntityCodServico;
|
2025-10-14 15:47:51 -03:00
|
|
|
logInfo(`Entidade encontrada por serviço: ${selectedEntityCodServico}`);
|
2025-10-10 09:06:44 -03:00
|
|
|
} else {
|
2025-10-14 15:47:51 -03:00
|
|
|
const selectedEntityCodCliente = await glpiModel.selectEntityId(ticketData.codigo_cliente);
|
|
|
|
|
if (selectedEntityCodCliente) {
|
|
|
|
|
ticketData.entidades_id = selectedEntityCodCliente;
|
|
|
|
|
logInfo(`Entidade encontrada por cliente: ${selectedEntityCodCliente}`);
|
|
|
|
|
} else {
|
|
|
|
|
ticketData.entidades_id = 0;
|
|
|
|
|
logInfo(`Nenhuma entidade encontrada para serviço="${ticketData.codigo_servico}" ou cliente="${ticketData.codigo_cliente}", atribuindo 0`);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-08 18:55:29 -03:00
|
|
|
await createGlpiTicket(ticketData);
|
2025-10-07 17:57:23 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
} catch (error) {
|
2025-10-13 00:42:38 -03:00
|
|
|
console.error(`Erro ao processar atendimento ${ticketData.id_atendimento}:`, error);
|
2025-10-08 18:55:29 -03:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// ================================================================================
|
|
|
|
|
// Função Principal (com opção de pular a etapa do HubSoft)
|
|
|
|
|
// ================================================================================
|
|
|
|
|
|
|
|
|
|
const processaAtendimentos = async (skipHubSoft = false) => {
|
|
|
|
|
try {
|
|
|
|
|
let atendimentosDB = [];
|
|
|
|
|
|
|
|
|
|
if (!skipHubSoft) {
|
|
|
|
|
// Esta parte depende da VPN
|
2025-10-13 00:42:38 -03:00
|
|
|
logInfo('Buscando atendimentos do HubSoft...');
|
2025-10-08 18:55:29 -03:00
|
|
|
atendimentosDB = await hubsoftModel.getAtendimentosFromDB();
|
2025-10-13 00:42:38 -03:00
|
|
|
logInfo(`Total de atendimentos obtidos do HubSoft: ${atendimentosDB.length}`);
|
2025-10-08 18:55:29 -03:00
|
|
|
|
|
|
|
|
for (const atendimento of atendimentosDB) {
|
|
|
|
|
try {
|
|
|
|
|
// Processa o ticket do HubSoft
|
|
|
|
|
const ticketData = await processTicketFromHubSoft(atendimento);
|
|
|
|
|
// Salva no banco intermediário (hubglpi)
|
|
|
|
|
await saveTicketToHubGlpi(ticketData);
|
|
|
|
|
}
|
|
|
|
|
catch (error) {
|
2025-10-13 00:42:38 -03:00
|
|
|
logError(`Erro ao processar atendimento ${atendimento.id_atendimento}:`, error);
|
2025-10-08 18:55:29 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else {
|
2025-10-13 00:42:38 -03:00
|
|
|
logInfo('Pulando a busca de atendimentos do HubSoft (skipHubSoft = true)');
|
2025-10-07 17:57:23 -03:00
|
|
|
}
|
2025-10-08 18:55:29 -03:00
|
|
|
|
|
|
|
|
// Coletando atendimentos do banco intermediário (hubglpi)
|
|
|
|
|
atendimentosDB = await hubglpiModel.getTicketDataPending();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (const atendimento of atendimentosDB) {
|
|
|
|
|
try {
|
|
|
|
|
// Processa o atendimento para o GLPI
|
|
|
|
|
await processAtendimento(atendimento);
|
|
|
|
|
|
2025-10-13 00:42:38 -03:00
|
|
|
|
2025-10-08 18:55:29 -03:00
|
|
|
} catch (error) {
|
2025-10-13 00:42:38 -03:00
|
|
|
logError(`Erro ao processar atendimento ${atendimento.id_atendimento}:, ${error}`);
|
2025-10-08 18:55:29 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-07 17:57:23 -03:00
|
|
|
} catch (error) {
|
2025-10-13 00:42:38 -03:00
|
|
|
logError(`Erro ao processar atendimentos: ${error}`);
|
2025-10-08 18:55:29 -03:00
|
|
|
}
|
|
|
|
|
};
|
2025-10-07 17:57:23 -03:00
|
|
|
|
|
|
|
|
module.exports = {
|
2025-10-08 18:55:29 -03:00
|
|
|
processaAtendimentos,
|
|
|
|
|
processAtendimento,
|
|
|
|
|
formatTicketDataForGlpi,
|
|
|
|
|
formatDescription
|
|
|
|
|
};
|