UNPKG

@tiledesk/tiledesk-server

Version:
1,448 lines (1,097 loc) 102 kB
'use strict'; var departmentService = require('../services/departmentService'); var Request = require("../models/request"); var Project_user = require("../models/project_user"); var Project = require("../models/project"); var messageService = require('../services/messageService'); const requestEvent = require('../event/requestEvent'); const leadEvent = require('../event/leadEvent'); var winston = require('../config/winston'); var RequestConstants = require("../models/requestConstants"); var requestUtil = require("../utils/requestUtil"); var cacheUtil = require("../utils/cacheUtil"); var arrayUtil = require("../utils/arrayUtil"); var cacheEnabler = require("../services/cacheEnabler"); var UIDGenerator = require("../utils/UIDGenerator"); const { TdCache } = require('../utils/TdCache'); const { QuoteManager } = require('./QuoteManager'); var configGlobal = require('../config/global'); const projectService = require('./projectService'); const axios = require("axios").default; let port = process.env.PORT || '3000'; let TILEBOT_ENDPOINT = "http://localhost:" + port + "/modules/tilebot/ext/";; if (process.env.TILEBOT_ENDPOINT) { TILEBOT_ENDPOINT = process.env.TILEBOT_ENDPOINT + "/ext/" } let tdCache = new TdCache({ host: process.env.CACHE_REDIS_HOST, port: process.env.CACHE_REDIS_PORT, password: process.env.CACHE_REDIS_PASSWORD }); tdCache.connect(); let qm = new QuoteManager({ tdCache: tdCache }); class RequestService { constructor() { this.listen(); } listen() { // 12 marzo 2024 I disabled these two functions due to performance problems for a chatbot created by Sponziello "Community bots Sendinblue Hubspot Qapla)" // this.updateSnapshotLead(); // this.sendMessageUpdateLead(); } // 12 marzo 2024 I disabled these two functions due to performance problems for a chatbot created by Sponziello "Community bots Sendinblue Hubspot Qapla)" // updateSnapshotLead() { // leadEvent.on('lead.update', function (lead) { // setImmediate(() => { // winston.debug("updateSnapshotLead on lead.update ", lead); // Request.updateMany({ lead: lead._id, id_project: lead.id_project }, { "$set": { "snapshot.lead": lead } }, function (err, updates) { // if (err) { // winston.error("Error updating requests updateSnapshotLead", err); // return 0; // } // winston.verbose("updateSnapshotLead updated for " + updates.nModified + " request") // requestEvent.emit('request.update.snapshot.lead', { lead: lead, updates: updates }); // return; // }); // // Request.find({lead: lead._id, id_project: lead.id_project}, function(err, requests) { // // if (err) { // // winston.error("Error getting request by lead", err); // // return 0; // // } // // if (!requests || (requests && requests.length==0)) { // // winston.warn("No request found for lead id " +lead._id ); // // return 0; // // } // // requests.forEach(function(request) { // // }); // // }); // }); // }); // } // 12 marzo 2024 I disabled these two functions due to performance problems for a chatbot created by Sponziello "Community bots Sendinblue Hubspot Qapla)" // sendMessageUpdateLead() { // leadEvent.on('lead.fullname.email.update', function (lead) { // winston.debug("lead.fullname.email.update "); // // leadEvent.on('lead.update', function(lead) { // setImmediate(() => { // winston.debug("sendMessageUpdateLead on lead.update ", lead); // Request.find({ lead: lead._id, id_project: lead.id_project }, function (err, requests) { // if (err) { // winston.error("Error getting sendMessageUpdateLead request by lead", err); // return 0; // } // if (!requests || (requests && requests.length == 0)) { // winston.warn("sendMessageUpdateLead No request found for lead id " + lead._id); // return 0; // } // // winston.info("sendMessageUpdateLead requests ", requests); // requests.forEach(function (request) { // winston.debug("sendMessageUpdateLead request ", request); // // send(sender, senderFullname, recipient, text, id_project, createdBy, attributes, type, metadata, language) // messageService.send( // 'system', // 'Bot', // // lead.fullname, // request.request_id, // "Lead updated", // request.id_project, // 'system', // { // subtype: "info/support", // "updateconversation": false, // messagelabel: { key: "LEAD_UPDATED" }, // updateUserEmail: lead.email, // updateUserFullname: lead.fullname // }, // undefined, // request.language // ); // }); // }); // }); // }); // } getAvailableAgentsCount(agents) { var project_users_available = agents.filter(function (projectUser) { if (projectUser.user_available == true) { return true; } }); winston.debug('++ AVAILABLE PROJECT USERS count ', project_users_available) if (project_users_available && project_users_available.length > 0) { return project_users_available.length; } else { return 0; } } //change create with this routeInternal(request, departmentid, id_project, nobot) { var that = this; return new Promise(function (resolve, reject) { var context = { request: request }; // getOperators(departmentid, projectid, nobot, disableWebHookCall, context) return departmentService.getOperators(departmentid, id_project, nobot, undefined, context).then(function (result) { // winston.debug("getOperators", result); var assigned_at = undefined; var status = RequestConstants.UNASSIGNED; var assigned_operator_id; var participants = []; var participantsAgents = []; var participantsBots = []; var hasBot = false; if (result.operators && result.operators.length > 0) { assigned_operator_id = result.operators[0].id_user; status = RequestConstants.ASSIGNED; var assigned_operator_idString = assigned_operator_id.toString(); participants.push(assigned_operator_idString); // botprefix if (assigned_operator_idString.startsWith("bot_")) { hasBot = true; // botprefix var assigned_operator_idStringBot = assigned_operator_idString.replace("bot_", ""); participantsBots.push(assigned_operator_idStringBot); } else { participantsAgents.push(assigned_operator_idString); hasBot = false; //?? } assigned_at = Date.now(); } winston.debug("routeInternal assigned_operator_id: " + assigned_operator_id); winston.debug("routeInternal status: " + status); // cosi modifica la request originale forse devi fare il clone????? request.status = status; request.participants = participants; request.participantsAgents = participantsAgents; request.participantsBots = participantsBots; request.hasBot = hasBot; request.department = result.department._id; // request.agents = result.agents; request.assigned_at = assigned_at; request.waiting_time = undefined //reset waiting_time on reroute if (!request.snapshot) { //if used other methods than .create request.snapshot = {} } request.snapshot.department = result.department; request.snapshot.agents = result.agents; request.snapshot.availableAgentsCount = that.getAvailableAgentsCount(result.agents); return resolve(request); }).catch(function (err) { return reject(err); }); }); } // TODO changePreflightByRequestId se un agente entra in request freflight true disabilitare add agente e reassing ma mettere un bottone removePreflight??? // usalo no_populate route(request_id, departmentid, id_project, nobot, no_populate) { var that = this; return new Promise(function (resolve, reject) { winston.debug("request_id:" + request_id); winston.debug("departmentid:" + departmentid); winston.debug("id_project:" + id_project); winston.debug("nobot:" + nobot); let q = Request .findOne({ request_id: request_id, id_project: id_project }); // if (cacheEnabler.request) { //(node:60837) UnhandledPromiseRejectionWarning: VersionError: No matching document found for id "633efe246a6cc0eda5732684" version 0 modifiedPaths "status, participants, participantsAgents, department, assigned_at, snapshot, snapshot.department, snapshot.department.updatedAt, snapshot.agents" // q.cache(cacheUtil.defaultTTL, id_project+":requests:request_id:"+request_id+":simple") //request_cache // winston.debug('request cache enabled'); // } return q.exec(function (err, request) { if (err) { winston.error(err); return reject(err); } winston.debug('request return', request); // cambia var in let //it is important to clone here var requestBeforeRoute = Object.assign({}, request.toObject()); winston.debug("requestBeforeRoute", requestBeforeRoute); var beforeParticipants = requestBeforeRoute.participants; winston.debug("beforeParticipants: ", beforeParticipants); return that.routeInternal(request, departmentid, id_project, nobot).then( async function (routedRequest) { winston.debug("after routeInternal", routedRequest); winston.debug("requestBeforeRoute.status:" + requestBeforeRoute.status); winston.debug("routedRequest.status:" + routedRequest.status); let beforeDepartmentId; if (requestBeforeRoute.department) { //requestBeforeRoute.department can be empty for internal ticket beforeDepartmentId = requestBeforeRoute.department.toString(); winston.debug("beforeDepartmentId:" + beforeDepartmentId); } let afterDepartmentId; if (routedRequest.department) { afterDepartmentId = routedRequest.department.toString(); winston.debug("afterDepartmentId:" + afterDepartmentId); } winston.debug("requestBefore status: ", requestBeforeRoute.status) winston.debug("routedRequest status: ", routedRequest.status) /** * Case 1 * After internal routing: * - same STATUS * - same DEPARTMENT * - same PARTICIPANTS */ if (requestBeforeRoute.status === routedRequest.status && beforeDepartmentId === afterDepartmentId && requestUtil.arraysEqual(beforeParticipants, routedRequest.participants)) { winston.verbose("Request " + request.request_id + " contains already the same participants at the same request status. Routed to the same participants"); if (routedRequest.attributes && routedRequest.attributes.fully_abandoned && routedRequest.attributes.fully_abandoned === true) { request.status = RequestConstants.ABANDONED; request.attributes.fully_abandoned = true; request.markModified('status'); request.markModified('attributes'); request.save((err, savedRequest) => { if (err) { winston.error("Error updating request with status ABANDONED ", err); } else { winston.verbose("Status modified in ABANDONED for request: " + savedRequest._id); } }) } if (no_populate === "true" || no_populate === true) { winston.debug("no_populate is true"); return resolve(request); } return request .populate('lead') .populate('department') .populate('participatingBots') .populate('participatingAgents') .populate({ path: 'requester', populate: { path: 'id_user' } }) .execPopulate(function (err, requestComplete) { winston.debug("requestComplete", requestComplete); return resolve(requestComplete); }); } let project = await projectService.getCachedProject(id_project).catch((err) => { winston.warn("Error getting cached project. Skip conversation quota check.") winston.warn("Getting cached project error: ", err) }) let isTestConversation = false; let isVoiceConversation = false; let isStandardConversation = false; let payload = { project: project, request: request } if (request.attributes && request.attributes.sourcePage && (request.attributes.sourcePage.indexOf("td_draft=true") > -1)) { winston.verbose("is a test conversation --> skip quote availability check") isTestConversation = true; } else if (request.channel && (request.channel.name === 'voice-vxml')) { winston.verbose("is a voice conversation --> skip quote availability check") isVoiceConversation = true; } else { isStandardConversation = true; let available = await qm.checkQuote(project, request, 'requests'); if (available === false) { winston.info("Requests limits reached for project " + project._id) return reject("Requests limits reached for project " + project._id); } } /** * Case 2 - Leaving TEMP status * After internal routing: * - STATUS changed from 50 to 100 or 200 */ if (requestBeforeRoute.status === RequestConstants.TEMP && (routedRequest.status === RequestConstants.ASSIGNED || routedRequest.status === RequestConstants.UNASSIGNED)) { // console.log("Case 2 - Leaving TEMP status") if (isStandardConversation) { requestEvent.emit('request.create.quote', payload); } } /** * Case 3 - Conversation opened through proactive message * After internal routing: * - STATUS changed from undefined to 100 */ if ((!requestBeforeRoute.status || requestBeforeRoute.status === undefined) && routedRequest.status === RequestConstants.ASSIGNED) { // console.log("Case 3 - 'Proactive' request") if (isStandardConversation) { requestEvent.emit('request.create.quote', payload); } } //cacheinvalidation return routedRequest.save(function (err, savedRequest) { // https://stackoverflow.com/questions/54792749/mongoose-versionerror-no-matching-document-found-for-id-when-document-is-being //return routedRequest.update(function(err, savedRequest) { if (err) { winston.error('Error saving the request. ', { err: err, routedRequest: routedRequest }); return reject(err); } winston.debug("after save savedRequest", savedRequest); return savedRequest .populate('lead') .populate('department') .populate('participatingBots') .populate('participatingAgents') .populate({ path: 'requester', populate: { path: 'id_user' } }) .execPopulate(function (err, requestComplete) { // return Request //to populate correctly i must re-exec the query // .findById(savedRequest.id) // .populate('lead') // .populate('department') // .populate('participatingBots') // .populate('participatingAgents') // .populate({path:'requester',populate:{path:'id_user'}}) // .exec( function(err, requestComplete) { if (err) { winston.error('Error populating the request.', err); return reject(err); } winston.verbose("Request routed", requestComplete.toObject()); var oldParticipants = beforeParticipants; winston.debug("oldParticipants ", oldParticipants); let newParticipants = requestComplete.participants; winston.debug("newParticipants ", newParticipants); var removedParticipants = oldParticipants.filter(d => !newParticipants.includes(d)); winston.debug("removedParticipants ", removedParticipants); var addedParticipants = newParticipants.filter(d => !oldParticipants.includes(d)); winston.debug("addedParticipants ", addedParticipants); requestEvent.emit('request.update', requestComplete); requestEvent.emit("request.update.comment", { comment: "REROUTE", request: requestComplete });//Deprecated requestEvent.emit("request.updated", { comment: "REROUTE", request: requestComplete, patch: { removedParticipants: removedParticipants, addedParticipants: addedParticipants } }); requestEvent.emit('request.participants.update', { beforeRequest: request, removedParticipants: removedParticipants, addedParticipants: addedParticipants, request: requestComplete }); requestEvent.emit('request.department.update', requestComplete); //se req ha bot manda messaggio \welcome winston.debug("here end"); return resolve(requestComplete); }); }); }).catch(function (err) { return reject(err); }); }); }); } reroute(request_id, id_project, nobot) { var that = this; var startDate = new Date(); return new Promise(function (resolve, reject) { // winston.debug("request_id", request_id); // winston.debug("newstatus", newstatus); let q = Request .findOne({ request_id: request_id, id_project: id_project }); if (cacheEnabler.request) { q.cache(cacheUtil.defaultTTL, id_project + ":requests:request_id:" + request_id + ":simple") //request_cache winston.debug('request cache enabled'); } return q.exec(function (err, request) { if (err) { winston.error(err); return reject(err); } winston.debug('request cache simple 3', request); winston.debug("here reroute1 "); // Cannot read property 'toString' of undefined at /usr/src/app/services/requestService.js:404:61 at /usr/src/app/node_modules/cachegoose/out/extend-query.js:44:13 at Command.cb [as callback] (/usr/src/app/node_modules/cacheman-redis/node/index.js:142:9) at normal_reply (/usr/src/app/node_modules/redis/index.js:655:21) at RedisClient.return_reply (/usr/src/app/node_modules/redis/index.js:753:9) at JavascriptRedisParser.returnReply (/usr/src/app/node_modules/redis/index.js:138:18) at JavascriptRedisParser.execute (/usr/src/app/node_modules/redis-parser/lib/parser.js:544:14) at Socket.<anonymous> (/usr/src/app/node_modules/redis/index.js:219:27) at Socket.emit (events.js:314:20) at addChunk (_stream_readable.js:297:12) at readableAddChunk (_stream_readable.js:272:9) at Socket.Readable.push (_stream_readable.js:213:10) at TCP.onStreamRead (internal/stream_base_commons.js:188:23) {"date":"Tue Mar 21 2023 18:45:47 GMT+0000 (Coordinated Unive if (request.department === undefined) { winston.error("Request with request_id " + request_id + " has empty department. So I can't reroute"); return reject("Request with request_id " + request_id + " has empty department. So I can't reroute"); } return that.route(request_id, request.department.toString(), id_project, nobot).then(function (routedRequest) { var endDate = new Date(); winston.verbose("Performance Request reroute in millis: " + endDate - startDate); return resolve(routedRequest); }).catch(function (err) { return reject(err); }); }); }); } createWithRequester(project_user_id, lead_id, id_project, first_text, departmentid, sourcePage, language, userAgent, status, createdBy, attributes, subject, preflight) { var request_id = 'support-group-' + id_project + "-" + UIDGenerator.generate(); winston.debug("request_id: " + request_id); return this.createWithIdAndRequester(request_id, project_user_id, lead_id, id_project, first_text, departmentid, sourcePage, language, userAgent, status, createdBy, attributes, subject, preflight); } createWithIdAndRequester(request_id, project_user_id, lead_id, id_project, first_text, departmentid, sourcePage, language, userAgent, status, createdBy, attributes, subject, preflight, channel, location) { var request = { request_id: request_id, project_user_id: project_user_id, lead_id: lead_id, id_project: id_project, first_text: first_text, departmentid: departmentid, sourcePage: sourcePage, language: language, userAgent: userAgent, status: status, createdBy: createdBy, attributes: attributes, subject: subject, preflight: preflight, channel: channel, location: location }; return this.create(request); }; async create(request) { if (!request.createdAt) { request.createdAt = new Date(); } var request_id = request.request_id; var project_user_id = request.project_user_id; var lead_id = request.lead_id; var id_project = request.id_project; var first_text = request.first_text; var departmentid = request.departmentid; var sourcePage = request.sourcePage; var language = request.language; var userAgent = request.userAgent; var status = request.status; var createdBy = request.createdBy; var attributes = request.attributes; var subject = request.subject; var preflight = request.preflight; var channel = request.channel; var location = request.location; var participants = request.participants || []; var tags = request.tags; var notes = request.notes; var priority = request.priority; var auto_close = request.auto_close; var followers = request.followers; let createdAt = request.createdAt; if (!departmentid) { departmentid = 'default'; } if (!createdBy) { if (project_user_id) { createdBy = project_user_id; } else { createdBy = "system"; } } // Utils let payload; let isTestConversation = false; let isVoiceConversation = false; let isStandardConversation = false; var that = this; return new Promise( async (resolve, reject) => { var context = { request: { request_id: request_id, project_user_id: project_user_id, lead_id: lead_id, id_project: id_project, first_text: first_text, departmentid: departmentid, sourcePage: sourcePage, language: language, userAgent: userAgent, status: status, createdBy: createdBy, attributes: attributes, subject: subject, preflight: preflight, channel: channel, location: location, participants: participants, tags: tags, notes: notes, priority: priority, auto_close: auto_close, followers: followers } }; winston.debug("context", context); var participantsAgents = []; var participantsBots = []; var hasBot = false; var dep_id = undefined; var assigned_at = undefined; var agents = []; var snapshot = {}; try { // (method) DepartmentService.getOperators(departmentid: any, projectid: any, nobot: any, disableWebHookCall: any, context: any): Promise<any> var result = await departmentService.getOperators(departmentid, id_project, false, undefined, context); winston.debug("getOperators", result); } catch (err) { return reject(err); } agents = result.agents; if (status == 50) { // skip assignment if (participants.length == 0) { dep_id = result.department._id; } } else { let project = await projectService.getCachedProject(id_project).catch((err) => { winston.warn("Error getting cached project. Skip conversation quota check.") winston.warn("Getting cached project error: ", err) }) payload = { project: project, request: request } if (attributes && attributes.sourcePage && (attributes.sourcePage.indexOf("td_draft=true") > -1)) { winston.verbose("is a test conversation --> skip quote availability check") isTestConversation = true; } else if (channel && (channel.name === 'voice-vxml')) { isVoiceConversation = true; let available = await qm.checkQuote(project, request, 'voice_duration'); if (available === false) { winston.info("Voice duration limits reached for project " + project._id); return reject("Voice duration limits reached for project " + project._id); } } else { isStandardConversation = true; let available = await qm.checkQuote(project, request, 'requests'); if (available === false) { winston.info("Requests limits reached for project " + project._id) return reject("Requests limits reached for project " + project._id); } } if (participants.length == 0) { if (result.operators && result.operators.length > 0) { participants.push(result.operators[0].id_user.toString()); } // for preflight it is important to save agents in req for trigger. try to optimize it dep_id = result.department._id; } if (participants.length > 0) { status = RequestConstants.ASSIGNED; // botprefix if (participants[0].startsWith("bot_")) { hasBot = true; winston.debug("hasBot:" + hasBot); // botprefix var assigned_operator_idStringBot = participants[0].replace("bot_", ""); winston.debug("assigned_operator_idStringBot:" + assigned_operator_idStringBot); participantsBots.push(assigned_operator_idStringBot); } else { participantsAgents.push(participants[0]); } assigned_at = Date.now(); } else { status = RequestConstants.UNASSIGNED; } } if (dep_id) { snapshot.department = result.department; } snapshot.agents = agents; snapshot.availableAgentsCount = that.getAvailableAgentsCount(agents); if (request.requester) { snapshot.requester = request.requester; } if (request.lead) { snapshot.lead = request.lead; } var newRequest = new Request({ request_id: request_id, requester: project_user_id, lead: lead_id, first_text: first_text, subject: subject, status: status, participants: participants, participantsAgents: participantsAgents, participantsBots: participantsBots, hasBot: hasBot, department: dep_id, // agents: agents, //others sourcePage: sourcePage, language: language, userAgent: userAgent, assigned_at: assigned_at, attributes: attributes, //standard id_project: id_project, createdBy: createdBy, updatedBy: createdBy, preflight: preflight, channel: channel, location: location, snapshot: snapshot, tags: tags, notes: notes, priority: priority, auto_close: auto_close, followers: followers, createdAt: createdAt }); if (isTestConversation) { newRequest.draft = true; } winston.debug('newRequest.', newRequest); //cacheinvalidation return newRequest.save( async function (err, savedRequest) { if (err) { winston.error('RequestService error for method createWithIdAndRequester for newRequest' + JSON.stringify(newRequest), err); return reject(err); } winston.debug("Request created", savedRequest.toObject()); requestEvent.emit('request.create.simple', savedRequest); if (isStandardConversation) { requestEvent.emit('request.create.quote', payload);; } return resolve(savedRequest); }); }) } // DEPRECATED // async _create(request) { // var startDate = new Date(); // if (!request.createdAt) { // request.createdAt = new Date(); // } // var request_id = request.request_id; // var project_user_id = request.project_user_id; // var lead_id = request.lead_id; // var id_project = request.id_project; // var first_text = request.first_text; // //removed for ticket // // // lascia che sia nico a fare il replace...certo tu devi fare il test che tutto sia ok quindi dopo demo // // var first_text; // // if (request.first_text) { //first_text can be empty for type image // // first_text = request.first_text.replace(/[\n\r]+/g, ' '); //replace new line with space // // } // var departmentid = request.departmentid; // var sourcePage = request.sourcePage; // var language = request.language; // var userAgent = request.userAgent; // var status = request.status; // var createdBy = request.createdBy; // var attributes = request.attributes; // var subject = request.subject; // var preflight = request.preflight; // var channel = request.channel; // var location = request.location; // var participants = request.participants || []; // var tags = request.tags; // var notes = request.notes; // var priority = request.priority; // var auto_close = request.auto_close; // var followers = request.followers; // let createdAt = request.createdAt; // if (!departmentid) { // departmentid = 'default'; // } // if (!createdBy) { // if (project_user_id) { // createdBy = project_user_id; // } else { // createdBy = "system"; // } // } // let isTestConversation = false; // let isVoiceConversation = false; // var that = this; // return new Promise(async (resolve, reject) => { // let q = Project.findOne({ _id: request.id_project, status: 100 }); // if (cacheEnabler.project) { // q.cache(cacheUtil.longTTL, "projects:id:" + request.id_project) //project_cache // winston.debug('project cache enabled for /project detail'); // } // q.exec(async function (err, p) { // if (err) { // winston.error('Error getting project ', err); // } // if (!p) { // winston.warn('Project not found '); // } // let payload = { // project: p, // request: request // } // if (attributes && attributes.sourcePage && (attributes.sourcePage.indexOf("td_draft=true") > -1)) { // winston.verbose("is a test conversation --> skip quote availability check") // isTestConversation = true; // } // else if (channel && (channel.name === 'voice-vxml')) { // winston.verbose("is a voice conversation --> skip quote availability check") // isVoiceConversation = true; // } // else { // // console.log("! check quota moved") // // let available = await qm.checkQuote(p, request, 'requests'); // // if (available === false) { // // winston.info("Requests limits reached for project " + p._id) // // return false; // // } // } // var context = { // request: { // request_id: request_id, project_user_id: project_user_id, lead_id: lead_id, id_project: id_project, // first_text: first_text, departmentid: departmentid, sourcePage: sourcePage, language: language, userAgent: userAgent, status: status, // createdBy: createdBy, attributes: attributes, subject: subject, preflight: preflight, channel: channel, location: location, // participants: participants, tags: tags, notes: notes, // priority: priority, auto_close: auto_close, followers: followers // } // }; // winston.debug("context", context); // var participantsAgents = []; // var participantsBots = []; // var hasBot = false; // var dep_id = undefined; // var assigned_at = undefined; // var agents = []; // var snapshot = {}; // try { // // getOperators(departmentid, projectid, nobot, disableWebHookCall, context) { // var result = await departmentService.getOperators(departmentid, id_project, false, undefined, context); // // console.log("************* after get operator: "+new Date().toISOString()); // winston.debug("getOperators", result); // } catch (err) { // return reject(err); // } // agents = result.agents; // if (status == 50) { // // skip assignment // if (participants.length == 0) { // dep_id = result.department._id; // } // } else { // if (participants.length == 0) { // if (result.operators && result.operators.length > 0) { // participants.push(result.operators[0].id_user.toString()); // } // // for preflight it is important to save agents in req for trigger. try to optimize it // dep_id = result.department._id; // } // if (participants.length > 0) { // status = RequestConstants.ASSIGNED; // /** // * QUOTAS - START!!! // */ // if (!isTestConversation && !isVoiceConversation) { // requestEvent.emit('request.create.quote', payload); // } // /** // * QUOTAS - END!!! // */ // // botprefix // if (participants[0].startsWith("bot_")) { // hasBot = true; // winston.debug("hasBot:" + hasBot); // // botprefix // var assigned_operator_idStringBot = participants[0].replace("bot_", ""); // winston.debug("assigned_operator_idStringBot:" + assigned_operator_idStringBot); // participantsBots.push(assigned_operator_idStringBot); // } else { // participantsAgents.push(participants[0]); // } // assigned_at = Date.now(); // } else { // status = RequestConstants.UNASSIGNED; // } // } // if (dep_id) { // snapshot.department = result.department; // } // // console.log("result.agents",result.agents); // snapshot.agents = agents; // snapshot.availableAgentsCount = that.getAvailableAgentsCount(agents); // if (request.requester) { //.toObject()???? // snapshot.requester = request.requester; // } // if (request.lead) { // snapshot.lead = request.lead; // } // // winston.debug("assigned_operator_id", assigned_operator_id); // // winston.debug("req status", status); // var newRequest = new Request({ // request_id: request_id, // requester: project_user_id, // lead: lead_id, // first_text: first_text, // subject: subject, // status: status, // participants: participants, // participantsAgents: participantsAgents, // participantsBots: participantsBots, // hasBot: hasBot, // department: dep_id, // // agents: agents, // //others // sourcePage: sourcePage, // language: language, // userAgent: userAgent, // assigned_at: assigned_at, // attributes: attributes, // //standard // id_project: id_project, // createdBy: createdBy, // updatedBy: createdBy, // preflight: preflight, // channel: channel, // location: location, // snapshot: snapshot, // tags: tags, // notes: notes, // priority: priority, // auto_close: auto_close, // followers: followers, // createdAt: createdAt // }); // if (isTestConversation) { // newRequest.draft = true; // } // winston.debug('newRequest.', newRequest); // //cacheinvalidation // return newRequest.save( async function (err, savedRequest) { // if (err) { // winston.error('RequestService error for method createWithIdAndRequester for newRequest' + JSON.stringify(newRequest), err); // return reject(err); // } // winston.debug("Request created", savedRequest.toObject()); // var endDate = new Date(); // winston.verbose("Performance Request created in millis: " + endDate - startDate); // requestEvent.emit('request.create.simple', savedRequest); // if (!isTestConversation && !isVoiceConversation) { // // requestEvent.emit('request.create.quote', payload);; // } // return resolve(savedRequest); // }); // // }).catch(function(err){ // // return reject(err); // // }); // }) // }); // } // DEPRECATED // async __create(request) { // var startDate = new Date(); // if (!request.createdAt) { // request.createdAt = new Date(); // } // var request_id = request.request_id; // var project_user_id = request.project_user_id; // var lead_id = request.lead_id; // var id_project = request.id_project; // var first_text = request.first_text; // //removed for ticket // // // lascia che sia nico a fare il replace...certo tu devi fare il test che tutto sia ok quindi dopo demo // // var first_text; // // if (request.first_text) { //first_text can be empty for type image // // first_text = request.first_text.replace(/[\n\r]+/g, ' '); //replace new line with space // // } // var departmentid = request.departmentid; // var sourcePage = request.sourcePage; // var language = request.language; // var userAgent = request.userAgent; // var status = request.status; // var createdBy = request.createdBy; // var attributes = request.attributes; // var subject = request.subject; // var preflight = request.preflight; // var channel = request.channel; // var location = request.location; // var participants = request.participants || []; // var tags = request.tags; // var notes = request.notes; // var priority = request.priority; // var auto_close = request.auto_close; // var followers = request.followers; // let createdAt = request.createdAt; // if (!departmentid) { // departmentid = 'default'; // } // if (!createdBy) { // if (project_user_id) { // createdBy = project_user_id; // } else { // createdBy = "system"; // } // } // var that = this; // return new Promise(async (resolve, reject) => { // var context = { // request: { // request_id: request_id, project_user_id: project_user_id, lead_id: lead_id, id_project: id_project, // first_text: first_text, departmentid: departmentid, sourcePage: sourcePage, language: language, userAgent: userAgent, status: status, // createdBy: createdBy, attributes: attributes, subject: subject, preflight: preflight, channel: channel, location: location, // participants: participants, tags: tags, notes: notes, // priority: priority, auto_close: auto_close, followers: followers // } // }; // winston.debug("context", context); // var participantsAgents = []; // var participantsBots = []; // var hasBot = false; // var dep_id = undefined; // var assigned_at = undefined; // var agents = []; // var snapshot = {}; // try { // // getOperators(departmentid, projectid, nobot, disableWebHookCall, context) { // var result = await departmentService.getOperators(departmentid, id_project, false, undefined, context); // // console.log("************* after get operator: "+new Date().toISOString()); // winston.debug("getOperators", result); // } catch (err) { // return reject(err); // } // agents = result.agents; // if (status == 50) { // // skip assignment // if (participants.length == 0) { // dep_id = result.department._id; // } // } else { // if (participants.length == 0) { // if (result.operators && result.operators.length > 0) { // participants.push(result.operators[0].id_user.toString()); // } // // for preflight it is important to save agents in req for trigger. try to optimize it // dep_id = result.department._id; // } // if (participants.length > 0) { // status = RequestConstants.ASSIGNED; // // botprefix // if (participants[0].startsWith("bot_")) { // hasBot = true; // winston.debug("hasBot:" + hasBot); // // botprefix // var assigned_operator_idStringBot = participants[0].replace("bot_", ""); // winston.debug("assigned_operator_idStringBot:" + assigned_operator_idStringBot); // participantsBots.push(assigned_operator_idStringBot); // } else { // participantsAgents.push(participants[0]); // } // assigned_at = Date.now(); // } else { // status = RequestConstants.UNASSIGNED; // } // } // if (dep_id) { // snapshot.department = result.department; // } // // console.log("result.agents",result.agents); // snapshot.agents = agents; // snapshot.availableAgentsCount = that.getAvailableAgentsCount(agents); // if (request.requester) { //.toObject()???? // snapshot.requester = request.requester; // } // if (request.lead) { // snapshot.lead = request.lead; // } // // winston.debug("assigned_operator_id", assigned_operator_id); // // winston.debug("req status", status); // var newRequest = new Request({ // request_id: request_id, // requester: project_user_id, // lead: lead_id, // first_text: first_text, // subject: subject, // status: status, // participants: participants, // participantsAgents: participantsAgents, // participantsBots: participantsBots, // hasBot: hasBot, // department: dep_id, // // agents: agents, // //others // sourcePage: sourcePage, // language: language, // userAgent: userAgent, // assigned_at: assigned_at, // attributes: attributes, // //standard // id_project: id_project, // createdBy: createdBy, // updatedBy: createdBy, // preflight: preflight, // channel: channel, // location: location, // snapshot: snapshot, // tags: tags, // notes: notes, // priority: priority, // auto_close: auto_close, // followers: followers, // createdAt: createdAt // }); // winston.debug('newRequest.', newRequest); // //cacheinvalidation // return newRequest.save(function (err, savedRequest) { // if (err) { // winston.error('RequestService error for method createWithIdAndRequester for newRequest' + JSON.stringify(newRequest), err); // return reject(err); // } // winston.debug("Request created", savedRequest.toObject()); // var endDate = new Date(); // winston.verbose("Performance Request created in millis: " + endDate - startDate); // requestEvent.emit('request.create.simple', savedRequest); // let q = Project.findOne({ _id: request.id_project, status: 100 }); // if (cacheEnabler.project) { // q.cache(cacheUtil.longTTL, "projects:id:" + request.id_project) //project_cache // winston.debug('project cache enabled for /project detail'); // } // q.exec(async function (err, p) { // if (err) { // winston.error('Error getting project ', err); // } // if (!p) { // winston.warn('Project not found '); // } // //TODO REMOVE settings from project // let payload = { // project: p, // request: request // } // requestEvent.emit('request.create.quote', payload);; // }); // return resolve(savedRequest); // }); // // }).catch(function(err){ // // return reject(err); // // }); // }); // } //DEPRECATED. USED ONLY IN SAME TESTS createWithId(request_id, requester_id, id_project, first_text, departmentid, sourcePage, language, userAgent, status, createdBy, attributes) { // winston.debug("request_id", request_id); if (!departmentid) { departmentid = 'default'; } if (!createdBy) { createdBy = requester_id; } var that = this; return new Promise(function (resolve, reject) { var context = { request: { request_id: request_id, requester_id: requester_id, id_project: id_project, first_text: first_text, departmentid: departmentid, sourcePage: sourcePage, language: language, userAgent: userAgent, status: status, createdBy: createdBy, attributes: attributes } }; // getOperators(departmentid, projectid, nobot, disableWebHookCall, context) return departmentService.getOperators(departmentid, id_project, false, undefined, context).then(function (result) { // winston.debug("getOperators", result); var status = RequestConstants.UNASSIGNED; var assigned_operator_id; var participants = []; var participantsAgents = []; var participantsBots = []; var hasBot = false; var assigned_at = undefined; if (result.operators && result.operators.length > 0) { assigned_operator_id = result.operators[0].id_user; status = RequestConstants.ASSIGNED; var assigned_operator_idString = assigned_operator_id.toString(); participants.push(assigned_operator_idString); // botprefix if (assigned_operator_idString.startsWith("bot_")) { hasBot = true; // botprefix var assigned_operator_idStringBot = assigned_operator_idString.replace("bot_", ""); winston.debug("assigned_operator_idStringBot:" + assigned_operator_idStringBot); participantsBots.push(assigned_operator_idStringBot); } else { participantsAgents.push(assigned_operator_idString); } assigned_at = Date.now(); } // winston.debug("assigned_operator_id", assigned_operator_id); // winston.debug("status", status); var newRequest = new Request({ request_id: request_id, requester_id: requester_id, first_text: first_text, status: status, participants: participants, participantsAgents: participantsAgents, participantsBots: participantsBots, hasBot: hasBot, department: result.department._id, agents: result.agents, //availableAgents: result.available_agents, // assigned_operator_id: result.assigned_operator_id, //others sourcePage: sourcePage, language: language, userAgent: userAgent, assigned_at: assigned_at, attributes: attributes, //standard id_project: id_project, createdBy: createdBy, updatedBy: createdBy }); // winston.debug('newRequest.',newRequest); //cacheinvalidation return newRequest.save(function (err, savedRequest) { if (err) { winston.error('RequestService error for method createWithId for newRequest' + JSON.stringify(newRequest), err); return reject(err); } winston.ver