FEAT: Motor de regras único de status/fechamento + mandante configurável
Consolida os dois controladores legados que decidiam status/fechamento de
forma concorrente (processGlpiClosureController + processStatusController)
em um único processTicketLifecycleController, eliminando a dependência do
campo source_last (mantido só como rastro de auditoria) e a flag
ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados
reabertos no SN voltavam a ser fechados no GLPI porque a regra de
precedência de finalização do fluxo legado forçava o status do GLPI de
volta pro SN.
Correções de bugs encontrados em teste (Frente 1):
- Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING
na criação do registro, prevenindo duplicação de tickets.
- Fechamento no SN agora é confirmado por leitura ao vivo do status antes
de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200
(a API do SN pode retornar sucesso e silenciosamente ignorar um valor de
estado inválido — descoberto e corrigido também no mandante).
- Nota de encerramento do SN pro GLPI agora é idempotente e criada uma
única vez por ticket.
- Erros de sincronização passam a ter um limite de tentativas
(MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent,
exigindo intervenção manual em vez de tentar para sempre.
- Chamados criados no GLPI passam a gravar o número do ticket do SN no
campo externalid.
Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por
conta própria antes do GLPI, além da nota informativa no GLPI (agora com o
nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/
sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais
atender aquele chamado e ele é transferido pra fila de TI da CAOA.
Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e
configurável de status intermediário (Aguardando Atendimento/Em
Atendimento/Em Espera) entre os dois sistemas, controlado pela env
MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual
(nenhum espelhamento de status intermediário). Nunca afeta os status finais
(resolvido/encerrado/fora de escopo), que continuam regidos pelas regras
fixas de fechamento.
Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml),
que ainda validava os controladores antigos (já removidos) e exigia
ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 09:45:34 -03:00
|
|
|
const { fetchCommentsFromServiceNow } = require('../services/servicenowService');
|
2025-10-17 16:58:14 -03:00
|
|
|
const { syncCommentsGlpitoSN, syncCommentsSNtoGlpi } = require('../services/glpiCommentService');
|
|
|
|
|
const TicketSyncModel = require('../models/ticketSyncModel');
|
2026-03-04 16:37:04 -03:00
|
|
|
const TicketGlpiModel = require('../models/ticketGlpiModel');
|
2025-11-19 16:01:37 -03:00
|
|
|
const { logInfo } = require('../utils/logger');
|
2025-10-13 06:06:52 -03:00
|
|
|
|
|
|
|
|
const processCommentsController = async () => {
|
2025-10-23 17:30:03 -03:00
|
|
|
const ticketsToMonitor = await TicketSyncModel.getTicketsToMonitor();
|
2026-03-04 16:37:04 -03:00
|
|
|
logInfo(`Tickets em monitoramento: ${ticketsToMonitor.length}`);
|
2025-11-19 16:01:37 -03:00
|
|
|
|
2026-03-04 16:37:04 -03:00
|
|
|
for (const ticket of ticketsToMonitor) {
|
FEAT: Motor de regras único de status/fechamento + mandante configurável
Consolida os dois controladores legados que decidiam status/fechamento de
forma concorrente (processGlpiClosureController + processStatusController)
em um único processTicketLifecycleController, eliminando a dependência do
campo source_last (mantido só como rastro de auditoria) e a flag
ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados
reabertos no SN voltavam a ser fechados no GLPI porque a regra de
precedência de finalização do fluxo legado forçava o status do GLPI de
volta pro SN.
Correções de bugs encontrados em teste (Frente 1):
- Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING
na criação do registro, prevenindo duplicação de tickets.
- Fechamento no SN agora é confirmado por leitura ao vivo do status antes
de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200
(a API do SN pode retornar sucesso e silenciosamente ignorar um valor de
estado inválido — descoberto e corrigido também no mandante).
- Nota de encerramento do SN pro GLPI agora é idempotente e criada uma
única vez por ticket.
- Erros de sincronização passam a ter um limite de tentativas
(MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent,
exigindo intervenção manual em vez de tentar para sempre.
- Chamados criados no GLPI passam a gravar o número do ticket do SN no
campo externalid.
Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por
conta própria antes do GLPI, além da nota informativa no GLPI (agora com o
nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/
sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais
atender aquele chamado e ele é transferido pra fila de TI da CAOA.
Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e
configurável de status intermediário (Aguardando Atendimento/Em
Atendimento/Em Espera) entre os dois sistemas, controlado pela env
MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual
(nenhum espelhamento de status intermediário). Nunca afeta os status finais
(resolvido/encerrado/fora de escopo), que continuam regidos pelas regras
fixas de fechamento.
Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml),
que ainda validava os controladores antigos (já removidos) e exigia
ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 09:45:34 -03:00
|
|
|
const glpiStatus = await TicketGlpiModel.getTicketStatus(ticket.glpi_ticket_id);
|
|
|
|
|
if (glpiStatus === 5) {
|
|
|
|
|
// Regra de negocio: enquanto o GLPI estiver Solucionado, nao manda comentario novo
|
|
|
|
|
// do SN pra dentro do chamado. A decisao de reabertura acontece em
|
|
|
|
|
// processTicketLifecycleController.js, que roda antes deste controlador no ciclo.
|
2026-03-04 18:15:53 -03:00
|
|
|
logInfo(`Ticket ${ticket.glpi_ticket_id} permanece Solucionado no GLPI. Comentarios SN -> GLPI bloqueados ate reabertura.`);
|
|
|
|
|
await syncCommentsGlpitoSN(ticket);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2025-10-17 16:58:14 -03:00
|
|
|
|
|
|
|
|
const comments = await fetchCommentsFromServiceNow(ticket);
|
2026-03-04 16:37:04 -03:00
|
|
|
if (comments.length !== 0) {
|
FEAT: Motor de regras único de status/fechamento + mandante configurável
Consolida os dois controladores legados que decidiam status/fechamento de
forma concorrente (processGlpiClosureController + processStatusController)
em um único processTicketLifecycleController, eliminando a dependência do
campo source_last (mantido só como rastro de auditoria) e a flag
ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados
reabertos no SN voltavam a ser fechados no GLPI porque a regra de
precedência de finalização do fluxo legado forçava o status do GLPI de
volta pro SN.
Correções de bugs encontrados em teste (Frente 1):
- Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING
na criação do registro, prevenindo duplicação de tickets.
- Fechamento no SN agora é confirmado por leitura ao vivo do status antes
de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200
(a API do SN pode retornar sucesso e silenciosamente ignorar um valor de
estado inválido — descoberto e corrigido também no mandante).
- Nota de encerramento do SN pro GLPI agora é idempotente e criada uma
única vez por ticket.
- Erros de sincronização passam a ter um limite de tentativas
(MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent,
exigindo intervenção manual em vez de tentar para sempre.
- Chamados criados no GLPI passam a gravar o número do ticket do SN no
campo externalid.
Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por
conta própria antes do GLPI, além da nota informativa no GLPI (agora com o
nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/
sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais
atender aquele chamado e ele é transferido pra fila de TI da CAOA.
Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e
configurável de status intermediário (Aguardando Atendimento/Em
Atendimento/Em Espera) entre os dois sistemas, controlado pela env
MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual
(nenhum espelhamento de status intermediário). Nunca afeta os status finais
(resolvido/encerrado/fora de escopo), que continuam regidos pelas regras
fixas de fechamento.
Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml),
que ainda validava os controladores antigos (já removidos) e exigia
ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 09:45:34 -03:00
|
|
|
await syncCommentsSNtoGlpi(comments, ticket);
|
2026-03-04 16:37:04 -03:00
|
|
|
}
|
|
|
|
|
|
2025-10-17 16:58:14 -03:00
|
|
|
await syncCommentsGlpitoSN(ticket);
|
2025-10-29 14:20:21 -03:00
|
|
|
}
|
2026-03-04 16:37:04 -03:00
|
|
|
};
|
2025-10-29 14:20:21 -03:00
|
|
|
|
2025-10-13 06:06:52 -03:00
|
|
|
module.exports = {
|
|
|
|
|
processCommentsController
|
2026-03-04 18:15:53 -03:00
|
|
|
};
|