fix: adjust API key handling and optimize call journaling

feat/hitphone-socket-integration
adriano 2024-07-18 21:41:03 -03:00
parent 050d711abc
commit 8f9afd5f23
13 changed files with 439 additions and 31 deletions

View File

@ -0,0 +1,188 @@
{
"authentication":{
"type": "bearer",
"token": "pat-na1-7aca13dd-9ba5-48db-bf35-570844d31abb",
"crmPhoneTest": "5511988334455"
},
"crmRest":[
{
"createContactRecord":{
"request":{
"requestContentType":"application/json",
"requestEncoding":"Json",
"requestType":"Post",
"responseType":"Json",
"url":"https://api.hubapi.com/contacts/v1/contact"
},
"body":{
"properties":[
{
"property":"phone",
"value":"crmPhone"
}
]
},
"response":{
"id":"vid"
}
}
},
{
"lookupContactByPhone":{
"request":{
"requestContentType":"application/json",
"requestEncoding":"Json",
"requestType":"Get",
"responseType":"Json",
"url":"https://api.hubapi.com/contacts/v1/search/query?q=crmPhone"
},
"response":{
"phone":"contacts.properties.phone.value",
"id":"contacts.vid"
}
}
},
{
"callJournaling":{
"request":{
"requestContentType":"application/json",
"requestEncoding":"Json",
"requestType":"Post",
"responseType":"Json",
"url":"https://api.hubapi.com/engagements/v1/engagements"
},
"calls": [
{
"inboundAnsweredCall": {
"engagement": {
"active": true,
"type": "CALL"
},
"associations": {
"contactIds": [
{
"_prop": "crmContactId",
"_type": "number"
}
]
},
"metadata": {
"toNumber": {
"_prop": "crmAgent",
"_type": "string"
},
"fromNumber": {
"_prop": "crmPhone",
"_type": "string"
},
"status": "COMPLETED",
"durationMilliseconds": {
"_prop": "crmCallDuration",
"_type": "number",
"_format": "milliseconds"
},
"body": "Ligação recebida - inbound call",
"disposition": "f240bbac-87c9-4f6e-bf70-924b57d47db7"
}
}
},
{
"inboundMissedCall": {
"engagement": {
"active": true,
"type": "CALL"
},
"associations": {
"contactIds": [
{
"_prop": "crmContactId",
"_type": "number"
}
]
},
"metadata": {
"toNumber": {
"_prop": "crmAgent",
"_type": "string"
},
"fromNumber": {
"_prop": "crmPhone",
"_type": "string"
},
"status": "COMPLETED",
"body": "Ligação perdida - inbound call",
"disposition": "f240bbac-87c9-4f6e-bf70-924b57d47db7"
}
}
},
{
"outboundAnsweredCall": {
"engagement": {
"active": true,
"type": "CALL"
},
"associations": {
"contactIds": [
{
"_prop": "crmContactId",
"_type": "number"
}
]
},
"metadata": {
"fromNumber": {
"_prop": "crmPhone",
"_type": "string"
},
"toNumber": {
"_prop": "crmAgent",
"_type": "string"
},
"status": "COMPLETED",
"durationMilliseconds": {
"_prop": "crmCallDuration",
"_type": "number",
"_format": "milliseconds"
},
"body": "Ligação atendida - outbound call",
"disposition": "f240bbac-87c9-4f6e-bf70-924b57d47db7"
}
}
},
{
"outboundUnansweredCall": {
"engagement": {
"active": true,
"type": "CALL"
},
"associations": {
"contactIds": [
{
"_prop": "crmContactId",
"_type": "number"
}
]
},
"metadata": {
"fromNumber": {
"_prop": "crmAgent",
"_type": "string"
},
"toNumber": {
"_prop": "crmPhone",
"_type": "string"
},
"status": "COMPLETED",
"body": "Ligação perdida - oubound call",
"disposition": "f240bbac-87c9-4f6e-bf70-924b57d47db7"
}
}
}
],
"response":{
}
}
}
]
}

View File

