From 0f67a53bfc1a869f2ba46d5dc356360b397aded2 Mon Sep 17 00:00:00 2001 From: "j.goderbauer" <j.goderbauer@adito.de> Date: Thu, 21 Nov 2019 15:26:38 +0100 Subject: [PATCH] =?UTF-8?q?[Projekt:=20Entwicklung=20-=20Neon][TicketNr.:?= =?UTF-8?q?=201046306][CTI=20-=20Reverse=20suche=20=C3=BCber=20Index]=20#?= =?UTF-8?q?=20Conflicts:=20#=09entity/Organisation=5Fentity/recordcontaine?= =?UTF-8?q?rs/index/query.js=20#=09entity/Person=5Fentity/recordcontainers?= =?UTF-8?q?/index/query.js=20#=09process/IncomingCallExecutor=5Flib/proces?= =?UTF-8?q?s.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../recordcontainers/index/query.js | 8 +- .../recordcontainers/index/query.js | 8 +- process/IncomingCallExecutor_lib/process.js | 97 +++++++++++++++---- process/ctiServerEvents/process.js | 14 ++- 4 files changed, 103 insertions(+), 24 deletions(-) diff --git a/entity/Organisation_entity/recordcontainers/index/query.js b/entity/Organisation_entity/recordcontainers/index/query.js index bb097e6fc4..0dc0d18978 100644 --- a/entity/Organisation_entity/recordcontainers/index/query.js +++ b/entity/Organisation_entity/recordcontainers/index/query.js @@ -6,7 +6,13 @@ import("system.db"); import("Sql_lib"); import("Communication_lib"); -//TODO: refactor to new SqlBuilder +/* +Before changing the results that are returned here: +Please keep in mind that some of the indexfields are used in other modules (like the duplicate-scanner or cti-call-handler). +You may want to check out if your change affects other modules. However adding more fields should not be a problem therefor. + */ + +var sqlQuery, sqlHelper, queryCondition, affectedIds; var CommMediumPhoneIds = db.array( db.COLUMN, "select KEYID from AB_KEYWORD_ENTRY join ab_keyword_attributerelation on AB_KEYWORD_ENTRYID = AB_KEYWORD_ENTRY_ID " + " join ab_keyword_attribute on AB_KEYWORD_ATTRIBUTEID = AB_KEYWORD_ATTRIBUTE_ID and CHAR_VALUE = 'TELEPHONE' and AB_KEYWORD_ATTRIBUTE.CONTAINER = 'CommunicationMedium'"); var sqlHelper = new SqlMaskingUtils(); diff --git a/entity/Person_entity/recordcontainers/index/query.js b/entity/Person_entity/recordcontainers/index/query.js index 67167891a8..d3029e1734 100644 --- a/entity/Person_entity/recordcontainers/index/query.js +++ b/entity/Person_entity/recordcontainers/index/query.js @@ -6,7 +6,13 @@ import("system.db"); import("Sql_lib"); import("Communication_lib"); -//TODO: refactor to new SqlBuilder +/* +Before changing the results that are returned here: +Please keep in mind that some of the indexfields are used in other modules (like the duplicate-scanner or cti-call-handler). +You may want to check out if your change affects other modules. However adding more fields should not be a problem therefor. + */ + +var sqlQuery, sqlHelper, queryCondition, affectedIds; var CommMediumPhoneIds = db.array( db.COLUMN, "select KEYID from AB_KEYWORD_ENTRY join ab_keyword_attributerelation on AB_KEYWORD_ENTRYID = AB_KEYWORD_ENTRY_ID " + " join ab_keyword_attribute on AB_KEYWORD_ATTRIBUTEID = AB_KEYWORD_ATTRIBUTE_ID and CHAR_VALUE = 'TELEPHONE' and AB_KEYWORD_ATTRIBUTE.CONTAINER = 'CommunicationMedium'"); var sqlHelper = new SqlMaskingUtils(); diff --git a/process/IncomingCallExecutor_lib/process.js b/process/IncomingCallExecutor_lib/process.js index eb8b65edb8..1a606d9a62 100644 --- a/process/IncomingCallExecutor_lib/process.js +++ b/process/IncomingCallExecutor_lib/process.js @@ -1,3 +1,4 @@ +import("system.entities"); import("system.datetime"); import("system.util"); import("system.notification"); @@ -7,9 +8,36 @@ import("system.tools"); import("system.db"); import("Sql_lib"); import("system.cti"); +import("system.indexsearch"); -//TODO: comment library +//TODO: comment library completely +/** + * object for processing cti-calls + * Within the constructor, data is collected but not further processed. To perform operations, different methods are provide (lke the .execute-function) + * + * @class + * @param {Object} pCallData object with all the basic call information, the object needs the following parameters: <ul> + * <li>action:for example: vars.get("$local.action") </li> + * <li>callId:uid of the call, requried, for example: vars.get("$local.callID") </li> + * <li>localAddress:the target phone address, for example: vars.get("$local.localAddress") </li> + * <li>localId:id of the call target, for example: vars.get("$local.localID") </li> + * <li>callAddress:the source phone address, for example: vars.get("$local.callAddress") </li> + * <li>isIncomingCall:Boolean:is the call an incoming or outgoing call, for example: vars.getString("$local.callIsIncoming") == "true" </li> + * <li>state:Number:callstate-constant (Ringing, talking, etc.), for example: Number(vars.get("$local.callState")) </li> + * <li>privateData:Object: additional telephony data when the tapi does provide it, for example: vars.exists("$local.privateData2") ? vars.get("$local.privateData2") : null </li> + * <li>isConnectedCall:Boolean:specifies if the call was redirected ("connected") from somebody else</li> + * </ul> + * + * @example + * + * var ic = new IncomingCallExecutor(callData); + * //most of the logic happens in the handler-fuctions + * ic.setHandlerRinging(ringingHandlerFn); + * ic.setHandlerTalking(talkingHandlerFn); + * ic.setHandlerDisconnect(disconnectingHandlerFn); + * ic.execute(); + */ function IncomingCallExecutor(pCallData) { this.callData = pCallData; @@ -98,9 +126,9 @@ IncomingCallExecutor.prototype.getNotificationBaseConfig = function(pUserName) return null; var notificationConfig = notification.createConfig() - .addUserWithId(pUserName) - .contentId(this.callData.callId) - .notificationType("_____SYSTEM_NOTIFICATION_PHONECALL"); + .addUserWithId(pUserName) + .contentId(this.callData.callId)//group all notifications of one call together + .notificationType("_____SYSTEM_NOTIFICATION_PHONECALL"); return notificationConfig; }; @@ -180,22 +208,49 @@ IncomingCallExecutor._callstateToText = function(pCallstate) IncomingCallExecutor._getContactsFromNumber = function(pNumber, pContactIds) { var phoneNumber = pNumber; - if (!phoneNumber && !pContactIds) + if (!phoneNumber && (!pContactIds || pContactIds.length == 0))//either of one needs to be specified, otherwise we wouldn't know what to search return []; - /* - var config = entities.createConfigForLoadingRows().entity("Communication_entity") - .fields(["CONTACT_ID"]) - .provider("PhoneCommunications") - .addParameter("Address_param", phoneNumber); - var rows = entities.getRows(config); - var contactIds = rows.map(function (e){ - return e.CONTACT_ID; - }); - config = entities.createConfigForLoadingRows().entity("AnyContact_entity") - .fields(["CONTACTID", "ORGANISATION_ID", "ORGANISATION_NAME", "PERSON_ID", "ISOLANGUAGE", "PERSON_FULL_NAME"]) - .uids(contactIds); - rows = entities.getRows(); + var contactIds = pContactIds || []; + + if (pNumber) + { + /* + Searching for a number is done via the index because + - it's fast + - there is no need to sanitize stored phone-addresses or the phone-address we are looking for + (this is done by the api automatically when the indexFieldType is configured as "TELEPHONE") + - the pattern and terms can be configured very detailed (fuzzy, wildcards, boosting) etc. to ensure that the best results are delivered + (currently a basic search is done because this has proven to return the best results till now; however this may need to be adjusted to a connected telephy-system) + + Searching the index is done via the indexsearch-methods and not an index-record container because we need to serach for both personContacts + and organisationContacts. There exists a entity "AnyContact_entity" which represents personContacts- and organisationContacts-data + but that entity has no index record container defined at the moment. So instead searching multiple IndexGroups is done here. + Because different indexGroup store data differently, we cannot directly load usage-data like the organisation-name, person-name and so on + from the index. Instead we are only loading the ID-field (which is the contactId in both groups) and then load the usage-data for these + contactIds. + */ + var patternConfig = indexsearch.createPatternConfig(); + var searchTerm = indexsearch.createTerm(pNumber).setIndexField("phone"); + patternConfig.plus(searchTerm); + var pattern = indexsearch.buildPatternString(patternConfig); + var indexQuery = indexsearch.createIndexQuery().setPattern(pattern) + .addIndexGroups("Person", "Organisation") + .addResultIndexFields([indexsearch.FIELD_ID]); + var indexResult = indexsearch.searchIndex(indexQuery); + if (indexResult.HITS) + contactIds = contactIds.concat(indexResult.HITS.map(function (e){return e[indexsearch.FIELD_ID];})); + } + + if (contactIds.length == 0) + return []; + + //load entities does not work in serverProcesses at the moment, so instead use a traditional sql-query: //TODO: change this after #1047680 is done + /* + var config = entities.createConfigForLoadingRows().entity("AnyContact_entity") + .fields(["CONTACTID", "ORGANISATION_ID", "ORGANISATION_NAME", "PERSON_ID", "ISOLANGUAGE", "PERSON_FULL_NAME"]) + .uids(contactIds); + rows = entities.getRows(config); return rows; */ //load entities does not work here, so use instead a traditional sql-query: @@ -204,12 +259,12 @@ IncomingCallExecutor._getContactsFromNumber = function(pNumber, pContactIds) .join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID") .leftJoin("PERSON", "CONTACT.PERSON_ID = PERSON.PERSONID") .join("COMMUNICATION", "COMMUNICATION.CONTACT_ID = CONTACT.CONTACTID") - .whereIfSet("COMMUNICATION.ADDR", phoneNumber) + .where("CONTACT.STATUS", $KeywordRegistry.contactStatus$active()) .and("COMMUNICATION.CONTACT_ID", pContactIds, SqlBuilder.IN()) - .and("CONTACT.STATUS", $KeywordRegistry.contactStatus$active()) .table(); - return contacts.map(function (e){//map to the result how the entities-methods would return it to have less effort later + //map to the result how the entities-methods would return it to have less effort later when the mentioned ticket is done + return contacts.map(function (e){ return { CONTACTID: e[0], ORGANISATION_ID: e[1], diff --git a/process/ctiServerEvents/process.js b/process/ctiServerEvents/process.js index d199d0b837..cceed473a5 100644 --- a/process/ctiServerEvents/process.js +++ b/process/ctiServerEvents/process.js @@ -62,7 +62,7 @@ var ringingHandlerFn = function() notificationConfig.linkInfo(text.encodeMS([affectedContext, affectedContactId])); } - + notification.addNotificationWith(notificationConfig); return null; }, this); @@ -140,6 +140,14 @@ var disconnectingHandlerFn = function() var notificationConfig = this.getNotificationBaseConfig(userObj[tools.NAME]); if (notificationConfig == null) return null; + + if (this.contactsCall.length > 0) + { + var affectedContext = this.contactsCall[0].PERSON_ID.trim() == "" ? "Organisation" : "Person"; + var affectedContactId = this.contactsCall[0].CONTACTID; + notificationConfig.linkInfo(text.encodeMS([affectedContext, affectedContactId])); + } + notificationConfig.description(desc).caption(title); notification.addNotificationWith(notificationConfig); @@ -162,6 +170,10 @@ var callData = { ,isConnectedCall: false }; +//for testing only: +//callData.callAddress = "01731858728"; +//callData.localAddress = "PJSIP/212"; + var ic = new IncomingCallExecutor(callData); //ic.logData(); ic.setHandlerRinging(ringingHandlerFn); -- GitLab