snglpi/src/controllers/processCommentsController.js

73 lines
3.4 KiB
JavaScript
Raw Normal View History

const { fetchCommentsFromServiceNow, fetchTicketLiveStatusFromServiceNow } = require('../services/servicenowService');
const { syncCommentsGlpitoSN, syncCommentsSNtoGlpi } = require('../services/glpiCommentService');
const TicketSyncModel = require('../models/ticketSyncModel');
const TicketSnModel = require('../models/ticketSnModel');
const TicketGlpiModel = require('../models/ticketGlpiModel');
const { logInfo } = require('../utils/logger');
2025-10-13 06:06:52 -03:00
const ensureReopenFromSNWhenGlpiSolved = async (ticket) => {
const glpiStatus = await TicketGlpiModel.getTicketStatus(ticket.glpi_ticket_id);
const glpiIsSolved = glpiStatus === 5;
if (!glpiIsSolved) {
return { reopened: false, glpiSolved: false };
}
// REGRA DE CONTENÇÃO: Só reabre se o monitoramento de status estiver ativo.
// Se o usuário desligou o sync de status, ele quer controle manual.
if (process.env.ENABLE_STATUS_SYNC === 'false') {
return { reopened: false, glpiSolved: true };
}
// CORREÇÃO: Verificar se o ticket foi fechado recentemente.
// Se o status já é 'solved', significa que o processGlpiClosureController
// tentou fechar recentemente. O SN pode ainda estar processando o close,
// então ignoramos a detecção de reopen para evitar falsos positivos.
if (ticket.glpi_sync_status === 'solved' || ticket.sn_sync_status === 'solved') {
logInfo(`Ticket GLPI ${ticket.glpi_ticket_id} fechou recentemente (status: ${ticket.glpi_sync_status}/${ticket.sn_sync_status}). Ignorando verificacao de reopen.`);
return { reopened: false, glpiSolved: true };
}
const ticketSn = await TicketSnModel.findById(ticket.sn_ticket_id);
if (!ticketSn) {
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 { reopened: false, glpiSolved: true };
}
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 };
};
2025-10-13 06:06:52 -03:00
const processCommentsController = async () => {
const ticketsToMonitor = await TicketSyncModel.getTicketsToMonitor();
logInfo(`Tickets em monitoramento: ${ticketsToMonitor.length}`);
for (const ticket of ticketsToMonitor) {
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, { highlightReopenContext: reopenedThisCycle });
}
await syncCommentsGlpitoSN(ticket);
}
};
2025-10-13 06:06:52 -03:00
module.exports = {
processCommentsController
};