@ -0,0 +1,188 @@
{
"authentication":{
"type": "bearer",
"token": "pat-na1-7aca13dd-9ba5-48db-bf35-570844d31abb",
"crmPhoneTest": "5511988334455"
},
"crmRest":[
{
"createContactRecord":{
"request":{
"requestContentType":"application/json",
"requestEncoding":"Json",
"requestType":"Post",
"responseType":"Json",
"url":"https://api.hubapi.com/contacts/v1/contact"
},
"body":{
"properties":[
{
"property":"phone",
"value":"crmPhone"
}
]
},
"response":{
"id":"vid"
}
}
},
{
"lookupContactByPhone":{
"request":{
"requestContentType":"application/json",
"requestEncoding":"Json",
"requestType":"Get",
"responseType":"Json",
"url":"https://api.hubapi.com/contacts/v1/search/query?q=crmPhone"
},
"response":{
"phone":"contacts.properties.phone.value",
"id":"contacts.vid"
}
}
},
{
"callJournaling":{
"request":{
"requestContentType":"application/json",
"requestEncoding":"Json",
"requestType":"Post",
"responseType":"Json",
"url":"https://api.hubapi.com/engagements/v1/engagements"
},
"calls": [
{
"inboundAnsweredCall": {
"engagement": {
"active": true,
"type": "CALL"
},
"associations": {
"contactIds": [
{
"_prop": "crmContactId",
"_type": "number"
}
]
},
"metadata": {
"toNumber": {
"_prop": "crmAgent",
"_type": "string"
},
"fromNumber": {
"_prop": "crmPhone",
"_type": "string"
},
"status": "COMPLETED",
"durationMilliseconds": {
"_prop": "crmCallDuration",
"_type": "number",
"_format": "milliseconds"
},
"body": "Ligação recebida - inbound call",
"disposition": "f240bbac-87c9-4f6e-bf70-924b57d47db7"
}
}
},
{
"inboundMissedCall": {
"engagement": {
"active": true,
"type": "CALL"
},
"associations": {
"contactIds": [
{
"_prop": "crmContactId",
"_type": "number"
}
]
},
"metadata": {
"toNumber": {
"_prop": "crmAgent",
"_type": "string"
},
"fromNumber": {
"_prop": "crmPhone",
"_type": "string"
},
"status": "COMPLETED",
"body": "Ligação perdida - inbound call",
"disposition": "f240bbac-87c9-4f6e-bf70-924b57d47db7"
}
}
},
{
"outboundAnsweredCall": {
"engagement": {
"active": true,
"type": "CALL"
},
"associations": {
"contactIds": [
{
"_prop": "crmContactId",
"_type": "number"
}
]
},
"metadata": {
"fromNumber": {
"_prop": "crmPhone",
"_type": "string"
},
"toNumber": {
"_prop": "crmAgent",
"_type": "string"
},
"status": "COMPLETED",
"durationMilliseconds": {
"_prop": "crmCallDuration",
"_type": "number",
"_format": "milliseconds"
},
"body": "Ligação atendida - outbound call",
"disposition": "f240bbac-87c9-4f6e-bf70-924b57d47db7"
}
}
},
{
"outboundUnansweredCall": {
"engagement": {
"active": true,
"type": "CALL"
},
"associations": {
"contactIds": [
{
"_prop": "crmContactId",
"_type": "number"
}
]
},
"metadata": {
"fromNumber": {
"_prop": "crmAgent",
"_type": "string"
},
"toNumber": {
"_prop": "crmPhone",
"_type": "string"
},
"status": "COMPLETED",
"body": "Ligação perdida - oubound call",
"disposition": "f240bbac-87c9-4f6e-bf70-924b57d47db7"
}
}
}
],
"response":{
}
}
}
]
}

View File

