diff --git a/backend/Templates-test/template_crm_sap_gradesco_using_tasks2.json b/backend/Templates-test/template_crm_sap_gradesco_using_tasks2.json
new file mode 100644
index 0000000..394b39b
--- /dev/null
+++ b/backend/Templates-test/template_crm_sap_gradesco_using_tasks2.json
@@ -0,0 +1,241 @@
+{
+ "authentication": {
+ "type": "basic",
+ "userName": "_INTEGRACAO_",
+ "passWord": "p3G44K10366",
+ "crmPhoneTest": "+5511998765123"
+ },
+ "crmRest": [
+ {
+ "createContactRecord": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Post",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/ContactCollection"
+ },
+ "body": {
+ "LastName": "crmLastName",
+ "FirstName": "crmFirstName",
+ "Phone": "+crmPhone",
+ "Mobile": "+crmPhone",
+ "AccountID": "1000320"
+ },
+ "response": {
+ "id": "d.results.ContactID",
+ "objectId": "d.results.ObjectID"
+ }
+ }
+ },
+ {
+ "createContactRecord2": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Post",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/IndividualCustomerCollection"
+ },
+ "body": {
+ "RoleCode": "CRM000",
+ "LastName": "crmLastName",
+ "FirstName": "crmFirstName",
+ "Phone": "+crmPhone",
+ "Mobile": "+crmPhone"
+ },
+ "response": {
+ "id": "d.results.CustomerID",
+ "objectId": "d.results.ObjectID"
+ }
+ }
+ },
+ {
+ "lookupContactByPhone": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Get",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/ContactCollection?$select=ObjectID,FirstName,LastName,Email,StatusCode,AccountID,StatusCodeText,Phone,Mobile,NormalisedMobile,ContactID&$filter=NormalisedMobile eq '%2BcrmPhone'"
+ },
+ "response": {
+ "phone": "d.results[0].NormalisedMobile",
+ "id": "d.results[0].ContactID",
+ "objectId": "d.results[0].ObjectID",
+ "accountId": "d.results[0].AccountID"
+ }
+ }
+ },
+ {
+ "lookupContactByPhone2": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Get",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/IndividualCustomerCollection?%24select=ObjectID%2CFirstName%2CLastName%2CEmail%2CPhone%2CMobile%2CNormalisedPhone%2CNormalisedMobile%2CCustomerID&%24filter=NormalisedPhone%20eq%20%27%2BcrmPhone%27"
+ },
+ "response": {
+ "phone": "d.results[0].NormalisedPhone",
+ "id": "d.results[0].CustomerID",
+ "objectId": "d.results[0].ObjectID"
+ }
+ }
+ },
+ {
+ "callJournaling": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Post",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/PhoneCallCollection"
+ },
+ "calls": [
+ {
+ "inboundAnsweredCall": {
+ "Subject": "Ligação recebida",
+ "Status": "1",
+ "InitiatorCode": "2",
+ "DataOriginTypeCode": "3",
+ "MainContactPartyID": "crmContactId"
+ }
+ },
+ {
+ "outboundAnsweredCall": {
+ "Subject": "Ligação Realizada",
+ "Status": "1",
+ "InitiatorCode": "3",
+ "DataOriginTypeCode": "3",
+ "MainContactPartyID": "crmContactId"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "chatJournaling": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Post",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/TasksCollection"
+ },
+ "chats": [
+ {
+ "chatDone": {
+ "Subject": "URL de la conversación en omnihit",
+ "Status": "1",
+ "PriorityCode": "3",
+ "MainContactPartyID": "crmContactId",
+ "TasksTextCollection": {
+ "results": [
+ {
+ "Text": "Conversación iniciada por WhatsApp. URL de la conversación de Ominhit: chatLink",
+ "TypeCode": "10002"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "redirectLink": {
+ "request": {
+ "url": "https://my365398.crm.ondemand.com/sap/public/byd/runtime?bo_ns=http%3A%2F%2Fsap.com%2FthingTypes&bo=COD_GENERIC&node=Root&operation=OnExtInspect¶m.Type=COD_CONTACT_TT¶m.InternalID=crmContactId"
+ }
+ }
+ },
+ {
+ "redirectLink2": {
+ "request": {
+ "url": "https://my365398.crm.ondemand.com/sap/ap/ui/clogin?saml2=disabled&app.component=%2fSAP_UI_CT%2fMain%2froot.uiccwoc&rootWindow=X&redirectUrl=%2fsap%2fpublic%2fbyd%2fruntime&supressAutoLogon=true&sap-ui-language=en_us#Nav/1/crmTicketId"
+ }
+ }
+ },
+ {
+ "createTicketRecord": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Post",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/ServiceRequestCollection"
+ },
+ "body": {
+ "Name": "Nova Solicitação de Serviço API (Com Contato) test 09",
+ "ServicePriorityCode": "3",
+ "ServiceRequestUserLifeCycleStatusCode": "1",
+ "DataOriginTypeCode": "3",
+ "BuyerPartyID": "crmAccountId",
+ "BuyerMainContactPartyID": "crmContactId",
+ "ServiceIssueCategoryID": "Z1000"
+ },
+ "response": {
+ "id": "d.results.ID",
+ "objectId": "d.results.ObjectID"
+ }
+ }
+ },
+ {
+ "createTicketRecord2": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Post",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/ServiceRequestCollection"
+ },
+ "body": {
+ "Name": "Nova Solicitação de Serviço API (Com Contato) individual customers 1",
+ "ServicePriorityCode": "3",
+ "ServiceRequestUserLifeCycleStatusCode": "1",
+ "DataOriginTypeCode": "3",
+ "BuyerPartyID": "crmContactId",
+ "ReportedForPartyID": "crmContactId",
+ "ServiceIssueCategoryID": "Z1000"
+ },
+ "response": {
+ "id": "d.results.ID",
+ "objectId": "d.results.ObjectID"
+ }
+ }
+ },
+ {
+ "lookupTicket": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Get",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/ServiceRequestCollection?$filter=BuyerMainContactPartyID%20eq%20%crmContactId%27%20and%20ServiceRequestUserLifeCycleStatusCode%20eq%20%271%27"
+ },
+ "response": {
+ "id": "d.results[0].ID",
+ "objectId": "d.results[0].ObjectID",
+ "status": "d.results[0].ServiceRequestUserLifeCycleStatusCodeText"
+ }
+ }
+ },
+ {
+ "lookupTicket2": {
+ "request": {
+ "requestContentType": "application/json",
+ "requestEncoding": "Json",
+ "requestType": "Get",
+ "responseType": "Json",
+ "url": "https://my365398.crm.ondemand.com/sap/c4c/odata/v1/c4codataapi/ServiceRequestCollection?$filter=BuyerPartyID%20eq%20%27crmContactId%27%20and%20ServiceRequestUserLifeCycleStatusCode%20eq%20%271%27"
+ },
+ "response": {
+ "id": "d.results[0].ID",
+ "objectId": "d.results[0].ObjectID",
+ "status": "d.results[0].ServiceRequestUserLifeCycleStatusCodeText"
+ }
+ }
+ }
+ ]
+}
diff --git a/backend/controllers/crmController.js b/backend/controllers/crmController.js
index 20e8f15..825f430 100644
--- a/backend/controllers/crmController.js
+++ b/backend/controllers/crmController.js
@@ -32,6 +32,7 @@ const sfcase = require('../utils/sfCase')
const sfCaseUpdate = require('../utils/sfCaseUpdate')
const removeZeroInicial = require('../utils/removeZeroInicial')
const lookupContactByEmail = require('../utils/lookupCRMContactByEmail')
+const generateC4CServiceRequestDeepLinkBase64 = require('../utils/generateC4CServiceRequestDeepLinkBase64')
const contactCreate = async (req, res) => {
@@ -39,11 +40,11 @@ const contactCreate = async (req, res) => {
const { companyId, crmFirstName, crmLastName, crmPhone, crmEmail, dynamicBodyRequest } = req.body
// mustContainProperties(req, ['companyId', 'crmPhone',])
-
+
if (!companyId || (!crmPhone && !crmEmail)) {
return res.status(StatusCodes.BAD_REQUEST).json({
message: 'companyId e crmPhone ou crmEmail são obrigatórios.'
- });
+ })
}
await createCRMContact(companyId, crmFirstName, crmPhone, crmEmail, crmLastName, dynamicBodyRequest)
@@ -72,39 +73,39 @@ const contactCreate = async (req, res) => {
// res.status(StatusCodes.OK).json({ exist: false })
// }
const checkContact = async (req, res) => {
- const { companyId, crmPhone, crmEmail } = req.body;
+ const { companyId, crmPhone, crmEmail } = req.body
if (!companyId || (!crmPhone && !crmEmail)) {
return res.status(StatusCodes.BAD_REQUEST).json({
message: 'companyId and either crmPhone or crmEmail are required.'
- });
+ })
}
- const crmFiles = await loadCRM(companyId);
+ const crmFiles = await loadCRM(companyId)
if (crmFiles.length > 0) {
- const { crmRest: rest, authentication } = crmFiles[0].crm;
- let contact = null;
+ const { crmRest: rest, authentication } = crmFiles[0].crm
+ let contact = null
if (crmPhone) {
- contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId);
+ contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId)
}
if (!contact?.exist && crmEmail) {
- contact = await lookupContactByEmail(rest, authentication, crmEmail, companyId);
+ contact = await lookupContactByEmail(rest, authentication, crmEmail, companyId)
}
if (contact?.exist) {
- return res.status(StatusCodes.OK).json({ exist: contact.exist });
+ return res.status(StatusCodes.OK).json({ exist: contact.exist })
}
}
- res.status(StatusCodes.OK).json({ exist: false });
-};
+ res.status(StatusCodes.OK).json({ exist: false })
+}
// const contactActivity = async (req, res) => {
// const { companyId, crmPhone, ticketId } = req.body
// mustContainProperties(req, ['companyId', 'crmPhone', 'ticketId'])
-
+
// await whatsappJournalingCRM(
// companyId,
// crmPhone,
@@ -117,16 +118,16 @@ const checkContact = async (req, res) => {
// }
const contactActivity = async (req, res) => {
// 1. Recebe 'crmEmail' do corpo da requisição
- const { companyId, crmPhone, crmEmail, ticketId, dynamicBodyRequest } = req.body;
+ const { companyId, crmPhone, crmEmail, ticketId, dynamicBodyRequest } = req.body
// 2. Ajusta a validação para que 'crmPhone' ou 'crmEmail' seja obrigatório
// Se nenhum dos dois for fornecido, a requisição é inválida.
if (!crmPhone && !crmEmail) {
return res.status(StatusCodes.BAD_REQUEST).send({
message: "crmPhone ou crmEmail é obrigatório."
- });
+ })
}
-
+
// A validação para 'companyId' e 'ticketId' continua, se forem obrigatórios
// mustContainProperties(req, ['companyId', 'ticketId']);
@@ -139,10 +140,10 @@ const contactActivity = async (req, res) => {
ticketId,
crmEmail,
dynamicBodyRequest
- );
+ )
- res.status(StatusCodes.OK).send();
-};
+ res.status(StatusCodes.OK).send()
+}
const deleteCrm = async (req, res) => {
@@ -191,13 +192,13 @@ const callJournaling = async (req, res) => {
// return res.status(StatusCodes.OK).send()
// Refactor this in the future. Integração Gradezco colombia, o crm sap precisa criar o contato com o + no inicio seguido do codigo do pais
- if(companyId == "4953"){ // companyId da gradezco colombia
+ if (companyId == "4953") { // companyId da gradezco colombia
crmPhone = '57' + crmPhone
}
- else{
+ else {
crmPhone = '55' + crmPhone
}
-
+
console.log('========> CRMPHONE: ', crmPhone)
console.log('========> COMPANY ID before: ', companyId)
@@ -223,17 +224,18 @@ const callJournaling = async (req, res) => {
// throw new CustomError.BadRequestError(`The crmCallDuration property must be provided when operation is outboundAsweredCall`)
-
-
if (!crmCallDuration || crmCallDuration.trim() == "" || crmCallDuration == "0")
crmCallDuration = "10"
- console.log("=======================> crmLastName: ", crmLastName)
+ console.log("=======================> crmLastName: ", crmLastName)
// crmLastName
- if (operationStatus == "hangup")
- await journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName, crmLastName)
+ if (operationStatus == "hangup") {
+ let resp = await journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration, crmFirstName, crmLastName)
+ return res.status(StatusCodes.OK).json({ ticketLinks: resp })
+ }
+
else if (operationStatus == "update-answer") {
@@ -269,27 +271,63 @@ const callJournaling = async (req, res) => {
}
-const contactLink = async (req, res) => {
- const { companyId, contactId } = req.query
+const ticketLink = async (req, res) => {
+
+ const { companyId, ticketId } = req.query
const crmFiles = await loadCRM(companyId)
-
+
const crmContactIds = []
for (const crmConfig of crmFiles) {
- const { crmRest: rest, authentication } = crmConfig.crm
+ const { crmRest: rest, authentication } = crmConfig.crm
+
+ let redirectLink = findProperty(rest, 'redirectLink2')
+
+ if (redirectLink) {
+
+ const url = redirectLink?.request?.url?.replace("crmTicketId", generateC4CServiceRequestDeepLinkBase64(ticketId))
+
+ console.log('===============> ticketLink redirect Link: ', url)
+
+ return res.status(StatusCodes.OK).json({ link: url })
+ }
+
+ }
+
+ res.status(StatusCodes.NOT_FOUND).json({ message: "Company id not found or not exist redirectLink2 property in template crm" })
+
+}
+
+const contactLink = async (req, res) => {
+ const { companyId, contactId } = req.query
+
+ // test start
+ // return res.status(StatusCodes.OK).json({
+ // "link": "https://my365398.crm.ondemand.com/sap/ap/ui/clogin?saml2=disabled&app.component=%2fSAP_UI_CT%2fMain%2froot.uiccwoc&rootWindow=X&redirectUrl=%2fsap%2fpublic%2fbyd%2fruntime&supressAutoLogon=true&sap-ui-language=en_us#Nav/1/eyJ0aGluZ3BhcmFtcyI6eyJLZXkiOiJPYm5LZXkkPD94bWwgdmVyc2lvbj1cIjEuMFwiIGVuY29kaW5nPVwidXRmLTE2XCI/PjxPYm5LZXk+PFNvdXJjZT48U291cmNlUGF0aD4vQllEX0NPRC9TZXJ2aWNlT25EZW1hbmQvUHJpdmF0ZUFjY291bnQvQ09EX1NFT0RfSU5EX0FDQ09VTlRfVEkuVEkudWljb21wb25lbnQ8L1NvdXJjZVBhdGg+PC9Tb3VyY2U+PFBhdGg+L1Jvb3QvVGlja2V0TGlzdFswMkMyQUM2NEFDRUMxRkQwQUJCREE2RTAwQTQ0MDQzN10vVVVJRDwvUGF0aD48RGF0YT48VVVJRD4wMkMyQUM2NEFDRUMxRkQwQUJCREE2RTAwQTQ0MDQzNzwvVVVJRD48L0RhdGE+PC9PYm5LZXk+IiwiU291cmNlUGF0aCI6Ii9Sb290L1RpY2tldExpc3RbMDJDMkFDNjRBQ0VDMUZEMEFCQkRBNkUwMEE0NDA0MzddL1VVSUQifSwiaW5Qb3J0IjoiSW5zcGVjdCIsInRhcmdldCI6Ii9CWURfQ09EL1NlcnZpY2VPbkRlbWFuZC9Db2xsYWJvcmF0aW9uL0NPRF9TUl9USS5USS51aWNvbXBvbmVudCIsIndpbklkIjoiYzE1YTIyOWY4ZmQwNGFmNmI0YTJlOTFjYTNlMGZkM2MifQ=="
+ // })
+ // test end
+
+
+ const crmFiles = await loadCRM(companyId)
+
+ const crmContactIds = []
+
+ for (const crmConfig of crmFiles) {
+
+ const { crmRest: rest, authentication } = crmConfig.crm
// Send the edited contact/lead link url to hitphone to open on another browser tab
let redirectLink = findProperty(rest, 'redirectLink')
- if (redirectLink) {
+ if (redirectLink) {
const url = redirectLink?.request?.url?.replace(/crmContactId/g, contactId)
console.log('===============> Contact id redirect Link: ', url)
- return res.status(StatusCodes.OK).json({ link: url});
+ return res.status(StatusCodes.OK).json({ link: url })
// console.log('new URL(url).hostname: ', new URL(url).hostname)
@@ -299,7 +337,7 @@ const contactLink = async (req, res) => {
}
- res.status(StatusCodes.NOT_FOUND).json({ message: "Company id not found!"});
+ res.status(StatusCodes.NOT_FOUND).json({ message: "Company id not found!" })
}
@@ -358,7 +396,7 @@ const oauthCallBack = async (req, res) => {
console.log('xxxxxxxxxx companyId: ', companyId)
console.log('xxxxxxxxxx code: ', code)
- if (code) {
+ if (code) {
let crmOauth = await CRM.findOne({ 'crm.authentication.crmClientId': clientId, 'companyId': companyId })
@@ -534,6 +572,7 @@ const createTicket = async (req, res) => {
.catch(function (error) {
console.error(`Error on create ticket: companyID ${companyId} | crmPhone: ${crmPhone}`)
+ console.error(error)
console.error(error?.response?.data)
console.error(error?.response?.status)
console.error(error?.response?.headers)
@@ -689,26 +728,26 @@ const webhook_crm = async (req, res) => {
}
return res.set('Content-Type', 'text/xml').status(StatusCodes.OK).send(responseXml)
-}
+}
const getClientAccessToken = async (req, res) => {
const { companyId } = req.params
const { clientId } = req.query
- console.log('========> getClientAccessToken companyId: ', companyId, ' clientId: ', clientId);
+ console.log('========> getClientAccessToken companyId: ', companyId, ' clientId: ', clientId)
if (!companyId || !clientId) {
- console.error('Company ID or Client ID is missing in the request parameters.');
- return res.status(StatusCodes.BAD_REQUEST).send({ msg: "Company ID and Client ID are required!" });
+ console.error('Company ID or Client ID is missing in the request parameters.')
+ return res.status(StatusCodes.BAD_REQUEST).send({ msg: "Company ID and Client ID are required!" })
}
- const accessToken = await getAccessToken(clientId, companyId);
+ const accessToken = await getAccessToken(clientId, companyId)
if (!accessToken) {
- console.error(`Access token not found for companyId: ${companyId} and clientId: ${clientId}`);
- return res.status(StatusCodes.NOT_FOUND).send({ msg: "Access token not found!" });
+ console.error(`Access token not found for companyId: ${companyId} and clientId: ${clientId}`)
+ return res.status(StatusCodes.NOT_FOUND).send({ msg: "Access token not found!" })
}
- return res.status(StatusCodes.OK).json({ accessToken });
+ return res.status(StatusCodes.OK).json({ accessToken })
}
module.exports = {
@@ -729,7 +768,8 @@ module.exports = {
checkContact,
contactActivity,
getClientAccessToken,
- contactLink
+ contactLink,
+ ticketLink
}
diff --git a/backend/models/CRM.js b/backend/models/CRM.js
index 556ced8..32ef680 100644
--- a/backend/models/CRM.js
+++ b/backend/models/CRM.js
@@ -77,22 +77,43 @@ const CRMRestSchema = new Schema({
body: Object,
response: Object
},
+ createContactRecord2: {
+ request: RequestSchema,
+ body: Object,
+ response: Object
+ },
lookupContactByPhone: {
request: RequestSchema,
response: Object
},
+ lookupContactByPhone2: {
+ request: RequestSchema,
+ response: Object
+ },
createTicketRecord: {
request: RequestSchema,
body: Object,
response: Object
},
+ createTicketRecord2: {
+ request: RequestSchema,
+ body: Object,
+ response: Object
+ },
lookupTicket: {
request: RequestSchema,
response: Object
},
+ lookupTicket2: {
+ request: RequestSchema,
+ response: Object
+ },
redirectLink: {
request: RedirectUrlSchema
},
+ redirectLink2: {
+ request: RedirectUrlSchema
+ },
callJournaling: CallJournalingSchema,
chatJournaling: ChatJournalingSchema,
createCase: {
diff --git a/backend/models/CRM_Ticket.js b/backend/models/CRM_Ticket.js
index a7ad280..dc8f258 100644
--- a/backend/models/CRM_Ticket.js
+++ b/backend/models/CRM_Ticket.js
@@ -11,17 +11,20 @@ const crmTicketSchema = new Schema({
type: mongoose.Schema.ObjectId,
ref: 'crm',
required: true
- },
+ },
ticketId: {
type: String,
required: true,
},
+ ticketId2: {
+ type: String,
+ },
contact: {
type: mongoose.Schema.ObjectId,
ref: 'contact',
required: true
},
-}, { timestamps: true })
+}, { timestamps: true })
const CRM_Ticket = mongoose.model('CRM_Ticket', crmTicketSchema)
diff --git a/backend/routes/crmRoute.js b/backend/routes/crmRoute.js
index ae2af45..0de4ac8 100644
--- a/backend/routes/crmRoute.js
+++ b/backend/routes/crmRoute.js
@@ -1,7 +1,7 @@
const express = require('express')
const router = express.Router()
const { authorization, } = require('../middleware/authentication')
-const { contactCreate, contactActivity, checkContact, sfCreateCase, sfUpdateCase, createTicket, testTemplate, webhook_crm, uploadCrmConfig, callJournaling, oauthCallBack, install, deleteCrm, deleteCompany, getCrms, webhook, getClientAccessToken, contactLink } = require('../controllers/crmController')
+const { contactCreate, contactActivity, checkContact, sfCreateCase, sfUpdateCase, createTicket, testTemplate, webhook_crm, uploadCrmConfig, callJournaling, oauthCallBack, install, deleteCrm, deleteCompany, getCrms, webhook, getClientAccessToken, contactLink, ticketLink } = require('../controllers/crmController')
const { fileUpload } = require("../utils")
router.route('/create-contact').post(authorization, contactCreate)
@@ -19,6 +19,7 @@ router.route('/salesforce/case').patch(authorization, sfUpdateCase)
router.route('/oauth-callback').get(oauthCallBack)
router.route('/contact-link').get(authorization, contactLink)
+router.route('/ticket-link').get(authorization, ticketLink)
router.route('/install').get(install)
router.route('/test').post(testTemplate)
diff --git a/backend/utils/createContact.js b/backend/utils/createContact.js
index c2dcc31..c2d5d2e 100644
--- a/backend/utils/createContact.js
+++ b/backend/utils/createContact.js
@@ -8,13 +8,27 @@ const CRM = require('../models/CRM')
const requestConfigHeader = require('./requestConfigHeader')
const sendMessageSocket = require('./sendMessageSocket')
-async function createContact(companyId, rest, authentication, crmPhone = '', crmFirstName = 'Username', crmLastName = 'Last name', crmEmail = '', test = {}, dynamicBodyRequest = {}) {
- let { request, body, response } = findProperty(rest, 'createContactRecord')
-
+async function createContact(companyId, rest, authentication, crmPhone = '', crmFirstName = 'Username', crmLastName = 'Last name', crmEmail = '', test = {}, dynamicBodyRequest = {}, flow = 1) {
+
+ let propertyKey
+
+ switch (flow) {
+ case 2:
+ propertyKey = 'createContactRecord2'
+ break
+ default:
+ propertyKey = 'createContactRecord'
+ break
+ }
+
+ console.log("===============> createContact propertyKey: ", propertyKey)
+
+ let { request, body, response } = findProperty(rest, propertyKey)
+
const { requestContentType, requestEncoding, requestType, responseType, url } = request
// O identificador a ser usado na requisição (prioriza telefone, mas usa e-mail se não houver)
- const lookupValue = crmPhone || crmEmail;
+ const lookupValue = crmPhone || crmEmail
body = flatten(body)
@@ -25,13 +39,13 @@ async function createContact(companyId, rest, authentication, crmPhone = '', crm
crmEmail
}
- for (const prop in body) {
+ for (const prop in body) {
// Para o crm SAP que precisa do +57 no inicio do contato para ser criado corretamente
- if(body[prop].includes("+crmPhone")){
- body[prop] = `+${crmPhone}`
+ if (body[prop].includes("+crmPhone")) {
+ body[prop] = `+${crmPhone}`
continue
- }
+ }
if (mapping.hasOwnProperty(body[prop])) {
@@ -49,7 +63,7 @@ async function createContact(companyId, rest, authentication, crmPhone = '', crm
}
}
- body = unflatten(body)
+ body = unflatten(body)
const { type, userName, passWord, token, crmClientId } = authentication
@@ -65,7 +79,7 @@ async function createContact(companyId, rest, authentication, crmPhone = '', crm
console.log('#####################')
console.log('CREATE CONTACT PAYLOAD: ', JSON.stringify(config, null, 6))
- console.log('#####################')
+ console.log('#####################')
if (dynamicBodyRequest && Object.keys(dynamicBodyRequest) !== 0) {
config.data = { ...config.data, ...dynamicBodyRequest }
@@ -95,8 +109,6 @@ async function createContact(companyId, rest, authentication, crmPhone = '', crm
throw error
}
- // let { data } = await axios(config)
-
data = flatten(data)
let auxContactId
@@ -107,7 +119,7 @@ async function createContact(companyId, rest, authentication, crmPhone = '', crm
const _prop = prop.replace(/^\d+\./, '').replace(/(?:^|\.)\d+\b/g, '')
if (_prop == response?.id?.trim()) {
- auxContactId = data[prop]
+ auxContactId = data[prop]
}
if (_prop == response?.objectId?.trim()) {
@@ -117,14 +129,14 @@ async function createContact(companyId, rest, authentication, crmPhone = '', crm
console.log('---------> createContact crmPhone: ', crmPhone, ' | auxContactId: ', auxContactId, ' | auxContactId2: ', auxContactId2)
- if (auxContactId && !test?.testing && crmEmail=='') {
-
+ if (auxContactId && !test?.testing && crmEmail == '') {
+
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 })
+ await CRM_Contact.create({ companyId, crm, crmBaseURL: new URL(url).hostname, contactId: auxContactId, phone: crmPhone })
}
- return { exist: true, contactId: auxContactId, phone: crmPhone, contactId2: auxContactId2}
+ return { exist: true, contactId: auxContactId, phone: crmPhone, contactId2: auxContactId2, flow: flow }
}
diff --git a/backend/utils/createTicket.js b/backend/utils/createTicket.js
index ad8807e..81dc6df 100644
--- a/backend/utils/createTicket.js
+++ b/backend/utils/createTicket.js
@@ -8,18 +8,39 @@ const findProperty = require('./findProperty')
const CRM = require('../models/CRM')
const requestConfigHeader = require('./requestConfigHeader')
const sendEventTicketCreatedToSocket = require('./sendEventTicketCreatedToSocket')
+const generateC4CServiceRequestDeepLinkBase64 = require('./generateC4CServiceRequestDeepLinkBase64')
-async function createTicket(companyId, rest, authentication, crmPhone, crmFirstName = 'Username', crmLastName = 'Last name', crmEmail = '', test = {}, crmContactId, crmAgent) {
+async function createTicket(companyId, rest, authentication, crmPhone, crmFirstName = 'Username', crmLastName = 'Last name', crmEmail = '', test = {}, contact, crmAgent) {
let ticketUrl = ''
- let { request, body, response } = findProperty(rest, 'createTicketRecord')
+ let crmContactId = contact.contactId
+
+ let flow = contact?.flow
+ let propertyKey
+
+ switch (flow) {
+ case 2:
+ propertyKey = 'createTicketRecord2'
+ break
+ default:
+ propertyKey = 'createTicketRecord'
+ break
+ }
+
+ console.log('==============> propertyKey createTicketRecord2: ', propertyKey)
+
+ let { request, body, response } = findProperty(rest, propertyKey)
console.log('==============> crmContactId: ', crmContactId)
+ console.log('==============> crmPhone: ', crmPhone)
+ console.log("==============> contact?.flow: ", contact?.flow)
+
const { requestContentType, requestEncoding, requestType, responseType, url } = request
console.log('========> body1: ', JSON.stringify(body, null, 6))
+ console.log("==========>createTicket contact: ", JSON.stringify(contact, null, 6))
body = flatten(body)
@@ -30,7 +51,8 @@ async function createTicket(companyId, rest, authentication, crmPhone, crmFirstN
crmLastName,
crmPhone,
crmEmail,
- crmContactId
+ crmContactId,
+ crmAccountId: contact?.accountId
}
for (const prop in body) {
@@ -62,11 +84,7 @@ async function createTicket(companyId, rest, authentication, crmPhone, crmFirstN
sendMessageSocket({ companyId, status: 'processing', data: { request: config, msg } })
}
- // console.log('===============> createTicket: ', JSON.stringify(config, null, 6))
-
-
-
-
+ console.log('===============> createTicket: ', JSON.stringify(config, null, 6))
let resp
@@ -100,6 +118,8 @@ async function createTicket(companyId, rest, authentication, crmPhone, crmFirstN
data = flatten(data)
let auxTicketId
+ let auxTicketId2
+
for (const prop in data) {
@@ -107,24 +127,40 @@ async function createTicket(companyId, rest, authentication, crmPhone, crmFirstN
if (_prop == response?.id?.trim()) {
auxTicketId = data[prop]
- break
+ }
+
+ if (_prop == response?.objectId?.trim()) {
+ auxTicketId2 = data[prop]
}
}
+ console.log("========> createTicket auxTicketId: ", auxTicketId, " | auxTicketId2: ", auxTicketId2)
+
if (auxTicketId && !test?.testing) {
- const contact = await CRM_Contact.findOne({ companyId, crmBaseURL: new URL(url).hostname, phone: crmPhone })
+
+ let contact2 = await CRM_Contact.findOne({ companyId, crmBaseURL: new URL(url).hostname, phone: crmPhone })
+
+ if (!contact2) {
+ const crm = await CRM.findOne({ companyId, crmBaseURL: new URL(url).hostname })
+ contact2 = await CRM_Contact.create({ companyId, crm, crmBaseURL: new URL(url).hostname, contactId: contact.contactId, phone: crmPhone })
+ }
+
const crm = await CRM.findOne({ companyId, crmBaseURL: new URL(url).hostname })
- await CRM_Ticket.create({ companyId, contact, ticketId: auxTicketId, crm })
+ await CRM_Ticket.create({ companyId, contact: contact2, ticketId: auxTicketId, ticketId2: auxTicketId2, crm })
- // ticketUrl = `https://app.hubspot.com/contacts/23636141/ticket/${auxTicketId}`
- ticketUrl = `https://app.hubspot.com/contacts/${crmAccountId}/ticket/${auxTicketId}`
+ if (url.includes("hubapi")) {
+ ticketUrl = `https://app.hubspot.com/contacts/${crmAccountId}/ticket/${auxTicketId}`
+ }
+ else if (url.includes("c4codataapi")) {
+ ticketUrl = `https://my365398.crm.ondemand.com/sap/ap/ui/clogin?saml2=disabled&app.component=%2fSAP_UI_CT%2fMain%2froot.uiccwoc&rootWindow=X&redirectUrl=%2fsap%2fpublic%2fbyd%2fruntime&supressAutoLogon=true&sap-ui-language=en_us#Nav/1/${generateC4CServiceRequestDeepLinkBase64(auxTicketId2)}`
+ }
sendEventTicketCreatedToSocket({ companyId, extension: crmAgent, ticketUrl: ticketUrl })
}
- return { exist: true, ticketId: auxTicketId, phone: crmPhone, ticketUrl }
+ return { exist: true, ticketId: auxTicketId, ticketId2: auxTicketId2, phone: crmPhone, ticketUrl }
}
diff --git a/backend/utils/generateC4CServiceRequestDeepLinkBase64.js b/backend/utils/generateC4CServiceRequestDeepLinkBase64.js
new file mode 100644
index 0000000..6d49e08
--- /dev/null
+++ b/backend/utils/generateC4CServiceRequestDeepLinkBase64.js
@@ -0,0 +1,34 @@
+
+function generateC4CServiceRequestDeepLinkBase64(objectId) {
+ // 1. Defina o XML Template.
+ // O UUID deve ser inserido duas vezes neste XML.
+ const xmlTemplate = `/BYD_COD/SalesOnDemand/Account/UI/COD_Account_TI.TI.uicomponent/Root/ServiceRequests[${objectId}]/UUID${objectId}`
+
+ // 2. Defina o objeto JSON completo (Payload).
+ const payload = {
+ "thingparams": {
+ // O XML deve ser incluído dentro da string 'Key' e escapar as aspas.
+ "Key": `ObnKey$${xmlTemplate.replace(/"/g, '\\"')}`,
+ "SourcePath": `/Root/ServiceRequests[${objectId}]/UUID`
+ },
+ "inPort": "Inspect",
+ "target": "/BYD_COD/ServiceOnDemand/Collaboration/COD_SR_TI.TI.uicomponent",
+ // Note: O 'winId' é geralmente fixo ou pode ser dinâmico em algumas implementações.
+ // Estamos usando o valor que você forneceu:
+ "winId": "b175025e290bfa7a7b5a8c88c3330546"
+ }
+
+ // 3. Converta o objeto JSON para uma string JSON (sem formatação).
+ const jsonString = JSON.stringify(payload)
+
+ // 4. Codifique a string JSON para Base64.
+ // Node.js utiliza Buffer.from(string).toString('base64').
+ const base64String = Buffer.from(jsonString, 'utf8').toString('base64')
+
+ return base64String
+}
+
+module.exports = generateC4CServiceRequestDeepLinkBase64
+
+
+
diff --git a/backend/utils/journaling.js b/backend/utils/journaling.js
index 34e92a5..f882949 100644
--- a/backend/utils/journaling.js
+++ b/backend/utils/journaling.js
@@ -4,20 +4,25 @@ const createContact = require('./createContact')
const findProperty = require('./findProperty')
const journalingRequest = require('./journalingRequest')
+const ticketCRM = require('./ticketCRM')
-async function journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration = 0, crmFirstName ='Username', crmLastName = 'Last name') {
-
- const crmFiles = await loadCRM(companyId)
+async function journaling(companyId, operation, crmPhone, crmAgent, crmCallDuration = 0, crmFirstName = 'Username', crmLastName = 'Last name') {
+
+ const crmFiles = await loadCRM(companyId)
+ const crmTicketLinks = []
for (const crmConfig of crmFiles) {
const { crmRest: rest, authentication } = crmConfig.crm
- let contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId)
-
+ let contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId)
+
+ console.log("===========> journaling contat ", JSON.stringify(contact, null, 6))
+
if (!contact.exist) {
- contact = await createContact(companyId, rest, authentication, crmPhone, crmFirstName, crmLastName)
- }
+ // createContact(companyId, rest, authentication, crmPhone = '', crmFirstName = 'Username', crmLastName = 'Last name', crmEmail = '', test = {}, dynamicBodyRequest = {})
+ contact = await createContact(companyId, rest, authentication, crmPhone, crmFirstName, crmLastName, crmEmail = '', test = {}, dynamicBodyRequest = {}, contact?.flow)
+ }
let { request, calls, response } = findProperty(rest, 'callJournaling')
@@ -25,6 +30,29 @@ async function journaling(companyId, operation, crmPhone, crmAgent, crmCallDurat
await journalingRequest(request, body, crmCallDuration, contact, crmAgent, crmPhone, authentication, rest, companyId)
+ // create ticket crm sap cliente gradezco. To each call is created or open a ticket
+ if (companyId == "4953") {
+
+ console.log("============> journaling contact?.flow: ", contact?.flow)
+
+ const crmTicketLinks = await ticketCRM(companyId, crmPhone, crmAgent, crmFirstName, contact?.flow)
+ .catch(function (error) {
+
+ console.error(`Error on create jounaling ticket: companyID ${companyId} | crmPhone: ${crmPhone}`)
+ console.error(error)
+ console.error(error?.response?.data)
+ console.error(error?.response?.status)
+ console.error(error?.response?.headers)
+
+ throw new Error(`Error on create jounaling ticket: companyID ${companyId} | crmPhone: ${crmPhone}`)
+ })
+
+ // console.log('jounaling crmTicketLinks: ', crmTicketLinks)
+ return crmTicketLinks
+
+ }
+
+ return []
}
}
diff --git a/backend/utils/lookupCRMContactByPhone.js b/backend/utils/lookupCRMContactByPhone.js
index 42d7187..f6c4e8d 100644
--- a/backend/utils/lookupCRMContactByPhone.js
+++ b/backend/utils/lookupCRMContactByPhone.js
@@ -12,12 +12,12 @@ const sendMessageSocket = require('./sendMessageSocket')
const CRM_Ticket = require('../models/CRM_Ticket')
async function lookupContactByPhone(rest, authentication, crmPhone, companyId, test = {}, cacheContact = false) {
-
+
let { request, body, response } = findProperty(rest, 'lookupContactByPhone')
let { requestContentType, requestEncoding, requestType, responseType, url } = request
- const { type, userName, passWord, token, crmClientId, crmAccountId} = authentication
+ const { type, userName, passWord, token, crmClientId, crmAccountId } = authentication
if (cacheContact) {
const crmInfo = await CRM_Contact.findOne({ companyId, crmBaseURL: new URL(url).hostname, phone: crmPhone })
@@ -35,13 +35,13 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
console.log("PAYLOAD CONFIG LOOKUP CONTACT BY PHONE CONFIG.url 1: ", config.url)
// Para consultar contato crm SAP, necessário consultar sem sinal de + no inicio numero
- const pattern = /%2B\+/g;
+ const pattern = /%2B\+/g
- if (pattern.test(config.url)){
- config.url = config.url.replace(/%2B\+/g, '%2B');
- }
+ if (pattern.test(config.url)) {
+ config.url = config.url.replace(/%2B\+/g, '%2B')
+ }
- console.log("PAYLOAD CONFIG LOOKUP CONTACT BY PHONE CONFIG.url 2: ", config.url)
+ console.log("PAYLOAD CONFIG LOOKUP CONTACT BY PHONE CONFIG.url 2: ", config.url)
console.log("PAYLOAD CONFIG LOOKUP CONTACT BY PHONE: ", JSON.stringify(config, null, 6))
@@ -50,6 +50,36 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
try {
let { data: _data } = await axios(config)
data = _data
+
+ const contactExists = JSON.stringify(data)?.includes(crmPhone)
+
+ console.log("=========> contactExists: ", contactExists)
+ console.log("=========> data 1: ", JSON.stringify(data, null, 6))
+
+ const lookupContactByPhone2 = findProperty(rest, 'lookupContactByPhone2')
+
+ if (lookupContactByPhone2?.request?.url && !contactExists) {
+ const { request: request2, response: response2 } = lookupContactByPhone2
+ const { url } = request2
+
+ config.url = url.replace("crmPhone", crmPhone)
+
+ console.log("==========> lookupContactByPhone2 url: ", url)
+
+ console.log("==========> lookupContactByPhone2 config: ", JSON.stringify(config, null, 6))
+
+ let { data: _data2 } = await axios(config)
+ data = _data2
+
+ data.flow = 2
+
+ if (response2) {
+ response = response2
+ }
+
+ console.log("=========> data 2: ", JSON.stringify(data, null, 6))
+ }
+
} catch (error) {
if (error.response) {
console.error('==================> lookupContactByPhone Erro na resposta da API:', {
@@ -106,8 +136,6 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
}
-
-
data = flatten(data)
let auxPhone
@@ -117,7 +145,7 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
let auxContactId2
for (const prop in data) {
-
+
const _prop = prop.replace(/^\d+\./, '').replace(/(?:^|\.)\d+\b/g, '')
if (_prop == response?.phone?.trim()) {
@@ -138,13 +166,12 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
console.log('===========> !auxPhone && !auxContactId: ', !auxPhone && !auxContactId)
-
if (!auxPhone && !auxContactId) {
for (const prop in data) {
let _prop = prop.replace(/\.(\d+)(\.|$)/g, '[$1]$2')
- // console.log("_prop: ", _prop, " | response ", JSON.stringify(response, null, 6))
+ // console.log("\n_prop: ", _prop, "\n| response: ", JSON.stringify(response, null, 6), "\n| data[prop]: ", data[prop], "\n| _prop: ", _prop)
// SALESFORCE GETTING THE NAME
if (_prop == response?.name?.trim()) {
@@ -175,10 +202,12 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
}
}
+ console.log("=========> auxAccountId from contact response: ", auxAccountId)
+
// Tenta pegar o accountId no body da resposta se não conseguir, pega do template se a propriedade crmAccountId existir no template
// Foi criado dessa forma para evitar problemas com integrações que já estão em funcionamento
- if(!auxAccountId && crmAccountId){
- console.log('---------> auxAccountId definido a partir do crmAccountId do template: ',crmAccountId)
+ if (!auxAccountId && crmAccountId) {
+ console.log('---------> auxAccountId definido a partir do crmAccountId do template: ', crmAccountId)
auxAccountId = crmAccountId
}
@@ -195,7 +224,7 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
phone: crmPhone,
contactId: { $ne: auxContactId }
})
-
+
if (contacts && contacts.length > 0) {
for (const contact of contacts) {
@@ -218,18 +247,14 @@ async function lookupContactByPhone(rest, authentication, crmPhone, companyId, t
console.log('----------------> CREATE CONTACT MONGO')
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: auxPhone })
-
-
}
}
- return { exist: true, contactId: auxContactId, phone: crmPhone, name: auxName, accountId: auxAccountId, contactId2: auxContactId2}
+ return { exist: true, contactId: auxContactId, phone: crmPhone, name: auxName, accountId: auxAccountId, contactId2: auxContactId2, flow: data?.flow }
}
- return { exist: false }
+ return { exist: false, flow: data?.flow }
}
module.exports = lookupContactByPhone
-
-
diff --git a/backend/utils/lookupCRMTicket.js b/backend/utils/lookupCRMTicket.js
index 3bac1ac..a5927e7 100644
--- a/backend/utils/lookupCRMTicket.js
+++ b/backend/utils/lookupCRMTicket.js
@@ -17,9 +17,23 @@ const findTicketOpenHubspotByContact = require('./findTicketOpenHubspotByContact
const lookupContactByPhone = require('./lookupCRMContactByPhone')
-async function lookupCrmTicket(rest, authentication, crmPhone, companyId, test = {}, ticketId) {
+async function lookupCrmTicket(rest, authentication, crmPhone, companyId, test = {}, ticketId, contact = null) {
- let { request, body, response } = findProperty(rest, 'lookupTicket')
+
+ let flow = contact?.flow
+ let propertyKey
+
+ switch (flow) {
+ case 2:
+ propertyKey = 'lookupTicket2'
+ break
+ default:
+ propertyKey = 'lookupTicket'
+ break
+ }
+
+
+ let { request, body, response } = findProperty(rest, propertyKey)
let { requestContentType, requestEncoding, requestType, responseType, url } = request
@@ -33,6 +47,51 @@ async function lookupCrmTicket(rest, authentication, crmPhone, companyId, test =
sendMessageSocket({ companyId, status: 'processing', data: { request: config, msg } })
}
+
+ // Para crm sap
+ if (url.includes("crmContactId") && contact && url.includes("c4codataapi")) {
+ // Valor do contato
+ const contactId = contact.contactId // Ex: "1112048"
+
+ console.log("============> entrou no if crmContactId: ", contactId)
+
+ // 1. O valor OData correto, com aspas simples, DEVE SER: '1112048'
+ const odataValueWithQuotes = `'${contactId}'`
+
+ // 2. Codificação URL do valor OData: '%271112048%27'
+ const correctEncodedValue = encodeURIComponent(odataValueWithQuotes)
+
+ // 3. Substitua a string incorreta (que contém o '%' extra e as aspas incorretas) pela correta.
+ // O template parece ser: ...eq%20%crmContactId%27
+ const templateToReplace = `%${'crmContactId'}%27`
+
+ // A string FINAL no URL deve ser: ...eq%20%271112048%27
+
+ // Tentativa de correção: Substitua a string inteira que contém o placeholder errado pela correta
+ // ATENÇÃO: Se o contactId for '1112048', o template incorreto que está no config.url é:
+ // `%1112048%27` (depois de rodar a primeira substituição)
+ // OU `%crmContactId%27` (se a substituição ainda não ocorreu)
+
+ // Vamos substituir a string do template ANTES de qualquer coisa.
+ // Usaremos 'crmContactId' como marcador de substituição:
+
+ config.url = config.url.replace(
+ // String que está incorreta no seu template (que gera o erro): "%crmContactId%27"
+ `%${'crmContactId'}%27`,
+
+ // String correta que o servidor OData espera (Aspas codificadas corretamente): "%27" + + "%27"
+ correctEncodedValue
+ )
+ }
+
+ if (url.includes("crmContactId") && contact && url.includes("c4codataapi")) {
+ config.url = config.url.replace('crmContactId', contact.contactId)
+ }
+
+ console.log("============ journaling contact: ", JSON.stringify(contact, null, 6))
+
+ console.log("PAYLOAD CONFIG LOOKUP TICKET BY PHONE: ", JSON.stringify(config, null, 6))
+
let resp
try {
@@ -46,7 +105,7 @@ async function lookupCrmTicket(rest, authentication, crmPhone, companyId, test =
if (error.response) {
console.error('==================> lookupCrmTicket Erro na resposta da API:', {
status: error.response.status,
- data: error.response.data,
+ data: JSON.stringify(error.response.data, null, 6),
})
}
else if (error.request) {
@@ -66,6 +125,8 @@ async function lookupCrmTicket(rest, authentication, crmPhone, companyId, test =
let auxTicketStatus
let auxTicketId
+ let auxTicketId2
+
for (const prop in data) {
@@ -79,7 +140,11 @@ async function lookupCrmTicket(rest, authentication, crmPhone, companyId, test =
auxTicketId = data[prop]
}
- if (auxTicketStatus && auxTicketId) break
+ if (_prop == response?.objectId?.trim()) {
+ auxTicketId2 = data[prop]
+ }
+
+ // if (auxTicketStatus && auxTicketId) break
}
@@ -96,20 +161,24 @@ async function lookupCrmTicket(rest, authentication, crmPhone, companyId, test =
auxTicketId = data[prop]
}
- if (auxTicketStatus && auxTicketId) break
+ if (_prop == response?.objectId?.trim()) {
+ auxTicketId2 = data[prop]
+ }
+
+ // if (auxTicketStatus && auxTicketId) break
}
}
- console.log(`[${new Date()}] auxTicketStatus: ${auxTicketStatus} | auxTicketId: ${auxTicketId}`)
+ console.log(`[${new Date()}] auxTicketStatus: ${auxTicketStatus} | auxTicketId: ${auxTicketId} | auxTicketId2: ${auxTicketId2}`)
if (url.includes('api.hubapi.com')) {
-
+
const contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId)
if (contact) {
const ticket = await findTicketOpenHubspotByContact(authentication, contact)
- console.log('=========> OPEN TICKET 1: ', JSON.stringify(ticket, null, 6))
+ console.log('=========> OPEN TICKET 1: ', JSON.stringify(ticket, null, 6))
if (ticket && Object.keys(ticket).length != 0) {
console.log('**** TICKET ESTA ABERTO 1 ****')
@@ -117,12 +186,20 @@ async function lookupCrmTicket(rest, authentication, crmPhone, companyId, test =
}
}
-
- return { auxTicketId, auxTicketStatus }
-
- }
- return { auxTicketId, auxTicketStatus }
+ return { auxTicketId, auxTicketStatus }
+
+ }
+ // To sap crm, consdering status open == 1
+ else if (url.includes("c4codataapi")) {
+ if (auxTicketStatus && auxTicketStatus.toLowerCase() == "open")
+ auxTicketStatus = 1
+ else
+ auxTicketStatus = 0
+ }
+
+
+ return { auxTicketId, auxTicketStatus, auxTicketId2 }
}
diff --git a/backend/utils/redirectContactLinkCRM.js b/backend/utils/redirectContactLinkCRM.js
index f53e76e..60af3be 100644
--- a/backend/utils/redirectContactLinkCRM.js
+++ b/backend/utils/redirectContactLinkCRM.js
@@ -5,7 +5,6 @@ const findProperty = require('./findProperty')
const CRM_Contact = require('../models/CRM_Contact')
const CRM_Ticket = require('../models/CRM_Ticket')
const CRM = require('../models/CRM')
-const createTicket = require('./createTicket')
const lookupCRMTicket = require('./lookupCRMTicket')
const sendEventTicketCreatedToSocket = require('./sendEventTicketCreatedToSocket')
@@ -20,7 +19,7 @@ async function redirectContactLinkCRM(companyId, crmPhone, crmAgent, crmFirstNam
for (const crmConfig of crmFiles) {
- const { crmRest: rest, authentication } = crmConfig.crm
+ const { crmRest: rest, authentication } = crmConfig.crm
// Send the edited contact/lead link url to hitphone to open on another browser tab
let redirectLink = findProperty(rest, 'redirectLink')
@@ -67,4 +66,4 @@ async function _lookupContact(rest, authentication, crmPhone, companyId, crmFirs
return { created: true, contactId: contact.contactId }
}
-
+
diff --git a/backend/utils/ticketCRM.js b/backend/utils/ticketCRM.js
index d33107b..ceb74ae 100644
--- a/backend/utils/ticketCRM.js
+++ b/backend/utils/ticketCRM.js
@@ -16,8 +16,9 @@ const getHubspotPipelines = require('./getHubspotPipelines')
const mongoose = require('mongoose')
const getHubspotTicketStatusByContact = require('./getHubspotTicketStatusByContact')
const findTicketOpenHubspotByContact = require('./findTicketOpenHubspotByContact')
+const generateC4CServiceRequestDeepLinkBase64 = require('./generateC4CServiceRequestDeepLinkBase64')
-async function ticketCRM(companyId, crmPhone, crmAgent = "0000", crmFirstName = 'Username') {
+async function ticketCRM(companyId, crmPhone, crmAgent = "0000", crmFirstName = 'Username', flow = 1) {
const crmFiles = await loadCRM(companyId)
@@ -26,40 +27,65 @@ async function ticketCRM(companyId, crmPhone, crmAgent = "0000", crmFirstName =
for (const crmConfig of crmFiles) {
- const { crmRest: rest, authentication } = crmConfig.crm
+ const { crmRest: rest, authentication } = crmConfig.crm
- // Send the ticket url link to hitphone to open on another browser tab
- let obj = findProperty(rest, 'lookupTicket')
+ let propertyKey
+
+ switch (flow) {
+ case 2:
+ propertyKey = 'lookupTicket2'
+ break
+ default:
+ propertyKey = 'lookupTicket'
+ break
+ }
+
+ // find ticket
+ let obj = findProperty(rest, propertyKey)
let ticket_id = ''
+ let ticket_id2 = ''
+ let ticket_url = ''
let isCreated = false
+ console.log("===========> ticketCRM obj: ", obj)
+
if (obj) {
const { crmAccountId } = authentication
- console.log("------------> ticketCRM crmAccountId: ",crmAccountId)
+ console.log("------------> ticketCRM crmAccountId: ", crmAccountId)
let { url } = obj.request
+ console.log("------------> ticketCRM url: ", url)
let contact = await _lookupContact(rest, authentication, crmPhone, companyId, crmFirstName, url)
+ console.log("------------> ticketCRM contact: ", JSON.stringify(contact, null, 6))
+
const crm = await CRM.findOne({
companyId, crmBaseURL: new URL(url.trim()).hostname
})
const obj_contact = await CRM_Contact.findOne({ companyId, crmBaseURL: new URL(url).hostname, phone: crmPhone })
+ console.log("------------> ticketCRM obj_contact: ", JSON.stringify(obj_contact, null, 6))
+
const obj_ticket = await CRM_Ticket.findOne(
{ companyId, crm, contact: obj_contact }
- ).select('ticketId')
+ ).select('ticketId ticketId2')
+
+ console.log("------------> ticketCRM obj_ticket: ", JSON.stringify(obj_ticket, null, 6))
if (obj_ticket) {
- const { ticketId } = obj_ticket
+ const { ticketId, ticketId2 } = obj_ticket
if (ticketId) {
ticket_id = ticketId
}
+ if (ticketId2) {
+ ticket_id2 = ticketId2
+ }
const obj_ticket_status = await lookupCRMTicket(
rest,
@@ -67,15 +93,19 @@ async function ticketCRM(companyId, crmPhone, crmAgent = "0000", crmFirstName =
crmPhone,
companyId,
test = { testing: false },
- obj_ticket.ticketId
+ obj_ticket.ticketId,
+ contact
)
-
if (obj_ticket_status)
console.log("obj_ticket_status: ", JSON.stringify(obj_ticket_status, null, 6))
+
if (obj_ticket_status) {
const { auxTicketStatus, error } = obj_ticket_status
+ console.log("===============> ticketCRM url: ", url, " | error: ", error, " | auxTicketStatus: ", auxTicketStatus)
+
+
// refactor this for production. For now only working with hubspot where status new is equal 1
if ((auxTicketStatus && auxTicketStatus != '1') || (error && error == 404)) {
@@ -105,9 +135,10 @@ async function ticketCRM(companyId, crmPhone, crmAgent = "0000", crmFirstName =
}
- const { ticketUrl, ticketId } = await _createTicket(rest, crmPhone, companyId, authentication, crmFirstName, contact, crmAgent)
+ const { ticketUrl, ticketId, ticketId2 } = await _createTicket(rest, crmPhone, companyId, authentication, crmFirstName, contact, crmAgent, flow)
ticket_id = ticketId
+ ticket_id2 = ticketId2
isCreated = true
// crmTicketLinks.push({ ticketUrl, ticketId })
@@ -117,7 +148,6 @@ async function ticketCRM(companyId, crmPhone, crmAgent = "0000", crmFirstName =
}
else {
-
if (url.includes("hubapi")) {
console.log(`[${new Date()}] ****** IS HUBSPOT CRM LETS TRY FINDING AN OPEN TICKET TO THE CONTACT****** `)
@@ -141,20 +171,77 @@ async function ticketCRM(companyId, crmPhone, crmAgent = "0000", crmFirstName =
continue
}
}
+ // To sap crm try to find ticket open
+ else if (url.includes("c4codataapi")) {
+ const result = await lookupCRMTicket(
+ rest,
+ authentication,
+ crmPhone,
+ companyId,
+ test = { testing: false },
+ obj_ticket?.ticketId,
+ contact
+ )
+ // elefante
+ const { auxTicketId, auxTicketStatus, auxTicketId2 } = result
+
+ console.log("============> TICKET STATUS: ", auxTicketStatus, " | auxTicketId: ", auxTicketId)
+
+ if (auxTicketStatus == 1 && auxTicketId2) {
+
+ ticket_id = auxTicketId
+ ticket_id2 = auxTicketId2
+
+ isCreated = false
+
+ const _ticketUrl = `https://my365398.crm.ondemand.com/sap/ap/ui/clogin?saml2=disabled&app.component=%2fSAP_UI_CT%2fMain%2froot.uiccwoc&rootWindow=X&redirectUrl=%2fsap%2fpublic%2fbyd%2fruntime&supressAutoLogon=true&sap-ui-language=en_us#Nav/1/${generateC4CServiceRequestDeepLinkBase64(auxTicketId2)}`
+
+ crmTicketLinks.push({
+ ticketId: auxTicketId2,
+ ticketUrl: _ticketUrl,
+ created: isCreated,
+ })
+
+ // sinc ticket
+ let __contact = await CRM_Contact.findOne({ companyId, crmBaseURL: new URL(url).hostname, phone: crmPhone })
+
+ await CRM_Ticket.deleteMany({ companyId, contact: __contact })
+
+ const crm = await CRM.findOne({ companyId, crmBaseURL: new URL(url).hostname })
+
+ await CRM_Ticket.create({ companyId, contact: __contact, ticketId: auxTicketId, ticketId2: auxTicketId2, crm })
+
+ continue
+ }
+ }
console.log(`[${new Date()}] ****** CREATE TICKET ****** `)
-
- const { ticketUrl, ticketId } = await _createTicket(rest, crmPhone, companyId, authentication, crmFirstName, contact, crmAgent)
+ const { ticketUrl, ticketId, ticketId2 } = await _createTicket(rest, crmPhone, companyId, authentication, crmFirstName, contact, crmAgent, flow)
ticket_id = ticketId
+ ticket_id2 = ticketId2
+ // ticket_url = ticketUrl
isCreated = true
}
- crmTicketLinks.push({
- ticketId: `https://app.hubspot.com/contacts/${crmAccountId}/ticket/${ticket_id}`,
- created: isCreated,
- })
+ if (url.includes("hubapi")) {
+ crmTicketLinks.push({
+ ticketId: `https://app.hubspot.com/contacts/${crmAccountId}/ticket/${ticket_id}`,
+ created: isCreated,
+ })
+ }
+ // To sap crm
+ else if (url.includes("c4codataapi")) {
+ console.log("=================> c4codataapi ticket_id2: ", ticket_id2)
+
+ crmTicketLinks.push({
+ ticketId: ticket_id2,
+ ticketUrl: `https://my365398.crm.ondemand.com/sap/ap/ui/clogin?saml2=disabled&app.component=%2fSAP_UI_CT%2fMain%2froot.uiccwoc&rootWindow=X&redirectUrl=%2fsap%2fpublic%2fbyd%2fruntime&supressAutoLogon=true&sap-ui-language=en_us#Nav/1/${generateC4CServiceRequestDeepLinkBase64(ticket_id2)}`,
+ created: isCreated,
+ })
+
+ }
}
//
@@ -213,7 +300,7 @@ async function _lookupContact(rest, authentication, crmPhone, companyId, crmFirs
let contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId)
if (contact?.exist) {
- return { created: false, contactId: contact.contactId }
+ return { created: false, contactId: contact.contactId, contactId2: contact.contactId2, accountId: contact?.accountId, flow: contact?.flow }
}
if (!contact?.exist) {
@@ -231,11 +318,23 @@ async function _lookupContact(rest, authentication, crmPhone, companyId, crmFirs
contact = await createContact(companyId, rest, authentication, crmPhone, crmFirstName)
}
- return { created: true, contactId: contact.contactId }
+ return { created: true, contactId: contact.contactId, contactId2: contact.contactId2, accountId: contact?.accountId, flow: contact?.flow }
}
-async function _createTicket(rest, crmPhone, companyId, authentication, crmFirstName, contact, crmAgent) {
- let obj = findProperty(rest, 'createTicketRecord')
+async function _createTicket(rest, crmPhone, companyId, authentication, crmFirstName, contact, crmAgent, flow = 1) {
+
+ let propertyKey
+
+ switch (flow) {
+ case 2:
+ propertyKey = 'createTicketRecord2'
+ break
+ default:
+ propertyKey = 'createTicketRecord'
+ break
+ }
+
+ let obj = findProperty(rest, propertyKey)
let ticket_url = ''
let ticket_id = ''
@@ -245,10 +344,10 @@ async function _createTicket(rest, crmPhone, companyId, authentication, crmFirst
if (request) {
msg = `Tentando criar ticket para o contato ${crmPhone}`
- // return { exist: true, ticketId: auxTicketId, phone: crmPhone, ticketUrl }
+ // return { exist: true, ticketId: auxTicketId, phone: crmPhone, ticketUrl }
// return { exist: true, ticketId: auxTicketId, phone: crmPhone, ticketUrl }
- const { ticketUrl, ticketId, } = await createTicket(companyId,
+ const { ticketUrl, ticketId, ticketId2 } = await createTicket(companyId,
rest,
authentication,
crmPhone,
@@ -256,14 +355,15 @@ async function _createTicket(rest, crmPhone, companyId, authentication, crmFirst
crmLastName = '',
crmEmail = '',
test = { testing: false },
- crmContactId = contact.contactId,
+ contact,
crmAgent
)
ticket_id = ticketId
+ ticket_id2 = ticketId2
ticket_url = ticketUrl
}
}
- return { crmFirstName, ticketUrl: ticket_url, ticketId: ticket_id }
+ return { crmFirstName, ticketUrl: ticket_url, ticketId: ticket_id, ticketId2: ticket_id2 }
}
diff --git a/backend/utils/whatsappJournalingCRM.js b/backend/utils/whatsappJournalingCRM.js
index 39acce6..3699420 100644
--- a/backend/utils/whatsappJournalingCRM.js
+++ b/backend/utils/whatsappJournalingCRM.js
@@ -6,12 +6,11 @@ const findProperty = require('./findProperty')
const CRM_Contact = require('../models/CRM_Contact')
const CRM_Ticket = require('../models/CRM_Ticket')
const CRM = require('../models/CRM')
-const createTicket = require('./createTicket')
const lookupCRMTicket = require('./lookupCRMTicket')
const sendEventTicketCreatedToSocket = require('./sendEventTicketCreatedToSocket')
const journalingRequest = require('./journalingRequest')
-
+
const getIntegrationsConfig = require('../utils/getIntegrationsConfig')
const updateLeadStatus = require('./updateLeadStatus')
const extractLeadStatusChange = require('./extractLeadStatusChange')
@@ -21,7 +20,7 @@ async function whatsappJournalingCRM(companyId, crmPhone = '', crmAgent, crmFirs
const crmFiles = await loadCRM(companyId)
- const crmContactIds = []
+ const crmContactIds = []
for (const crmConfig of crmFiles) {
@@ -31,11 +30,11 @@ async function whatsappJournalingCRM(companyId, crmPhone = '', crmAgent, crmFirs
let chatJournaling = findProperty(rest, 'chatJournaling')
console.log('===============> chatJournaling: ', JSON.stringify(chatJournaling, null, 6))
-
+
if (chatJournaling) {
- let contact = await _lookupContact(rest, authentication, crmPhone, crmEmail, companyId, crmFirstName)
+ let contact = await _lookupContact(rest, authentication, crmPhone, crmEmail, companyId, crmFirstName)
console.log("================> whatsappJournalingCRM contact: ", JSON.stringify(contact, null, 6))
@@ -44,7 +43,7 @@ async function whatsappJournalingCRM(companyId, crmPhone = '', crmAgent, crmFirs
let body = findProperty(chats, 'chatDone')
- let config = await getIntegrationsConfig(companyId, 'omnihit')
+ let config = await getIntegrationsConfig(companyId, 'omnihit')
if (ticketId && config) {
@@ -62,7 +61,7 @@ async function whatsappJournalingCRM(companyId, crmPhone = '', crmAgent, crmFirs
body = JSON.parse(body)
console.log('===============> body3: ', JSON.stringify(body, null, 6))
}
-
+
await journalingRequest(request, body, crmCallDuration = 0, contact, crmAgent, crmPhone, authentication, rest, companyId, dynamicBodyRequest)
// Se vier um novo status (__newLeadStatus), executa PATCH aproveitando as validações do fluxo de Activity
@@ -106,42 +105,46 @@ module.exports = whatsappJournalingCRM
// }
async function _lookupContact(rest, authentication, crmPhone, crmEmail, companyId, crmFirstName) {
- let contact = null;
+ let contact = null
// 1. Tenta buscar o contato por telefone se o crmPhone for fornecido
if (crmPhone) {
- console.log(`Buscando contato por telefone: ${crmPhone}`);
- contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId);
+ console.log(`Buscando contato por telefone: ${crmPhone}`)
+ contact = await lookupContactByPhone(rest, authentication, crmPhone, companyId)
}
// 2. Se não encontrou por telefone, tenta buscar por e-mail se o crmEmail for fornecido
if (!contact?.exist && crmEmail) {
- console.log(`Contato não encontrado por telefone. Tentando por e-mail: ${crmEmail}`);
- contact = await lookupContactByEmail(rest, authentication, crmEmail, companyId);
+ console.log(`Contato não encontrado por telefone. Tentando por e-mail: ${crmEmail}`)
+ contact = await lookupContactByEmail(rest, authentication, crmEmail, companyId)
}
// 3. Se o contato já existe (seja por telefone ou e-mail), retorna as informações
if (contact?.exist) {
- console.log(`Contato encontrado! ID: ${contact.contactId}`);
- return { created: false, contactId: contact.contactId, contactId2: contact?.contactId2 };
+ console.log(`Contato encontrado! ID: ${contact.contactId}`)
+ return { created: false, contactId: contact.contactId, contactId2: contact?.contactId2 }
}
// 4. Se o contato não foi encontrado por nenhuma das formas, cria um novo
- console.log(`Contato não encontrado. Criando um novo com base no ${crmPhone ? 'telefone' : 'e-mail'}.`);
-
+ console.log(`Contato não encontrado. Criando um novo com base no ${crmPhone ? 'telefone' : 'e-mail'}.`)
+
// AQUI ESTÁ A ÚNICA MUDANÇA NECESSÁRIA:
// Chamamos createContact passando os valores de telefone e e-mail separadamente.
// A função createContact agora sabe como lidar com ambos, mesmo que um deles seja vazio.
- contact = await createContact(companyId, rest, authentication, crmPhone, crmFirstName, 'Last name', crmEmail);
-
+ // createContact(companyId, rest, authentication, crmPhone = '', crmFirstName = 'Username', crmLastName = 'Last name', crmEmail = '', test = {}, dynamicBodyRequest = {}, flow = 1)
+
+ console.log("=================> whatsappJournalingCRM contact?.flow: ", contact?.flow)
+
+ contact = await createContact(companyId, rest, authentication, crmPhone, crmFirstName, 'Last name', crmEmail, test = {}, dynamicBodyRequest = {}, flow = contact?.flow)
+
// Se o contato for criado, retorna suas informações
if (contact?.contactId) {
- console.log(`Novo contato criado com ID: ${contact.contactId}`);
- return { created: true, contactId: contact.contactId, contactId2: contact?.contactId2};
+ console.log(`Novo contato criado com ID: ${contact.contactId}`)
+ return { created: true, contactId: contact.contactId, contactId2: contact?.contactId2 }
}
// Caso não tenha nem telefone nem e-mail, retorna um erro ou um valor nulo
- console.error("Erro: Não foi possível encontrar ou criar um contato. Telefone e e-mail não fornecidos.");
- return null;
+ console.error("Erro: Não foi possível encontrar ou criar um contato. Telefone e e-mail não fornecidos.")
+ return null
}