FEAT: Adiciona novas URLs de API no .env e implementa funções para sincronização de comentários no ServiceNow
This commit is contained in:
parent
2960292066
commit
a8f1eea206
2
.env
2
.env
@ -5,6 +5,8 @@
|
|||||||
# ServiceNow API Configuration
|
# ServiceNow API Configuration
|
||||||
SERVICENOW_INCIDENT_URL="https://caoadev.service-now.com/api/now/table/incident?sysparm_display_value=all&sysparm_limit=20&sysparm_query=ORDERBYDESCsys_created_on&sysparm_fields=number%2state%2Copened_by%2Copened_at%2Clocation%2Cshort_description%2Cdescription%2Cvariables.caller_id%2Cvariables.location%2Cvariables.telephone_favorecido_rh%2Cvariables.numero_ramal%2Copened_by.email%2Csys_id%5Eassignment_group%3D46d44f91c611227500713c12f0b7c78d"
|
SERVICENOW_INCIDENT_URL="https://caoadev.service-now.com/api/now/table/incident?sysparm_display_value=all&sysparm_limit=20&sysparm_query=ORDERBYDESCsys_created_on&sysparm_fields=number%2state%2Copened_by%2Copened_at%2Clocation%2Cshort_description%2Cdescription%2Cvariables.caller_id%2Cvariables.location%2Cvariables.telephone_favorecido_rh%2Cvariables.numero_ramal%2Copened_by.email%2Csys_id%5Eassignment_group%3D46d44f91c611227500713c12f0b7c78d"
|
||||||
SERVICENOW_REQUEST_URL="https://caoadev.service-now.com/api/now/table/sc_req_item?sysparm_fields=number%2Cstate%2Crequest%2Copened_by%2Copened_at%2Clocation%2Cshort_description%2Cdescription%2Cassignment_group%2Csys_id&sysparm_display_value=all&sysparm_query=assignment_group%3D1132c9e01bfad410e77eb9121b4bcbab"
|
SERVICENOW_REQUEST_URL="https://caoadev.service-now.com/api/now/table/sc_req_item?sysparm_fields=number%2Cstate%2Crequest%2Copened_by%2Copened_at%2Clocation%2Cshort_description%2Cdescription%2Cassignment_group%2Csys_id&sysparm_display_value=all&sysparm_query=assignment_group%3D1132c9e01bfad410e77eb9121b4bcbab"
|
||||||
|
SERVICENOW_TABLE_INCIDENT_URL="https://caoadev.service-now.com/api/now/table/incident/"
|
||||||
|
SERVICENOW_TABLE_JOURNAL_URL="https://caoadev.service-now.com/api/now/table/sys_journal_field"
|
||||||
SERVICENOW_USERNAME=SOTHIS.CAOA
|
SERVICENOW_USERNAME=SOTHIS.CAOA
|
||||||
SERVICENOW_PASSWORD=#Sothis20
|
SERVICENOW_PASSWORD=#Sothis20
|
||||||
|
|
||||||
|
|||||||
@ -28,10 +28,20 @@ const snRequestConfig = {
|
|||||||
baseUrl: process.env.SERVICENOW_REQUEST_URL,
|
baseUrl: process.env.SERVICENOW_REQUEST_URL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const snTableIncidentConfig = {
|
||||||
|
baseUrl: process.env.SERVICENOW_TABLE_INCIDENT_URL,
|
||||||
|
}
|
||||||
|
|
||||||
|
const snTableJournalConfig = {
|
||||||
|
baseUrl: process.env.SERVICENOW_TABLE_JOURNAL_URL,
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// configuração do ServiceNow e outras já existentes podem permanecer
|
// configuração do ServiceNow e outras já existentes podem permanecer
|
||||||
glpiDbConfig,
|
glpiDbConfig,
|
||||||
snIncidentConfig,
|
snIncidentConfig,
|
||||||
snRequestConfig,
|
snRequestConfig,
|
||||||
|
snTableIncidentConfig,
|
||||||
|
snTableJournalConfig,
|
||||||
servicenowAuthentication
|
servicenowAuthentication
|
||||||
};
|
};
|
||||||
@ -38,6 +38,7 @@ class TicketSyncModel {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @module TicketSyncModel
|
* @module TicketSyncModel
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class TicketUpdateModel {
|
|||||||
const values = [
|
const values = [
|
||||||
updateData.ticket_sync_id,
|
updateData.ticket_sync_id,
|
||||||
'note',
|
'note',
|
||||||
'glpi',
|
updateData.source_system,
|
||||||
updateData.content,
|
updateData.content,
|
||||||
'Sothis',
|
'Sothis',
|
||||||
updateData.created_at,
|
updateData.created_at,
|
||||||
|
|||||||
@ -4,12 +4,23 @@ const TicketGlpiModel = require('../models/ticketGlpiModel');
|
|||||||
const TicketSyncModel = require('../models/ticketSyncModel');
|
const TicketSyncModel = require('../models/ticketSyncModel');
|
||||||
const TicketUpdateModel = require('../models/ticketUpdateModel');
|
const TicketUpdateModel = require('../models/ticketUpdateModel');
|
||||||
const { logInfo, logError } = require('../utils/logger');
|
const { logInfo, logError } = require('../utils/logger');
|
||||||
|
const { getTicketSysId, createCommentInServiceNow } = require('./servicenowService');
|
||||||
|
|
||||||
|
|
||||||
// Sincroniza comentários do GLPI para o Banco de Dados local
|
// Sincroniza comentários do GLPI para o Banco de Dados local
|
||||||
const syncCommentsGlpi = async () => {
|
const syncCommentsGlpi = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// Função interna para sincronizar comentário no ServiceNow
|
||||||
|
const syncCommentToServiceNow = async (ticketNumber, comment) => {
|
||||||
|
const snSysId = await getTicketSysId(ticketNumber);
|
||||||
|
if (!snSysId) {
|
||||||
|
logError(`❌ sys_id do ServiceNow não encontrado para o ticket SN Ticket: ${ticketNumber}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return await createCommentInServiceNow(snSysId, comment.content);
|
||||||
|
};
|
||||||
|
|
||||||
logInfo('🔄 Iniciando sincronização de comments do GLPI para o Service Now iniciada...');
|
logInfo('🔄 Iniciando sincronização de comments do GLPI para o Service Now iniciada...');
|
||||||
const effectiveTickets = await TicketSyncModel.getTicketsToSync();
|
const effectiveTickets = await TicketSyncModel.getTicketsToSync();
|
||||||
logInfo(`🔍 ${effectiveTickets.length} tickets encontrados para sincronização de comentários`, { step: 1 });
|
logInfo(`🔍 ${effectiveTickets.length} tickets encontrados para sincronização de comentários`, { step: 1 });
|
||||||
@ -29,10 +40,13 @@ const syncCommentsGlpi = async () => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const snCommentId = await syncCommentToServiceNow(ticket.sn_ticket_id, comment);
|
||||||
|
|
||||||
const sync_id = await TicketSyncModel.getIdSyncByGlpiId(ticket.glpi_ticket_id);
|
const sync_id = await TicketSyncModel.getIdSyncByGlpiId(ticket.glpi_ticket_id);
|
||||||
|
|
||||||
const commentData = {
|
const commentData = {
|
||||||
ticket_sync_id: sync_id,
|
ticket_sync_id: sync_id,
|
||||||
|
source_system: 'glpi',
|
||||||
content: comment.content,
|
content: comment.content,
|
||||||
created_at: new Date(comment.date_creation),
|
created_at: new Date(comment.date_creation),
|
||||||
updated_at: new Date(comment.date_mod),
|
updated_at: new Date(comment.date_mod),
|
||||||
@ -59,6 +73,9 @@ const syncCommentsGlpi = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @module glpiCommentService
|
* @module glpiCommentService
|
||||||
* @description Este módulo fornece serviços para sincronizar comentários do GLPI para o banco de dados local.
|
* @description Este módulo fornece serviços para sincronizar comentários do GLPI para o banco de dados local.
|
||||||
|
|||||||
@ -4,6 +4,7 @@ const apiConfig = require('../../config/apiConfig');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const TicketSnModel = require('../models/ticketSnModel');
|
const TicketSnModel = require('../models/ticketSnModel');
|
||||||
const { logInfo, logError, logSync } = require('../utils/logger');
|
const { logInfo, logError, logSync } = require('../utils/logger');
|
||||||
|
const TicketUpdateModel = require('../models/ticketUpdateModel');
|
||||||
|
|
||||||
const fetchTicketsFromServiceNow = async () => {
|
const fetchTicketsFromServiceNow = async () => {
|
||||||
try {
|
try {
|
||||||
@ -55,7 +56,78 @@ const fetchRequestsFromServiceNow = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Função para obter o sys_id de um ticket pela tabela de sincronização do banco de dados local
|
||||||
|
|
||||||
|
const getTicketSysId = async (ticketNumber) => {
|
||||||
|
try {
|
||||||
|
const ticket = await TicketSnModel.findByTicketNumber(ticketNumber);
|
||||||
|
return ticket.sys_id;
|
||||||
|
} catch (error) {
|
||||||
|
logError(error, '🚨Falha ao obter sys_id do ticket');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Função para obter o código de um comentário dentro de um ticket do ServiceNow
|
||||||
|
const getCommentId = async (sysId, comment) => {
|
||||||
|
try {
|
||||||
|
// Exemplo de requisição GET para buscar comentários:
|
||||||
|
// GET https://SEU_INSTANCE.service-now.com/api/now/table/sys_journal_field?sysparm_query=name=incident^element=comments^element_id={SYS_ID_DO_INCIDENTE}&sysparm_fields=sys_id,sys_created_on,sys_created_by,value&sysparm_orderby_desc=sys_created_on&sysparm_limit=1&sysparm_orderby_desc=sys_created_on&sysparm_limit=1
|
||||||
|
|
||||||
|
const url = `${apiConfig.snTableJournalConfig.baseUrl}?sysparm_query=name=incident^element=comments^element_id=${sysId}&sysparm_fields=sys_id,sys_created_on,sys_created_by,value&sysparm_orderby_desc=sys_created_on&sysparm_limit=1`;
|
||||||
|
|
||||||
|
const response = await axios.get(url, {
|
||||||
|
auth: apiConfig.servicenowAuthentication.auth
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const entry of response.data.result) {
|
||||||
|
if (entry.value.includes(comment)) {
|
||||||
|
return entry.sys_id;
|
||||||
|
} else {
|
||||||
|
logInfo('Comentário não encontrado no ticket', { sysId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
logError(error, '🚨Falha ao obter ID do comentário no ServiceNow');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Função para criar um comentário em um ticket no ServiceNow
|
||||||
|
const createCommentInServiceNow = async (sysId, comment) => {
|
||||||
|
try {
|
||||||
|
// Exemplo de requisição PATCH para atualizar um ticket:
|
||||||
|
// curl -u user:pass \
|
||||||
|
// -H "Content-Type: application/json" \
|
||||||
|
// -X PATCH "https://SEU_INSTANCE.service-now.com/api/now/table/incident/{SYS_ID_DO_INCIDENTE}" \
|
||||||
|
// -d '{"comments":"Estamos analisando seu chamado. Retorno em breve."}'
|
||||||
|
|
||||||
|
const url = `${apiConfig.snTableIncidentConfig.baseUrl}${sysId}`;
|
||||||
|
const payload = {
|
||||||
|
comments: comment
|
||||||
|
};
|
||||||
|
|
||||||
|
await axios.patch(url, payload, {
|
||||||
|
auth: apiConfig.servicenowAuthentication.auth
|
||||||
|
});
|
||||||
|
|
||||||
|
logInfo('💬 Comentário criado com sucesso no ServiceNow', { sysId, comment });
|
||||||
|
|
||||||
|
// retornar id do comentário criado
|
||||||
|
const commentId = await getCommentId(sysId, comment);
|
||||||
|
return commentId;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
logError(error, '🚨Falha ao criar comentário no ServiceNow');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
fetchTicketsFromServiceNow,
|
fetchTicketsFromServiceNow,
|
||||||
fetchRequestsFromServiceNow
|
fetchRequestsFromServiceNow,
|
||||||
|
getTicketSysId,
|
||||||
|
createCommentInServiceNow,
|
||||||
|
getCommentId,
|
||||||
|
updateTicketInServiceNow
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user