diff --git a/.env.example b/.env.example
index 6c4aeac..1969916 100644
--- a/.env.example
+++ b/.env.example
@@ -46,3 +46,4 @@ GLPI_DB_USER=
GLPI_DB_PASSWORD=
GLPI_DB_NAME=glpi_data
GLPI_DB_CHARSET=utf8mb4
+GLPI_USER_ID=
\ No newline at end of file
diff --git a/src/controller/processController.js b/src/controller/processController.js
index 4423ef2..86b662f 100644
--- a/src/controller/processController.js
+++ b/src/controller/processController.js
@@ -2,7 +2,7 @@
const hubsoftModel = require('../model/hubsoftModel.js');
const hubglpiModel = require('../model/hubglpiModel.js');
const glpiModel = require('../model/glpiModel.js');
-const { logError, logInfo } = require('../utils/logger');
+const { logError, logInfo } = require('../shared/utils/logger.js');
// ================================================================================
diff --git a/src/cron.js b/src/cron.js
index 4fcb4ae..f090c16 100644
--- a/src/cron.js
+++ b/src/cron.js
@@ -2,7 +2,7 @@ const loadEnv = require('./config/envLoader');
loadEnv();
const cron = require('node-cron');
-const { processaAtendimentos } = require('./controller/processController.js');
+const { processAtendimentos}= require('./modules/createTickets/controller/createTickets.controller.js');
const commentService = require('./services/commentService.js'); // 1. Importar o novo serviço
const { logInfo, logError } = require('./utils/logger.js');
@@ -21,7 +21,7 @@ cron.schedule('* * * * *', async () => {
try {
// --- Tarefa 1: Sincronizar criação de tickets ---
logInfo('CRON (Etapa 1/2): Processando criação de tickets...');
- await processaAtendimentos();
+ await processAtendimentos();
logInfo('CRON (Etapa 1/2): Criação de tickets concluída.');
// --- Tarefa 2: Sincronizar comentários ---
diff --git a/src/model/glpiModel.js b/src/model/glpiModel.js
index 2b82ff3..b1b5376 100644
--- a/src/model/glpiModel.js
+++ b/src/model/glpiModel.js
@@ -1,6 +1,6 @@
// src/models/glpiModel.js
const dbConfig = require('../config/dbConfig.js');
-const { logError, logInfo} = require('../utils/logger');
+const { logError, logInfo} = require('../utils/logger.js');
const mysql = require('mysql2/promise');
const pool = mysql.createPool({
@@ -63,7 +63,6 @@ class GlpiModel {
throw error;
}
}
-
static async selectEntityIdCodCliente(id) {
const query = `SELECT id FROM glpi_entities WHERE name LIKE ? LIMIT 1;`;
@@ -85,7 +84,6 @@ class GlpiModel {
throw err;
}
}
-
static async selectEntityIdCodServico(idCliente, idServico) {
const query = `SELECT id FROM glpi_entities WHERE name LIKE ? LIMIT 1;`;
@@ -107,7 +105,6 @@ class GlpiModel {
throw err;
}
}
-
static async insertGroupTickets(glpiTicketId) {
const query = `
INSERT INTO glpi_groups_tickets (tickets_id, groups_id, type)
@@ -122,18 +119,18 @@ class GlpiModel {
logError(`Erro ao Adicionar Grupo Operação NOC: ${err}`);
throw err;
}
+ }
+ static async insertComment(commentData) {
+ const query = `INSERT INTO glpi_itilfollowups(itemtype, items_id, date, users_id, content, date_creation, date_mod) VALUES('Ticket',? , NOW(), ?, ?, NOW(), NOW())`;
+ const values = [commentData.tickets_id, parseInt(process.env.GLPI_USER_ID), commentData.content];
+ try {
+ const [rows] = await pool.query(query, values);
+ return rows && rows.insertId ? { id: rows.insertId } : null;
}
- static async insertComment(commentData) {
- const query = `INSERT INTO glpi_itilfollowups(itemtype, items_id, date, users_id, content, date_creation, date_mod) VALUES('Ticket',? , NOW(), ?, ?, NOW(), NOW())`;
- const values = [commentData.tickets_id, parseInt(process.env.GLPI_USER), commentData.content];
- try {
- const [rows] = await pool.query(query, values);
- return rows && rows.insertId ? { id: rows.insertId } : null;
- }
- catch (err) {
- logError(`Erro ao inserir comentário no GLPI: ${err}`);
- throw err;
- }
+ catch (err) {
+ logError(`Erro ao inserir comentário no GLPI: ${err}`);
+ throw err;
}
+ }
}
module.exports = GlpiModel;
diff --git a/src/model/hubsoftModel.js b/src/model/hubsoftModel.js
index b05cfc1..60b47af 100644
--- a/src/model/hubsoftModel.js
+++ b/src/model/hubsoftModel.js
@@ -1,5 +1,5 @@
const dbConfig = require('../config/dbConfig.js');
-const { logError, logInfo } = require('../utils/logger');
+const { logError, logInfo } = require('../utils/logger.js');
const hubsoftDbConfig = {
host: dbConfig.hubsoft.databaseHost,
diff --git a/src/modules/createTickets/controller/createTickets.controller.js b/src/modules/createTickets/controller/createTickets.controller.js
index de6a0f7..6302906 100644
--- a/src/modules/createTickets/controller/createTickets.controller.js
+++ b/src/modules/createTickets/controller/createTickets.controller.js
@@ -1,46 +1,51 @@
// src/modules/createTickets/controller/createTickets.controller.js
const mundialeService = require('../services/mundiale.service.js');
const implantacaoService = require('../services/implantacao.service.js');
-const appMobileService = require('../services/appMobile.service.js');
+const sacService = require('../services/sac.service.js');
const ticketShared = require('../services/createTickets.service.js');
-const { logInfo } = require('../../utils/logger.js');
+const { logInfo } = require('../../../utils/logger.js');
-async function processaAtendimentos() {
+async function processAtendimentos() {
logInfo("[CONTROLLER] Iniciando processamento");
// 1️⃣ Buscar por fonte
const mundiale = await mundialeService.fetchNew();
+ logInfo(`Encontrados ${mundiale.length} tickets Mundiale para processar.`);
const implantacao = await implantacaoService.fetchNew();
- const app = await appMobileService.fetchNew();
+ logInfo(`Encontrados ${implantacao.length} tickets de Implantação para processar.`);
+ //const sac = await sacService.fetchNew();
// 2️⃣ Salvar no hubglpi
await mundialeService.saveHubGlpi(mundiale);
- await implantacaoService.saveHubglpi(implantacao);
- await appMobileService.saveHubglpi(app);
+ await implantacaoService.saveHubGlpi(implantacao);
+ //await sacService.saveHubGlpi(sac);
// 3️⃣ Buscar pendentes que foram salvos no banco hubglpi
- const pendentes = await ticketShared.buscarPendentesHubglpi();
+ const pendentes = await ticketShared.fetchPendingTickets();
// 4️⃣ Roteamento por tipo
for (const ticket of pendentes) {
-
+
if (ticket.ticket_type === 'MUNDIALE') {
await mundialeService.sendToGlpi(ticket);
} else if (ticket.ticket_type === 'IMPLANTACAO') {
await implantacaoService.sendToGlpi(ticket);
- } else if (ticket.ticket_type === 'APP_MOBILE') {
- await appMobileService.sendToGlpi(ticket);
+ } else if (ticket.ticket_type === 'SAC') {
+ await sacService.sendToGlpi(ticket);
} else {
logInfo(`Tipo desconhecido, ignorando ticket id=${ticket.id}`);
continue;
}
- await ticketShared.marcarComoProcessado(ticket.id);
}
logInfo("[CONTROLLER] Finalizado.");
}
+
+module.exports = { processAtendimentos };
+
+
diff --git a/src/modules/createTickets/services/createTickets.service.js b/src/modules/createTickets/services/createTickets.service.js
index 0fbcadb..c4b98a9 100644
--- a/src/modules/createTickets/services/createTickets.service.js
+++ b/src/modules/createTickets/services/createTickets.service.js
@@ -1,17 +1,18 @@
// src/modules/createTickets/services/createTickets.service.js
const repositoryHubGlpi = require('../../../shared/repositories/hubglpi.repository.js');
+const repositoryGlpi = require('../../../shared/repositories/glpi.repository.js');
// --------------------------------------
// Funções principais do serviço
// --------------------------------------
-async function fetcPendingTickets() {
+async function fetchPendingTickets() {
return repositoryHubGlpi.fetchPendingTickets();
}
-async function resolveEntityId(ticketData, glpiModel) {
+async function resolveEntityId(ticketData) {
- const entityByService = await glpiModel.selectEntityIdCodServico(
+ const entityByService = await repositoryGlpi.getEntitiesByService(
ticketData.codigo_cliente,
ticketData.codigo_servico
);
@@ -21,8 +22,7 @@ async function resolveEntityId(ticketData, glpiModel) {
return ticketData;
}
- // Tenta entidade pelo cliente
- const entityByClient = await glpiModel.selectEntityIdCodCliente(
+ const entityByClient = await repositoryGlpi.getEntitiesByClient(
ticketData.codigo_cliente
);
@@ -31,14 +31,30 @@ async function resolveEntityId(ticketData, glpiModel) {
return ticketData;
}
- // Fallback
ticketData.entities_id = 0;
return ticketData;
}
+// Funcao para definir ticket como processado
+async function setAsCreated(dataTicket) {
+
+}
+
+
+//Cria uma nova entidade no GLPI
+async function createEntity(ticketData) {
+
+ const entity_name = `${ticketData.codigo_cliente} - ${ticketData.nome_razao_social}`;
+
+ await repositoryGlpi.insertEntity(entity_name);
+
+ return;
+}
module.exports = {
- fetcPendingTickets,
- resolveEntityId
+ fetchPendingTickets,
+ resolveEntityId,
+ setAsCreated,
+ createEntity
}
\ No newline at end of file
diff --git a/src/modules/createTickets/services/implantacao.service.js b/src/modules/createTickets/services/implantacao.service.js
index e69de29..446a21a 100644
--- a/src/modules/createTickets/services/implantacao.service.js
+++ b/src/modules/createTickets/services/implantacao.service.js
@@ -0,0 +1,254 @@
+// src/modules/createTickets/services/mundiale.service.js
+const repositoryHubGlpi = require('../../../shared/repositories/hubglpi.repository.js');
+const repositoryGlpi = require('../../../shared/repositories/glpi.repository.js');
+const repositoryHubsoft = require('../../../shared/repositories/hubsoft.repository.js');
+const modelHubGlpi = require('../../../shared/model/hubglpi.model.js');
+const modelGlpi = require('../../../shared/model/glpi.model.js');
+const ticketShared = require('./createTickets.service.js');
+const { logInfo, logWarning } = require('../../../utils/logger.js');
+
+// --------------------------------------
+// Funções principais do serviço
+// --------------------------------------
+
+async function fetchNew() {
+ return repositoryHubsoft.getImplantacaoTickets();
+}
+
+async function saveHubGlpi(tickets) {
+ if (!tickets.length) return;
+
+ const ticketsFormatted = tickets.map(ticket =>
+ modelHubGlpi.mapHubsoftToHubglpi(ticket, 'IMPLANTACAO')
+ );
+
+ const inserted = await repositoryHubGlpi.insertTickets(ticketsFormatted);
+
+ if (inserted) {
+ await repositoryHubGlpi.insertSyncData(
+ ticketsFormatted.map(ticket => ticket.id_atendimento)
+ );
+ }
+
+ return inserted;
+}
+
+async function sendToGlpi(ticket) {
+
+ const ticketsResolved = await ticketShared.resolveEntityId(ticket);
+
+ if (ticketsResolved.entities_id === 0) {
+ logWarning(`Entidade não encontrada para o ticket id=${ticket.id_atendimento}.`);
+ }
+
+ formatGlpiPayload(ticketsResolved);
+
+ const payload = modelGlpi.mapHubGlpiToGlpi(ticketsResolved);
+
+ const glpiId = await repositoryGlpi.insertTicket(payload);
+ logInfo(`Ticket GLPI criado com ID=${glpiId} para o ticket id=${ticket.id_atendimento}.`);
+
+ await repositoryGlpi.insertGroupTicket(glpiId);
+ await repositoryHubGlpi.updateSyncDataCreated(ticket.id_atendimento, glpiId);
+}
+
+
+// --------------------------------------
+// Formatar dados antes de enviar para o GLPI
+// --------------------------------------
+
+function formatGlpiPayload(ticket) {
+ const title = `IMPLANTAÇÃO - ${ticket.codigo_cliente}-${ticket.codigo_servico}-${ticket.cliente_nome} - ${ticket.servico_nome}`;
+ const description = formatDescription(ticket);
+ ticket.name = title;
+ ticket.content = description;
+ return;
+}
+
+
+// --------------------------------------
+// Dicionário de Serviços
+// --------------------------------------
+
+const serviceDictionary = {
+ // ---------- LAN-TO-LAN ----------
+ "Lan-to-Lan 50 Mbps": { produto: "Lan-to-Lan", qtd: 1, descricao: "50 Mbps" },
+ "Lan-to-Lan 100 Mbps": { produto: "Lan-to-Lan", qtd: 1, descricao: "100 Mbps" },
+ "Lan-to-Lan 200 Mbps": { produto: "Lan-to-Lan", qtd: 1, descricao: "200 Mbps" },
+ "Lan-to-Lan 300 Mbps": { produto: "Lan-to-Lan", qtd: 1, descricao: "300 Mbps" },
+ "Lan-to-Lan 500 Mbps": { produto: "Lan-to-Lan", qtd: 1, descricao: "500 Mbps" },
+ "Lan-to-Lan 700 Mbps": { produto: "Lan-to-Lan", qtd: 1, descricao: "700 Mbps" },
+ "Lan-to-Lan": { produto: "Lan-to-Lan", qtd: 1, descricao: null },
+
+ // ---------- LINK DEDICADO ----------
+ "Link de Internet Dedicado 20 Mbps Full Duplex":
+ { produto: "Link de Internet Dedicado", qtd: 1, descricao: "20 Mbps Full Duplex" },
+
+ "Link de Internet Dedicado 100 Mbps Full Duplex":
+ { produto: "Link de Internet Dedicado", qtd: 1, descricao: "100 Mbps Full Duplex" },
+
+ "Link de Internet Dedicado 1Gbps Full Duplex":
+ { produto: "Link de Internet Dedicado", qtd: 1, descricao: "1 Gbps Full Duplex" },
+
+ "Link de Internet Dedicado 2 Gbps Full Duplex":
+ { produto: "Link de Internet Dedicado", qtd: 1, descricao: "2 Gbps Full Duplex" },
+
+ // Default genérico caso venha coisa nova
+};
+
+
+// --------------------------------------
+// Tabela HTML da descrição
+// --------------------------------------
+
+const formatDescription = (ticket) => {
+
+ const documentoFormatado = formatDocument(ticket.cpf_cnpj, ticket.tipo_pessoa);
+ const docLabel = ticket.tipo_pessoa === "pf" ? "CPF" : "CNPJ";
+ const servico = resolveService(ticket.servico_nome);
+
+ return `
+
+
+
+
+ |
+ Dados Comercial
+ |
+
+
+
+ | Nº de Operação |
+ ${ticket.protocolo_hub || "N/A"} |
+
+
+
+ | Gerente Responsável |
+ ${ticket.usuario_que_abriu || "N/A"} |
+
+
+
+ | Código do Cliente |
+ ${ticket.codigo_cliente} |
+
+
+
+
+ |
+ Dados Cliente
+ |
+
+
+
+ | Cliente |
+ ${ticket.cliente_nome} |
+
+
+
+ | ${docLabel} |
+ ${documentoFormatado} |
+
+
+
+ | Nome Contato |
+ ${ticket.nome_razaosocial || "N/A"} |
+
+
+
+ | Email Contato |
+ ${ticket.email || "N/A"} |
+
+
+
+ | Telefone Contato |
+ ${ticket.telefone || "N/A"} |
+
+
+
+ | Endereço Instalação |
+ ${ticket.endereco || "N/A"} |
+
+
+
+
+ |
+ Dados do Serviço Contratado
+ |
+
+
+
+
+
+
+ | Produto |
+ Quantidade |
+ Descrição |
+
+
+ | ${servico.produto} |
+ ${servico.qtd} |
+ ${servico.descricao || ""} |
+
+
+ |
+
+
+
+
+ |
+ Observações
+ |
+
+
+
+ | ${ticket.descricao_abertura || "N/A"} |
+
+
+
+ `;
+};
+
+
+
+// --------------------------------------
+// Formatadores de Documento
+// --------------------------------------
+
+function formatCPF(cpf) {
+ cpf = cpf.replace(/\D/g, "");
+ return cpf.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, "$1.$2.$3-$4");
+}
+
+function formatCNPJ(cnpj) {
+ cnpj = cnpj.replace(/\D/g, "");
+ return cnpj.replace(/(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})/, "$1.$2.$3/$4-$5");
+}
+
+function formatDocument(doc, tipo) {
+ if (!doc) return "N/A";
+ return tipo === "pf" ? formatCPF(doc) : formatCNPJ(doc);
+}
+
+
+// --------------------------------------
+// Resolve Serviço
+// --------------------------------------
+
+function resolveService(servicoNome) {
+ return serviceDictionary[servicoNome] || {
+ produto: servicoNome,
+ qtd: 1,
+ descricao: null
+ };
+}
+
+
+// --------------------------------------
+// Exportação
+// --------------------------------------
+
+module.exports = {
+ fetchNew,
+ saveHubGlpi,
+ sendToGlpi
+};
diff --git a/src/modules/createTickets/services/mundiale.service.js b/src/modules/createTickets/services/mundiale.service.js
index 81d6b12..8d083d5 100644
--- a/src/modules/createTickets/services/mundiale.service.js
+++ b/src/modules/createTickets/services/mundiale.service.js
@@ -1,11 +1,12 @@
// src/modules/createTickets/services/mundiale.service.js
const repositoryHubGlpi = require('../../../shared/repositories/hubglpi.repository.js');
-const repositoryGlpi = require('../../../repositories/glpi.repository.js');
+const repositoryGlpi = require('../../../shared/repositories/glpi.repository.js');
const repositoryHubsoft = require('../../../shared/repositories/hubsoft.repository.js');
const modelHubGlpi = require('../../../shared/model/hubglpi.model.js');
const modelGlpi = require('../../../shared/model/glpi.model.js');
const ticketShared = require('./createTickets.service.js');
const { logInfo, logError, logWarning } = require('../../../utils/logger.js');
+const { log } = require('winston');
// --------------------------------------
// Funções principais do serviço
@@ -31,18 +32,36 @@ async function saveHubGlpi(tickets) {
async function sendToGlpi(ticket) {
- const ticketsResolved = await ticketShared.resolveEntityId(ticket, modelGlpi);
+ const ticketsResolved = await ticketShared.resolveEntityId(ticket);
- const formattedTickets = formatGlpiPayload(ticketsResolved);
+ formatGlpiPayload(ticketsResolved);
- const payload = modelGlpi.mapHubGlpiToGlpi(formattedTickets);
+ const payload = modelGlpi.mapHubGlpiToGlpi(ticketsResolved);
+
+ const glpiId = await repositoryGlpi.insertTicket(payload);
+ logInfo(`Ticket GLPI criado com ID: ${glpiId} para ticket Hubsoft ID: ${ticket.id_atendimento}`);
+
+ await repositoryGlpi.insertGroupTicket(glpiId);
+ logInfo(`Grupo padrão atribuído ao ticket GLPI ID: ${glpiId}`);
+
+ await repositoryHubGlpi.updateSyncDataCreated(ticket.id_atendimento, glpiId);
+ logInfo(`Ticket HubGlpi ID: ${ticket.id_atendimento} marcado como criado no Banco intermediario com ID: ${glpiId}`);
- const glpiId = await repositoryGlpi.insertTickets([payload]);
-
- await repositoryHubGlpi.updateSyncDataCreated(ticket.id_atendimento, glpiId[0]);
-
}
+// --------------------------------------
+// Mapeamento e formatação de dados
+// --------------------------------------
+
+
+const statusAtendimentoGLPI = {
+ 'Novo': 1,
+ 'Pendente': 4,
+ 'Em atendimento': 2,
+ 'Resolvido': 5
+};
+
+
// --------------------------------------
// Formatar dados antes de enviar para o GLPI
@@ -50,22 +69,14 @@ async function sendToGlpi(ticket) {
function formatGlpiPayload(ticket) {
- const statusTexto = statusAtendimentoHubGlpi[ticket.status_atendimento] || 'Novo';
- const statusGlpi = statusAtendimentoGLPI[statusTexto] || 1;
+ ticket.status = statusAtendimentoGLPI[ticket.status_atendimento] || 1;
- const categoria = categoriaGLPI[ticket.servico_nome] || 0;
+ ticket.name = `Mundiale - Protocolo: ${ticket.ticket_mundiale} - ${ticket.cliente_nome}`;
- const title = `[Mundiale] ${ticket.cliente_nome} - ${ticket.servico_nome} - ${ticket.ticket_mundiale}`;
+ ticket.content = formatDescription(ticket);
- const description = formatDescription(ticket);
- return {
- name: title,
- content: description,
- status: statusGlpi,
- itilcategories_id: categoria,
- created_at: ticket.created_at,
- };
+ return;
}
diff --git a/src/scripts/data/database.sql b/src/scripts/data/database.sql
index 795b68d..503a257 100644
--- a/src/scripts/data/database.sql
+++ b/src/scripts/data/database.sql
@@ -89,7 +89,18 @@ INSERT INTO sync_control (job_name, last_run_timestamp) VALUES ('hubsoft_comment
-- ALTERAÇÕES NA TABELA hubsoft_tickets
-- =============================================
ALTER TABLE hubsoft_tickets
-ADD COLUMN ticket_type VARCHAR(50) NOT NULL DEFAULT 'MUNDIALE';
+ADD COLUMN ticket_type VARCHAR(50) NOT NULL DEFAULT 'MUNDIALE',
+ADD COLUMN ticket_type VARCHAR(50),
+ADD COLUMN descricao_abertura TEXT;
+ADD COLUMN endereco TEXT,
+ADD COLUMN telefone VARCHAR(25),
+ADD COLUMN cpf_cnpj VARCHAR(30),
+ADD COLUMN tipo_pessoa CHAR(2),
+ADD COLUMN email VARCHAR(150),
+ADD COLUMN nome_razaosocial VARCHAR(255);;
ALTER TABLE hubsoft_tickets
ADD CONSTRAINT hubsoft_id_atendimento_unique UNIQUE (id_atendimento);
+
+
+
diff --git a/src/shared/infra/database/glpi.pool.js b/src/shared/infra/database/glpi.pool.js
new file mode 100644
index 0000000..b330413
--- /dev/null
+++ b/src/shared/infra/database/glpi.pool.js
@@ -0,0 +1,17 @@
+// src/shared/infra/database/glpi.pool.js
+// MySQL / MariaDB - GLPI
+const mysql = require('mysql2/promise');
+const { Pool } = require('pg');
+
+const pool = mysql.createPool({
+ host: process.env.GLPI_DB_HOST,
+ port: process.env.GLPI_DB_PORT,
+ user: process.env.GLPI_DB_USER,
+ password: process.env.GLPI_DB_PASSWORD,
+ database: process.env.GLPI_DB_NAME,
+ waitForConnections: true,
+ connectionLimit: 20,
+ queueLimit: 0,
+});
+
+module.exports = pool;
diff --git a/src/shared/infra/database/hubglpi.pool.js b/src/shared/infra/database/hubglpi.pool.js
new file mode 100644
index 0000000..45af961
--- /dev/null
+++ b/src/shared/infra/database/hubglpi.pool.js
@@ -0,0 +1,15 @@
+// src/shared/infra/database/hubglpi.pool.js
+// PostgreSQL - HUBSOFT
+const { Pool } = require("pg");
+
+const hubglpiPool = new Pool({
+ host: process.env.HUBGLPI_DB_HOST,
+ port: process.env.HUBGLPI_DB_PORT,
+ user: process.env.HUBGLPI_DB_USER,
+ password: process.env.HUBGLPI_DB_PASSWORD,
+ database: process.env.HUBGLPI_DB_NAME,
+ max: 20,
+ idleTimeoutMillis: 30000,
+});
+
+module.exports = hubglpiPool;
diff --git a/src/shared/infra/database/hubsoft.pool.js b/src/shared/infra/database/hubsoft.pool.js
new file mode 100644
index 0000000..5c38f07
--- /dev/null
+++ b/src/shared/infra/database/hubsoft.pool.js
@@ -0,0 +1,14 @@
+// PostgreSQL - HUBSOFT
+const { Pool } = require("pg");
+
+const hubsoftPool = new Pool({
+ host: process.env.HUBSOFT_DATABASE_HOST,
+ port: process.env.HUBSOFT_DATABASE_PORT,
+ user: process.env.HUBSOFT_DATABASE_USER,
+ password: process.env.HUBSOFT_DATABASE_PASSWORD,
+ database: process.env.HUBSOFT_DATABASE_NAME,
+ max: 20,
+ idleTimeoutMillis: 30000,
+});
+
+module.exports = hubsoftPool;
diff --git a/src/shared/infra/database/index.js b/src/shared/infra/database/index.js
new file mode 100644
index 0000000..1821b4b
--- /dev/null
+++ b/src/shared/infra/database/index.js
@@ -0,0 +1,7 @@
+// src/shared/infra/database/index.js
+
+module.exports = {
+ hubsoft: require("./hubsoft.pool"),
+ hubglpi: require("./hubglpi.pool"),
+ glpi: require("./glpi.pool")
+};
diff --git a/src/shared/model/glpi.model.js b/src/shared/model/glpi.model.js
index 01db487..ddd0f0c 100644
--- a/src/shared/model/glpi.model.js
+++ b/src/shared/model/glpi.model.js
@@ -5,15 +5,16 @@ function mapHubGlpiToGlpi(ticket) {
entities_id: ticket.entities_id || 0,
name: ticket.name,
date: ticket.created_at,
- date_mod: Now(),
- status: defineStatusGlpi(ticket.status_atendimento),
- users_id_recipient: process.env.GLPI_USER_ID || 0,
+ status: defineStatusGlpi(ticket.status),
+ users_id_recipient: parseInt(process.env.GLPI_USER_ID) || 0,
content: ticket.content,
urgency: 3,
impact: 3,
priority: 3,
type: 2,
- date_creation : ticket.date_creation || Now(),
+ requesttypes_id: 2,
+ date_creation : ticket.date_creation || new Date(),
+ itilcategories_id: 1,
slas_id_ttr: 37
};
}
@@ -26,7 +27,7 @@ function defineStatusGlpi(Status) {
'Resolvido': 5
};
- return mapStatusDBtoGLPI[Status] || 'Novo';
+ return mapStatusDBtoGLPI[Status] || 1;
};
diff --git a/src/shared/model/hubglpi.model.js b/src/shared/model/hubglpi.model.js
index a3bba71..b6c0069 100644
--- a/src/shared/model/hubglpi.model.js
+++ b/src/shared/model/hubglpi.model.js
@@ -1,33 +1,99 @@
// src/shared/model/hubglpi.model.js
function mapHubsoftToHubglpi(ticket, type) {
- return {
+ return {
id_atendimento: ticket.id_atendimento,
codigo_cliente: ticket.codigo_cliente,
status_atendimento: defineStatusHubglpi(ticket.id_atendimento_status),
servico_nome: ticket.descricao,
protocolo_hub: ticket.protocolo,
- ticket_mundiale: parseInt(ticket.descricao_abertura.replace(/[^0-9]/g, ''))|| null,
+
+ // Extrai número do protocolo do Mundiale
+ ticket_mundiale: extractMundiale(ticket.descricao_abertura, type),
+
codigo_servico: ticket.id_cliente_servico,
cliente_nome: ticket.nome_contato,
descricao_fechamento: ticket.descricao_fechamento || null,
data_fechamento: ticket.data_fechamento || null,
created_at: ticket.data_cadastro,
- ticket_type: type
+ ticket_type: type,
+ descricao_abertura: ticket.descricao_abertura || null,
+ endereco: endereco(ticket),
+ telefone: sanitizePhone(ticket.telefone),
+
+ cpf_cnpj: sanitizeCpfCnpj(ticket.cpf_cnpj),
+
+ tipo_pessoa: ticket.tipo_pessoa || null,
+ email: ticket.email || null,
+ nome_razaosocial: ticket.nome_razaosocial || null
};
}
+/* -----------------
+ Sanitização
+------------------ */
+
+function sanitizeCpfCnpj(value) {
+ if (!value) return null;
+
+ // Se vier número gigantesco do JS tipo 3.2e+22 → converte pra string
+ const str = String(value);
+
+ // Remove qualquer coisa que não seja número
+ const clean = str.replace(/\D/g, "");
+
+ return clean.length > 0 ? clean : null;
+}
+
+function sanitizePhone(phone) {
+ if (!phone) return null;
+ const clean = String(phone).replace(/\D/g, "");
+ return clean || null;
+}
+
+function extractMundiale(descricao, type) {
+ if (type === 'IMPLANTACAO') return null;
+
+ if (!descricao) return null;
+
+ // Extrai apenas dígitos
+ const num = descricao.replace(/\D/g, "");
+
+ // Previne NaN
+ return num ? parseInt(num, 10) : null;
+}
+
+/* -----------------
+ Endereço
+------------------ */
+
+function endereco(ticket) {
+ if (!ticket.endereco || !ticket.numero || !ticket.cidade || !ticket.estado) {
+ return null;
+ }
+
+ const complemento = ticket.complemento ? ` - ${ticket.complemento}` : "";
+ const bairro = ticket.bairro ? `${ticket.bairro}` : "";
+ const cep = ticket.cep ? ticket.cep : "";
+
+ return `${ticket.endereco}, ${ticket.numero}${complemento}, ${bairro} - ${ticket.cidade}/${ticket.estado} - CEP ${cep}`;
+}
+
+/* -----------------
+ Status Mapper
+------------------ */
+
function defineStatusHubglpi(hubsoftStatus) {
const statusMap = {
- 1: 'Pendente',
- 2: 'Em atendimento',
- 3: 'Resolvido',
- 31: 'Pendente',
- 32: 'Pendente',
- 33: 'Novo'
- }
- return statusMap[hubsoftStatus] || 'Novo';
-};
+ 1: "Pendente",
+ 2: "Em atendimento",
+ 3: "Resolvido",
+ 31: "Pendente",
+ 32: "Pendente",
+ 33: "Novo"
+ };
+ return statusMap[hubsoftStatus] || "Novo";
+}
module.exports = {
mapHubsoftToHubglpi
diff --git a/src/shared/repositories/glpi.repository.js b/src/shared/repositories/glpi.repository.js
index 627659c..6eac3fd 100644
--- a/src/shared/repositories/glpi.repository.js
+++ b/src/shared/repositories/glpi.repository.js
@@ -1,40 +1,86 @@
// src/shared/repositories/glpi.repository.js
-const db = require('../../../config/database.js');
+const { glpi } = require("../../shared/infra/database");
const { logInfo, logError } = require('../../utils/logger.js');
-async function insertTickets(tickets) {
-
- const values = tickets.map(t => [
- t.status,
- t.content,
- t.users_id_recipient,
- t.entities_id,
- t.type,
- t.requesttypes_id,
- t.urgency,
- t.impact,
- t.priority,
- t.date,
- t.name
- ]);
-
- const placeholders = values
- .map(() => "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
- .join(",");
-
+async function insertTicket(ticket) {
const sql = `
INSERT INTO glpi_tickets
- (status, content, users_id_recipient, entities_id, type, requesttypes_id,
- urgency, impact, priority, date, name)
- VALUES ${placeholders}
+ (entities_id, name, date, date_mod, status, users_id_recipient, content, urgency, impact, priority, type, itilcategories_id, date_creation, slas_id_ttr)
+ VALUES (?, ?, ?, NOW(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`;
- const result = await mariadb.execute(sql, values.flat());
+ const values = [
+ ticket.entities_id,
+ ticket.name,
+ ticket.date,
+ ticket.status,
+ ticket.users_id_recipient,
+ ticket.content,
+ ticket.urgency,
+ ticket.impact,
+ ticket.priority,
+ ticket.type,
+ ticket.itilcategories_id,
+ ticket.date_creation,
+ ticket.slas_id_ttr
+ ];
- return result.insertId ? [result.insertId] : [];
+ const [result] = await glpi.execute(sql, values);
+ return result.insertId;
}
+async function getEntitiesByService(codigoCliente, codigoServico) {
+ try {
+ const sql = `SELECT id FROM glpi_entities WHERE name LIKE ? or name LIKE ? or name LIKE ? LIMIT 1;`;
+ const values = [`${codigoCliente}-${codigoServico}-%`, `${codigoCliente} -${codigoServico}-%`, `${codigoCliente} - ${codigoServico} -%`];
+ const [rows] = await glpi.execute(sql, values);
+ if (rows.length > 0) {
+ return rows[0].id;
+ }
+ return null;
+ } catch (error) {
+ logError(`Erro ao buscar entidade por código de serviço: ${error}`);
+ throw error;
+ }
+}
+
+async function getEntitiesByClient(codigoCliente) {
+ try {
+ const sql = `SELECT id FROM glpi_entities WHERE name LIKE ? or name LIKE ? LIMIT 1;`;
+ const values = [`${codigoCliente}-%`, `${codigoCliente} -%`];
+ const [rows] = await glpi.execute(sql, values);
+ if (rows.length > 0) {
+ return rows[0].id;
+ }
+ return null;
+ } catch (error) {
+ logError(`Erro ao buscar entidade por código de cliente: ${error}`);
+ throw error;
+ }
+}
+
+async function insertEntity(entity_name){
+
+}
+
+async function insertGroupTicket(ticketId) {
+ try {
+ const sql = ` INSERT INTO glpi_groups_tickets (tickets_id, groups_id, type)
+ VALUES (?, 25, 2)
+ `;
+ const values = [ticketId];
+ await glpi.execute(sql, values);
+ logInfo(`Grupo associado ao ticket GLPI ID: ${ticketId}`);
+ } catch (error) {
+ logError(`Erro ao associar grupo ao ticket GLPI ID ${ticketId}: ${error}`);
+ throw error;
+ }
+
+}
module.exports = {
- insertTickets
+ insertTicket,
+ getEntitiesByService,
+ getEntitiesByClient,
+ insertGroupTicket
};
\ No newline at end of file
diff --git a/src/shared/repositories/hubglpi.repository.js b/src/shared/repositories/hubglpi.repository.js
index 1525019..61c7e5c 100644
--- a/src/shared/repositories/hubglpi.repository.js
+++ b/src/shared/repositories/hubglpi.repository.js
@@ -1,92 +1,125 @@
// src/shared/repositories/hubglpi.repository.js
-const { get } = require('pm2');
-const db = require('../../../config/database.js');
-const { logInfo, logError } = require('../../utils/logger.js');
-const { query } = require('winston');
-const { hubsoft } = require('../../config/dbConfig.js');
+
+const { hubglpi } = require("../../shared/infra/database");
+const { logInfo, logError } = require("../../utils/logger.js");
async function insertTickets(tickets) {
- try {
- const values = tickets.map(t => [
- t.id_atendimento,
- t.codigo_cliente,
- t.status_atendimento,
- t.servico_nome,
- t.protocolo_hub,
- t.ticket_mundiale,
- t.codigo_servico,
- t.cliente_nome,
- t.descricao_fechamento,
- t.data_fechamento,
- t.created_at,
- t.updated_at,
- t.ticket_type
- ]);
+ try {
+ const values = tickets.map(t => [
+ t.id_atendimento,
+ t.codigo_cliente,
+ t.status_atendimento,
+ t.servico_nome,
+ t.protocolo_hub,
+ t.ticket_mundiale,
+ t.codigo_servico,
+ t.cliente_nome,
+ t.descricao_fechamento,
+ t.data_fechamento,
+ t.created_at,
+ t.updated_at,
+ t.ticket_type,
+ t.descricao_abertura,
+ t.endereco,
+ t.telefone,
+ t.cpf_cnpj,
+ t.tipo_pessoa,
+ t.email,
+ t.nome_razaosocial
+ ]);
- const rowPlaceholders = values
- .map(
- (_, i) =>
- `(${Array(13)
- .fill(0)
- .map((_, j) => `$${i * 13 + j + 1}`)
- .join(", ")})`
- )
- .join(", ");
+ const totalColumns = 20;
- const query = `
- INSERT INTO hubsoft_tickets
- (id_atendimento, codigo_cliente, status_atendimento, servico_nome, protocolo_hub, ticket_mundiale,
- codigo_servico, cliente_nome, descricao_fechamento, data_fechamento, created_at, updated_at, type)
- VALUES ${rowPlaceholders}
- ON CONFLICT (id_atendimento)
- DO UPDATE SET
- codigo_cliente = EXCLUDED.codigo_cliente,
- status_atendimento = EXCLUDED.status_atendimento,
- servico_nome = EXCLUDED.servico_nome,
- protocolo_hub = EXCLUDED.protocolo_hub,
- ticket_mundiale = EXCLUDED.ticket_mundiale,
- codigo_servico = EXCLUDED.codigo_servico,
- cliente_nome = EXCLUDED.cliente_nome,
- descricao_fechamento = EXCLUDED.descricao_fechamento,
- data_fechamento = EXCLUDED.data_fechamento,
- updated_at = EXCLUDED.updated_at,
- type = EXCLUDED.type
- `;
+ const rowPlaceholders = values
+ .map(
+ (_, rowIndex) =>
+ `(${Array.from({ length: totalColumns })
+ .map((_, colIndex) => `$${rowIndex * totalColumns + colIndex + 1}`)
+ .join(", ")})`
+ )
+ .join(", ");
- const flattened = values.flat();
+ const query = `
+ INSERT INTO public.hubsoft_tickets
+ (
+ id_atendimento,
+ codigo_cliente,
+ status_atendimento,
+ servico_nome,
+ protocolo_hub,
+ ticket_mundiale,
+ codigo_servico,
+ cliente_nome,
+ descricao_fechamento,
+ data_fechamento,
+ created_at,
+ updated_at,
+ ticket_type,
+ descricao_abertura,
+ endereco,
+ telefone,
+ cpf_cnpj,
+ tipo_pessoa,
+ email,
+ nome_razaosocial
+ )
+ VALUES ${rowPlaceholders}
+ ON CONFLICT (id_atendimento)
+ DO UPDATE SET
+ codigo_cliente = EXCLUDED.codigo_cliente,
+ status_atendimento = EXCLUDED.status_atendimento,
+ servico_nome = EXCLUDED.servico_nome,
+ protocolo_hub = EXCLUDED.protocolo_hub,
+ ticket_mundiale = EXCLUDED.ticket_mundiale,
+ codigo_servico = EXCLUDED.codigo_servico,
+ cliente_nome = EXCLUDED.cliente_nome,
+ descricao_fechamento = EXCLUDED.descricao_fechamento,
+ data_fechamento = EXCLUDED.data_fechamento,
+ updated_at = EXCLUDED.updated_at,
+ ticket_type = EXCLUDED.ticket_type,
+ descricao_abertura = EXCLUDED.descricao_abertura,
+ endereco = EXCLUDED.endereco,
+ telefone = EXCLUDED.telefone,
+ cpf_cnpj = EXCLUDED.cpf_cnpj,
+ tipo_pessoa = EXCLUDED.tipo_pessoa,
+ email = EXCLUDED.email,
+ nome_razaosocial = EXCLUDED.nome_razaosocial
+ `;
- await db.query(query, flattened);
+ const flattened = values.flat();
- return { success: true, ids: tickets.map(t => t.id_atendimento) };
+ await hubglpi.query(query, flattened);
- } catch (error) {
- logError("Erro ao inserir tickets no HubGLPI:", error);
- throw error;
- }
+ logInfo(`Tickets salvos/atualizados: ${tickets.length}`);
+
+ return { success: true, ids: tickets.map(t => t.id_atendimento) };
+
+ } catch (error) {
+ logError("Erro ao inserir tickets no HubGLPI:", error);
+ throw error;
+ }
}
async function insertSyncData(ids) {
try {
- const values = ids.map(id => [id]);
-
- const rowPlaceholders = values
+ const rowPlaceholders = ids
.map((_, i) => `($${i + 1})`)
.join(", ");
-
+
const query = `
- INSERT INTO hubsoft_sync_data (hubsoft_ticket_id)
+ INSERT INTO sync_data (hubsoft_ticket_id)
VALUES ${rowPlaceholders}
- ON CONFLICT (hubsoft_ticket_id) DO UPDATE SET
- hubsoft_ticket_id = $1
+ ON CONFLICT (hubsoft_ticket_id)
+ DO UPDATE SET hubsoft_ticket_id = EXCLUDED.hubsoft_ticket_id
`;
- const flattened = ids;
+ await hubglpi.query(query, ids);
- await db.query(query, flattened);
+ logInfo(`Sync data criada/atualizada para ${ids.length} tickets.`);
return true;
- }
- catch (error) {
+
+ } catch (error) {
logError("Erro ao inserir dados de sincronização no HubGLPI:", error);
throw error;
}
@@ -94,39 +127,79 @@ async function insertSyncData(ids) {
async function fetchPendingTickets() {
try {
- const query = `SELECT ht.id_atendimento, ht.codigo_cliente, ht.status_atendimento, ht.codigo_servico, ht.servico_nome, ht.protocolo_hub, ht.ticket_mundiale, ht.cliente_nome, ht.created_at, sd.id AS sync_data_id, sd.glpi_ticket_id, sd.status_sync, sd.sync_metadata, sd.last_sync_attempt, sd.sync_error_message, sd.created_at AS sync_created_at, sd.updated_at AS sync_updated_at, ht.ticket_type as ticket_type
- FROM hubsoft_tickets AS ht
- LEFT JOIN sync_data AS sd ON ht.id_atendimento = sd.hubsoft_ticket_id
- WHERE sd.status_sync IS NULL OR sd.status_sync = 'pending_create'
- ORDER BY ht.created_at ASC;`
- const result = await db.query(query);
- return result.rows
+ const query = `
+ SELECT
+ ht.id_atendimento,
+ ht.codigo_cliente,
+ ht.status_atendimento,
+ ht.codigo_servico,
+ ht.servico_nome,
+ ht.protocolo_hub,
+ ht.ticket_mundiale,
+ ht.cliente_nome,
+ ht.created_at,
+ ht.ticket_type,
+
+ -- NOVOS CAMPOS
+ ht.descricao_abertura,
+ ht.endereco,
+ ht.telefone,
+ ht.cpf_cnpj,
+ ht.tipo_pessoa,
+ ht.email,
+ ht.nome_razaosocial,
+
+ -- CAMPOS DA SYNC_DATA
+ sd.id AS sync_data_id,
+ sd.glpi_ticket_id,
+ sd.status_sync,
+ sd.sync_metadata,
+ sd.last_sync_attempt,
+ sd.sync_error_message,
+ sd.created_at AS sync_created_at,
+ sd.updated_at AS sync_updated_at
+
+ FROM hubsoft_tickets AS ht
+ LEFT JOIN sync_data AS sd
+ ON ht.id_atendimento = sd.hubsoft_ticket_id
+ WHERE sd.status_sync IS NULL
+ OR sd.status_sync = 'pending_create'
+ ORDER BY ht.created_at ASC;
+ `;
+
+ const result = await hubglpi.query(query);
+ return result.rows;
+
} catch (error) {
logError("Erro ao buscar tickets pendentes no HubGLPI:", error);
throw error;
}
}
+
async function updateSyncDataCreated(hubsoftTicketId, glpiId) {
- const sql = `
- UPDATE sync_data
- SET
- status_sync = 'created_glpi',
- updated_at = NOW(),
- last_sync_attempt = NOW(),
- glpi_ticket_id = ?
- WHERE hubsoft_ticket_id = ?
- `;
+ try {
+ const sql = `
+ UPDATE sync_data
+ SET
+ status_sync = 'created_glpi',
+ updated_at = NOW(),
+ last_sync_attempt = NOW(),
+ glpi_ticket_id = $1
+ WHERE hubsoft_ticket_id = $2
+ `;
- await db.query(sql, [glpiId, hubsoftTicketId]);
+ await hubglpi.query(sql, [glpiId, hubsoftTicketId]);
+
+ } catch (error) {
+ logError("Erro ao atualizar sync_data para ticket criado no GLPI:", error);
+ throw error;
+ }
}
-
-
-
module.exports = {
insertTickets,
insertSyncData,
fetchPendingTickets,
updateSyncDataCreated
-};
\ No newline at end of file
+};
diff --git a/src/shared/repositories/hubsoft.repository.js b/src/shared/repositories/hubsoft.repository.js
index ab2276e..44b2b52 100644
--- a/src/shared/repositories/hubsoft.repository.js
+++ b/src/shared/repositories/hubsoft.repository.js
@@ -1,6 +1,6 @@
// src/shared/repositories/hubsoft.repository.js
const { get } = require('pm2');
-const db = require('../../../config/database.js');
+const { hubsoft } = require("../../shared/infra/database");
const { logInfo, logError } = require('../../utils/logger.js');
@@ -8,7 +8,7 @@ async function getMundialeTickets() {
try {
const query = `SELECT a.id_atendimento, a.id_usuario_abertura, a.id_atendimento_status, a.protocolo, a.descricao_abertura, a.data_cadastro, a.nome_contato, c.codigo_cliente, s.descricao, cs.id_cliente_servico FROM atendimento AS a INNER JOIN cliente_servico AS cs ON a.id_cliente_servico = cs.id_cliente_servico INNER JOIN cliente AS c ON cs.id_cliente = c.id_cliente INNER JOIN servico AS s ON cs.id_servico = s.id_servico WHERE a.id_tipo_atendimento = 4 AND a.id_usuario_abertura = 248 AND a.id_atendimento_status IN (1, 2, 33) AND s.ativo = true;`;
- const { rows } = await db.query(query);
+ const { rows } = await hubsoft.query(query);
return rows;
} catch (error) {
logError("Erro ao buscar tickets Mundiale:", error);
@@ -18,8 +18,67 @@ async function getMundialeTickets() {
async function getImplantacaoTickets() {
try {
- const query = `SELECT a.id_atendimento, a.id_usuario_abertura, a.id_atendimento_status, a.protocolo, a.descricao_abertura, a.data_cadastro, a.nome_contato, c.codigo_cliente, s.descricao, cs.id_cliente_servico FROM atendimento AS a INNER JOIN cliente_servico AS cs ON a.id_cliente_servico = cs.id_cliente_servico INNER JOIN cliente AS c ON cs.id_cliente = c.id_cliente INNER JOIN servico AS s ON cs.id_servico = s.id_servico WHERE a.id_tipo_atendimento = 21 AND a.id_atendimento_status IN (1, 2, 33) AND s.ativo = true;`;
- const { rows } = await db.query(query);
+ const query = `
+ SELECT
+ a.id_atendimento,
+ a.id_usuario_abertura,
+ a.id_atendimento_status,
+ a.protocolo,
+ a.descricao_abertura,
+ a.data_cadastro,
+ a.nome_contato,
+
+ -- DADOS DO CLIENTE (novos)
+ c.nome_razaosocial,
+ c.telefone_primario AS telefone,
+ c.cpf_cnpj,
+ c.tipo_pessoa,
+ c.email_principal AS email,
+
+ c.codigo_cliente,
+ s.descricao AS descricao,
+ cs.id_cliente_servico,
+
+ -- ENDEREÇO DE INSTALAÇÃO
+ en.endereco,
+ en.numero,
+ en.complemento,
+ en.bairro,
+ en.cep,
+ ci.nome AS cidade,
+ es.sigla AS estado
+
+ FROM atendimento AS a
+
+ INNER JOIN cliente_servico AS cs
+ ON a.id_cliente_servico = cs.id_cliente_servico
+
+ INNER JOIN cliente AS c
+ ON cs.id_cliente = c.id_cliente
+
+ INNER JOIN servico AS s
+ ON cs.id_servico = s.id_servico
+
+ -- endereço do cliente
+ INNER JOIN cliente_servico_endereco AS cse
+ ON cse.id_cliente_servico = cs.id_cliente_servico
+ AND cse.tipo = 'instalacao'
+
+ INNER JOIN endereco_numero AS en
+ ON en.id_endereco_numero = cse.id_endereco_numero
+
+ INNER JOIN cidade AS ci
+ ON ci.id_cidade = en.id_cidade
+
+ INNER JOIN estado AS es
+ ON es.id_estado = ci.id_estado
+
+ WHERE
+ a.id_tipo_atendimento = 21
+ AND a.id_atendimento_status IN (1, 2, 33)
+ AND s.ativo = TRUE;
+ `;
+ const { rows } = await hubsoft.query(query);
return rows;
} catch (error) {
@@ -31,7 +90,7 @@ async function getImplantacaoTickets() {
async function getCancelamentoTickets() {
try {
const query = `SELECT a.id_atendimento, a.id_usuario_abertura, a.id_atendimento_status, a.protocolo, a.descricao_abertura, a.data_cadastro, a.nome_contato, c.codigo_cliente, s.descricao, cs.id_cliente_servico FROM atendimento AS a INNER JOIN cliente_servico AS cs ON a.id_cliente_servico = cs.id_cliente_servico INNER JOIN cliente AS c ON cs.id_cliente = c.id_cliente INNER JOIN servico AS s ON cs.id_servico = s.id_servico WHERE a.id_tipo_atendimento = 27 AND a.id_atendimento_status IN (1, 2, 33) AND s.ativo = true;`;
- const { rows } = await db.query(query);
+ const { rows } = await hubsoft.query(query);
return rows;
} catch (error) {
logError("Erro ao buscar tickets Cancelamento:", error);
@@ -42,7 +101,7 @@ async function getCancelamentoTickets() {
async function getSacTickets() {
try {
const query = `SELECT a.id_atendimento, a.id_usuario_abertura, a.id_atendimento_status, a.protocolo, a.descricao_abertura, a.data_cadastro, a.nome_contato, c.codigo_cliente, s.descricao, cs.id_cliente_servico FROM atendimento AS a INNER JOIN cliente_servico AS cs ON a.id_cliente_servico = cs.id_cliente_servico INNER JOIN cliente AS c ON cs.id_cliente = c.id_cliente INNER JOIN servico AS s ON cs.id_servico = s.id_servico WHERE a.id_tipo_atendimento = 41 AND a.id_atendimento_status IN (1, 2, 33) AND s.ativo = true;`;
- const { rows } = await db.query(query);
+ const { rows } = await hubsoft.query(query);
return rows;
} catch (error) {
logError("Erro ao buscar tickets SAC:", error);