// src/models/ticketSnModel.js const pool = require('../data/database'); const { logInfo, logError, logWarning } = require('../utils/logger'); class TicketSnModel { static async saveTicket(ticketData, typeTicket) { const query = ` INSERT INTO tickets_sn (ticket_number, short_description, status, description, caller_id, caller_email, location_id, location_name, ramal, telefone, opened_at, tipo) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) ON CONFLICT (ticket_number) DO UPDATE SET short_description = EXCLUDED.short_description, status = EXCLUDED.status, description = EXCLUDED.description, caller_id = EXCLUDED.caller_id, caller_email = EXCLUDED.caller_email, location_id = EXCLUDED.location_id, location_name = EXCLUDED.location_name, ramal = EXCLUDED.ramal, telefone = EXCLUDED.telefone, opened_at = EXCLUDED.opened_at, tipo = EXCLUDED.tipo, updated_at = NOW() RETURNING id, xmax = 0 as inserted`; const values = [ ticketData.number?.value || null, // $1 - ticket_number ticketData.short_description?.value || null, // $2 - short_description ticketData.state?.display_value || null, // $3 - status ticketData.description?.value || null, // $4 - description ticketData.opened_by?.display_value || null, // $5 - caller_id ticketData['opened_by.email']?.value || null, // $6 - caller_email ticketData.location?.value || null, // $7 - location_id ticketData.location?.display_value || null, // $8 - location_name ticketData['variables.numero_ramal']?.value || null, // $9 - ramal ticketData['variables.telephone_favorecido_rh']?.value || null, // $10 - telefone ticketData.opened_at?.value ? new Date(ticketData.opened_at.value) : null, // $11 - opened_at typeTicket // $12 - tipo ]; try { const result = await pool.query(query, values); const wasInserted = result.rows[0].inserted; // true = INSERT, false = UPDATE if (wasInserted) { logInfo(`✅ NOVO ticket salvo! ID: ${result.rows[0].id}`, { ticket_id: result.rows[0].id, ticket_number: values[0], action: 'insert' }); } else { logInfo(`🔄 Ticket atualizado! ID: ${result.rows[0].id}`, { ticket_id: result.rows[0].id, ticket_number: values[0], action: 'update' }); } return result.rows[0].id; } catch (error) { logError(error, `❌ Erro ao salvar ticket ${values[0]}`); throw error; } } // NOVO: Buscar tickets pendentes para sincronização com GLPI static async getPendingTickets(limit = 3) { try { const query = ` SELECT id, ticket_number, short_description, description, status, caller_id, caller_email, location_id, location_name, ramal, telefone, opened_at, tipo, created_at, updated_at FROM tickets_sn WHERE glpi_sync_status IS NULL ORDER BY opened_at ASC LIMIT $1 `; const result = await pool.query(query, [limit]); logInfo(`📋 Tickets pendentes encontrados: ${result.rows.length}`); return result.rows; } catch (error) { logError(error, '❌ Erro ao buscar tickets pendentes'); return []; } } // NOVO: Atualizar status de sincronização com GLPI static async updateSyncStatus(ticketId, status, glpiTicketId = null) { try { const query = ` UPDATE tickets_sn SET glpi_sync_status = $1, glpi_ticket_id = $2, glpi_sync_date = NOW() WHERE id = $3 RETURNING id, ticket_number `; const result = await pool.query(query, [status, glpiTicketId, ticketId]); if (result.rows.length > 0) { logInfo(`🔄 Status atualizado: ${status} para ticket ${result.rows[0].ticket_number}`, { ticket_id: result.rows[0].id, ticket_number: result.rows[0].ticket_number, glpi_ticket_id: glpiTicketId, status: status }); } } catch (error) { logError(error, `❌ Erro ao atualizar status de sync para ticket ${ticketId}`); } } // NOVO: Resetar status de sync para testes (opcional) static async resetSyncStatus() { try { const query = ` UPDATE tickets_sn SET glpi_sync_status = NULL, glpi_ticket_id = NULL, glpi_sync_date = NULL WHERE id IN ( SELECT id FROM tickets_sn ORDER BY opened_at DESC LIMIT $1 ) RETURNING id, ticket_number `; const result = await pool.query(query, [limit]); logInfo(`🔄 Status resetado para ${result.rows.length} tickets`); return result.rows; } catch (error) { logError(error, '❌ Erro ao resetar status de sync'); return []; } } // NOVO: Verificar status de sincronização static async getSyncStatus() { try { const query = ` SELECT glpi_sync_status, COUNT(*) as total, COUNT(glpi_ticket_id) as synchronized FROM tickets_sn GROUP BY glpi_sync_status `; const result = await pool.query(query); return result.rows; } catch (error) { logError(error, '❌ Erro ao verificar status de sync'); return []; } } } module.exports = TicketSnModel;