WIP: Refactoring CreateTickets e solidificando estrutura para Feature de trazer chamados provenientes do SAC e de Implantacoes
This commit is contained in:
parent
14949bf4df
commit
4b2d26e469
@ -62,8 +62,6 @@ const categoriaGLPI = {
|
|||||||
'PABX IP - Até 30 ramais com telefones IPs (CAOA OUTROS ESTADOS)' : 5717 ,
|
'PABX IP - Até 30 ramais com telefones IPs (CAOA OUTROS ESTADOS)' : 5717 ,
|
||||||
'Link de Internet Dedicado 700MB Full Duplex' : 5707 ,
|
'Link de Internet Dedicado 700MB Full Duplex' : 5707 ,
|
||||||
'Link de Internet Dedicado - Temporário' : 5707
|
'Link de Internet Dedicado - Temporário' : 5707
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -121,7 +119,7 @@ const formatTicketDataForGlpi = async (ticketData) => {
|
|||||||
type: 1,
|
type: 1,
|
||||||
itilcategories_id: categoriaGLPI[ticketData.servico_nome] || 1,
|
itilcategories_id: categoriaGLPI[ticketData.servico_nome] || 1,
|
||||||
date_creation: new Date(),
|
date_creation: new Date(),
|
||||||
// entidades_id: 0 //await glpiModel.selectEntityId() //TODO: Implementar a busca da entidade
|
// entidades_id: 0 //await glpiModel.selectyId() //TODO: Implementar a busca da entidade
|
||||||
};
|
};
|
||||||
return formattedData;
|
return formattedData;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -53,8 +53,7 @@ class HubglpiModel {
|
|||||||
logError(`Erro ao inserir/atualizar ticket na tabela hubsoft_tickets: ${err}`);
|
logError(`Erro ao inserir/atualizar ticket na tabela hubsoft_tickets: ${err}`);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static async insertSyncData(syncData) {
|
static async insertSyncData(syncData) {
|
||||||
|
|
||||||
@ -114,8 +113,7 @@ class HubglpiModel {
|
|||||||
logError(`Erro ao atualizar dados na tabela sync_data: ${err}`);
|
logError(`Erro ao atualizar dados na tabela sync_data: ${err}`);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static async get_idSyncByHubsoftId(hubsoft_ticket_id) {
|
static async get_idSyncByHubsoftId(hubsoft_ticket_id) {
|
||||||
const query = `
|
const query = `
|
||||||
@ -192,8 +190,9 @@ class HubglpiModel {
|
|||||||
logError(`Erro ao obter glpi_ticket_id por id_atendimento, ${err}`);
|
logError(`Erro ao obter glpi_ticket_id por id_atendimento, ${err}`);
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static async updateClosingTicket(syncId, closeMessage) {
|
|
||||||
|
static async updateClosingTicket(syncId, closeMessage) {
|
||||||
const client = await pool.connect();
|
const client = await pool.connect();
|
||||||
try {
|
try {
|
||||||
await client.query('BEGIN'); // inicia transação
|
await client.query('BEGIN'); // inicia transação
|
||||||
@ -238,10 +237,7 @@ static async updateClosingTicket(syncId, closeMessage) {
|
|||||||
} finally {
|
} finally {
|
||||||
client.release();
|
client.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static async updateSyncDataStatus( ticketId, status_sync, source_last){
|
static async updateSyncDataStatus( ticketId, status_sync, source_last){
|
||||||
const query = `
|
const query = `
|
||||||
@ -262,7 +258,6 @@ static async updateClosingTicket(syncId, closeMessage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static async updateSyncaDataError(sync_error_message, id_atendimento) {
|
static async updateSyncaDataError(sync_error_message, id_atendimento) {
|
||||||
const query = `
|
const query = `
|
||||||
UPDATE sync_data
|
UPDATE sync_data
|
||||||
@ -304,8 +299,6 @@ static async updateClosingTicket(syncId, closeMessage) {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
module.exports = HubglpiModel;
|
module.exports = HubglpiModel;
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
// 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 ticketShared = require('../services/createTickets.service.js');
|
||||||
|
|
||||||
|
const { logInfo } = require('../../utils/logger.js');
|
||||||
|
|
||||||
|
async function processaAtendimentos() {
|
||||||
|
logInfo("[CONTROLLER] Iniciando processamento");
|
||||||
|
|
||||||
|
// 1️⃣ Buscar por fonte
|
||||||
|
const mundiale = await mundialeService.fetchNew();
|
||||||
|
const implantacao = await implantacaoService.fetchNew();
|
||||||
|
const app = await appMobileService.fetchNew();
|
||||||
|
|
||||||
|
// 2️⃣ Salvar no hubglpi
|
||||||
|
await mundialeService.saveHubGlpi(mundiale);
|
||||||
|
await implantacaoService.saveHubglpi(implantacao);
|
||||||
|
await appMobileService.saveHubglpi(app);
|
||||||
|
|
||||||
|
// 3️⃣ Buscar pendentes que foram salvos no banco hubglpi
|
||||||
|
const pendentes = await ticketShared.buscarPendentesHubglpi();
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
logInfo(`Tipo desconhecido, ignorando ticket id=${ticket.id}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ticketShared.marcarComoProcessado(ticket.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
logInfo("[CONTROLLER] Finalizado.");
|
||||||
|
}
|
||||||
44
src/modules/createTickets/services/createTickets.service.js
Normal file
44
src/modules/createTickets/services/createTickets.service.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
// src/modules/createTickets/services/createTickets.service.js
|
||||||
|
const repositoryHubGlpi = require('../../../shared/repositories/hubglpi.repository.js');
|
||||||
|
|
||||||
|
// --------------------------------------
|
||||||
|
// Funções principais do serviço
|
||||||
|
// --------------------------------------
|
||||||
|
|
||||||
|
async function fetcPendingTickets() {
|
||||||
|
return repositoryHubGlpi.fetchPendingTickets();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function resolveEntityId(ticketData, glpiModel) {
|
||||||
|
|
||||||
|
const entityByService = await glpiModel.selectEntityIdCodServico(
|
||||||
|
ticketData.codigo_cliente,
|
||||||
|
ticketData.codigo_servico
|
||||||
|
);
|
||||||
|
|
||||||
|
if (entityByService) {
|
||||||
|
ticketData.entities_id = entityByService;
|
||||||
|
return ticketData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tenta entidade pelo cliente
|
||||||
|
const entityByClient = await glpiModel.selectEntityIdCodCliente(
|
||||||
|
ticketData.codigo_cliente
|
||||||
|
);
|
||||||
|
|
||||||
|
if (entityByClient) {
|
||||||
|
ticketData.entities_id = entityByClient;
|
||||||
|
return ticketData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback
|
||||||
|
ticketData.entities_id = 0;
|
||||||
|
return ticketData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetcPendingTickets,
|
||||||
|
resolveEntityId
|
||||||
|
}
|
||||||
115
src/modules/createTickets/services/mundiale.service.js
Normal file
115
src/modules/createTickets/services/mundiale.service.js
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
// src/modules/createTickets/services/mundiale.service.js
|
||||||
|
const repositoryHubGlpi = require('../../../shared/repositories/hubglpi.repository.js');
|
||||||
|
const repositoryGlpi = require('../../../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');
|
||||||
|
|
||||||
|
// --------------------------------------
|
||||||
|
// Funções principais do serviço
|
||||||
|
// --------------------------------------
|
||||||
|
|
||||||
|
async function fetchNew() {
|
||||||
|
return repositoryHubsoft.getMundialeTickets();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveHubGlpi(tickets) {
|
||||||
|
if (!tickets.length) return;
|
||||||
|
|
||||||
|
const ticketsFormatted = tickets.map(ticket => modelHubGlpi.mapHubsoftToHubglpi(ticket, 'MUNDIALE'));
|
||||||
|
|
||||||
|
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, modelGlpi);
|
||||||
|
|
||||||
|
const formattedTickets = formatGlpiPayload(ticketsResolved);
|
||||||
|
|
||||||
|
const payload = modelGlpi.mapHubGlpiToGlpi(formattedTickets);
|
||||||
|
|
||||||
|
const glpiId = await repositoryGlpi.insertTickets([payload]);
|
||||||
|
|
||||||
|
await repositoryHubGlpi.updateSyncDataCreated(ticket.id_atendimento, glpiId[0]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------------
|
||||||
|
// Formatar dados antes de enviar para o GLPI
|
||||||
|
// --------------------------------------
|
||||||
|
|
||||||
|
function formatGlpiPayload(ticket) {
|
||||||
|
|
||||||
|
const statusTexto = statusAtendimentoHubGlpi[ticket.status_atendimento] || 'Novo';
|
||||||
|
const statusGlpi = statusAtendimentoGLPI[statusTexto] || 1;
|
||||||
|
|
||||||
|
const categoria = categoriaGLPI[ticket.servico_nome] || 0;
|
||||||
|
|
||||||
|
const title = `[Mundiale] ${ticket.cliente_nome} - ${ticket.servico_nome} - ${ticket.ticket_mundiale}`;
|
||||||
|
|
||||||
|
const description = formatDescription(ticket);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: title,
|
||||||
|
content: description,
|
||||||
|
status: statusGlpi,
|
||||||
|
itilcategories_id: categoria,
|
||||||
|
created_at: ticket.created_at,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const formatDescription = (ticketData) => {
|
||||||
|
|
||||||
|
let htmlDescription = `
|
||||||
|
<table style="width:100%; border-collapse: collapse;">
|
||||||
|
<tr style="background-color:#f2f2f2;">
|
||||||
|
<th style="padding: 8px; border: 1px solid #ddd; text-align: left;">Campo</th>
|
||||||
|
<th style="padding: 8px; border: 1px solid #ddd; text-align: left;">Valor</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Nome:</strong></td>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.cliente_nome}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Codigo:</strong></td>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.codigo_cliente}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Serviço:</strong></td>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.servico_nome}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Ticket Mundiale</strong></td>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.ticket_mundiale}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;"><strong>Protocolo Hub:</strong></td>
|
||||||
|
<td style="padding: 8px; border: 1px solid #ddd;">${ticketData.protocolo_hub || 'N/A'}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return htmlDescription;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
fetchNew,
|
||||||
|
saveHubGlpi,
|
||||||
|
sendToGlpi
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @module CreateTickets/MundialeService
|
||||||
|
* @description Serviço responsável por interagir com o Hubsoft e GLPI criação de tickets que provêm da Mundiale.
|
||||||
|
*/
|
||||||
0
src/modules/createTickets/services/sac.service.js
Normal file
0
src/modules/createTickets/services/sac.service.js
Normal file
@ -85,4 +85,11 @@ CREATE TABLE sync_control (
|
|||||||
-- Inserir o registro inicial para o nosso novo cron de comentários
|
-- Inserir o registro inicial para o nosso novo cron de comentários
|
||||||
INSERT INTO sync_control (job_name, last_run_timestamp) VALUES ('hubsoft_comments_sync', '2024-01-01 00:00:00');
|
INSERT INTO sync_control (job_name, last_run_timestamp) VALUES ('hubsoft_comments_sync', '2024-01-01 00:00:00');
|
||||||
|
|
||||||
|
-- =============================================
|
||||||
|
-- ALTERAÇÕES NA TABELA hubsoft_tickets
|
||||||
|
-- =============================================
|
||||||
|
ALTER TABLE hubsoft_tickets
|
||||||
|
ADD COLUMN ticket_type VARCHAR(50) NOT NULL DEFAULT 'MUNDIALE';
|
||||||
|
|
||||||
|
ALTER TABLE hubsoft_tickets
|
||||||
|
ADD CONSTRAINT hubsoft_id_atendimento_unique UNIQUE (id_atendimento);
|
||||||
|
|||||||
37
src/shared/model/glpi.model.js
Normal file
37
src/shared/model/glpi.model.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
// src/shared/model/glpi.model.js
|
||||||
|
|
||||||
|
function mapHubGlpiToGlpi(ticket) {
|
||||||
|
return {
|
||||||
|
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,
|
||||||
|
content: ticket.content,
|
||||||
|
urgency: 3,
|
||||||
|
impact: 3,
|
||||||
|
priority: 3,
|
||||||
|
type: 2,
|
||||||
|
date_creation : ticket.date_creation || Now(),
|
||||||
|
slas_id_ttr: 37
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function defineStatusGlpi(Status) {
|
||||||
|
const mapStatusDBtoGLPI = {
|
||||||
|
'Novo': 1,
|
||||||
|
'Pendente': 4,
|
||||||
|
'Em atendimento': 2,
|
||||||
|
'Resolvido': 5
|
||||||
|
};
|
||||||
|
|
||||||
|
return mapStatusDBtoGLPI[Status] || 'Novo';
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mapHubGlpiToGlpi,
|
||||||
|
defineStatusGlpi
|
||||||
|
};
|
||||||
34
src/shared/model/hubglpi.model.js
Normal file
34
src/shared/model/hubglpi.model.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// src/shared/model/hubglpi.model.js
|
||||||
|
|
||||||
|
function mapHubsoftToHubglpi(ticket, type) {
|
||||||
|
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,
|
||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function defineStatusHubglpi(hubsoftStatus) {
|
||||||
|
const statusMap = {
|
||||||
|
1: 'Pendente',
|
||||||
|
2: 'Em atendimento',
|
||||||
|
3: 'Resolvido',
|
||||||
|
31: 'Pendente',
|
||||||
|
32: 'Pendente',
|
||||||
|
33: 'Novo'
|
||||||
|
}
|
||||||
|
return statusMap[hubsoftStatus] || 'Novo';
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
mapHubsoftToHubglpi
|
||||||
|
};
|
||||||
40
src/shared/repositories/glpi.repository.js
Normal file
40
src/shared/repositories/glpi.repository.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// src/shared/repositories/glpi.repository.js
|
||||||
|
const db = require('../../../config/database.js');
|
||||||
|
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(",");
|
||||||
|
|
||||||
|
const sql = `
|
||||||
|
INSERT INTO glpi_tickets
|
||||||
|
(status, content, users_id_recipient, entities_id, type, requesttypes_id,
|
||||||
|
urgency, impact, priority, date, name)
|
||||||
|
VALUES ${placeholders}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const result = await mariadb.execute(sql, values.flat());
|
||||||
|
|
||||||
|
return result.insertId ? [result.insertId] : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
insertTickets
|
||||||
|
};
|
||||||
132
src/shared/repositories/hubglpi.repository.js
Normal file
132
src/shared/repositories/hubglpi.repository.js
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// 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');
|
||||||
|
|
||||||
|
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
|
||||||
|
]);
|
||||||
|
|
||||||
|
const rowPlaceholders = values
|
||||||
|
.map(
|
||||||
|
(_, i) =>
|
||||||
|
`(${Array(13)
|
||||||
|
.fill(0)
|
||||||
|
.map((_, j) => `$${i * 13 + j + 1}`)
|
||||||
|
.join(", ")})`
|
||||||
|
)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
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 flattened = values.flat();
|
||||||
|
|
||||||
|
await db.query(query, flattened);
|
||||||
|
|
||||||
|
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
|
||||||
|
.map((_, i) => `($${i + 1})`)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
|
const query = `
|
||||||
|
INSERT INTO hubsoft_sync_data (hubsoft_ticket_id)
|
||||||
|
VALUES ${rowPlaceholders}
|
||||||
|
ON CONFLICT (hubsoft_ticket_id) DO UPDATE SET
|
||||||
|
hubsoft_ticket_id = $1
|
||||||
|
`;
|
||||||
|
|
||||||
|
const flattened = ids;
|
||||||
|
|
||||||
|
await db.query(query, flattened);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
logError("Erro ao inserir dados de sincronização no HubGLPI:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
} 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 = ?
|
||||||
|
`;
|
||||||
|
|
||||||
|
await db.query(sql, [glpiId, hubsoftTicketId]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
insertTickets,
|
||||||
|
insertSyncData,
|
||||||
|
fetchPendingTickets,
|
||||||
|
updateSyncDataCreated
|
||||||
|
};
|
||||||
60
src/shared/repositories/hubsoft.repository.js
Normal file
60
src/shared/repositories/hubsoft.repository.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
// src/shared/repositories/hubsoft.repository.js
|
||||||
|
const { get } = require('pm2');
|
||||||
|
const db = require('../../../config/database.js');
|
||||||
|
const { logInfo, logError } = require('../../utils/logger.js');
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rows;
|
||||||
|
} catch (error) {
|
||||||
|
logError("Erro ao buscar tickets Mundiale:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rows;
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
logError("Erro ao buscar tickets Implantação:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rows;
|
||||||
|
} catch (error) {
|
||||||
|
logError("Erro ao buscar tickets Cancelamento:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return rows;
|
||||||
|
} catch (error) {
|
||||||
|
logError("Erro ao buscar tickets SAC:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getMundialeTickets,
|
||||||
|
getImplantacaoTickets,
|
||||||
|
getCancelamentoTickets,
|
||||||
|
getSacTickets
|
||||||
|
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user