diff --git a/.gitignore b/.gitignore index c4c84b1..99f8087 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ servicenow_tickets.json location_mapping.log .env* !.env.example +docs/checklist.md \ No newline at end of file diff --git a/src/controllers/processCommentsController.js b/src/controllers/processCommentsController.js index ab780f4..425246c 100644 --- a/src/controllers/processCommentsController.js +++ b/src/controllers/processCommentsController.js @@ -6,27 +6,27 @@ const TicketGlpiModel = require('../models/ticketGlpiModel'); const { logInfo } = require('../utils/logger'); const ensureReopenFromSNWhenGlpiSolved = async (ticket) => { - if (ticket.glpi_sync_status !== 'solved') { - return; + const glpiStatus = await TicketGlpiModel.getTicketStatus(ticket.glpi_ticket_id); + const glpiIsSolved = glpiStatus === 5; + if (!glpiIsSolved) { + return { reopened: false, glpiSolved: false }; } const ticketSn = await TicketSnModel.findById(ticket.sn_ticket_id); if (!ticketSn) { - return; + return { reopened: false, glpiSolved: true }; } const liveSnStatus = await fetchTicketLiveStatusFromServiceNow(ticketSn.sys_id, ticketSn.tipo); const snIsFinal = liveSnStatus === 'Resolvido' || liveSnStatus === 'Encerrado' || liveSnStatus === 'Encerrado - Omitido'; if (snIsFinal) { - return; + return { reopened: false, glpiSolved: true }; } - const glpiStatus = await TicketGlpiModel.getTicketStatus(ticket.glpi_ticket_id); - if (glpiStatus === 5) { - await TicketGlpiModel.updateStatus(ticket.glpi_ticket_id, 'Em Atendimento'); - await TicketSyncModel.updateStatus(ticket.sn_ticket_id, 'synced', 'synced'); - logInfo(`Reabertura detectada no SN para ticket ${ticket.sn_ticket_id}. GLPI ${ticket.glpi_ticket_id} retornou para Em Atendimento.`); - } + await TicketGlpiModel.updateStatus(ticket.glpi_ticket_id, 'Em Atendimento'); + await TicketSyncModel.updateStatus(ticket.sn_ticket_id, 'synced', 'synced'); + logInfo(`Reabertura detectada no SN para ticket ${ticket.sn_ticket_id}. GLPI ${ticket.glpi_ticket_id} retornou para Em Atendimento.`); + return { reopened: true, glpiSolved: true }; }; const processCommentsController = async () => { @@ -34,11 +34,18 @@ const processCommentsController = async () => { logInfo(`Tickets em monitoramento: ${ticketsToMonitor.length}`); for (const ticket of ticketsToMonitor) { - await ensureReopenFromSNWhenGlpiSolved(ticket); + const reopenState = await ensureReopenFromSNWhenGlpiSolved(ticket); + const reopenedThisCycle = reopenState.reopened; + const glpiWasSolved = reopenState.glpiSolved; + if (glpiWasSolved && !reopenedThisCycle) { + logInfo(`Ticket ${ticket.glpi_ticket_id} permanece Solucionado no GLPI. Comentarios SN -> GLPI bloqueados ate reabertura.`); + await syncCommentsGlpitoSN(ticket); + continue; + } const comments = await fetchCommentsFromServiceNow(ticket); if (comments.length !== 0) { - await syncCommentsSNtoGlpi(comments, ticket); + await syncCommentsSNtoGlpi(comments, ticket, { highlightReopenContext: reopenedThisCycle }); } await syncCommentsGlpitoSN(ticket); @@ -47,4 +54,4 @@ const processCommentsController = async () => { module.exports = { processCommentsController -}; \ No newline at end of file +}; diff --git a/src/services/glpiCommentService.js b/src/services/glpiCommentService.js index aac446e..f5aaf6f 100644 --- a/src/services/glpiCommentService.js +++ b/src/services/glpiCommentService.js @@ -28,7 +28,7 @@ const normalizeAuthorName = (rawAuthor) => { return toTitleCase(normalizedRaw); }; -const formatSNUpdateForGlpi = (update) => { +const formatSNUpdateForGlpi = (update, options = {}) => { const escapeHtml = (value) => String(value || '') .replace(/&/g, '&') .replace(/ { const content = escapeHtml(update.content || ''); const isAutomaticTask = update.update_type === 'task' && /registro alterado por:/i.test(String(update.content || '')); const isSnClosureMessage = update.update_type === 'comment' && /chamado resolvido|chamado encerrado/i.test(String(update.content || '')); + const isSnReopenMessageByText = update.update_type === 'comment' && /reabert|reopen/i.test(String(update.content || '')); + const isSnReopenMessageByContext = Boolean(options.isReopenContextComment); + const isSnReopenMessage = isSnReopenMessageByText || isSnReopenMessageByContext; if (isAutomaticTask) { return ` @@ -59,6 +62,14 @@ const formatSNUpdateForGlpi = (update) => { `; } + if (isSnReopenMessage) { + return ` +