FEAT: Integração ServiceNow + PostgreSQL com salvamento automático

- Implementa conexão API ServiceNow → PostgreSQL
- Salva automaticamente tickets e requisições
- Resultado: 673 tickets sincronizados
- Créditos: @TulioCastro pelo GET da API
This commit is contained in:
Rafael Alves Lopes 2025-09-03 21:40:04 -03:00
parent 56cb7b4c91
commit cb73486caa
8 changed files with 94 additions and 32 deletions

View File

2
package-lock.json generated
View File

@ -9,7 +9,7 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
"axios": "^0.21.4",
"dotenv": "^10.0.0",
"pg": "^8.7.1"
}

View File

@ -9,7 +9,7 @@
"test": "echo \"No tests specified\" && exit 0"
},
"dependencies": {
"axios": "^0.21.1",
"axios": "^0.21.4",
"dotenv": "^10.0.0",
"pg": "^8.7.1"
},

View File

@ -1,8 +1,24 @@
// config/database.js
module.exports = {
// src/data/database.js
// Configuração da conexão com o banco de dados PostgreSQL
const { Pool } = require('pg');
const pool = new Pool({
host: '10.0.120.75',
port: 5432,
database: 'snglpi',
user: 'desenvolvimento',
password: 'Ut@2S@$M9Xs@@W'
};
});
// testa a conexao
pool.on('connect', () => {
console.log('Conectado ao PostgreSQL');
});
pool.on('error', (err) => {
console.error('Erro de conexão PostgreSQL:', err);
});
//exporta o pool para ser usado em outros arquivos
module.exports = pool;

View File

@ -1,28 +1,53 @@
const { Sequelize } = require('sequelize');
require('dotenv').config();
//Conetnando ao banco de dados
const pool = require('../data/database');
// Database connection configuration
const dbConfig = {
host: process.env.DB_HOST,
dialect: process.env.DB_DIALECT || 'mysql', // Default to MySQL if not specified
logging: false, // Disable logging; enable for debugging
};
class TicketSnModel {
// Salvar os tickets
static async saveTickets(ticketData, typeTicket) {
// Create a new Sequelize instance
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, dbConfig);
//Query SQL
const query = `INSERT INTO tickets_sn
(ticket_number, short_description, description, caller_email,
location_name, ramal, telefone, opened_at, tipo)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
ON CONFLICT (ticket_number)
DO UPDATE SET
short_description = EXCLUDED.short_description,
description = EXCLUDED.description,
location_name = EXCLUDED.location_name,
updated_at = NOW()
RETURNING id
`;
// Test the database connection
const testConnection = async () => {
try {
await sequelize.authenticate();
console.log('Connection to the database has been established successfully.');
} catch (error) {
console.error('Unable to connect to the database:', error);
// Dados do ticket
const values = [
ticketData.number?.value || null,
ticketData.short_description?.value || null,
ticketData.description?.value || null,
ticketData.caller_email?.value || null,
ticketData.location_name?.value || null,
ticketData.u_ramal?.value || null,
ticketData.u_telefone?.value || null,
ticketData.opened_at?.value || null,
typeTicket
];
// Executa a query
try {
console.log('Salvando ticket:', values[0]);
const result = await pool.query(query, values);
console.log('Ticket salvo com sucesso, ID:', result.rows[0].id);
return result.rows[0].id;
} catch (error) {
console.error('Erro ao salvar ticket:', error);
throw error;
}
}
};
// Export the sequelize instance and the test function
module.exports = {
sequelize,
testConnection,
};
// Poderemos adicionar mais métodos aqui para outras operações no banco de dados, se necessário.
// Exemplo: buscar tickets, atualizar tickets.
}
module.exports = TicketSnModel;

View File

@ -3,6 +3,7 @@ CREATE TABLE tickets_sn (
ticket_number VARCHAR(32) NOT NULL UNIQUE, -- Número do ticket (INC0140378) - ÚNICO
sn_ticket_id VARCHAR(64), -- ID interno do ServiceNow
short_description TEXT, -- Resumo do problema
tipo VARCHAR(10), -- Requisição ou incidente
description TEXT, -- Descrição completa
caller_id VARCHAR(255), -- ID de quem abriu o ticket
caller_email VARCHAR(255), -- Email do solicitante
@ -11,6 +12,7 @@ CREATE TABLE tickets_sn (
ramal VARCHAR(100), -- Ramal do solicitante
telefone VARCHAR(100), -- Telefone do solicitante
opened_at TIMESTAMP, -- Quando o ticket foi aberto
created_at TIMESTAMP DEFAULT NOW(), -- Quando registramos no BD
created_at TIMESTAMP DEFAULT NOW(), -- Quando registramos no BD
updated_at TIMESTAMP DEFAULT NOW() -- Quando atualizamos pela última vez
);
);

View File

View File

@ -1,16 +1,27 @@
const axios = require('axios');
const apiConfig = require('../../config/apiConfig');
const fs = require('fs');
const TicketSnModel = require('../models/databaseModel');
const { Console } = require('console');
const fetchTicketsFromServiceNow = async () => {
try {
const ticketsResponse = await axios.get(apiConfig.snIncidentConfig.baseUrl, {
auth: apiConfig.servicenowAuthentication.auth
});
// gerar um JSON das respostas da API
// gerar um JSON das respostas da API //Mantive o json enquanto testo a integração com o banco
fs.writeFileSync('servicenow_tickets.json', JSON.stringify(ticketsResponse.data, null, 2));
// Salvar os tickets no banco de dados
console.log('Iniciando salvamento dos tickets no banco de dados...');
for (const ticket of ticketsResponse.data.result) {
await TicketSnModel.saveTickets(ticket, 'incidente');
}
} catch (error) {
console.log('SERVICE NOW Tickets error: ', error.message);
}
@ -22,9 +33,17 @@ const fetchRequestsFromServiceNow = async () => {
auth: apiConfig.servicenowAuthentication.auth
});
// gerar um JSON das respostas da API
// gerar um JSON das respostas da API //Mantive o json enquanto testo a integração com o banco
fs.writeFileSync('servicenow_requests.json', JSON.stringify(requestsResponse.data, null, 2));
// Salvar os tickets no banco de dados
console.log('Iniciando salvamento das requisições no banco de dados...');
for (const request of requestsResponse.data.result) {
await TicketSnModel.saveTickets(request, 'requisicao');
}
} catch (error) {
console.log('SERVICE NOW Requests error: ', error.message);
}