diff --git a/.liquibase/Data_alias/basic/2021.0.0/EwsContactSync/create_ab_synccontact.xml b/.liquibase/Data_alias/basic/2021.0.0/EwsContactSync/create_ab_synccontact.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9de2f01cc35fba70afd6992a3995da9c8e1b7431
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2021.0.0/EwsContactSync/create_ab_synccontact.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
+    <changeSet author="A.Riedl" id="9820d74b-1b58-4ffd-9f5d-8c4d670bda47">
+        <createTable tableName="AB_SYNCCONTACT">
+            <column name="SYNCCONTACTID" type="char(36)">
+                <constraints primaryKey="true" primaryKeyName="PK_SYNCCONTACTID"/>
+            </column>
+            <column name="ASYS_FAVORITEID" type="char(36)"/>
+            <column name="EXCHANGEID" type="varchar(254)"/>
+            <column name="USER_ID" type="char(46)"/>            
+            <column name="CONTACT_ID" type="char(36)"/>
+            <column name="DATE_DEL" type="datetime"/>
+            <column name="DATE_EDIT" type="datetime"/>
+            <column name="DATE_NEW" type="datetime"/>
+        </createTable>
+        <createIndex indexName="idx_exchangeId" tableName="AB_SYNCCONTACT">
+            <column name="EXCHANGEID"/>
+        </createIndex>
+        <createIndex tableName="AB_SYNCCONTACT" indexName="idx_UserId">
+            <column name="USER_ID"/>
+        </createIndex>
+        <createIndex tableName="AB_SYNCCONTACT" indexName="idx_ContactId">
+            <column name="CONTACT_ID"/>
+        </createIndex>
+        <addUniqueConstraint 
+            columnNames="ASYS_FAVORITEID"
+            constraintName="const_uniqueFavoriteId"  
+            tableName="AB_SYNCCONTACT"/>  
+    </changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2021.0.0/changelog.xml b/.liquibase/Data_alias/basic/2021.0.0/changelog.xml
index b020b1e6d1dcadcd1c6ddcff09cb36cf57dd4dca..21d9b6123c339868f578deb1c41f89eb8269b0d3 100644
--- a/.liquibase/Data_alias/basic/2021.0.0/changelog.xml
+++ b/.liquibase/Data_alias/basic/2021.0.0/changelog.xml
@@ -14,4 +14,5 @@
     <include relativeToChangelogFile="true" file="Keywords/changelog.xml"/>
     <include relativeToChangelogFile="true" file="KeywordMigration/changelog.xml"/>
     <include relativeToChangelogFile="true" file="addDateNewToSalesproject.xml"/>
+    <include relativeToChangelogFile="true" file="EwsContactSync/create_ab_synccontact.xml"/>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/entity/Campaign_entity/Campaign_entity.aod b/entity/Campaign_entity/Campaign_entity.aod
index f5c04fb9aa81e250a12f0f2253e8201607d2aa53..8e4f23dc87086a0d65df0b391c3816b4f4641e26 100644
--- a/entity/Campaign_entity/Campaign_entity.aod
+++ b/entity/Campaign_entity/Campaign_entity.aod
@@ -498,8 +498,8 @@
       </children>
     </entityConsumer>
     <entityField>
-      <name>CAMPAIGN_OBEJCTTYPE</name>
-      <valueProcess>%aditoprj%/entity/Campaign_entity/entityfields/campaign_obejcttype/valueProcess.js</valueProcess>
+      <name>CAMPAIGN_OBJECTTYPE</name>
+      <valueProcess>%aditoprj%/entity/Campaign_entity/entityfields/campaign_objecttype/valueProcess.js</valueProcess>
     </entityField>
     <entityConsumer>
       <name>PersonConsumer</name>
@@ -687,6 +687,14 @@
           <filterConditionProcess>%aditoprj%/entity/Campaign_entity/recordcontainers/db/filterextensions/attribute_filter/filterConditionProcess.js</filterConditionProcess>
           <filtertype>BASIC</filtertype>
         </filterExtensionSet>
+        <filterExtension>
+          <name>Favorite_Filter</name>
+          <title>Favoritegroup</title>
+          <contentType>TEXT</contentType>
+          <filterValuesProcess>%aditoprj%/entity/Campaign_entity/recordcontainers/db/filterextensions/favorite_filter/filterValuesProcess.js</filterValuesProcess>
+          <filterConditionProcess>%aditoprj%/entity/Campaign_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js</filterConditionProcess>
+          <filtertype>BASIC</filtertype>
+        </filterExtension>
       </filterExtensions>
     </dbRecordContainer>
   </recordContainers>
diff --git a/entity/Campaign_entity/entityfields/campaign_obejcttype/valueProcess.js b/entity/Campaign_entity/entityfields/campaign_objecttype/valueProcess.js
similarity index 100%
rename from entity/Campaign_entity/entityfields/campaign_obejcttype/valueProcess.js
rename to entity/Campaign_entity/entityfields/campaign_objecttype/valueProcess.js
diff --git a/entity/Campaign_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/Campaign_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..8c69112797b6d3dfddda65853554193ffd335918
--- /dev/null
+++ b/entity/Campaign_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -0,0 +1,12 @@
+import("system.vars");
+import("Favorites_lib");
+import("system.result");
+import("Sql_lib");
+
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
+
+var objecttype = vars.get("$field.CAMPAIGN_OBJECTTYPE");
+var idcolumn = "CAMPAIGN.CAMPAIGNID";
+
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
\ No newline at end of file
diff --git a/entity/Campaign_entity/recordcontainers/db/filterextensions/favorite_filter/filterValuesProcess.js b/entity/Campaign_entity/recordcontainers/db/filterextensions/favorite_filter/filterValuesProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..419128ca73fe597afc7ca4aeed50b28e610206ec
--- /dev/null
+++ b/entity/Campaign_entity/recordcontainers/db/filterextensions/favorite_filter/filterValuesProcess.js
@@ -0,0 +1,5 @@
+import("Context_lib");
+import("system.result");
+import("Favorites_lib");
+
+result.object(FavoritesUtil.getUserFavoriteGroupsByContext(ContextUtils.getCurrentContextId()));
\ No newline at end of file
diff --git a/entity/Communication_entity/Communication_entity.aod b/entity/Communication_entity/Communication_entity.aod
index fa0187084e458d0756e6a7f8402b4504bba23bb5..6825e5edc558a5f1ce8fa754382231dd31d125e9 100644
--- a/entity/Communication_entity/Communication_entity.aod
+++ b/entity/Communication_entity/Communication_entity.aod
@@ -6,6 +6,7 @@
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <documentation>%aditoprj%/entity/Communication_entity/documentation.adoc</documentation>
   <contentTitleProcess>%aditoprj%/entity/Communication_entity/contentTitleProcess.js</contentTitleProcess>
+  <afterOperatingState>%aditoprj%/entity/Communication_entity/afterOperatingState.js</afterOperatingState>
   <recordContainer>db</recordContainer>
   <entityFields>
     <entityField>
diff --git a/entity/Communication_entity/afterOperatingState.js b/entity/Communication_entity/afterOperatingState.js
new file mode 100644
index 0000000000000000000000000000000000000000..7085e9f853c10e7ebaadcd76f44b8786c5d621ed
--- /dev/null
+++ b/entity/Communication_entity/afterOperatingState.js
@@ -0,0 +1,5 @@
+import("system.vars");
+import("system.neon");
+
+if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_VIEW)
+    vars.set("$context.PushDataPrivacyNotification", "false");
\ No newline at end of file
diff --git a/entity/Communication_entity/recordcontainers/db/onDBInsert.js b/entity/Communication_entity/recordcontainers/db/onDBInsert.js
index 5497aac10e4c84e9d6f63bdd28012b0bfe75cc06..7d836ae39e0b9d809ba388111d4ab1ab4302a6f9 100644
--- a/entity/Communication_entity/recordcontainers/db/onDBInsert.js
+++ b/entity/Communication_entity/recordcontainers/db/onDBInsert.js
@@ -11,7 +11,11 @@ var rowdata = vars.get("$local.rowdata");
 var standard = new StandardObject("Communication", vars.get("$local.uid"), "Person", rowdata["COMMUNICATION.CONTACT_ID"])
 standard.onCommunicationInsert(rowdata["COMMUNICATION.MEDIUM_ID"]);
 
-DataPrivacyUtils.notifyNeedDataPrivacyUpdate(rowdata["COMMUNICATION.CONTACT_ID"], vars.get("$param.ShowDsgvoMessage_param"));
+if(vars.exists("$context.PushDataPrivacyNotification") && vars.get("$context.PushDataPrivacyNotification") == "false" && vars.get("$sys.isclient"))
+{
+    DataPrivacyUtils.notifyNeedDataPrivacyUpdate(rowdata["COMMUNICATION.CONTACT_ID"], vars.get("$param.ShowDsgvoMessage_param"));
+    vars.set("$context.PushDataPrivacyNotification", "true");
+} 
 
 if (vars.exists("$param.AdditionalContactIds_param") && vars.get("$param.AdditionalContactIds_param"))
 {
diff --git a/entity/Communication_entity/recordcontainers/db/onDBUpdate.js b/entity/Communication_entity/recordcontainers/db/onDBUpdate.js
index da680f82c23c27da4f2cfb65488df9b1426b77bc..ebf288114b69f9c461bebc6ca31b2c39ada5b513 100644
--- a/entity/Communication_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/Communication_entity/recordcontainers/db/onDBUpdate.js
@@ -10,7 +10,11 @@ if (rowdata["COMMUNICATION.CONTACT_ID"] != null)
     var standard = new StandardObject("Communication", vars.get("$local.uid"), "Person", rowdata["COMMUNICATION.CONTACT_ID"])
     standard.onCommunicationUpdate(rowdata["COMMUNICATION.MEDIUM_ID"]);
 }
-  
-DataPrivacyUtils.notifyNeedDataPrivacyUpdate(rowdata["COMMUNICATION.CONTACT_ID"], vars.get("$param.ShowDsgvoMessage_param"));
+
+if(vars.exists("$context.PushDataPrivacyNotification") && vars.get("$context.PushDataPrivacyNotification") == "false" && vars.get("$sys.isclient"))
+{
+    DataPrivacyUtils.notifyNeedDataPrivacyUpdate(rowdata["COMMUNICATION.CONTACT_ID"], vars.get("$param.ShowDsgvoMessage_param"));
+    vars.set("$context.PushDataPrivacyNotification", "true");
+}  
 
 WorkflowSignalSender.updated();
\ No newline at end of file
diff --git a/entity/Contract_entity/Contract_entity.aod b/entity/Contract_entity/Contract_entity.aod
index 3e3262421190782abc4d26f6b958f51acb4dc26b..49afa5872c3c02495fe5846da0a83f2234d4fa72 100644
--- a/entity/Contract_entity/Contract_entity.aod
+++ b/entity/Contract_entity/Contract_entity.aod
@@ -596,6 +596,7 @@
           <contentType>TEXT</contentType>
           <filterValuesProcess>%aditoprj%/entity/Contract_entity/recordcontainers/db/filterextensions/favorite_filter/filterValuesProcess.js</filterValuesProcess>
           <filterConditionProcess>%aditoprj%/entity/Contract_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js</filterConditionProcess>
+          <groupedRecordField></groupedRecordField>
           <filtertype>BASIC</filtertype>
         </filterExtension>
       </filterExtensions>
