crm-api-template-generator/backend/services/hubspotService.js

142 lines
4.2 KiB
JavaScript
Raw Normal View History

const axios = require('axios');
2025-06-16 17:56:12 +00:00
const Logger = console;
require('dotenv').config();
2025-06-16 17:56:12 +00:00
const loadCRM = require('../utils/loadCRM')
const lookupContactByPhone = require('../utils/lookupCRMContactByPhone')
const createContact = require('../utils/createContact')
/**
* Serviço para integração com a API do HubSpot.
*/
class HubspotService {
/**
* Inicializa o serviço HubspotService com configuração da API.
*/
constructor() {
this.logger = Logger;
this.baseUrl = 'https://api.hubapi.com';
this.apiKey = process.env.HUBSPOT_API_KEY;
this.client = axios.create({
baseURL: this.baseUrl,
headers: {
'Authorization': `Bearer ${this.apiKey}`,
'Content-Type': 'application/json'
}
});
}
/**
* Cria uma nota de chamada no HubSpot e associa ao contato e opcionalmente a um ticket.
*
* @param {string} contactId - ID do contato no HubSpot.
* @param {Object} callData - Dados da chamada.
* @param {string} callData.transcription - Transcrição completa da chamada.
* @param {string} callData.summary - Resumo da chamada.
* @param {string} callData.recordingUrl - URL da gravação da chamada.
* @param {string} callData.callerId - Número do chamador.
* @param {string} callData.uniqueId - Identificador único da chamada.
* @param {string} [callData.ticketId] - (Opcional) ID do ticket no HubSpot.
* @returns {Promise<Object>} - Dados da nota criada.
*/
async createCallNote(contactId, callData) {
try {
const { transcription, summary, recordingUrl, callerId, uniqueId, ticketId } = callData;
const noteContent = `
Chamada Recebida
------------------
Número: ${callerId}
ID da Chamada: ${uniqueId}
Data/Hora: ${new Date().toLocaleString('pt-BR', { timeZone: 'America/Sao_Paulo' })}
Resumo:
${summary}
Transcrição Completa:
${transcription}
Link da Gravação: ${recordingUrl}
`.trim();
// 1. Cria a nota
const response = await this.client.post('/crm/v3/objects/notes', {
properties: {
hs_timestamp: new Date().toISOString(),
hs_note_body: noteContent
}
});
const noteId = response.data.id;
// 2. Associa a nota ao contato
await this.client.put(`/crm/v3/objects/notes/${noteId}/associations/contact/${contactId}/note_to_contact`);
// 3. (Opcional) Associa a nota ao ticket, se houver
if (ticketId) {
await this.client.put(`/crm/v3/objects/notes/${noteId}/associations/ticket/${ticketId}/note_to_ticket`);
this.logger.log(`Nota associada ao ticket ${ticketId}`);
}
this.logger.log(`Nota ${noteId} criada com sucesso.`);
return response.data;
} catch (error) {
this.logger.error('Erro ao criar nota:', error?.response?.data || error.message);
throw error;
}
}
/**
* Busca um contato no HubSpot pelo número de telefone.
*
* @param {string} phoneNumber - Número de telefone para buscar.
* @returns {Promise<Object|null>} - Contato encontrado ou null.
*/
async findContactByPhone(phoneNumber) {
try {
const response = await this.client.post('/crm/v3/objects/contacts/search', {
filterGroups: [{
filters: [{
propertyName: 'phone',
operator: 'EQ',
value: phoneNumber
}]
}]
});
return response.data.results[0] || null;
} catch (error) {
this.logger.error('Erro ao buscar contato:', error?.response?.data || error.message);
throw error;
}
}
/**
* Cria um contato com o número informado caso não exista.
*
2025-06-16 17:56:12 +00:00
* @param {string} crmPhone - Número de telefone do contato.
* @returns {Promise<Object>} - Contato existente ou novo contato criado.
*/
2025-06-16 17:56:12 +00:00
async createContactIfNotExists(companyId, crmPhone) {
const crmFiles = await loadCRM(companyId)
if (crmFiles.length > 0) {
const { crmRest: rest, authentication } = crmFiles[0].crm
let contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId)
if (!contact.exist) {
contact = await createContact(companyId, rest, authentication, crmPhone)
}
2025-06-16 17:56:12 +00:00
return contact
}
}
}
module.exports = HubspotService;