From cb73486caafddfaebffb1016daae787b8e245a0c Mon Sep 17 00:00:00 2001 From: Rafael Lopes Date: Wed, 3 Sep 2025 21:40:04 -0300 Subject: [PATCH] =?UTF-8?q?FEAT:=20Integra=C3=A7=C3=A3o=20ServiceNow=20+?= =?UTF-8?q?=20PostgreSQL=20com=20salvamento=20autom=C3=A1tico?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Implementa conexão API ServiceNow → PostgreSQL - Salva automaticamente tickets e requisições - Resultado: 673 tickets sincronizados - Créditos: @TulioCastro pelo GET da API --- .env.example => .env | 0 package-lock.json | 2 +- package.json | 2 +- src/data/database.js | 22 ++++++- src/models/databaseModel.js | 71 +++++++++++++++-------- src/scripts/database/01_create_tables.sql | 6 +- src/services/databaseService.js | 0 src/services/servicenowService.js | 23 +++++++- 8 files changed, 94 insertions(+), 32 deletions(-) rename .env.example => .env (100%) create mode 100644 src/services/databaseService.js diff --git a/.env.example b/.env similarity index 100% rename from .env.example rename to .env diff --git a/package-lock.json b/package-lock.json index adbdcd2..a8675b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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" } diff --git a/package.json b/package.json index 2baeeb9..504f284 100644 --- a/package.json +++ b/package.json @@ -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" }, diff --git a/src/data/database.js b/src/data/database.js index d75b175..aaf7791 100644 --- a/src/data/database.js +++ b/src/data/database.js @@ -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' -}; \ No newline at end of file +}); + + +// 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; \ No newline at end of file diff --git a/src/models/databaseModel.js b/src/models/databaseModel.js index 0db0d7c..b5462d8 100644 --- a/src/models/databaseModel.js +++ b/src/models/databaseModel.js @@ -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, -}; \ No newline at end of file + // 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; diff --git a/src/scripts/database/01_create_tables.sql b/src/scripts/database/01_create_tables.sql index eac32ec..5c79e31 100644 --- a/src/scripts/database/01_create_tables.sql +++ b/src/scripts/database/01_create_tables.sql @@ -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 -); \ No newline at end of file + +); diff --git a/src/services/databaseService.js b/src/services/databaseService.js new file mode 100644 index 0000000..e69de29 diff --git a/src/services/servicenowService.js b/src/services/servicenowService.js index b3b7a58..5f8be7d 100644 --- a/src/services/servicenowService.js +++ b/src/services/servicenowService.js @@ -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); }