diff --git a/entity/Contract_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/Contract_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
index 6b54c170684381c41d00387e9f2371c7d327d05a..8f9bf3561bdd112fd994940777b7e761b607f768 100644
--- a/entity/Contract_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
+++ b/entity/Contract_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("CONTRACT.CONTRACTID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.CONTRACT_OBJECTTYPE");
+var idcolumn = "CONTRACT.CONTRACTID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
\ No newline at end of file
diff --git a/entity/DocumentTemplate_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/DocumentTemplate_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
index c3deb28e584154a76101902faaebb110e2c5d7d8..73410be03fab8d10e3ee99009855a5dcd5b4df12 100644
--- a/entity/DocumentTemplate_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
+++ b/entity/DocumentTemplate_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("DOCUMENTTEMPLATE.DOCUMENTTEMPLATEID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.DOCUMENTTEMPLATE_OBJECTTYPE");
+var idcolumn = "DOCUMENTTEMPLATE.DOCUMENTTEMPLATEID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
diff --git a/entity/EwsSyncAddContacts_entity/EwsSyncAddContacts_entity.aod b/entity/EwsSyncAddContacts_entity/EwsSyncAddContacts_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..332169d840fba95e4b9a7507ede82835e4fda87e
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/EwsSyncAddContacts_entity.aod
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.18" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.18">
+  <name>EwsSyncAddContacts_entity</name>
+  <title>add  contact to ewssync</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <titlePlural></titlePlural>
+  <recordContainer>datalessConfig</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+    </entityProvider>
+    <entityProvider>
+      <name>#PROVIDER_AGGREGATES</name>
+      <useAggregates v="true" />
+    </entityProvider>
+    <entityField>
+      <name>contactIds</name>
+      <state>EDITABLE</state>
+      <valueProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/contactids/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>countForSync</name>
+      <title>count</title>
+      <state>EDITABLE</state>
+      <valueProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/countforsync/valueProcess.js</valueProcess>
+    </entityField>
+    <entityParameter>
+      <name>ContactFilter_param</name>
+      <expose v="true" />
+    </entityParameter>
+    <entityParameter>
+      <name>ContactIds_param</name>
+      <expose v="true" />
+    </entityParameter>
+    <entityActionField>
+      <name>syncContacts</name>
+      <title>add to sync</title>
+      <onActionProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/onActionProcess.js</onActionProcess>
+      <iconId>VAADIN:REFRESH</iconId>
+      <stateProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/stateProcess.js</stateProcess>
+      <tooltip></tooltip>
+    </entityActionField>
+    <entityParameter>
+      <name>Mode_param</name>
+      <expose v="true" />
+    </entityParameter>
+    <entityActionField>
+      <name>removeSyncContacts</name>
+      <title>remove from sync</title>
+      <onActionProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/onActionProcess.js</onActionProcess>
+      <isObjectAction v="true" />
+      <iconId>NEON:RECURRING_APPOINTMENT_MOVED</iconId>
+      <stateProcess>%aditoprj%/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/stateProcess.js</stateProcess>
+    </entityActionField>
+  </entityFields>
+  <recordContainers>
+    <datalessRecordContainer>
+      <name>datalessConfig</name>
+      <alias>Data_alias</alias>
+    </datalessRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/contactids/valueProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/contactids/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..373f61e18faccaead7724225f920d46437148b77
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/contactids/valueProcess.js
@@ -0,0 +1,10 @@
+import("system.result");
+import("system.vars");
+import("FilterViewAction_lib");
+
+var contactIds = JSON.parse(vars.get("$param.ContactIds_param"));
+var contactFilter = vars.get("$param.ContactFilter_param");
+
+contactIds = FilterViewActionUtils.getUidsBySelectionOrFilter("Person", contactIds, contactFilter);
+
+result.string(JSON.stringify(contactIds));
\ No newline at end of file
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/countforsync/valueProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/countforsync/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..4d01818ca409c8b5746f74b408c7b4456931abe8
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/countforsync/valueProcess.js
@@ -0,0 +1,10 @@
+import("system.vars");
+import("system.result");
+
+var res = "";
+if (vars.get("$field.contactIds"))
+{
+    res = JSON.parse(vars.getString("$field.contactIds")).length;
+}
+
+result.string(res);
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/onActionProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..b0a2ce611876352836e323dcd13a38cc97f0a718
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/onActionProcess.js
@@ -0,0 +1,8 @@
+import("system.neon");
+import("system.tools");
+import("EwsClientSync_lib");
+import("system.vars");
+
+var contactIds = JSON.parse(vars.get("$field.contactIds"));
+EwsClientSyncUtils.removeFromFavorite(contactIds, tools.getCurrentUser()[tools.NAME]);
+neon.closeImage(vars.get("$sys.currentimage"), true);
\ No newline at end of file
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/stateProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ae3eef9a8407cd8e4edaee71f77b14a6c233d03
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/removesynccontacts/stateProcess.js
@@ -0,0 +1,11 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+var mode = vars.get("$param.Mode_param");
+var ret = neon.COMPONENTSTATE_INVISIBLE; 
+
+if(mode == "REMOVE")
+    ret = neon.COMPONENTSTATE_EDITABLE;
+
+result.string(ret);
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/onActionProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..34578d4b676914a1e2aa7b8ec83e9277bd82aea1
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/onActionProcess.js
@@ -0,0 +1,9 @@
+import("system.neon");
+import("EwsClientSync_lib");
+import("system.vars");
+
+var toSncContacts = JSON.parse(vars.get("$field.contactIds"));
+
+//the handling of already Contacts in the Exchange is handeled by the function itself
+EwsClientSyncUtils.addToEwsFavorite(toSncContacts);
+neon.closeImage(vars.get("$sys.currentimage"), true);
\ No newline at end of file
diff --git a/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/stateProcess.js b/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/stateProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c10e581fee4f5e13e064bbbb4a8faa11c9470aa3
--- /dev/null
+++ b/entity/EwsSyncAddContacts_entity/entityfields/synccontacts/stateProcess.js
@@ -0,0 +1,11 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+
+var mode = vars.get("$param.Mode_param");
+var ret = neon.COMPONENTSTATE_INVISIBLE; 
+
+if(mode == "ADD")
+    ret = neon.COMPONENTSTATE_EDITABLE;
+
+result.string(ret);
diff --git a/entity/ExportTemplate_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/ExportTemplate_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
index 27c569099821e96f51c9ab7e3e5c7a6db87d6e09..57784ebda7e75d58197542d071b5afb2a61cc74e 100644
--- a/entity/ExportTemplate_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
+++ b/entity/ExportTemplate_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("EXPORTTEMPLATE.EXPORTTEMPLATEID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.EXPORTTEMPLATE_OBJECTTYPE");
+var idcolumn = "EXPORTTEMPLATE.EXPORTTEMPLATEID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
\ No newline at end of file
diff --git a/entity/Leadimport_entity/Leadimport_entity.aod b/entity/Leadimport_entity/Leadimport_entity.aod
index 1f79a0d182c36726786038ae468c2f973dd8066f..6dd8755383e13bf7bbebf6c77c00bf0e3f0688dc 100644
--- a/entity/Leadimport_entity/Leadimport_entity.aod
+++ b/entity/Leadimport_entity/Leadimport_entity.aod
@@ -68,7 +68,6 @@
       <name>STATUS</name>
       <title>Status</title>
       <consumer>KeywordImportStatus</consumer>
-      <groupable v="true" />
       <state>READONLY</state>
       <valueProcess>%aditoprj%/entity/Leadimport_entity/entityfields/status/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Leadimport_entity/entityfields/status/displayValueProcess.js</displayValueProcess>
@@ -131,7 +130,6 @@
     <entityField>
       <name>IMPORTSOURCE</name>
       <title>Import source</title>
-      <groupable v="true" />
       <mandatory v="true" />
     </entityField>
     <entityConsumer>
diff --git a/entity/Offer_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/Offer_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
index 4157abe2c850e42fb49e06207d907884670e46e2..63107e39aba496b0175d11ffbcc930fcef263d46 100644
--- a/entity/Offer_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
+++ b/entity/Offer_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("OFFER.OFFERID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.OFFER_OBJECTTYPE");
+var idcolumn = "OFFER.OFFERID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
diff --git a/entity/Order_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/Order_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
index 647507498cf404c675a2a3225f36369d7012659d..7d1adc14150119dd7ff8be0b48535cccc4aadf52 100644
--- a/entity/Order_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
+++ b/entity/Order_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("SALESORDER.SALESORDERID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.ORDER_OBJECTTYPE");
+var idcolumn = "SALESORDER.SALESORDERID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
diff --git a/entity/Organisation_entity/recordcontainers/db/filterextensions/favorites_filter/filterConditionProcess.js b/entity/Organisation_entity/recordcontainers/db/filterextensions/favorites_filter/filterConditionProcess.js
index d42520a347c8e8d594fb1af389acb8af1a2e824c..888ac0657242f41866a37f471b9765b045b52594 100644
--- a/entity/Organisation_entity/recordcontainers/db/filterextensions/favorites_filter/filterConditionProcess.js
+++ b/entity/Organisation_entity/recordcontainers/db/filterextensions/favorites_filter/filterConditionProcess.js
@@ -1,19 +1,27 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
+var objecttype = vars.get("$field.ORGANISATION_OBJECTTYPE");
+var idcolumn = "ORGANISATION.ORGANISATIONID";
+
+
+var rowIds = FavoritesUtil.getRowIdsOfFavorites(objecttype, operator, rawvalue);
+var preparedIds = [];
 
 for(i = 0; i < rowIds.length; i++)
 {        
-    var orga_id = new SqlBuilder().select("CONTACT.ORGANISATION_ID")
+    var person_id = new SqlBuilder().select("CONTACT.ORGANISATION_ID")
         .from("CONTACT")
         .where(newWhere("CONTACT.CONTACTID", rowIds[i]))
         .arrayColumn();
 
-    if(orga_id.length > 0)
-        favoFilterCond.or("ORGANISATION.ORGANISATIONID", orga_id[0], SqlBuilder.EQUAL());
+    if(person_id.length > 0)
+        preparedIds.push(person_id[0]);
 }
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn, preparedIds));
\ No newline at end of file
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index ac6d2e755a3059859fd1adb11bc724f80856ea89..b5d6a079e7970a57ac684887b51d6c2edda3b287 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -1333,6 +1333,20 @@
           <stateProcess>%aditoprj%/entity/Person_entity/entityfields/filterviewactiongroup/children/cancelobservation/stateProcess.js</stateProcess>
           <titleProcess>%aditoprj%/entity/Person_entity/entityfields/filterviewactiongroup/children/cancelobservation/titleProcess.js</titleProcess>
         </entityActionField>
+        <entityActionField>
+          <name>addToContactSync</name>
+          <title>add Contact to Sync</title>
+          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocontactsync/onActionProcess.js</onActionProcess>
+          <iconId>NEON:RECURRING_APPOINTMENT</iconId>
+          <state>EDITABLE</state>
+        </entityActionField>
+        <entityActionField>
+          <name>removeFromContactSync</name>
+          <title>remove Contact from Sync</title>
+          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/filterviewactiongroup/children/removefromcontactsync/onActionProcess.js</onActionProcess>
+          <iconId>NEON:RECURRING_APPOINTMENT_MOVED</iconId>
+          <state>AUTO</state>
+        </entityActionField>
       </children>
     </entityActionGroup>
     <entityActionGroup>
diff --git a/entity/Person_entity/entityfields/attributes/children/showdsgvomessage_param/valueProcess.js b/entity/Person_entity/entityfields/attributes/children/showdsgvomessage_param/valueProcess.js
index fce9fde135bfde9221a9956f545862641098ff7c..c96eec50f67631c175c60d748ded5821644aea70 100644
--- a/entity/Person_entity/entityfields/attributes/children/showdsgvomessage_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/attributes/children/showdsgvomessage_param/valueProcess.js
@@ -2,4 +2,4 @@ import("system.vars");
 import("system.neon");
 import("system.result");
 
-result.string(vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW);
\ No newline at end of file
+result.string(vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW && vars.get("$sys.recordstate") != neon.OPERATINGSTATE_EDIT);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/communications/children/showdsgvomessage_param/valueProcess.js b/entity/Person_entity/entityfields/communications/children/showdsgvomessage_param/valueProcess.js
index fce9fde135bfde9221a9956f545862641098ff7c..c96eec50f67631c175c60d748ded5821644aea70 100644
--- a/entity/Person_entity/entityfields/communications/children/showdsgvomessage_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/communications/children/showdsgvomessage_param/valueProcess.js
@@ -2,4 +2,4 @@ import("system.vars");
 import("system.neon");
 import("system.result");
 
-result.string(vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW);
\ No newline at end of file
+result.string(vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW && vars.get("$sys.recordstate") != neon.OPERATINGSTATE_EDIT);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocontactsync/onActionProcess.js b/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocontactsync/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..3ba5646790e532ee17f5d19d6fd57fbaece4a4d1
--- /dev/null
+++ b/entity/Person_entity/entityfields/filterviewactiongroup/children/addtocontactsync/onActionProcess.js
@@ -0,0 +1,4 @@
+import("EwsClientSync_lib");
+import("system.vars");
+
+EwsClientSyncUtils.openEwsSyncAddContactView(vars.get("$sys.selection"), vars.get("$sys.filter"), "ADD");
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/filterviewactiongroup/children/removefromcontactsync/onActionProcess.js b/entity/Person_entity/entityfields/filterviewactiongroup/children/removefromcontactsync/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..1c6e00c85cdc5ec2423caf9c9f046f3fb7305168
--- /dev/null
+++ b/entity/Person_entity/entityfields/filterviewactiongroup/children/removefromcontactsync/onActionProcess.js
@@ -0,0 +1,4 @@
+import("EwsClientSync_lib");
+import("system.vars");
+
+EwsClientSyncUtils.openEwsSyncAddContactView(vars.get("$sys.selection"), vars.get("$sys.filter"), "REMOVE");
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/persaddresses/children/showdsgvomessage_param/valueProcess.js b/entity/Person_entity/entityfields/persaddresses/children/showdsgvomessage_param/valueProcess.js
index fce9fde135bfde9221a9956f545862641098ff7c..c96eec50f67631c175c60d748ded5821644aea70 100644
--- a/entity/Person_entity/entityfields/persaddresses/children/showdsgvomessage_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/persaddresses/children/showdsgvomessage_param/valueProcess.js
@@ -2,4 +2,4 @@ import("system.vars");
 import("system.neon");
 import("system.result");
 
