diff --git a/src/controllers/processStatusController.js b/src/controllers/processStatusController.js index 99851ad..adbb31f 100644 --- a/src/controllers/processStatusController.js +++ b/src/controllers/processStatusController.js @@ -4,7 +4,7 @@ const TicketGlpiModel = require('../models/ticketGlpiModel'); const { logInfo, logError, logWarning } = require('../utils/logger'); const { stripHTML } = require('../utils/commentSanitizer'); const { closeTicketInServiceNow, updateStatusInServiceNow, addWorkNoteToServiceNow } = require('../services/servicenowService'); -const { closeTicketInGlpi } = require('../services/glpiTicketService'); +const { addServiceNowClosureNoteToGlpi } = require('../services/glpiTicketService'); const processStatusAndClosureController = async () => { logInfo('Iniciando processamento de status e fechamento de tickets...'); @@ -40,9 +40,12 @@ const processStatusAndClosureController = async () => { // Compara o status real do GLPI com o status que temos do ServiceNow if (glpiLiveStatus !== null && glpiLiveStatusAsString !== snCurrentStatus) { - logInfo(`Mudança de status detectada no GLPI para o ticket ${ticket.glpi_ticket_id}. GLPI está como '${glpiLiveStatusAsString}', SN está como '${snCurrentStatus}'.`); - // Se uma mudança foi detectada no GLPI, forçamos o "bastão" para ele. - ticket.source_last = 'GLPI'; + logInfo(`Mudanca de status detectada no GLPI para o ticket ${ticket.glpi_ticket_id}. GLPI esta como '${glpiLiveStatusAsString}', SN esta como '${snCurrentStatus}'.`); + if (ticket.source_last !== 'SNOW') { + ticket.source_last = 'GLPI'; + } else { + logInfo(`Direcao mantida como SNOW -> GLPI para o ticket ${ticketSnDetails.ticket_number}.`); + } } // ================= LÓGICA SNOW -> GLPI ================= @@ -56,17 +59,22 @@ const processStatusAndClosureController = async () => { // Se o ticket no GLPI está permanentemente Fechado (6), não fazemos nada. if (glpiCurrentStatus === 6) { logWarning(`Ticket GLPI ${ticket.glpi_ticket_id} está permanentemente Fechado (6). Ação de reabertura pelo SN ('${snCurrentStatus}') foi bloqueada.`); - } else if (snCurrentStatus === 'Resolvido' && glpiCurrentStatus !== 5) { // SN foi para 'Resolved' e GLPI ainda não está 'Solucionado' - logInfo(`SN ${ticketSnDetails.ticket_number} foi Resolvido. Sincronizando para GLPI...`); - await closeTicketInGlpi(ticket); - await TicketSyncModel.updateStatus(ticket.sn_ticket_id, 'solved', 'solved'); - } else if (snCurrentStatus === 'Resolvido' && glpiCurrentStatus === 5) { - // Ambos já estão resolvidos, nenhuma ação necessária. - logInfo(`SN ${ticketSnDetails.ticket_number} e GLPI ${ticket.glpi_ticket_id} já estão no estado Resolvido/Solucionado. Nenhuma ação necessária.`); + } else if (snCurrentStatus === 'Resolvido') { + logInfo(`SN ${ticketSnDetails.ticket_number} foi Resolvido. Enviando nota para GLPI sem fechar o chamado...`); + + // Regra de negocio: resolucao vinda do SN nao fecha no GLPI. + // Apenas registra uma nota e remove o ticket do monitoramento da integracao. + const collaboratorName = ticketSnDetails.updated_by || ticketSnDetails.closed_by || null; + await addServiceNowClosureNoteToGlpi(ticket, collaboratorName, 'solucionado'); + await TicketSyncModel.updateStatusAndSourceLast(ticket.sn_ticket_id, 'closed', 'closed', 'SNOW'); } else if (snCurrentStatus === 'Encerrado - Omitido' || snCurrentStatus === 'Encerrado') { // SN foi para 'Closed' - logInfo(`SN ${ticketSnDetails.ticket_number} foi Fechado. Sincronizando para GLPI...`); - await TicketGlpiModel.forceCloseTicket(ticket.glpi_ticket_id); - await TicketSyncModel.updateStatus(ticket.sn_ticket_id, 'closed', 'closed'); + logInfo(`SN ${ticketSnDetails.ticket_number} foi Fechado. Enviando nota para GLPI sem fechar o chamado...`); + + // Regra de negocio: encerramento vindo do SN nao fecha no GLPI. + // Apenas registra uma nota e remove o ticket do monitoramento da integracao. + const collaboratorName = ticketSnDetails.updated_by || ticketSnDetails.closed_by || null; + await addServiceNowClosureNoteToGlpi(ticket, collaboratorName, 'encerrado'); + await TicketSyncModel.updateStatusAndSourceLast(ticket.sn_ticket_id, 'closed', 'closed', 'SNOW'); } else { // Se estiver Solucionado (5) ou em qualquer outro estado, permite a atualização (reabertura). await TicketGlpiModel.updateStatus(ticket.glpi_ticket_id, snCurrentStatus); diff --git a/src/services/glpiTicketService.js b/src/services/glpiTicketService.js index 6b3e609..cf8fb95 100644 --- a/src/services/glpiTicketService.js +++ b/src/services/glpiTicketService.js @@ -147,6 +147,36 @@ const checkGlpiStatusChanges = async () => { } }; +const addServiceNowClosureNoteToGlpi = async (ticket, collaboratorName, finalStatus = 'encerrado') => { + try { + const resolvedBy = collaboratorName && collaboratorName.trim() + ? collaboratorName.trim() + : 'colaborador CAOA'; + const statusText = finalStatus === 'solucionado' + ? 'Chamado solucionado no Service Now pela CAOA.' + : 'Chamado encerrado no Service Now pela CAOA.'; + + const styledMessage = ` +
+
Atualizacao automatica de encerramento
+
+ ${statusText} +
+
+ Responsavel informado: ${resolvedBy} +
+
`; + + await TicketGlpiModel.insertComment({ content: styledMessage }, ticket.glpi_ticket_id); + await TicketSyncModel.updateLastSync(ticket.sn_ticket_id, 'glpi'); + logInfo(`Nota de encerramento do ServiceNow adicionada ao GLPI ${ticket.glpi_ticket_id}.`); + return true; + } catch (error) { + logError(error, `Falha ao adicionar nota de encerramento do SN no GLPI ${ticket.glpi_ticket_id}`); + return false; + } +}; + const closeTicketInGlpi = async (ticket) => { try { logInfo(`🔒 Iniciando fechamento do chamado GLPI ${ticket.glpi_ticket_id}...`); @@ -167,7 +197,8 @@ const closeTicketInGlpi = async (ticket) => { module.exports = { syncTicketsToGlpi, checkGlpiStatusChanges, - closeTicketInGlpi + closeTicketInGlpi, + addServiceNowClosureNoteToGlpi }; /**