crm-api-template-generator/backend/controllers/crmController.js

296 lines
8.4 KiB
JavaScript
Raw Normal View History

2023-11-29 20:05:48 +00:00
const path = require('path')
const { StatusCodes } = require("http-status-codes")
const { createCRMContact,
sendMessageSocket,
mustContainProperties,
journaling,
2024-07-19 18:48:34 +00:00
ticketCRM,
2023-11-29 20:05:48 +00:00
findProperty,
journalingRequest,
createContact,
lookupContactByPhone,
templateValidator } = require('../utils')
const fs = require("fs")
const { URL } = require('url')
const { oauth2 } = require('../utils')
const { exchangeForTokens } = oauth2
const Company = require('../models/Company')
const CRM = require('../models/CRM')
const CustomError = require('../errors')
const contactCreate = async (req, res) => {
const { companyId, crmFirstName, crmLastName, crmPhone, crmEmail } = req.body
mustContainProperties(req, ['companyId', 'crmPhone',])
await createCRMContact(companyId, crmFirstName, crmPhone, crmEmail, crmLastName)
res.status(StatusCodes.OK).send()
}
const deleteCrm = async (req, res) => {
let { companyId, crmBaseURL } = req.body
2023-11-29 20:05:48 +00:00
mustContainProperties(req, ['companyId', 'crmBaseURL',])
if (!crmBaseURL.startsWith('http://') && !crmBaseURL.startsWith('https://')) {
crmBaseURL = `https://${crmBaseURL.trim()}`
}
2023-11-29 20:05:48 +00:00
const crm = await CRM.findOne({
companyId, crmBaseURL: new URL(crmBaseURL.trim()).hostname
})
if (crm) await crm.deleteOne()
res.status(StatusCodes.OK).send()
}
const deleteCompany = async (req, res) => {
const { companyId } = req.body
mustContainProperties(req, ['companyId',])
const company = await Company.findOne({ companyId, })
if (company) await company.deleteOne()
res.status(StatusCodes.OK).send()
}
const callJournaling = async (req, res) => {
let { companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName, operationStatus } = req.body
2024-09-25 11:57:28 +00:00
console.log('REQ.BODY CRM TESTe: ', JSON.stringify(req.body, null, 6))
2024-07-19 18:48:34 +00:00
2024-09-25 11:57:28 +00:00
// Refactor this in the future.
crmPhone = '55' + crmPhone
console.log('========> CRMPHONE: ', crmPhone)
console.log('========> COMPANY ID before: ', companyId)
companyId = '40'
console.log('========> COMPANY ID after: ', companyId)
2024-09-25 11:57:28 +00:00
//
2023-11-29 20:05:48 +00:00
mustContainProperties(req, ['companyId', 'operation', 'crmPhone', 'crmAgent',])
// if (operation == 'inboundAnsweredCall' && !crmCallDuration)
// throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is inboundAnsweredCall`)
// if (operation == 'outboundAsweredCall' && !crmCallDuration)
// throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is outboundAsweredCall`)
2023-11-29 20:05:48 +00:00
if (!crmCallDuration || crmCallDuration.trim() == "" || crmCallDuration == "0")
crmCallDuration = "10"
2024-07-19 18:48:34 +00:00
if (operationStatus == "hangup")
await journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName)
else if (operationStatus == "update-answer") {
console.log('update-answer')
2024-07-19 18:48:34 +00:00
await ticketCRM(companyId, crmPhone, crmAgent, crmFirstName)
}
2023-11-29 20:05:48 +00:00
res.status(StatusCodes.OK).send()
2024-07-19 18:48:34 +00:00
}
2023-11-29 20:05:48 +00:00
const install = async (req, res) => {
const { authUrl, companyId } = req.query
console.log('--------> authUrl: ', authUrl)
2023-11-29 20:05:48 +00:00
// Store the authUrl in the session
req.session.authUrl = authUrl
res.redirect(authUrl)
}
const oauthCallBack = async (req, res) => {
const { code } = req.query
// Retrieve the stored authUrl from the session
const storedAuthUrl = req.session.authUrl
console.log('xxxxxxxxxx storedAuthUrl: ', storedAuthUrl)
2023-11-29 20:05:48 +00:00
const parsedUrl = new URL(storedAuthUrl)
const clientId = parsedUrl.searchParams.get('client_id')
if (code) {
2023-11-29 20:05:48 +00:00
let crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId })
crmOauth = crmOauth.toObject()
let authCodeProof = {
2023-11-29 20:05:48 +00:00
grant_type: 'authorization_code',
client_id: crmOauth.crm.authentication.crmClientId,
client_secret: crmOauth.crm.authentication.crmClientSecret,
redirect_uri: process.env.URL_OAUTH_CALLBACK,
code
}
2024-09-25 13:28:42 +00:00
//The PKCE is mandatory for salesforce. This is for salesforce only oauth2 that need a code_challenge and code_verifier.
const rest = crmOauth.crm.crmRest
const salesforceUrls = rest.map(endpoint => {
const key = Object.keys(endpoint)[0]
const url = endpoint[key].request.url
if (url.includes("salesforce")) {
return `${key} URL: ${url}`
}
}).filter(Boolean)
if (salesforceUrls.find(url => url.includes('salesforce'))) {
authCodeProof = {
...authCodeProof, ...{
code_verifier: `gwkPueV2GSzkFvGFiHbNjpRuq_XBEGBsihM59pMaiFalZrOQ_7J4hgtBR8GIbLHutcuUwba2k0xeKhD8ELjWEswE3xv-H2e6Jh8EOwOccj2i_rYPUlMGdPDqpuRs8D3w`,
code: `${code.split('%')[0]}`
}
}
}
//
2023-11-29 20:05:48 +00:00
2023-11-29 20:05:48 +00:00
// Exchange the authorization code for an access token and refresh token
await exchangeForTokens(crmOauth, authCodeProof)
2023-11-29 20:05:48 +00:00
const url = `${process.env.URL_OAUTH_FRONTEND_SUCCESS_REDIRECT}?clientId=${encodeURIComponent(clientId)}`
return res.redirect(url)
// return res.redirect(process.env.URL_OAUTH_FRONTEND_SUCCESS_REDIRECT)
}
res.status(StatusCodes.OK).send()
}
const testTemplate = async (req, res) => {
const { clientId, companyId } = req.body
2023-11-29 20:05:48 +00:00
let crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId, testing: true })
if (!crmOauth)
return res.status(StatusCodes.OK).send()
crmOauth = crmOauth.toObject()
2023-11-29 20:05:48 +00:00
const { crmPhoneTest } = crmOauth.crm.authentication
await templateValidator(crmPhoneTest, crmOauth.crm, companyId)
2023-11-29 20:05:48 +00:00
crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId })
crmOauth.testing = false
await crmOauth.save()
res.status(StatusCodes.OK).send()
}
const uploadCrmConfig = async (req, res) => {
const { companyId, } = req.body
mustContainProperties(req, ['companyId',])
if (!req?.file)
throw new CustomError.BadRequestError(`The crm property file must be provided`)
const file = req.file
let newCrm = fs.readFileSync(file.path, "utf8")
newCrm = JSON.parse(newCrm)
const index = newCrm.crmRest.findIndex(rest => rest?.createContactRecord)
const crmBaseURL = new URL(newCrm.crmRest[index].createContactRecord.request.url.trim()).hostname
let company = await Company.findOne({ companyId })
if (!company) {
company = await Company.create({ companyId })
}
let crm = await CRM.findOne({ companyId, crmBaseURL })
if (crm) {
crm.testing = true
crm.crm = newCrm
await crm.save()
}
else {
crm = await CRM.create({
crmBaseURL,
companyId: company.companyId,
company,
testing: true,
crm: newCrm
})
}
fs.unlinkSync(file.path)
const { type, crmClientId, crmClientSecret, crmScopes, crmPhoneTest } = crm.crm.authentication
if (type == 'oauth2') {
const { request, body, response } = findProperty(crm.crm.crmRest, 'authorizationEndpoint')
let { url } = request
url = url.replace('crmClientId', crmClientId)
.replace('crmClientSecret', crmClientSecret)
.replace('crmScopes', crmScopes)
.replace('crmRedirectURI', process.env.URL_OAUTH_CALLBACK)
const authUrl = `https://api-integracao-crm.hitmanager.app.br/api/v1/crm/install?authUrl=${encodeURIComponent(url)}&companyId=${encodeURIComponent(companyId)}`
2023-11-29 20:05:48 +00:00
console.log('--------> authUrl: ', authUrl)
return res.status(StatusCodes.OK).json({ url: authUrl })
}
else {
await templateValidator(crmPhoneTest, newCrm, companyId)
crm.testing = false
await crm.save()
}
res.status(StatusCodes.OK).send()
}
const getCrms = async (req, res) => {
const { companyId, } = req.params
if (!companyId)
throw new CustomError.BadRequestError(`The companyId must be provided in the URL`)
const crms = await CRM.find({ companyId }, { _id: 1, crmBaseURL: 1, createdAt: 1, companyId: 1, enabled: 1 })
res.status(StatusCodes.OK).send(crms)
}
2023-11-29 20:05:48 +00:00
module.exports = {
contactCreate,
uploadCrmConfig,
callJournaling,
oauthCallBack,
install,
deleteCrm,
deleteCompany,
testTemplate,
getCrms
2023-11-29 20:05:48 +00:00
}