-result.string(vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW);
\ No newline at end of file
+result.string(vars.get("$sys.recordstate") != neon.OPERATINGSTATE_NEW && vars.get("$sys.recordstate") != neon.OPERATINGSTATE_EDIT);
\ No newline at end of file
diff --git a/entity/Person_entity/recordcontainers/db/filterextensions/favorites_filter/filterConditionProcess.js b/entity/Person_entity/recordcontainers/db/filterextensions/favorites_filter/filterConditionProcess.js
index 26e0adde33d17eab1378a9d8aa4cfee3eea401bb..0c4956dc698a76bdf4426e973ffeb5237ad7d641 100644
--- a/entity/Person_entity/recordcontainers/db/filterextensions/favorites_filter/filterConditionProcess.js
+++ b/entity/Person_entity/recordcontainers/db/filterextensions/favorites_filter/filterConditionProcess.js
@@ -1,9 +1,17 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
+var objecttype = vars.get("$field.PERSON_OBJECTTYPE");
+var idcolumn = "PERSON.PERSONID";
+
+
+var rowIds = FavoritesUtil.getRowIdsOfFavorites(objecttype, operator, rawvalue);
+var preparedIds = [];
 
 for(i = 0; i < rowIds.length; i++)
 {        
@@ -13,7 +21,7 @@ for(i = 0; i < rowIds.length; i++)
         .arrayColumn();
 
     if(person_id.length > 0)
-        favoFilterCond.or("PERSON.PERSONID", person_id[0], SqlBuilder.EQUAL());
+        preparedIds.push(person_id[0]);
 }
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn, preparedIds));
diff --git a/entity/Product_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/Product_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
index 2db1e9e36cfa068a562f0c1c253c874eb648f33a..d06b0214dc625cee8ca5f435880df2f5deae3b5c 100644
--- a/entity/Product_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
+++ b/entity/Product_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("PRODUCT.PRODUCTID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.PRODUCT_OBJECTTYPE");
+var idcolumn = "PRODUCT.PRODUCTID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
diff --git a/entity/Productprice_entity/Productprice_entity.aod b/entity/Productprice_entity/Productprice_entity.aod
index 20e53fc299aadd601a2a2fed53c8ab2ee8e05b96..32ad155d4473c1621475321e718f8af1d08e71be 100644
--- a/entity/Productprice_entity/Productprice_entity.aod
+++ b/entity/Productprice_entity/Productprice_entity.aod
@@ -25,6 +25,7 @@
       <name>CURRENCY</name>
       <title>Currency</title>
       <consumer>KeywordCurrencies</consumer>
+      <groupable v="true" />
       <mandatory v="true" />
       <valueProcess>%aditoprj%/entity/Productprice_entity/entityfields/currency/valueProcess.js</valueProcess>
       <displayValueProcess>%aditoprj%/entity/Productprice_entity/entityfields/currency/displayValueProcess.js</displayValueProcess>
@@ -58,6 +59,7 @@
       <name>PRODUCT_ID</name>
       <title>Product</title>
       <consumer>Products</consumer>
+      <groupable v="true" />
       <linkedContext>Product</linkedContext>
       <mandatory v="true" />
       <stateProcess>%aditoprj%/entity/Productprice_entity/entityfields/product_id/stateProcess.js</stateProcess>
@@ -93,6 +95,7 @@
       <contentType>NUMBER</contentType>
       <outputFormat>#,##0.00</outputFormat>
       <inputFormat>#,##0.00</inputFormat>
+      <groupable v="true" />
       <mandatory v="true" />
       <stateProcess>%aditoprj%/entity/Productprice_entity/entityfields/vat/stateProcess.js</stateProcess>
       <valueProcess>%aditoprj%/entity/Productprice_entity/entityfields/vat/valueProcess.js</valueProcess>
@@ -104,6 +107,7 @@
       <title>Price list</title>
       <colorProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/colorProcess.js</colorProcess>
       <consumer>KeywordPricelists</consumer>
+      <groupable v="true" />
       <state>AUTO</state>
       <stateProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/stateProcess.js</stateProcess>
       <titleProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/titleProcess.js</titleProcess>
@@ -316,10 +320,6 @@
           <name>CURRENCY.displayValue</name>
           <expression>%aditoprj%/entity/Productprice_entity/recordcontainers/db/recordfieldmappings/currency.displayvalue/expression.js</expression>
         </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>PRODUCT_ID.displayValue</name>
-          <expression>%aditoprj%/entity/Productprice_entity/recordcontainers/db/recordfieldmappings/product_id.displayvalue/expression.js</expression>
-        </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>FROMQUANTITY.displayValue</name>
           <expression>%aditoprj%/entity/Productprice_entity/recordcontainers/db/recordfieldmappings/fromquantity.displayvalue/expression.js</expression>
diff --git a/entity/Productprice_entity/recordcontainers/db/filterextensions/favoritefilter/filterConditionProcess.js b/entity/Productprice_entity/recordcontainers/db/filterextensions/favoritefilter/filterConditionProcess.js
index c657ebe1ac71578a6aa535aa58f3c953ae76ceeb..2b8c460855ed332f311597ff9151edecd5835c4e 100644
--- a/entity/Productprice_entity/recordcontainers/db/filterextensions/favoritefilter/filterConditionProcess.js
+++ b/entity/Productprice_entity/recordcontainers/db/filterextensions/favoritefilter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("PRODUCTPRICE.PRODUCTPRICEID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.PRODUCTPRICE_OBJECTTYPE");
+var idcolumn = "PRODUCTPRICE.PRODUCTPRICEID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
diff --git a/entity/Productprice_entity/recordcontainers/db/recordfieldmappings/product_id.displayvalue/expression.js b/entity/Productprice_entity/recordcontainers/db/recordfieldmappings/product_id.displayvalue/expression.js
deleted file mode 100644
index d43ca1490d74c4fc1baa5dd375e5c77f6a2b61fd..0000000000000000000000000000000000000000
--- a/entity/Productprice_entity/recordcontainers/db/recordfieldmappings/product_id.displayvalue/expression.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import("system.result");
-
-result.string("select PRODUCT.PRODUCTNAME from PRODUCT where PRODUCT.PRODUCTID = PRODUCTPRICE.PRODUCT_ID");
\ No newline at end of file
diff --git a/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/contentProcess.js b/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/contentProcess.js
index afa79b535cb636c95d551fedb42eb8aa4035fc97..d4d779b0c5261b8ad759fec03c049e544903aac1 100644
--- a/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/contentProcess.js
+++ b/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/contentProcess.js
@@ -13,8 +13,7 @@ var phasenManager = new SalesprojectConversionRate();
 
 var sql = new SqlBuilder()
 .from("AB_KEYWORD_ENTRY")