@ -2,7 +2,7 @@
"authentication": { "authentication": {
"type": "api_token", "type": "api_token",
"token": "1c97c52596abc18d3f727df3a620b5ef3f4f7d29", "token": "1c97c52596abc18d3f727df3a620b5ef3f4f7d29",
"crmPhoneTest": "5511988334455" "crmPhoneTest": "5511988325936"
}, },
"crmRest": [ "crmRest": [
{ {
@ -40,8 +40,8 @@
"url": "https://api.pipedrive.com/v1/persons/search?term=crmPhone" "url": "https://api.pipedrive.com/v1/persons/search?term=crmPhone"
}, },
"response": { "response": {
"phone": "data.items.item.phones[0]", "phone": "data.items[0].item.phones[0]",
"id": "data.item.id" "id": "data.items[0].item.id"
} }
} }
}, },
@ -52,7 +52,7 @@
"requestEncoding": "Json", "requestEncoding": "Json",
"requestType": "Post", "requestType": "Post",
"responseType": "Json", "responseType": "Json",
"url": "https://api.hubapi.com/engagements/v1/engagements" "url": "https://api.pipedrive.com/v1/activities"
}, },
"calls": [ "calls": [
{ {
@ -61,8 +61,8 @@
"type": "Call", "type": "Call",
"person_id": "crmContactId", "person_id": "crmContactId",
"done": "1", "done": "1",
"deal_id": "2", "due_date": "YYYY-MM-DD",
"note": "Ligação recebida +crmPhone" "due_time": "HH:MM"
} }
}, },
{ {
@ -71,8 +71,8 @@
"type": "Call", "type": "Call",
"person_id": "crmContactId", "person_id": "crmContactId",
"done": "0", "done": "0",
"deal_id": "2", "due_date": "YYYY-MM-DD",
"note": "Ligação perdida +crmPhone" "due_time": "HH:MM"
} }
}, },
{ {
@ -81,8 +81,9 @@
"type": "Call", "type": "Call",
"person_id": "crmContactId", "person_id": "crmContactId",
"done": "1", "done": "1",
"deal_id": "2", "due_date": "YYYY-MM-DD",
"note": "Ligação realizada para +crmPhone" "due_time": "HH:MM",
"note": ""
} }
}, },
{ {
@ -91,8 +92,8 @@
"type": "Call", "type": "Call",
"person_id": "crmContactId", "person_id": "crmContactId",
"done": "0", "done": "0",
"deal_id": "2", "due_date": "YYYY-MM-DD",
"note": "Ligação realizada para +crmPhone" "due_time": "HH:MM"
} }
} }
], ],

View File

@ -0,0 +1 @@
pat-na1-37da6668-e0b1-44cb-bd2d-596f5f65634a

View File

@ -60,16 +60,16 @@ const deleteCompany = async (req, res) => {
const callJournaling = async (req, res) => { const callJournaling = async (req, res) => {
const { companyId, operation, crmPhone, crmAgent, crmCallDuration } = req.body const { companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName } = req.body
mustContainProperties(req, ['companyId', 'operation', 'crmPhone', 'crmAgent',]) mustContainProperties(req, ['companyId', 'operation', 'crmPhone', 'crmAgent',])
if (operation == 'inboundAnsweredCall' && !crmCallDuration) // if (operation == 'inboundAnsweredCall' && !crmCallDuration)
throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is inboundAnsweredCall`) // throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is inboundAnsweredCall`)
if (operation == 'outboundAsweredCall' && !crmCallDuration) // if (operation == 'outboundAsweredCall' && !crmCallDuration)
throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is outboundAsweredCall`) // throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is outboundAsweredCall`)
await journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration,) await journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName)
res.status(StatusCodes.OK).send() res.status(StatusCodes.OK).send()
} }

View File

