feat: added feature to register whatsapp journaling from omnihit
parent
5b4406584b
commit
b654ce11a9
|
@ -152,6 +152,29 @@
|
|||
"response": {}
|
||||
}
|
||||
},
|
||||
{
|
||||
"chatJournaling": {
|
||||
"request": {
|
||||
"requestContentType": "application/json",
|
||||
"requestEncoding": "Json",
|
||||
"requestType": "Post",
|
||||
"responseType": "Json",
|
||||
"url": "https://nocompany-a9-dev-ed.develop.my.salesforce.com/services/data/v61.0/sobjects/Task"
|
||||
},
|
||||
"chats": [
|
||||
{
|
||||
"chatDone":{
|
||||
"WhoId": "crmContactId",
|
||||
"Subject": "WhatsApp Chat",
|
||||
"Description": "Conversation started via WhatsApp.",
|
||||
"ActivityDate": "YYYY-MM-DD",
|
||||
"Status": "Completed",
|
||||
"Priority": "Normal"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"redirectLink": {
|
||||
"request": {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
const path = require('path')
|
||||
const omnihitV2Integration = require('../data/omihitV2IntegrationCRM.json')
|
||||
const { StatusCodes } = require("http-status-codes")
|
||||
const { createCRMContact,
|
||||
sendMessageSocket,
|
||||
|
@ -21,6 +22,8 @@ const CustomError = require('../errors')
|
|||
const CRM_Contact = require('../models/CRM_Contact')
|
||||
const axios = require('axios')
|
||||
const { get, set } = require('../utils/redisClient')
|
||||
const { getContactIdChatwoot, createConversation, toggleConversationStatus } = require('../utils/ScheduleTicketCRM')
|
||||
const timeStamp = require('../utils/toTimestamp')
|
||||
|
||||
const contactCreate = async (req, res) => {
|
||||
|
||||
|
@ -292,6 +295,9 @@ const getCrms = async (req, res) => {
|
|||
|
||||
const webhook = async (req, res) => {
|
||||
|
||||
const originIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress
|
||||
console.log('========> Origem da requisição IP: ', originIP)
|
||||
|
||||
console.log('========> webhook req.body: ', JSON.stringify(req.body, null, 6))
|
||||
|
||||
console.log('========> req.body: ', req.body)
|
||||
|
@ -329,6 +335,9 @@ const webhook = async (req, res) => {
|
|||
|
||||
const webhook_crm = async (req, res) => {
|
||||
|
||||
const originIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress
|
||||
console.log('========> Crm Origem da requisição IP: ', originIP)
|
||||
|
||||
console.log('========> webhook crm req.body: ', JSON.stringify(req.body, null, 6))
|
||||
|
||||
const responseXml = `
|
||||
|
@ -347,22 +356,29 @@ const webhook_crm = async (req, res) => {
|
|||
return res.set('Content-Type', 'text/xml').status(StatusCodes.OK).send(responseXml)
|
||||
}
|
||||
|
||||
const url = req.body['soapenv:Envelope']['soapenv:Body']?.notifications?.EnterpriseUrl
|
||||
|
||||
console.log('========> salesforce url: ', url)
|
||||
|
||||
const crm = await CRM.findOne({ crmBaseURL: new URL(url.trim()).hostname })
|
||||
|
||||
const { companyId } = crm
|
||||
|
||||
console.log('========> crm companyId: ', companyId)
|
||||
|
||||
const whoId = sObject['sf:WhoId']
|
||||
const EventSubtype = sObject['sf:EventSubtype']
|
||||
const StartDateTime = sObject['sf:StartDateTime']
|
||||
|
||||
|
||||
console.log('==========> crm EventSubtype: ', EventSubtype)
|
||||
console.log('==========> crm StartDateTime: ', StartDateTime)
|
||||
console.log('==========> crm StartDateTime timeStamp: ', timeStamp(StartDateTime))
|
||||
|
||||
|
||||
|
||||
if (EventSubtype == 'Event') {
|
||||
|
||||
const contact = await CRM_Contact.findOne({
|
||||
companyId: "99",
|
||||
crmBaseURL: 'nocompany-a9-dev-ed.develop.my.salesforce.com',
|
||||
companyId,
|
||||
crmBaseURL: new URL(url.trim()).hostname,
|
||||
contactId: whoId
|
||||
})
|
||||
|
||||
|
@ -371,20 +387,32 @@ const webhook_crm = async (req, res) => {
|
|||
|
||||
const { phone } = contact
|
||||
|
||||
const contactIdChatwoot = await getContactIdChatwoot(phone)
|
||||
const obj = omnihitV2Integration.find(o => o.companyId == companyId)
|
||||
|
||||
if (!contactIdChatwoot) {
|
||||
return res.set('Content-Type', 'text/xml').status(StatusCodes.OK).send(responseXml)
|
||||
if (obj) {
|
||||
|
||||
const { companyId,
|
||||
omnihit: { accountId, api: { url, token } = {},
|
||||
createConversation: { inbox_id, status, team_id } = {} } = {} } = obj
|
||||
|
||||
const contactIdChatwoot = await getContactIdChatwoot(url, token, phone)
|
||||
|
||||
if (!contactIdChatwoot) {
|
||||
return res.set('Content-Type', 'text/xml').status(StatusCodes.OK).send(responseXml)
|
||||
}
|
||||
|
||||
console.log('==========> crm contactIdChatwoot: ', contactIdChatwoot)
|
||||
|
||||
let data = { inbox_id, contact_id: contactIdChatwoot, status, team_id }
|
||||
const omnihitConfig = { url, accountId, token }
|
||||
const ticketId = await createConversation(data, omnihitConfig)
|
||||
|
||||
console.log('==========> crm ticketId: ', ticketId)
|
||||
|
||||
data = { "status": "snoozed", "snoozed_until": timeStamp(StartDateTime) }
|
||||
|
||||
await toggleConversationStatus(url, accountId, token, ticketId, data)
|
||||
}
|
||||
|
||||
console.log('==========> crm contactIdChatwoot: ', contactIdChatwoot)
|
||||
|
||||
const ticketId = await createConversation(contactIdChatwoot)
|
||||
|
||||
console.log('==========> crm ticketId: ', ticketId)
|
||||
|
||||
await toggleConversationStatus({ "status": "snoozed", "snoozed_until": timeStamp(StartDateTime) }, ticketId)
|
||||
|
||||
}
|
||||
|
||||
return res.set('Content-Type', 'text/xml').status(StatusCodes.OK).send(responseXml)
|
||||
|
@ -406,82 +434,3 @@ module.exports = {
|
|||
|
||||
|
||||
|
||||
|
||||
async function getContactIdChatwoot(phone) {
|
||||
|
||||
const config = {
|
||||
method: 'get',
|
||||
url: `http://172.31.187.47:3333/api/v1/accounts/15/contacts/search?q=${phone}`,
|
||||
headers: {
|
||||
'api_access_token': 'WpeGuicvuQ3pyLvYQ11eAxxL'
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await axios(config)
|
||||
|
||||
return data.payload[0].id
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function createConversation(contact_id) {
|
||||
const data = JSON.stringify({
|
||||
"inbox_id": "2",
|
||||
"contact_id": `${contact_id}`,
|
||||
"status": "pending",
|
||||
"team_id": "1"
|
||||
})
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: 'http://172.31.187.47:3333/api/v1/accounts/15/conversations',
|
||||
headers: {
|
||||
'api_access_token': 'WpeGuicvuQ3pyLvYQ11eAxxL',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: data
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const { data } = await axios(config)
|
||||
return data.id
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleConversationStatus(payload, ticketId) {
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: `http://172.31.187.47:3333/api/v1/accounts/15/conversations/${ticketId}/toggle_status`,
|
||||
headers: {
|
||||
'api_access_token': 'WpeGuicvuQ3pyLvYQ11eAxxL',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify(payload)
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await axios(config)
|
||||
console.log(JSON.stringify(response.data))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
function timeStamp(dateTimeISO8601) {
|
||||
const date = new Date(dateTimeISO8601)
|
||||
|
||||
date.setHours(date.getUTCHours() - 3)
|
||||
|
||||
const timestamp = date.getTime() / 1000
|
||||
|
||||
return timestamp
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
const omnihitV2Integration = require('../data/omihitV2IntegrationCRM.json')
|
||||
|
||||
const obj = omnihitV2Integration.find(o => o.companyId === "99")
|
||||
|
||||
if (obj) {
|
||||
console.log(obj)
|
||||
|
||||
const { companyId, omnihit: { accountId, api: { url, token } = {}, createConversation: { inbox_id, status, team_id } = {} } = {} } = obj
|
||||
|
||||
console.log('companyId: ', companyId, ' accountId: ', accountId, ' url: ', url, ' token: ', token, ' inbox_id: ', inbox_id, ' status: ', status, ' team_id: ', team_id)
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
[
|
||||
{
|
||||
"companyId":"99",
|
||||
"omnihit": {
|
||||
"accountId":"15",
|
||||
"api":{
|
||||
"url":"http://172.31.187.47:3333",
|
||||
"token": "WpeGuicvuQ3pyLvYQ11eAxxL"
|
||||
},
|
||||
"createConversation":{
|
||||
"inbox_id": "2",
|
||||
"status":"pending",
|
||||
"team_id": "1"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
]
|
|
@ -38,12 +38,21 @@ const CallsSchema = new Schema({
|
|||
outboundUnansweredCall: Object
|
||||
})
|
||||
|
||||
const ChatsSchema = new Schema({
|
||||
chatDone: Object,
|
||||
})
|
||||
|
||||
const CallJournalingSchema = new Schema({
|
||||
request: RequestSchema,
|
||||
calls: [CallsSchema],
|
||||
response: Object
|
||||
})
|
||||
|
||||
const ChatJournalingSchema = new Schema({
|
||||
request: RequestSchema,
|
||||
chats: [ChatsSchema],
|
||||
response: Object
|
||||
})
|
||||
|
||||
|
||||
const RedirectUrlSchema = new Schema({
|
||||
|
@ -53,12 +62,6 @@ const RedirectUrlSchema = new Schema({
|
|||
}
|
||||
})
|
||||
|
||||
// const redirectLinkSchema = new Schema({
|
||||
// request: RedirectUrlSchema,
|
||||
// })
|
||||
|
||||
|
||||
|
||||
|
||||
// Define main schema
|
||||
const CRMRestSchema = new Schema({
|
||||
|
@ -91,7 +94,8 @@ const CRMRestSchema = new Schema({
|
|||
redirectLink: {
|
||||
request: RedirectUrlSchema
|
||||
},
|
||||
callJournaling: CallJournalingSchema
|
||||
callJournaling: CallJournalingSchema,
|
||||
chatJournaling: ChatJournalingSchema
|
||||
})
|
||||
|
||||
const AuthenticationSchema = new Schema({
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
const axios = require('axios')
|
||||
|
||||
async function getContactIdChatwoot(url, token, phone) {
|
||||
|
||||
const config = {
|
||||
method: 'get',
|
||||
url: `${url}/api/v1/accounts/15/contacts/search?q=${phone}`,
|
||||
headers: {
|
||||
'api_access_token': token
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await axios(config)
|
||||
|
||||
return data.payload[0].id
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function createConversation(data, omnihitConfig) {
|
||||
|
||||
const { url, accountId, token } = omnihitConfig
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: `${url}/api/v1/accounts/${accountId}/conversations`,
|
||||
headers: {
|
||||
'api_access_token': token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: data
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const { data } = await axios(config)
|
||||
return data.id
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleConversationStatus(url, accountId, token, ticketId, payload) {
|
||||
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: `${url}/api/v1/accounts/${accountId}/conversations/${ticketId}/toggle_status`,
|
||||
headers: {
|
||||
'api_access_token': token,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
data: JSON.stringify(payload)
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await axios(config)
|
||||
console.log(JSON.stringify(response.data))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getContactIdChatwoot,
|
||||
createConversation,
|
||||
toggleConversationStatus
|
||||
}
|
|
@ -9,6 +9,7 @@ const createTicket = require('./createTicket')
|
|||
|
||||
const lookupCRMTicket = require('./lookupCRMTicket')
|
||||
const sendEventTicketCreatedToSocket = require('./sendEventTicketCreatedToSocket')
|
||||
const journalingRequest = require('./journalingRequest')
|
||||
|
||||
|
||||
async function ticketCRM(companyId, crmPhone, crmAgent, crmFirstName = 'Username') {
|
||||
|
@ -21,6 +22,26 @@ async function ticketCRM(companyId, crmPhone, crmAgent, crmFirstName = 'Username
|
|||
|
||||
const { crmRest: rest, authentication } = crmConfig.crm
|
||||
|
||||
// Record whatsapp conversation that happened in omnihit v2
|
||||
let chatJournaling = findProperty(rest, 'chatJournaling')
|
||||
|
||||
console.log('===============> chatJournaling: ', chatJournaling)
|
||||
|
||||
|
||||
if (chatJournaling) {
|
||||
|
||||
let contact = await _lookupContact(rest, authentication, crmPhone, companyId, crmFirstName)
|
||||
|
||||
const { contactId, created } = contact
|
||||
|
||||
let { request, chats, response } = chatJournaling
|
||||
|
||||
let body = findProperty(chats, 'chatDone')
|
||||
|
||||
await journalingRequest(request, body, crmCallDuration = 0, contact, crmAgent, crmPhone, authentication, rest)
|
||||
}
|
||||
|
||||
|
||||
// Send the edited contact/lead link url to hitphone to open on another browser tab
|
||||
let redirectLink = findProperty(rest, 'redirectLink')
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
function timeStamp(dateTimeISO8601) {
|
||||
const date = new Date(dateTimeISO8601)
|
||||
|
||||
date.setHours(date.getUTCHours() - 3)
|
||||
|
||||
const timestamp = date.getTime() / 1000
|
||||
|
||||
return timestamp
|
||||
}
|
||||
|
||||
|
||||
module.exports = timeStamp
|
Loading…
Reference in New Issue