-.where("AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID", KeywordUtils.getCategoryIdByName($KeywordRegistry.salesprojectPhase()))
-.and("AB_KEYWORD_ENTRY.KEYID", $KeywordRegistry.salesprojectPhase$nego(), SqlBuilder.NOT_EQUAL());
+.where("AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID", KeywordUtils.getCategoryIdByName($KeywordRegistry.salesprojectPhase()));
 
 if (filter != null)
 {
diff --git a/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/rowCountProcess.js b/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/rowCountProcess.js
index e6aab30159a1feb28c3a40b69c9c87559a4403af..9d19863bd9c26153fd71bfb7d5b648dee630245b 100644
--- a/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/rowCountProcess.js
+++ b/entity/SalesprojectConversionRate_entity/recordcontainers/jdito/rowCountProcess.js
@@ -13,8 +13,7 @@ var phasenManager = new SalesprojectConversionRate();
 
 var sql = new SqlBuilder()
 .from("AB_KEYWORD_ENTRY")
-.where("AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID", KeywordUtils.getCategoryIdByName($KeywordRegistry.salesprojectPhase()))
-.and("AB_KEYWORD_ENTRY.KEYID", $KeywordRegistry.salesprojectPhase$nego(), SqlBuilder.NOT_EQUAL());
+.where("AB_KEYWORD_ENTRY.AB_KEYWORD_CATEGORY_ID", KeywordUtils.getCategoryIdByName($KeywordRegistry.salesprojectPhase()));
 
 if (filter != null)
 {
diff --git a/entity/Salesproject_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/Salesproject_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
index bf9199d48642536122035a91a371f8193e23271c..157e471a8f17a97b96a9efe7098a4b2e12448118 100644
--- a/entity/Salesproject_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
+++ b/entity/Salesproject_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("SALESPROJECT.SALESPROJECTID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.SALESPROJECT_OBJECTTYPE");
+var idcolumn = "SALESPROJECT.SALESPROJECTID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
diff --git a/entity/SupportTicket_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js b/entity/SupportTicket_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
index 765e2ce46b47b556bb602c68ad610db83b1195df..a49514ad69abfed288c70f506f3b9dd30bdd53de 100644
--- a/entity/SupportTicket_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
+++ b/entity/SupportTicket_entity/recordcontainers/db/filterextensions/favorite_filter/filterConditionProcess.js
@@ -1,11 +1,12 @@
+import("system.vars");
 import("Favorites_lib");
 import("system.result");
 import("Sql_lib");
 
-var favoFilterCond = newWhere();
-var rowIds = FavoritesUtil.getRowIdsOfFavoriteGroup();
+var operator = vars.get("$local.operator");
+var rawvalue = vars.get("$local.rawvalue");
 
-for(i = 0; i < rowIds.length; i++)
-    favoFilterCond.or("TICKET.TICKETID", rowIds[i], SqlBuilder.EQUAL());
+var objecttype = vars.get("$field.SUPPORTTICKET_OBJECTTYPE");
+var idcolumn = "TICKET.TICKETID";
 
-result.string(favoFilterCond.toString());
\ No newline at end of file
+result.string(FavoritesUtil.getFilterDisplayCondition(objecttype, operator, rawvalue, idcolumn));
diff --git a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
index 3862818fc360f7faff3c17add78ff2a8d0eebf87..d83d2bfa5211143d335e6ea2407a6021157a1a49 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -1297,7 +1297,7 @@
     </entry>
     <entry>
       <key>VAT</key>
-      <value>UmsSt.</value>
+      <value>Ust.</value>
     </entry>
     <entry>
       <key>The expiry date must be after the start date!</key>
@@ -4153,7 +4153,7 @@
     </entry>
     <entry>
       <key>VAT in %</key>
-      <value>UmsSt. in %</value>
+      <value>Ust. in %</value>
     </entry>
     <entry>
       <key>Sales manager</key>
diff --git a/neonContext/EwsSyncAddContacts/EwsSyncAddContacts.aod b/neonContext/EwsSyncAddContacts/EwsSyncAddContacts.aod
new file mode 100644
index 0000000000000000000000000000000000000000..9f9809ee4ab68bc9abc7fd254e23aba11fb0b2c3
--- /dev/null
+++ b/neonContext/EwsSyncAddContacts/EwsSyncAddContacts.aod
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.1">
+  <name>EwsSyncAddContacts</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <editView>EwsSyncAddContactsEdit_view</editView>
+  <entity>EwsSyncAddContacts_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>c4d8f240-388e-4a1d-9455-e100a33c4819</name>
+      <view>EwsSyncAddContactsEdit_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonView/CampaignPreview_view/CampaignPreview_view.aod b/neonView/CampaignPreview_view/CampaignPreview_view.aod
index ec8f409750341079fcb3b9df759203224d129457..b593d6ee9b2adf5e547c89853ff5bcdd33bb79ae 100644
--- a/neonView/CampaignPreview_view/CampaignPreview_view.aod
+++ b/neonView/CampaignPreview_view/CampaignPreview_view.aod
@@ -24,7 +24,7 @@
     </cardViewTemplate>
     <favoriteViewTemplate>
       <name>Favorites</name>
-      <objectType>CAMPAIGN_OBEJCTTYPE</objectType>
+      <objectType>CAMPAIGN_OBJECTTYPE</objectType>
       <rowId>#UID</rowId>
       <entityField>#ENTITY</entityField>
       <title>favorites</title>
diff --git a/neonView/EwsSyncAddContactsEdit_view/EwsSyncAddContactsEdit_view.aod b/neonView/EwsSyncAddContactsEdit_view/EwsSyncAddContactsEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..74bbe50bf1c6529cfb43c1c895441220675f604e
--- /dev/null
+++ b/neonView/EwsSyncAddContactsEdit_view/EwsSyncAddContactsEdit_view.aod
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.8" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.8">
+  <name>EwsSyncAddContactsEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <size>SMALL</size>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <scoreCardViewTemplate>
+      <name>ewsSyncScorecard</name>
+      <fields>
+        <entityFieldLink>
+          <name>bb922a4f-c170-4158-9241-8ba04ae92370</name>
+          <entityField>countForSync</entityField>
+        </entityFieldLink>
+      </fields>
+    </scoreCardViewTemplate>
+    <actionsViewTemplate>
+      <name>syncAction</name>
+      <actions>
+        <element>syncContacts</element>
+        <element>removeSyncContacts</element>
+      </actions>
+    </actionsViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/LeadimportFilter_view/LeadimportFilter_view.aod b/neonView/LeadimportFilter_view/LeadimportFilter_view.aod
index 5d877503efcf5ae4bc33bfb5c893b37ee2a32312..3e22dae8dcc9dbd2598cc3bd9c2bbbd27d3cfbaa 100644
--- a/neonView/LeadimportFilter_view/LeadimportFilter_view.aod
+++ b/neonView/LeadimportFilter_view/LeadimportFilter_view.aod
@@ -36,32 +36,5 @@
         </neonTableColumn>
       </columns>
     </tableViewTemplate>
-    <treeTableViewTemplate>
-      <name>Treetable</name>
-      <entityField>#ENTITY</entityField>
-      <favoriteActionGroup1>observeActionGroup</favoriteActionGroup1>
-      <columns>
-        <neonTreeTableColumn>
-          <name>5b550d07-b92f-4429-a9f7-e18013aa3280</name>
-          <entityField>#IMAGE</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>e25d671d-50c8-4c77-9a2b-8214b0b87814</name>
-          <entityField>NAME</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>3ffd6131-6064-4ca2-958b-50f7eef0b3e1</name>
-          <entityField>IMPORTSOURCE</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>5fe0eed1-ed45-478d-b84e-ad65e1e5fd0a</name>
-          <entityField>LEADIMPORT_DATE</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>9563e615-fc93-406f-8cbb-2eceafc5bcc4</name>
-          <entityField>STATUS</entityField>
-        </neonTreeTableColumn>
-      </columns>
-    </treeTableViewTemplate>
   </children>
 </neonView>
diff --git a/neonView/SerialLetterFilter_view/SerialLetterFilter_view.aod b/neonView/SerialLetterFilter_view/SerialLetterFilter_view.aod
index 3d50021ba764c65d7988291de910790a9c9f4e33..e4cd6299bc886c4b7d4e78d294cad6edfce3c4fe 100644
--- a/neonView/SerialLetterFilter_view/SerialLetterFilter_view.aod
+++ b/neonView/SerialLetterFilter_view/SerialLetterFilter_view.aod
@@ -38,34 +38,5 @@
         </neonTableColumn>
       </columns>
     </tableViewTemplate>
-    <treeTableViewTemplate>
-      <name>Treetable</name>
-      <entityField>#ENTITY</entityField>
-      <linkedColumns>
-        <element>TITLE</element>
-      </linkedColumns>
-      <columns>
-        <neonTreeTableColumn>
-          <name>cae0d686-5109-4106-9b35-421e79e265db</name>
-          <entityField>ICON</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>a5a9f4f1-14ad-4997-94c7-f76de7c5f8da</name>
-          <entityField>TITLE</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>dc1a061a-95fa-499e-aee4-9b49aed28cfc</name>
-          <entityField>STATUS</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>ec667f9a-65e3-482c-a459-87545b22af2a</name>
-          <entityField>DOCUMENTTEMPLATE_ID</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>88b074e6-587a-477f-97d6-fde128cae267</name>
-          <entityField>DESCRIPTION</entityField>
-        </neonTreeTableColumn>
-      </columns>
-    </treeTableViewTemplate>
   </children>
 </neonView>
diff --git a/process/Communication_lib/process.js b/process/Communication_lib/process.js
index 055813cf362081fd583c1d8d2cd33fb0b4c0c4c4..f9e30868d8e9c816f642e8a383504605b2ba4990 100644
--- a/process/Communication_lib/process.js
+++ b/process/Communication_lib/process.js
@@ -31,11 +31,11 @@ CommUtil.getMediumIdsByCategory = function (pCategory)
     var keywordAttr = new KeywordAttribute($KeywordRegistry.communicationMedium(), "category");
     //TODO: use getRows() via JDito
     var mediumIds = newSelect("AB_KEYWORD_ENTRY.KEYID")
-                        .from("AB_KEYWORD_ATTRIBUTERELATION")
-                        .join("AB_KEYWORD_ENTRY", "AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID = AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID")
-                        .where("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", keywordAttr.id)
-                        .and("AB_KEYWORD_ATTRIBUTERELATION." + keywordAttr.dbField, pCategory)
-                        .arrayColumn();
+    .from("AB_KEYWORD_ATTRIBUTERELATION")
+    .join("AB_KEYWORD_ENTRY", "AB_KEYWORD_ENTRY.AB_KEYWORD_ENTRYID = AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ENTRY_ID")
+    .where("AB_KEYWORD_ATTRIBUTERELATION.AB_KEYWORD_ATTRIBUTE_ID", keywordAttr.id)
+    .and("AB_KEYWORD_ATTRIBUTERELATION." + keywordAttr.dbField, pCategory)
+    .arrayColumn();
     return mediumIds;
 };
 
@@ -73,19 +73,19 @@ CommUtil.setStandardForCategory = function(pAffectedRowId, pNewStandardCommId, p
     
     //set current standard comm-record as non-standard
     var cond = newWhere("ISSTANDARD = 1")
-                .and("COMMUNICATION.CONTACT_ID", pAffectedRowId)
-                .and("COMMUNICATION.MEDIUM_ID", mediumIds, SqlBuilder.IN());
+    .and("COMMUNICATION.CONTACT_ID", pAffectedRowId)
+    .and("COMMUNICATION.MEDIUM_ID", mediumIds, SqlBuilder.IN());
     
-     statements.push(["COMMUNICATION", cols, null, ["0"], cond.build()]);
+    statements.push(["COMMUNICATION", cols, null, ["0"], cond.build()]);
 
     //pNewStandardCommId can be an empty string if the standard has to only be removed
     if (pNewStandardCommId != "")
     {
         //set the new standard comm-record
         cond = newWhere("COMMUNICATION.COMMUNICATIONID", pNewStandardCommId)
-            //check communicationid, contactId and medium to prevent data-inconsistency when bad function params are passed by (e.g communicationid of a different category)
-            .and("COMMUNICATION.CONTACT_ID", pAffectedRowId)
-            .and("COMMUNICATION.MEDIUM_ID", mediumIds, SqlBuilder.IN());
+        //check communicationid, contactId and medium to prevent data-inconsistency when bad function params are passed by (e.g communicationid of a different category)
+        .and("COMMUNICATION.CONTACT_ID", pAffectedRowId)
+        .and("COMMUNICATION.MEDIUM_ID", mediumIds, SqlBuilder.IN());
             
         statements.push(["COMMUNICATION", cols, null, ["1"], cond.build()]);
     }
@@ -148,8 +148,8 @@ CommUtil.getStandardSubSqlForCategory = function(pCategory, pContactField)
         return "''";
     
     var selectStandardAddr = newSelect("max(COMMUNICATION.ADDR)")
-                                .from("COMMUNICATION")
-                                .where();
+    .from("COMMUNICATION")
+    .where();
                                 
     if (pContactField == undefined)
         selectStandardAddr.and("COMMUNICATION.CONTACT_ID = CONTACT.CONTACTID");
@@ -215,6 +215,41 @@ CommUtil.getStandardMail = function (pContactId)
     return db.cell(query);
 }
 
+/**
+ * Returns a sub sql-string (without brackets) for getting the address of a COMMUNICATION.<br>
+ * 
+ * @param {String} pMediumKey                                                <p>
+ *                                                                          Key of the keyword "COMMUNICATION.MEDIUM".<br>
+ *                                                                          (custom.category; e.g. "PHONE")<br>
+ * @param {String|Object} pContactField=CONTACT.CONTACTID (optional)        <p>
+ *                                                                          SQL-fieldname that shall be used for filtering the CONTACT_ID, <br>
+ *                                                                          this can be a string(fieldname) or an SqlBuilder object.<br>
+ * @return {String}                                                         <p>
+ *                                                                          Sub-sql.<br>
+ */
+CommUtil.getMediumAddrSubSqlByKey = function(pMediumKey, pContactField)
+{
+    var selectAddr = newSelect("max(COMMUNICATION.ADDR)")
+    .from("COMMUNICATION")
+    .where();
+                                
+    if (pContactField == undefined)
+        selectAddr.and("COMMUNICATION.CONTACT_ID = CONTACT.CONTACTID");
+    else if (typeof(pContactField) == "string")
+        selectAddr.and("COMMUNICATION.CONTACT_ID", pContactField);
+    else if (typeof(pContactField) == "object")
+    {
+        //you may want to sepcify a concrete value
+        selectAddr.and(pContactField);
+    }
+    else
+        return "''";
+    
+    selectAddr.andIfSet("COMMUNICATION.MEDIUM_ID", pMediumKey);
+    
+    return selectAddr.toString();    
+}
+
 /**
  * Provides static methods for validation of communication data.<br>
  * <b>Do not create an instance of this!</b>
diff --git a/process/EwsClientSync_lib/EwsClientSync_lib.aod b/process/EwsClientSync_lib/EwsClientSync_lib.aod
new file mode 100644
index 0000000000000000000000000000000000000000..a53260007b9ecc486117433576e3c03b8723ff43
--- /dev/null
+++ b/process/EwsClientSync_lib/EwsClientSync_lib.aod
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.2">
+  <name>EwsClientSync_lib</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/EwsClientSync_lib/process.js</process>
+  <alias>Data_alias</alias>
+  <variants>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/EwsClientSync_lib/process.js b/process/EwsClientSync_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..2366e6b5af77b5ba73399379f2f2d2c14fe88c1b
--- /dev/null
+++ b/process/EwsClientSync_lib/process.js
@@ -0,0 +1,357 @@
+import("system.neon");
+import("Util_lib");
+import("system.translate");
+import("Communication_lib");
+import("Placeholder_lib");
+import("system.SQLTYPES");
+import("system.vars");
+import("system.datetime");
+import("system.util");
+import("system.tools");
+import("system.favorite");
+import("system.logging");
+import("Sql_lib");
+import("system.db");
+import("system.entities")
+
+/**
+ * Provides  methods for handling and interacting with the EWS Plugin
+ * 
+ * @class
+ */
+function EwsClientSyncUtils() {}
+
+/*
+ * Constant which contains the ewsSync Tag
+ * if the tag has to be changed a constant is the better way
+ */
+EwsClientSyncUtils.EWSSYNCTAG = function(){
+    return "ewssync";
+}
+
+/*
+ * prepares the synctable, insert new entries and mark for deletion 
+ * 
+ */
+EwsClientSyncUtils.prepareContactSyncTable = function(){
+    
+    var favoriteDataArray = EwsClientSyncUtils.getEwsFavorites();
+    var ewsSyncData = newSelect("SYNCCONTACTID, ASYS_FAVORITEID, USER_ID, CONTACT_ID")
+    .from("ab_synccontact")
+    .table();
+    
+    var dataIndex = {
+        index: new Map(),
+        add: function (pA, pB)
+        {
+            var idxMap = this.index;
+            if (!idxMap.has(pA))
+                idxMap.set(pA, new Set());
+            idxMap.get(pA).add(pB);
+        },
+        has: function (pA, pB)
+        {
+            return this.index.has(pA) && this.index.get(pA).has(pB);
+        }
+    };
+    
+    //preparing the value for inserting in ewsSync Table
+    var toInsertFavs = []; 
+    for (let i = 0, l = ewsSyncData.length; i < l; i++) 
+    {
+        //3 - contactID     2 userID
+        dataIndex.add(ewsSyncData[i][3], ewsSyncData[i][2]);
+    }
+    ​
+    //we want to insert those which aren't in the sync table yet but which are tagged for sync
+    toInsertFavs = favoriteDataArray.filter(function (row) {
+        return !dataIndex.has(row[1], row[2]);
+    });
+    
+    
+    //preparing values for updating entrys in the ewsSync Table
+    dataIndex.index.clear();
+    
+    var toUpdate = [];
+    
+    for (let i = 0, l = favoriteDataArray.length; i < l; i++) 
+    {
+        dataIndex.add(favoriteDataArray[i][1], favoriteDataArray[i][2]);
+    }
+    
+    ​//dataset which are in the synctable but aren't tagged for sync (favorites ewssync) has to be updated for deletion
+    toUpdate = ewsSyncData.filter(function (row){
+        ​
+        return !dataIndex.has(row[3], row[2]);
+    }
+    ​);
+    
+    
+    let statements = [];
+    let toInsert = [];
+    let cols = ["SYNCCONTACTID", "ASYS_FAVORITEID", "CONTACT_ID", "USER_ID"];
+    let vals = [];
+    let table = "AB_SYNCCONTACT";
+    let updStatements = [];
+    
+    for(let i = 0; i < toInsertFavs.length; i++)
+    {
+        vals = [];
+        vals = [util.getNewUUID(), toInsertFavs[i][0], toInsertFavs[i][1], toInsertFavs[i][2]]
+        
+        statements.push([table, cols, null, vals]);
+    }
+    for(let i = 0; i < toUpdate.length; i++)
+    {
+        updStatements.push([table, ["DATE_DEL"], null, [vars.get("$sys.date")], "ASYS_FAVORITEID = '" + toUpdate[i][1] + "'"  ]);
+    }
+    
+    try{
+        let count = db.inserts(statements, "Data_alias");
+        let updCount = db.updates(updStatements, "Data_alias");
+    }
+    catch(exc){
+        logging.log(exc)
+    }
+}
+
+/*
+ *  get the contact which are marked with the ewssync favorite Tag
+ *   
+ *  @return [Array] favorite Data [[]]
+ */
+EwsClientSyncUtils.getEwsFavorites = function(){
+    
+    
+    //get Favorites which are tagged with the Sync Tag
+    //    var conf = favorite.createGetFavoritesConfig(); 
+    //    conf.setFavoriteGroupTitle(EwsClientSyncUtils.EWSSYNCTAG()); 
+    //    conf.setObjectType("Person");
+    //
+    //    var favoriteData = favorite.getFavorites(conf);
+    //    var favoriteDataArray = [];
+    //    
+    //    for (var temp in favoriteData)
+    //    {
+    //        let favId = favoriteData[temp]["id"];
+    //        let rowId = favoriteData[temp]["rowid"]; 
+    //        let userID = favoriteData[temp]["group"]["groupuser"]; 
+    //        
+    //        favoriteDataArray.push([favId, rowId, userID]);
+    //    }
+    
+    
+    //in the current version it isn't possible to call the favorite API within a Serverprocess this will be implemented in the next RC 
+    
+    var favoriteDataArray = new SqlBuilder("_____SYSTEMALIAS")
+    .selectDistinct("ASYS_RECORD.ID, ASYS_RECORD.ROW_ID, ASYS_RECORDGROUP.USER_ID")
+    .from("ASYS_RECORD")
+    .join("ASYS_RECORDGROUP", "ASYS_RECORDGROUP.ID = ASYS_RECORD.RECORDGROUP_ID")
+    .where("ASYS_RECORD.OBJECT_TYPE", "Person")
+    .and("ASYS_RECORDGROUP.TITLE", EwsClientSyncUtils.EWSSYNCTAG(), "LOWER(#) = ?")
+    .groupBy("ASYS_RECORDGROUP.USER_ID, ASYS_RECORD.ROW_ID, ASYS_RECORD.ID")
+    .table();
+    
+    return favoriteDataArray;
+}
+
+/*
+ * sets the editdate for the entrys in the synctable, in reason to get synced with exchange
+ *
+ * @param {String} pTableName
+ * @param {String} pDataSetID req 
+ * @param {String} pDate req
+ *
+ * @return {void}
+
+ */
+EwsClientSyncUtils.setContactToSync = function(pTableName, pDataSetID, pDate){
+    
+    var affectedTables = ["ORGANISATION" , "PERSON", "CONTACT", "ADDRESS", "COMMUNICATION"];
+    var affectedIDs = [];
+    
+    if (affectedTables.indexOf(pTableName) != -1)
+    {
+        switch(pTableName)
+        {
+            case "ORGANISATION":
+                affectedIDs = newSelect("CONTACT.CONTACTID").from("CONTACT").where("CONTACT.ORGANISATION_ID", pDataSetID).arrayColumn();
+                break;
+            case "PERSON":
+                affectedIDs = newSelect("CONTACT.CONTACTID").from("CONTACT").where("CONTACT.PERSON_ID", pDataSetID).arrayColumn();
+                break;
+            case "CONTACT":
+                affectedIDs = [pDataSetID];
+                break;
+            case "ADDRESS":
+                affectedIDs = newSelect("ADDRESS.CONTACT_ID").from("ADDRESS")
+                .where("ADDRESS.ADDRESSID", pDataSetID)
+                .union(newSelect("CONTACT.CONTACT_ID").from("CONTACT").where("CONTACT.ADDRESS_ID", pDataSetID)).arrayColumn();
+                break;
+            case "COMMUNICATION":
+                affectedIDs = newSelect("COMMUNICATION.CONTACT_ID").from("COMMUNICATION").where("COMMUNICATION.COMMUNICATIONID", pDataSetID).arrayColumn();
+                break;
+        }
+        
+        if (affectedIDs.length > 0)
+        {
+            var upd = db.updateData("AB_SYNCCONTACT", ["DATE_EDIT"], null, [pDate], 
+                "EXCHANGEID is not null and CONTACT_ID in ('" + affectedIDs.join("','") + "')");        
+        }
+    }
+}
+
+
+/*
+ * prepare Placholder for Exchange contacts
+ * 
+ * @param  {String} pUserId
+ */
+EwsClientSyncUtils.getPlaceholders = function(pUserId){
+    var ewsPlaceholders = [];
+    
+    //EWS Sync Placeholder
+    //See EWS API Doc for other placeholder
+    //new Placeholder that has to be synced probably has also to be added in addDataToValueObjects() in the serverprocess
+    _addSqlPart("CONTACTID", "CONTACT.CONTACTID"); 
+    _addSqlPart("EXCHANGEID", "select EXCHANGEID from ab_synccontact where Ab_synccontact.contact_id = contact.contactid and user_id = '"+ pUserId +"'", null, null)
+    
+    _addSqlPart("Givenname", "PERSON.FIRSTNAME");
+    _addSqlPart("Surname", "PERSON.LASTNAME");
+    _addSqlPart("Department", "CONTACT.DEPARTMENT");
+    _addSqlPart("JobTitle", "CONTACT.CONTACTROLE");
+    _addSqlPart("CompanyName", "ORGANISATION.NAME");
+    
+    
+    _addAddressFormat("Business_street", "{street} {buildingno}");
+    _addAddressFormat("Business_postalcode", "{zip}");
+    _addAddressFormat("Business_city", "{city}");
+    _addAddressFormat("Business_state", "{district}");
+    _addAddressFormat("Business_countryorregion", "{country}");
+    
+    _addSqlPart("EmailAddress1", CommUtil.getStandardSubSqlMail()); 
+    
+    _addSqlPart("BusinessPhone", CommUtil.getStandardSubSqlPhone()); 
+    _addSqlPart("BusinessHomepage", CommUtil.getMediumAddrSubSqlByKey("COMMINTERNET"));
+    
+    _addSqlPart("OtherFax", CommUtil.getMediumAddrSubSqlByKey("COMMFAX")); 
+    _addSqlPart("MobilePhone", CommUtil.getMediumAddrSubSqlByKey("COMMMOBIL")); 
+    _addSqlPart("FileAsMapping","case when PERSON_ID is not null then 'SurnameCommaGivenName' else 'Company' end" , null, null);
+    
+    
+    //    _addSqlPart("HomePhone", "''"); 
+    //    _addSqlPart("HomeFax", "''");
+    //    _addSqlPart("EmailAddress2", "''");
+    
+    
+    
+    return ewsPlaceholders;
+    
+    function _addSqlPart (pName, pSqlPart, pTarget, pTitle)
+    {
+        ewsPlaceholders.push(new Placeholder(pName, Placeholder.types.SQLPART, "(" + pSqlPart + ")", pTarget, pTitle));
+    }
+    /**
+     * add an address format placeholder to placeholders
+     */
+    function _addAddressFormat (pName, pFormat, pTarget, pTitle)
+    {
+        ewsPlaceholders.push(new Placeholder(pName, Placeholder.types.ADDRESSFORMAT, pFormat, pTarget, pTitle));
+    }
+}
+
+/*
+ * removes Person favorites with the EWS Tag 
+ * 
+ * @param {Array} pToDelete contains contact_ids for which the favorite should be removed
+ * @param {String} pUserId - User for which the favorites should be removed 
+ * 
+ * @return {Boolean} true if successfull
+ * 
+ */
+EwsClientSyncUtils.removeFromFavorite = function(pToDelete, pUserId ){
+    
+    //maybe in a future version there will be a way to remove favorites on a better way
+ 
+    //all ews related Favorites for the user
+    var config = favorite.createGetFavoritesConfig()
+    .setFavoriteGroupTitle(EwsClientSyncUtils.EWSSYNCTAG())
+    .setGroupType(favorite.FAVORITE_GROUP).setObjectType("Person")
+    .setUserId(pUserId); 
+    
+    var ewsFavorite = favorite.getFavorites(config);
+    var favsToDelete = [];
+    
+    var dataIndex = {
+        index: new Map(),
+        add: function (pA)
+        {
+            var idxMap = this.index;
+            if (!idxMap.has(pA))
+                idxMap.set(pA, new Set());
+        },
+        has: function (pA)
+        {
+            return this.index.has(pA);
+        }
+    };
+
+    for each(let row in pToDelete)
+    {
+        dataIndex.add(row)
+    }
+    
+    // delete those which are in the selection and are also in ewsFavorite 
+    for each (let row in  ewsFavorite)
+    {
+        if(dataIndex.has(row["rowid"]))
+            favsToDelete.push(row["id"]);
+    }
+
+    var delConfig = favorite.createRemoveMultipleByIdConfig().setFavoriteRecordIds(favsToDelete);
+    
+    return favorite.remove(delConfig);
+}
+
+/*
+ * Add contacts to favorites as ewssync group
+ * 
+ * @param {Array} pToInsert         Array with contactIds which should be added to the sync
+ */
+EwsClientSyncUtils.addToEwsFavorite = function(pToInsert){
+    var userID = tools.getCurrentUser()[tools.NAME]
+
+    var config = favorite.createAddFavoriteConfig(); 
+    config.setFavoriteGroupTitle(EwsClientSyncUtils.EWSSYNCTAG()); 
+    config.setObjectType("Person");
+    config.setUserId(userID); 
+    config.setGroupType(favorite.FAVORITE_GROUP) 
+    
+    for(let i = 0, l = pToInsert.length; i < l; i++){
+        config.setRowId(pToInsert[i]);
+        favorite.add(config);
+    }
+}
+
+/**
+ * Opens a context to add or remove contacts from the ewssync<br>
+ * 
+ * @param {String[]} pContactIds        Contacts that should be added.<br>
+ * @param {String|Object} pFilter       the filter for the contacts that should be used if no contact is selected
+ * @param {String} pMode                the mode which should be used ("ADD" or "REMOVE") default ADD
+ */
+EwsClientSyncUtils.openEwsSyncAddContactView = function(pContactIds, pFilter, pMode)
+{
+    if (!Utils.isString(pContactIds))
+        pContactIds = JSON.stringify(pContactIds);
+    if (!Utils.isString(pFilter))
+        pFilter = JSON.stringify(pFilter);
+    
+    var params = {
+        "ContactIds_param": pContactIds,
+        "ContactFilter_param": pFilter, 
+        "Mode_param": pMode
+    }
+    neon.openContext("EwsSyncAddContacts", "EwsSyncAddContactsEdit_view", null, neon.OPERATINGSTATE_VIEW, params);
+}
+    
\ No newline at end of file
diff --git a/process/EwsClient_lib/process.js b/process/EwsClient_lib/process.js
index 2de3addde44d76ac3ad80c4f264e837fc6d90e45..51dd088565b42911b3354abcf3b823cf6c1152f1 100644
--- a/process/EwsClient_lib/process.js
+++ b/process/EwsClient_lib/process.js
@@ -62,7 +62,10 @@ $EwsClientTaskDescriptions.GET_CONTACTS_BY_FOLDERS =            function(){retur
 $EwsClientTaskDescriptions.GET_CONTACTSDEFAULTFOLDER =          function(){return "GET_CONTACTSDEFAULTFOLDER"};
 $EwsClientTaskDescriptions.GET_CONTACTFOLDERS =                 function(){return "GET_CONTACTFOLDERS"};
 $EwsClientTaskDescriptions.UPDATE_CONTACT =                     function(){return "UPDATE_CONTACT"};
-
+$EwsClientTaskDescriptions.INSERT_CONTACT_LIST_TO_FOLDER =      function(){return "INSERT_CONTACT_LIST_TO_FOLDER"}; 
+$EwsClientTaskDescriptions.INSERT_CONTACT_LIST =                function(){return "INSERT_CONTACT_LIST"}; 
+$EwsClientTaskDescriptions.UPDATE_CONTACT_LIST =                function(){return "UPDATE_CONTACT_LIST"};
+$EwsClientTaskDescriptions.DELETE_CONTACT_LIST_BY_IDS =         function(){return "DELETE_CONTACT_LIST_BY_IDS"};
 function $EwsClientImpersonationModes(){}
 /**
  * Impersonation mode NONE should be set if no impersonation user is used and every user is authenticated per user-data
@@ -400,4 +403,394 @@ EwsClientCalendarPermissionUtils._getCalendarPermissionFromResult = function (pP
             + "there exists a write but no read permission");
 
     return retVal;
+}
+
+
+
+/*
+ * provides static methods for the use of the exchange Contact Sync
+ * @class
+ */
+function EwsSyncContactUtils(){}
+
+EwsSyncContactUtils.getEwsSyncTag = function(){
+    return "ewssync";
+}
+
+
+/*
+ * returns the contact Folder for the passed mailbox
+ * requires the EWSClientPlugin
+ * 
+ * @param {String} pAliasName name of the exchange alias 
+ * @param {String} pMailbox mailbox of which the folder should be read
+ * 
+ * @return {Array} array with maps [["id"], ["name"]]
+ */
+EwsSyncContactUtils.getContactFolders = function(pAliasName, pMailbox){
+    
+    let taskDescription = $EwsClientTaskDescriptions.GET_CONTACTFOLDERS();
+    
+    let task = <mailbox>{
+    pMailbox
+    }</mailbox>;
+    
+    let pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, task, $EwsClientImpersonationModes.SINGLE(), pAliasName);
+    let xmlOutput = EwsClientUtils.callPlugin(pluginInput);
+    let retVal = [];
+    
+    for each (folder in xmlOutput.folders.folder)
+    {
+        let map = {};
+        map["id"] = folder.id;
+        map["name"] = folder.name;
+        retVal.push(map);
+    }
+    return retVal;
+}
+
+
+EwsSyncContactUtils.updateContacts = function(pAliasName, pMailbox, pObjects, doDebug ){
+    let taskDescription = $EwsClientTaskDescriptions.UPDATE_CONTACT_LIST();
+    
+    let tasks = <mailbox>{
+    pMailbox
+    }
+    </mailbox>;
+  
+    let contactsXml = <contacts/>
+     
+    for each(let [pUniqueId, pData, pAddresses] in pObjects)
+    {
+        if(pUniqueId)
+            contactsXml.appendChild(EwsSyncContactXMLUtils.mapContactToXML(pData, pAddresses, pUniqueId, true));
+    } 
+    tasks += contactsXml;
+    
+    let pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, tasks, $EwsClientImpersonationModes.SINGLE(), pAliasName);
+    
+    let xmlOutput = EwsClientUtils.callPlugin(pluginInput); 
+
+    return EwsSyncContactUtils.proceedPluginXmlOutput(xmlOutput, 2, doDebug); 
+}
+
+
+/**
+ * Adds a contact in a specific folder
+ * requires EWSClientPlugin 
+ * 
+ * @param {String} pAliasName name of the Alias which contains connectiondata 
+ * @param {String} pMailbox owner of the contact
+ * @param {String} pUniqueId defines folder
+ * @param {[[dataArray, adressArray]]} pObjects
+ * @param {boolean} doDebug
+ * 
+ * @return {String} new unique ID of the contact (ExchangeID)
+ * 
+ * pData array with maps with following structure:
+ * ["key"]
+ * ["value"]
+ * 
+ * pAddresses array with following Maps
+ * ["addressKey"]
+ * ["value"]    -> array with Maps with following structure ["key"]
+ *                                                          ["value]
+ *                                          
+ * existing Key for a exchange Contact:
+ * title, givenname, middlename, surname
+ * jobtitle, officelocation, department, companyname, manager, assistentname, businesshomepage
+ * fileasmapping
+ * messagebody, categories
+ * id, changekey, lastmodifiedtime, datetimecreated (read only)
+ *
+ * - possible phone numbers:
+ * AssistantPhone, BusinessFax, BusinessPhone, BusinessPhone2, Callback, CarPhone, CompanyMainPhone, HomeFax, HomePhone,
+ * HomePhone2, Isdn, MobilePhone, OtherFax, OtherTelephone, Pager, PrimaryPhone, RadioPhone, Telex, TtyTddPhone
+ *
+ * - possible Mailing:
+ * EmailAddress1, EmailAddress2, EmailAddress3
+ *
+ * - possible Instant Messaging:
+ * ImAddress1, ImAddress2, ImAddress3
+ *
+ * - possible Adressen:
+ * Business, Home, Other
+ * - possible values of a adress:
+ * street, postalcode, city, state, countryorregion
+ *
+ * postaladdressindex
+ * - possible value for "postaladdressindex"
+ * None, Business, Home, Other
+ */
+EwsSyncContactUtils.insertContactsToFolder = function(pAliasName, pMailbox, pUniqueId, pObjects, doDebug)
+{
+
+    let taskDescription = $EwsClientTaskDescriptions.INSERT_CONTACT_LIST_TO_FOLDER();
+    
+    let task = <uniqueId>{
+    pUniqueId
+    }</uniqueId>
+
+    task += <mailbox>{
+    pMailbox
+    }</mailbox>
+     
+    let contactsXml = <contacts/>
+     
+    for each(let [pData, pAddresses] in pObjects)
+    {
+        contactsXml.appendChild(EwsSyncContactXMLUtils.mapContactToXML(pData, pAddresses));
+    }
+    task += contactsXml;
+    
+    let pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, task, $EwsClientImpersonationModes.SINGLE(), pAliasName);
+    let xmlOutput = EwsClientUtils.callPlugin(pluginInput); 
+    
+    return EwsSyncContactUtils.proceedPluginXmlOutput(xmlOutput, 1, doDebug); 
+}
+
+/**
+ * deletes unique Contacts out of EWS
+ * Voraussetzung ist EWSClientPlugin 
+ * 
+ * @param {String} pAliasName Name des Alias aus dem die Verbindungsdaten ausgelesen werden können
+ * @param {String} pUniqueIds Definiert Die Kontakte die 
+ * @param {String} pMailBox opt falls angegen wird der ImpersonatedUser verwendet
+ * @param {boolean} doDebug
+ * 
+ * @return {String[]} Array with results for Structure see Example
+ * @example
+ * Structure of the result from plugin   
+ * [
+ *  [exchangeIdsWithNoError, n],
+ *  [[id, "Error", "errorMsg", "Type"], [idn, "Error", "errorMsg", "Type"] ]    
+ * ]
+ */
+EwsSyncContactUtils.deleteContactByID = function(pAliasName, pUniqueIds, pMailBox, doDebug)
+{
+    let taskDescription = $EwsClientTaskDescriptions.DELETE_CONTACT_LIST_BY_IDS();
+    
+    let task = <uniqueIds/>;
+    
+    for each(let pUniqueId in pUniqueIds)
+    {
+        if(pUniqueId)
+            task.appendChild(<uniqueId>{
+                pUniqueId
+                }</uniqueId>)
+    }
+    
+    let pluginInput;
+    
+    if ( pMailBox == undefined )
+    {
+        pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, task, $EwsClientImpersonationModes.NONE(), pAliasName);
+    }
+    else
+    {
+        task += <mailbox>{
+        pMailBox
+        }</mailbox>;
+        pluginInput = EwsClientXMLUtils.getRequestXMLforAlias(taskDescription, task, $EwsClientImpersonationModes.SINGLE(), pAliasName);
+    }
+
+    var xmlOutput = EwsClientUtils.callPlugin(pluginInput);
+    
+    return EwsSyncContactUtils.proceedPluginXmlOutput(xmlOutput, 3, doDebug); 
+}
+
+/*
+ * proceeds the plugin outputXMl  and returns contactId and ExchangeID,
+ *
+ *  @param {XML} pXmlOutput output of the plugin call
+ *  @param {int} pMode controlls proceeding 1 - insert, 2 - update, 3 - delete
+ *  @param {boolean} doDebug 
+ *  
+ *  @return {Array} 2d Array with contactIds, unigueID(ExchangeID) and ErrorArray
+ *
+ */
+EwsSyncContactUtils.proceedPluginXmlOutput = function(pXmlOutput, pMode, doDebug){
+    
+    var contactRes = [];
+    var failedIds = [];
+    var status, uniqueId, resultMessage, resultCode;
+    
+    //insert and Update
+    if(pMode < 3)
+    {
+        //for every contactResult in the contactResults list
+        for each( contactResult in pXmlOutput.contactResults.contactResult )
+        {
+            var keyValues = contactResult.contact.keyValues.keyValue;
+            var contactid = "";
+        
+            for each( keyValue in keyValues )
+            {
+                if(keyValue.key.toString() == "CONTACTID")//we only need the contactid value
+                {
+                    contactid = keyValue.value.toString();
+                    break;
+                }
+            }
+        
+            status = contactResult.result.toString();
+            resultMessage = contactResult.resultMessage.toString();
+            
+            //during update the xml structure is slightly different
+            uniqueId = (Number(pMode) == 2) ? contactResult.contact.@uniqueId.toString() : contactResult.uniqueId.toString();
+        
+            if(status == "Success" && contactid != "" && uniqueId != "")//only if the action was successfull
+            {
+                if(pMode == 2)//update
+                    contactRes.push(uniqueId);
+                else
+                    contactRes.push([contactid, uniqueId]);//push for update/insert in AB_SYNCCONTACT
+            }
+            else
+            {
+                resultCode = contactResult.resultCode.toString();
+                failedIds.push([contactid, status, resultMessage, resultCode, contactResult.contact.toString()])
+            }
+        }
+        if(doDebug)  logging.log("failedIds: " + failedIds.toSource());
+    }//pMode < 3
+    else 
+    //the delete result xml differs from insert and update  
+    if (pMode == 3)
+    {
+        for each( contactResult in pXmlOutput.resultBundles.resultBundle )
+        {
+            //keyvalues
+            status = contactResult.result.toString();
+            uniqueId = contactResult.uniqueId.toString();
+            
+            if(status == "Success" && uniqueId != "")
+            {
+                contactRes.push(uniqueId);//push for deleting in AB_SYNCCONTACT
+            }
+            else
+            {
+                //get Keyvalues
+                resultMessage = contactResult.resultMessage.toString();
+                resultCode = contactResult.resultCode.toString();
+                
+                failedIds.push([uniqueId, status, resultMessage, resultCode]);
+            }
+        }
+    }
+
+    return [contactRes, failedIds];
+}
+
+/*
+ *Class for handling ews XML
+ *
+ * @class
+ */
+function EwsSyncContactXMLUtils(){}
+
+
+EwsSyncContactXMLUtils.mapContactToXML = function( pData, pAddresses, pExchangeId, isUpdate)
+{
+    var content = <contact>
+                      <keyValues/>
+                      <physicalAddresses/>
+                  </contact>;
+              
+    if(isUpdate)
+    {
+        content = <contact uniqueId={
+        pExchangeId
+        }>
+        <keyValues/>
+        <physicalAddresses/>
+        </contact>;
+    }
+    
+    //add contactData e.g. Name,Lastname, department etc.
+    for each (let map in pData)
+    {  
+        let keyXml = <keyValue/>
+        let mapKey = map["key"]; 
+        let mapVal = map["value"]; 
+
+        keyXml.appendChild(<key>{
+            mapKey
+            }</key>);
+        keyXml.appendChild(<value>{
+            mapVal
+            }</value>);
+        
+        //append contactdata to parent xml
+        content.keyValues.appendChild(keyXml);
+    }
+   
+    //TODO: refactor when for of Loop is available
+    for each( let outerMap in pAddresses )
+    {
+        var adressXml = <physicalAddresse/>
+        var pAdressKey = outerMap["addressKey"];
+    
+        adressXml.appendChild(<addressKey>{
+            pAdressKey
+            }</addressKey>)
+        
+        var list = outerMap["value"];
+       
+        adressXml.appendChild(<keyValues/>)
+        
+            for each( let innerMap in list )
+            {
+                let keyXml = <keyValue/>
+                let innerMapKey =  innerMap["key"];
+                let innerMapValue = innerMap["value"];
+                
+                    
+                keyXml.appendChild(<key>{
+                    innerMapKey
+                    }</key>);
+                keyXml.appendChild(<value>{
+                    innerMapValue
+                    }</value>);
+                
+                adressXml.keyValues.appendChild(keyXml);
+            }
+            //append adressxml to parent
+            content.physicalAddresses.appendChild(adressXml);
+        }
+    return content;
+    }
+    
+EwsSyncContactXMLUtils.mapContactFromXML = function( pContactXML )
+{
+    let retVal = {};
+    let shallow = [];
+
+    for each (keyValue in pContactXML.keyValues.keyValue)
+    {   
+        let map = {};
+        map["key"] = keyValue.key;
+        map["value"] = keyValue.value;
+        shallow.push(map);
+    }
+    retVal["shallow"] = shallow;
+    
+    let addresses = [];
+    for each (physicalAddresse in pContactXML.physicalAddresses.physicalAddresse)
+    {
+
+        let outerMap = {};
+        outerMap["addressKey"] = physicalAddresse.addressKey;
+        let list = [];
+        for each(keyValue in physicalAddresse.keyValues)
+        {
+            let innerMap = {};
+            innerMap["key"] = keyValue.key;
+            outerMap["value"] = keyValue.value;
+            list.push(innerMap);
+        }
+        outerMap["value"] = list;
+    }
+    retVal["addresses"] = addresses;
+    return retVal;
 }