@ -69,7 +69,7 @@ const CRMRestSchema = new Schema({
const AuthenticationSchema = new Schema({ const AuthenticationSchema = new Schema({
type: { type: {
type: String, type: String,
enum: ['basic', 'bearer', 'oauth2'], enum: ['basic', 'bearer', 'oauth2', "api_token"],
default: 'bearer' default: 'bearer'
}, },
userName: String, userName: String,

View File

@ -8,7 +8,7 @@ const CRM = require('../models/CRM')
const requestConfigHeader = require('./requestConfigHeader') const requestConfigHeader = require('./requestConfigHeader')
const sendMessageSocket = require('./sendMessageSocket') const sendMessageSocket = require('./sendMessageSocket')
async function createContact(companyId, rest, authentication, crmPhone, crmFirstName = '', crmLastName = '', crmEmail = '', test = {}) { async function createContact(companyId, rest, authentication, crmPhone, crmFirstName = 'unnamed', crmLastName = 'no surname', crmEmail = '', test = {}) {
let { request, body, response } = findProperty(rest, 'createContactRecord') let { request, body, response } = findProperty(rest, 'createContactRecord')
const { requestContentType, requestEncoding, requestType, responseType, url } = request const { requestContentType, requestEncoding, requestType, responseType, url } = request
@ -65,6 +65,7 @@ async function createContact(companyId, rest, authentication, crmPhone, crmFirst
} }
} }
if (auxContactId && !test?.testing) { if (auxContactId && !test?.testing) {
const crm = await CRM.findOne({ companyId, crmBaseURL: new URL(url).hostname }) const crm = await CRM.findOne({ companyId, crmBaseURL: new URL(url).hostname })
await CRM_Contact.create({ companyId, crm, crmBaseURL: new URL(url).hostname, contactId: auxContactId, phone: crmPhone }) await CRM_Contact.create({ companyId, crm, crmBaseURL: new URL(url).hostname, contactId: auxContactId, phone: crmPhone })

View File

@ -5,7 +5,7 @@ const findProperty = require('./findProperty')
const journalingRequest = require('./journalingRequest') const journalingRequest = require('./journalingRequest')
async function journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration = 0) { async function journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration = 0, crmFirstName ='unnamed') {
const crmFiles = await loadCRM(companyId) const crmFiles = await loadCRM(companyId)
@ -16,7 +16,7 @@ async function journaling(companyId, operation, crmPhone, crmAgent, crmCallDurat
let contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId) let contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId)
if (!contact.exist) { if (!contact.exist) {
contact = await createContact(companyId, rest, authentication, crmPhone) contact = await createContact(companyId, rest, authentication, crmPhone, crmFirstName)
} }
let { request, calls, response } = findProperty(rest, 'callJournaling') let { request, calls, response } = findProperty(rest, 'callJournaling')

View File

@ -53,6 +53,24 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
} }
if (!auxPhone && !auxContactId) {
for (const prop in data) {
let _prop = prop.replace(/\.(\d+)(\.|$)/g, '[$1]$2')
if (_prop == response?.phone?.trim()) {
auxPhone = data[prop].replace('+', '')
}
if (_prop == response?.id?.trim()) {
auxContactId = data[prop]
}
if (auxPhone && auxContactId) break
}
}
if (auxPhone) { if (auxPhone) {
if (auxPhone && auxContactId) { if (auxPhone && auxContactId) {

View File

@ -4,6 +4,16 @@ async function requestConfigHeader(url, crmPhone, requestType, requestContentTyp
let config = {} let config = {}
url = url.replace('crmPhone', crmPhone) url = url.replace('crmPhone', crmPhone)
if (type == 'api_token') {
if (requestType.trim().toLowerCase() == 'post') {
url = `${url}?api_token=${token}`
}
else if (requestType.trim().toLowerCase() == 'get') {
url = `${url}&api_token=${token}`
}
}
let commonConfig = { let commonConfig = {
method: requestType, method: requestType,
url, url,

View File

@ -23,7 +23,7 @@ async function templateValidator(crmPhoneTest, crm, companyId) {
rest = crm.crmRest, rest = crm.crmRest,
authentication = crm.authentication, authentication = crm.authentication,
crmPhone = phoneTest, crmPhone = phoneTest,
crmFirstName = '', crmFirstName = 'unnamed',
crmLastName = '', crmLastName = '',
crmEmail = '', crmEmail = '',
test = { testing: true }) test = { testing: true })

View File

@ -63,6 +63,7 @@ const UploadFile = () => {
setUploadStatus('Error uploading file.') setUploadStatus('Error uploading file.')
setStatus('error') setStatus('error')
console.log('error: ', error)
setErrorResponse(error.response.data.msg) setErrorResponse(error.response.data.msg)
} }
} }