\ No newline at end of file
diff --git a/process/Favorites_lib/process.js b/process/Favorites_lib/process.js
index d5e32f5145cb4d324f5f47e69cfe2de852b52ca9..a02f3dfcc2146f31e6936f51870c92120f0f427c 100644
--- a/process/Favorites_lib/process.js
+++ b/process/Favorites_lib/process.js
@@ -30,30 +30,56 @@ FavoritesUtil.getUserFavoriteGroups = function()
     return Array.from(allTypes);
 }
 
+/**
+ * Here we prepare the filtercondition for favorites of a certain pObjecttype, pOperator and pRowvalue.
+ * In certain circumstances, the rowids need to be prepared earlier (Person / Organisation). If so, they can be inserted by pPreparedRowIds.
+ * Then they won't be loaded again inside this method.
+ */
+FavoritesUtil.getFilterDisplayCondition = function(pObjecttype, pOperator, pRawvalue, pIdColumn, pPreparedRowIds)
+{
+    var favoFilterCond = newWhere();
+    
+    if(pPreparedRowIds == null || pPreparedRowIds.length == 0)
+        pPreparedRowIds = FavoritesUtil.getRowIdsOfFavorites(pObjecttype, pOperator, pRawvalue);
 
+    if(pOperator == "1" || pOperator == "2" || pOperator == "11") // equal / not equal / not empty -> compare on result values
+    {
+        for(i = 0; i < pPreparedRowIds.length; i++)
+            favoFilterCond.or(pIdColumn, pPreparedRowIds[i], SqlBuilder.EQUAL());
+    }
+    else if(pOperator == "12") // empty
+        favoFilterCond.and(pIdColumn, pPreparedRowIds, SqlBuilder.NOT_IN());
 
-FavoritesUtil.getRowIdsOfFavoriteGroup = function()
+    return favoFilterCond.toString();
+}
+/**
+ *  Gets all favorized datasetids by a given pObjecttype, pOperator and the Favoritegroup-Title it is stored with
+ */
+FavoritesUtil.getRowIdsOfFavorites = function(pObjecttype, pOperator, pRawvalue)
 {
     var sysAlias = favorite.getFavoritesAlias();
+    var op = "";
 
-    var value = vars.get("$local.rawvalue");
-    var operator = vars.get("$local.operator") //noch zu implementieren
+    if(pOperator == "1")
+        op = SqlBuilder.EQUAL();
+    else if(pOperator == "2")
+        op = SqlBuilder.NOT_EQUAL();
+    else if(pOperator == "11")
+        op = SqlBuilder.IN();
+    else if(pOperator == "12")
+        op = SqlBuilder.NOT_IN();
 
-    if(value && operator)
-    {
-        var filterCond = newWhere("ASYS_RECORDGROUP.TITLE", value, null, null, sysAlias); //Operators fehlen noch
-        filterCond.and(newWhere("ASYS_RECORDGROUP.USER_ID", tools.getCurrentUser()["name"], null, null, sysAlias));
-
-        var rowIds = new SqlBuilder(sysAlias).selectDistinct("ASYS_RECORD.ROW_ID")
-                                .from("ASYS_RECORD")
-                                .join("ASYS_RECORDGROUP", "ASYS_RECORD.RECORDGROUP_ID = ASYS_RECORDGROUP.ID")
-                                .where(filterCond)
-                                .arrayColumn();
-                                
-        return rowIds;
-    }
-    
-    return null;
+    var filterCond = newWhereIfSet("ASYS_RECORDGROUP.TITLE", pRawvalue, op, null, sysAlias); //Operators fehlen noch
+    filterCond.and(newWhere("ASYS_RECORDGROUP.USER_ID", tools.getCurrentUser()["name"], null, null, sysAlias));
+    filterCond.and(newWhere("ASYS_RECORD.OBJECT_TYPE", pObjecttype, null, null, sysAlias));
+
+    var rowIds = new SqlBuilder(sysAlias).selectDistinct("ASYS_RECORD.ROW_ID")
+                            .from("ASYS_RECORD")
+                            .join("ASYS_RECORDGROUP", "ASYS_RECORD.RECORDGROUP_ID = ASYS_RECORDGROUP.ID")
+                            .where(filterCond)
+                            .arrayColumn();
+
+    return rowIds;
 }
     
 FavoritesUtil.getUserFavoriteGroupsByContext = function(pContext)
diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js
index 98fe8cc944264fe98c8ffc7a636128705da4ec35..f3708067a34ad01930d3ade922c9520011e1bb91 100644
--- a/process/Sql_lib/process.js
+++ b/process/Sql_lib/process.js
@@ -3527,7 +3527,8 @@ SqlMaskingUtils.prototype.cast = function (pField, pTargetDatatype, pTargetLengt
             switch(pTargetDatatype)
             {
                 case SQLTYPES.TIMESTAMP:
-                    return "datetime";
+                    sqlDataType = "datetime";
+                    break;
                 case SQLTYPES.DATE:
                 case SQLTYPES.DECIMAL:
                 case SQLTYPES.INTEGER:
diff --git a/process/ewsSyncContacts_serverProcess/ewsSyncContacts_serverProcess.aod b/process/ewsSyncContacts_serverProcess/ewsSyncContacts_serverProcess.aod
new file mode 100644
index 0000000000000000000000000000000000000000..fbbe02fc2fff34c845acc1f03e22f34836da4ab6
--- /dev/null
+++ b/process/ewsSyncContacts_serverProcess/ewsSyncContacts_serverProcess.aod
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.2" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.2">
+  <name>ewsSyncContacts_serverProcess</name>
+  <title>Sync Exchange Contacts</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <process>%aditoprj%/process/ewsSyncContacts_serverProcess/process.js</process>
+  <alias>Data_alias</alias>
+  <variants>
+    <element>EXECUTABLE</element>
+    <element>LIBRARY</element>
+  </variants>
+</process>
diff --git a/process/ewsSyncContacts_serverProcess/process.js b/process/ewsSyncContacts_serverProcess/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..fd420916d9172146ce5f60943ae629bf8578cd82
--- /dev/null
+++ b/process/ewsSyncContacts_serverProcess/process.js
@@ -0,0 +1,588 @@
+import("Util_lib");
+import("system.project");
+import("system.favorite");
+import("system.db");
+import("system.result");
+import("EwsClient_lib");
+import("system.text");
+import("Address_lib");
+import("Communication_lib");
+import("system.vars");
+import("Sql_lib");
+import("system.tools");
+import("system.logging");
+import("EwsClientSync_lib");
+
+//inserting new Data in the asys_synccontact table and deleting those which aren't anymore in the favorite context
+EwsClientSyncUtils.prepareContactSyncTable();
+
+//start Sync with Exchange
+var msg = runSync();
+
+if(msg.length){
+    result.string(msg.join("\n"));
+}
+
+function runSync(){
+    var doDebug = false;
+    var retMsg = [];
+    
+    var syncUser = newSelect("distinct USER_ID").from("AB_SYNCCONTACT").arrayColumn();
+    
+    for (var i= 0 ; i < syncUser.length; i++)
+    {
+        var user = tools.getUserByAttribute(tools.NAME, [syncUser[i]], tools.PROFILE_DEFAULT);
+        if (user)
+        {
+            var mailBox = user[tools.PARAMS][tools.EXCHANGE_EMAIL];
+            
+            if(!mailBox)//use the mail of the user as backup exchangeMail adress
+                mailBox = user[tools.PARAMS][tools.EMAIL];
+            
+            
+            var exAlias = user[tools.PARAMS][tools.CALENDAR_ALIAS]; 
+            
+            if (!exAlias)
+                exAlias = project.getInstanceConfigValue("calendarAlias", null);
+            
+            var login = user[tools.TITLE]; 
+            var lastRunDate = user[tools.PARAMS]["lastEwsSyncContact"];
+            var runDate = vars.get("$sys.date");
+            user[tools.PARAMS]["lastEwsSyncContact"] = runDate;
+            
+            if (mailBox != "" && exAlias != "")
+            {                       
+                if(doDebug) logging.log("ContactSync for User: " + login + " started")         
+  
+                let delContacts = EWSdeleteContactsForUser(syncUser[i], mailBox, exAlias, login, doDebug); 
+                let updateContacts = EWSupdateContactsForUser(syncUser[i], mailBox, exAlias, lastRunDate, login, doDebug);
+                let insertContacts = EWSinsertContactsForUser(syncUser[i], mailBox, exAlias, runDate, login, doDebug);
+                    
+                if(delContacts.length)
+                    retMsg.push(delContacts);
+                if(updateContacts.length)    
+                    retMsg.push(updateContacts);
+                if(insertContacts.length)
+                    retMsg.push(insertContacts);
+
+                tools.updateUser(user);
+ 
+                if(doDebug) logging.log("ContactSync for User: " + login + " completed")                          
+            }
+            else
+            {
+                retMsg.push(["No exchange configuration exists for user " + login]);
+            }
+        }
+    }    
+    if(doDebug) logging.log("EWSContactSync completed");
+    
+    return retMsg;
+}
+
+/**************************************************************************************************/
+
+/*
+ * deletes the Synced Contacts for the passed User
+ * 
+ * @param {String} pUserID ID of the User for which Contact should be removed from sync
+ * @param {String} pMailBox Exchange Mail
+ * @param {String} pAlias name of the Exchange Alias
+ * @param {String} pUser Login of the User
+ * @param {boolean} doDebug 
+ *
+*/
+function EWSdeleteContactsForUser(pUserID, pMailBox, pAlias, pUser, doDebug)
+{
+    //delete all Entrys with a DATE_DEL tag, those were removed between the last import and yet
+    var cond = newWhere("AB_SYNCCONTACT.DATE_DEL is not null").and("AB_SYNCCONTACT.USER_ID", pUserID);
+    
+    var delContacts = newSelect("AB_SYNCCONTACT.EXCHANGEID")
+    .from("AB_SYNCCONTACT")
+    .where(cond)
+    .and("AB_SYNCCONTACT.EXCHANGEID is not null")
+    .arrayColumn();
+    
+    var deletions = Utils.clone(delContacts);
+    
+    var exchangeids = [];
+    while(deletions.length > 0)
+    {
+        let deletionPart = deletions.splice(0, 200);
+        try{
+            exchangeids = exchangeids.concat(EwsSyncContactUtils.deleteContactByID(pAlias, deletionPart, pMailBox, doDebug));
+        }
+        catch(ex)
+        {
+            let errMsg = "Error while calling the plugin: " + logging.toLogString(ex.rhinoException != undefined ? ex.rhinoException : ex, true) + "\r\n"; 
+            logging.log(errMsg);
+            return [errMsg];
+        }                
+    }
+      
+    var errorItems = []; 
+    var notFoundItems = []; 
+    var deletedItems = [];
+    
+    if(exchangeids.length > 0)
+    {
+        //no errors during deletion in Exchange
+        while (exchangeids[0].length > 0) 
+        {
+            let exchangeidsPart = exchangeids[0].splice(0, 30);//max limit 30
+                
+            cond.and("AB_SYNCCONTACT.EXCHANGEID", exchangeidsPart, SqlBuilder.IN()).deleteData();
+            deletedItems = deletedItems.concat(exchangeidsPart);
+        }
+        
+        //exchange Entrys with errors for deleting
+        while (exchangeids[1].length > 0) 
+        {
+            if(doDebug) logging.log("Exchange Entrys with Errors: " + exchangeids[1].length);
+            var deletes = [];
+        
+            let exchangeidsPart = exchangeids[1].splice(0, 30);//max limit 30
+                
+            for (let i = 0; i < exchangeidsPart.length; i++) 
+            {
+                if(exchangeidsPart[i][3] == "ErrorItemNotFound")
+                {
+                    deletes.push(exchangeidsPart[i][0]);
+                    notFoundItems.push(exchangeidsPart[i][0] , pUserID);
+                }
+                else
+                {
+                    errorItems.push(exchangeidsPart[i][0] , pUserID);
+                }
+            }
+            
+            if(deletes.length > 0)
+            {
+                let affectedRows = cond.and("AB_SYNCCONTACT.EXCHANGEID", deletes, SqlBuilder.IN()).deleteData();
+                if(doDebug) logging.log("Anzahl der gelöschten Einträge: " + affectedRows);
+                deletedItems = deletedItems.concat(deletes);
+            }
+            
+            //clearing the where condition and preset it to it's origin condition
+            cond.clearWhere();
+            cond.where("AB_SYNCCONTACT.DATE_DEL is not null").and("AB_SYNCCONTACT.USER_ID", pUserID);
+        }
+        
+        if(doDebug && notFoundItems.length > 0)
+            logging.log("EWSSYnc not found items: " + notFoundItems.toSource());
+        
+        if(errorItems.length > 0)
+            logging.log("EWSSYnc error items: " + errorItems.toSource());
+        
+        if(doDebug && deletedItems.length > 0)
+            logging.log("EWSSYnc deleted items: " + deletedItems.toSource());
+    }
+    return errorItems;
+}
+
+
+
+/*
+ * updates the Synced Contacts for the passed User
+ * 
+ * @param {String} pUserID ID of the User for which Contact should be updated
+ * @param {String} pMailBox Exchange Mail
+ * @param {String} pAlias name of the Exchange Alias
+ * @param {String} pRunDate lastRunDate of the sync
+ * @param {String} pUser Login of the User
+ * @param {boolean} doDebug 
+ *
+*/
+function EWSupdateContactsForUser(pUserID, pMailBox, pAlias, pRunDate, pUser, doDebug) 
+{   
+    var runDate = (!pRunDate) ? 0 : pRunDate;
+       
+    //get Contacts for update 
+    var cond = newWhere("AB_SYNCCONTACT.EXCHANGEID is not null")
+    .and("AB_SYNCCONTACT.USER_ID", pUserID)
+    .and("AB_SYNCCONTACT.DATE_EDIT", runDate, SqlBuilder.GREATER());
+    
+    var contactsData = newSelect("AB_SYNCCONTACT.CONTACT_ID")
+    .from("AB_SYNCCONTACT")
+    .where(cond)
+    .arrayColumn();
+    
+    var retMsg = [];
+    
+    if (contactsData.length > 0)
+    {
+        //get data with config
+        var config = EwsClientSyncUtils.getPlaceholders(pUserID);
+        var data = getAddressData(contactsData, config);
+        
+        //data pos 0 contains column Name - use them as key for the User object
+        var header = [];
+        for (let i = 0; i < data[0].length; i++)
+        {
+            header.push(data[0][i].replace(new RegExp("[{@}]","g"), "")); //replace start and end delimeter which are set in the getAdressData Method
+        }
+        
+        var dataObj, addrObj, addrValueObjBusiness, addrValueObjHome, addrValueObjOther, exchangeId;
+        var objects = [];
+        //loop through array at pos 1, header has been already collected
+        for (let i = 1; i < data.length; i++)
+        {
+            //dataObj at pos data[i][j] will match to the header[j]
+            dataObj = new Object();
+            addrObj = new Object();
+            addrValueObjBusiness = {};
+            addrValueObjHome = {};
+            addrValueObjOther = {};
+            
+            //addressdata will allocated with tags (Business_, Home_, Other_) to each object
+            for (let j = 0; j < header.length; j++)
+            {
+                addDataToValueObjects(header[j], data[i][j], dataObj, addrValueObjBusiness, addrValueObjHome, addrValueObjOther);
+            }
+            
+            //build addr object out of the objects generated above 
+            buildAddrObject(addrObj, addrValueObjHome, addrValueObjBusiness, addrValueObjOther);
+            
+            // Get the exchangeID from the data-object for update
+            let exchangeId = dataObj["EXCHANGEID"].value;
+            objects.push([exchangeId, dataObj, addrObj]);
+        }
+        
+        var errorItems = []; 
+        var notFoundItems = []; 
+        var deletedItems = [];
+        
+        while(objects.length > 0)
+        {
+            let objectsPart = objects.splice(0, 200);//currently max limit: 200
+            try
+            {
+                exchangeIds = EwsSyncContactUtils.updateContacts(pAlias, pMailBox, objectsPart, doDebug);//run plugin
+            }
+            catch(ex)
+            {
+                let errMsg = "Error while calling the plugin: " + logging.toLogString(ex.rhinoException != undefined ? ex.rhinoException : ex, true) + "\r\n"; 
+                logging.log(errMsg);
+                return [errMsg];
+            }
+        
+            //exchangeIDs[1] array for the contacts which got an error
+            while(exchangeIds[1].length > 0) 
+            {
+                var deletes = [];
+                    
+                let exchangeIdsPart = exchangeIds[1].splice(0, 30);
+                
+                for (let i = 0; i < exchangeIdsPart.length; i++) 
+                {
+                    //contact which aren't in Exchange anymore can be deleted out of the sync
+                    if(exchangeIdsPart[i][3] == "ErrorItemNotFound")
+                    {
+                        deletes.push(exchangeIdsPart[i][0]);
+                        notFoundItems.push(exchangeIdsPart[i][0] , pUserID);
+                    }
+                    else
+                    {
+                        errorItems.push(exchangeIdsPart[i].toSource(), pUserID);
+                        retMsg.push( exchangeIDs[1][0] + " : " + exchangeIDs[1][2] + " " + exchangeIDs[1][3] );
+                    }
+                }
+                    
+                if(deletes.length > 0)
+                {
+                    //delete out of sync table
+                    db.deleteData("AB_SYNCCONTACT", " CONTACT_ID in  ('" + deletes.join("', '") + "') and USER_ID = '" + pUserID + "'", "Data_alias", 300000);
+                    
+                    //remove set favorite for those which are delted - otherwise they would appear in the next run as 'new' Contacts
+                    EwsClientSyncUtils.removeFromFavorite(deletes, pUserID);
+                    deletedItems = deletedItems.concat(deletes);
+                }
+            }
+        }//while object > 0
+            
+        if(doDebug && notFoundItems.length > 0)
+            logging.log("EWSSYnc not found items: " + notFoundItems.toSource());
+        
+        if(errorItems.length > 0)
+            logging.log("EWSSYnc error items: " + errorItems.toSource());
+        
+        if(doDebug && deletedItems.length > 0)
+            logging.log("EWSSYnc deleted items: " + deletedItems.toSource());
+    }//contactsData.length > 0 
+    
+    return retMsg; 
+}
+
+/*
+ * updates the Synced Contacts for the passed User
+ * 
+ * @param {String} pUserID ID of the User for which Contact should be updated
+ * @param {String} pMailBox Exchange Mail
+ * @param {String} pAlias name of the Exchange Alias
+ * @param {String} pRunDate lastRunDate of the sync
+ * @param {String} pUser Login of the User
+ * @param {boolean} doDebug 
+ *
+*/
+function EWSinsertContactsForUser(pUserID, pMailBox, pAlias, pRunDate, pUser, doDebug)
+{    
+    var cond = newWhere("AB_SYNCCONTACT.EXCHANGEID is null")
+    .and("AB_SYNCCONTACT.USER_ID", pUserID); 
+    
+    var contactsData = newSelect("AB_SYNCCONTACT.CONTACT_ID")
+    .from("AB_SYNCCONTACT")
+    .where(cond)
+    .arrayColumn();
+    var retMsg = [];
+    if (contactsData.length > 0)
+    {   
+        var config = EwsClientSyncUtils.getPlaceholders(pUserID)
+        var data = getAddressData(contactsData, config);
+        
+        var header  = [];
+        for (let i = 0; i < data[0].length; i++)
+        {
+            header.push(data[0][i].replace(new RegExp("[{@}]","g"), ""))
+        }
+        
+        var dataObj;
+        var addrObj;
+        var objects = [];
+        var addrValueObjHome = {};
+        var addrValueObjBusiness = {};
+        var addrValueObjOther = {};
+       
+        
+        //get ID of the ADITO-Ordners 
+        var folderID = getExchangeFolderID(pAlias, pMailBox, "ADITO");
+        if (folderID != "")
+        {
+            //loop through array at pos 1, header has been already collected
+            for (var i = 1; i < data.length; i++)
+            {
+                dataObj = new Object();
+                addrObj = new Object();
+                addrValueObjBusiness = {};
+                addrValueObjHome = {};
+                addrValueObjOther = {};
+                
+                // The address data gets assigned to the respective object
+                for (let j = 0; j < header.length; j++)
+                {
+                    addDataToValueObjects(header[j], data[i][j], dataObj, addrValueObjBusiness, addrValueObjHome, addrValueObjOther);
+                }
+                
+                buildAddrObject(addrObj, addrValueObjHome, addrValueObjBusiness, addrValueObjOther);
+                objects.push([dataObj, addrObj]);
+            }
+            
+            while(objects.length > 0)
+            {    
+                let objectPart = objects.splice(0, 200); //current limit 200
+                
+
+                let exchangeIDs = EwsSyncContactUtils.insertContactsToFolder(pAlias, pMailBox, folderID, objectPart, doDebug);
+         
+                while(exchangeIDs[0].length > 0) 
+                {
+                    let exchangeIDsPart = exchangeIDs[0].splice(0, 30);//current limit 30
+                    updateADITOContactsAfterAction(exchangeIDsPart, pUserID);
+                }
+                
+                //when errors occured 
+                while(exchangeIDs[1].length > 0)
+                {
+                    retMsg.push( exchangeIDs[1][0] + " : " + exchangeIDs[1][2] + " " + exchangeIDs[1][3] )
+                }
+            }//objects.length > 0 
+        }
+        else 
+            return ["No folder 'ADITO' for account '" + pMailBox + "' and user '" + pUser + "' found"];
+    }
+    return retMsg;
+}
+
+
+/*
+ * allocates passed headers/values to their object
+ * 
+ * @param pHeader {String} fieldname in exchange
+ * @param pData {String} value for Header
+ * @param pDataObj {{}} object for contactdata
+ * @param pAddrValueObjBusiness {{}} adressobject Organisations
+ * @param pAddrValueObjHome {{}} adressobject homeadress
+ * @param pAddrValueObjOther {{}} adressobject others
+ * 
+ */
+function addDataToValueObjects(pHeader, pData, pDataObj, pAddrValueObjBusiness, pAddrValueObjHome, pAddrValueObjOther)
+{
+    //with used appendChild method the pData values will be escaped automatically
+    
+    //differ contactdata and adressdata
+    //none of the abbreviation defined by the config
+    var headerNotNull = ["EmailAdress1", "EmailAddress2", "BusinessPhone", "BusinessHomepage", "HomePhone", "HomeFax", "OtherFax", "MobilePhone"];
+    
+    if (pData != "" || headerNotNull.indexOf(pHeader) == -1)
+    {
+        if (pHeader.indexOf("Business_") == -1 && pHeader.indexOf("Home_") == -1 && pHeader.indexOf("Other_") == -1 && pData != "")
+        {
+            pDataObj[pHeader] = {
+                "key" : pHeader,
+                "value" : pData
+            };
+        }
+        else 
+        {
+            //Organisation Adress
+            if (pHeader.indexOf("Business") != -1)
+            {
+                pHeader = pHeader.replace("Business_", "");
+                pAddrValueObjBusiness[pHeader] = {
+                    "key" : pHeader,
+                    "value" : pData
+                }
+            }
+            //Privatadress
+            else if (pHeader.indexOf("Home") != -1)
+            {
+                pHeader = pHeader.replace("Home_", "");
+                pAddrValueObjHome[pHeader] = {
+                    "key" : pHeader,
+                    "value" : pData
+                }
+            }
+            //other Adress
+            else if (pHeader.indexOf("Other") != -1)
+            {
+                pHeader = pHeader.replace("Other_", "");
+                pAddrValueObjOther[pHeader] = {
+                    "key" : pHeader,
+                    "value" : pData
+                }
+            }
+        }
+    }
+}
+
+/*
+ * Build Address Object for the plugin call
+ * 
+ * @param pAddrObject {{}} addressobject for call
+ * @param pAddrValueObjHome {{}} adressobject with Privatadresse
+ * @param pAddrValueObjBusiness {{}} adressobject for Organisation
+ * @param pAddrValueObjOther {{}} adressobject for other adresses
+ */
+function buildAddrObject(pAddrObject, pAddrValueObjHome, pAddrValueObjBusiness, pAddrValueObjOther) 
+{
+    var homeOk = false;
+    var businessOk = false;
+    var otherOk = false;
+    
+    for each (var obj in pAddrValueObjHome)
+    {
+        if (obj["value"] != "")
+        {
+            homeOk = true;
+            break;
+        }
+    }
+    for each (obj in pAddrValueObjBusiness)
+    {
+        if (obj["value"] != "")
+        {
+            businessOk = true;
+            break;
+        }
+    }
+    for each (obj in pAddrValueObjOther)
+    {
+        if (obj["value"] != "")
+        {
+            otherOk = true;
+            break;
+        }
+    }
+    
+    if (homeOk)
+    {
+        pAddrObject["Home"] = {
+            "addressKey" : "Home",
+            "value" : pAddrValueObjHome
+        };
+    }
+    if (businessOk)
+    {
+        pAddrObject["Business"] = {
+            "addressKey" : "Business",
+            "value" : pAddrValueObjBusiness
+        };
+    }
+    if (otherOk)
+    {
+        pAddrObject["Other"] = {
+            "addressKey" : "Other",
+            "value" : pAddrValueObjOther
+        };
+    }
+}
+
+/*
+ * returns the exchangeID of the ADITO Folder of an exchange User
+ * if no folder is passed all folderIDs will be returned
+ * 
+ * @param {String} pAlias exchange-alias
+ * @param {String} pMailBox mail-adress of the user
+ * @param {String} pFolderName name of the folder for which the ID should returned none if all
+ */
+function getExchangeFolderID(pAlias, pMailBox, pFolderName)
+{
+    var folders = EwsSyncContactUtils.getContactFolders(pAlias, pMailBox);
+    
+    for ( var i = 0; i < folders.length; i++)
+    {    
+        if( folders[i].name.toUpperCase() == pFolderName.toUpperCase() )
+            return folders[i].id;
+    }
+    return "";
+}
+
+function escapeValuesForXML(pValue){
+    
+    var reps = {};
+    reps["&"]  = "&amp;";
+    reps["\""] = "&quot";
+    reps["'"]  = "&apos";
+    reps["<"]  = "&lt;";
+    reps[">"]  = "&gt;";
+    
+    pValue = text.replaceAll(pValue, reps).trim();
+    
+    return pValue
+}
+
+/*
+* Updates the Edit-Date and the exchangeID into the associated data set of AOSYS_SYNCCONTACT
+* If the ExchangeID isn't passed, then it will just update DATE_EDIT
+*
+* @param {Array<Array>} pUpdateValues 2d-array in the following form: [[CONTACTID, matching new EXCHANGEID]]
+* @param {String} pUserID ID of the corresponding user
+*/
+function updateADITOContactsAfterAction(pUpdateValues, pUserID)
+{
+    var cols = ["EXCHANGEID"];
+    var types = db.getColumnTypes("AB_SYNCCONTACT", cols);
+    var vals;
+    var cond = "";
+    var updArr = [];
+    for (let i = 0; i < pUpdateValues.length; i++)
+    {
+        vals = [];
+        // Get EXCHANGEID
+        if (pUpdateValues[i][1])
+            vals.push(pUpdateValues[i][1]);
+
+        cond = "CONTACT_ID = '" + pUpdateValues[i][0] + "' and USER_ID = '" + pUserID + "'";
+        updArr.push(["AB_SYNCCONTACT", cols, types, vals, cond]);
+    }
+    db.updates(updArr, "Data_alias", 300000);
+}