diff --git a/.liquibase/Data_alias/basic/2021.0.3/Duplicate/alter_unrelatedduplicates.xml b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/alter_unrelatedduplicates.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b6e59bdbd9153071bac10d9f15d87c48b7c2b300
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/alter_unrelatedduplicates.xml
@@ -0,0 +1,24 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<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="p.neub" id="082919b2-ebfd-4864-9839-89e593fb6f2d">
+        <dropColumn tableName="UNRELATEDDUPLICATES">
+            <column name="CLUSTERID"/>
+        </dropColumn>
+        <addColumn tableName="UNRELATEDDUPLICATES">
+            <column name="DUPLICATETYPE"  type="NVARCHAR(63)"/>
+        </addColumn>
+        <createIndex indexName="IDX_UNRELATEDDUPLICATES_DUPLICATETYPE" tableName="UNRELATEDDUPLICATES">
+            <column name="DUPLICATETYPE"/>
+        </createIndex>
+        <createIndex indexName="IDX_UNRELATEDDUPLICATES_SOURCEDUPLICATEID" tableName="UNRELATEDDUPLICATES">
+            <column name="SOURCEDUPLICATEID"/>
+        </createIndex>
+        <createIndex indexName="IDX_UNRELATEDDUPLICATES" tableName="UNRELATEDDUPLICATES">
+            <column name="DUPLICATETYPE"/>
+            <column name="SOURCEDUPLICATEID"/>
+            <column name="UNRELATEDDUPLICATEID"/>
+        </createIndex>
+    </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2021.0.3/Duplicate/changelog.xml b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/changelog.xml
new file mode 100644
index 0000000000000000000000000000000000000000..10ee1b9cc2cb6cd02db3b863cb695a114c9625d1
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/changelog.xml
@@ -0,0 +1,10 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<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">
+    <include relativeToChangelogFile="true" file="create_hasduplicate.xml"/>
+    <include relativeToChangelogFile="true" file="drop_duplicateclusters.xml"/>
+    <include relativeToChangelogFile="true" file="drop_duplicatescannerresultfieldconfig.xml"/>
+    <include relativeToChangelogFile="true" file="alter_unrelatedduplicates.xml"/>
+    <include relativeToChangelogFile="true" file="migrate_unrelatedduplicates.xml"/>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2021.0.3/Duplicate/create_hasduplicate.xml b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/create_hasduplicate.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f61d512d35ce13c2928fc3e6922ac8f25058542d
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/create_hasduplicate.xml
@@ -0,0 +1,21 @@
+<?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="p.neub" id="db282e4c-01c2-4b55-aa85-01306f4b1f7a">
+    <createTable tableName="HASDUPLICATE">
+      <column name="HASDUPLICATEID" type="CHAR(36)">
+        <constraints primaryKey="true" primaryKeyName="PK_HASDUPLICATE_HASDUPLICATEID"></constraints>
+      </column>
+
+      <column name="OBJECT_TYPE" type="NVARCHAR(63)"/>
+      <column name="OBJECT_ROWID" type="CHAR(36)"/>
+      <column name="DUPLICATECOUNT" type="INTEGER"/>
+    </createTable>
+    <createIndex indexName="IDX_HASDUPLICATE" tableName="HASDUPLICATE">
+      <column name="OBJECT_TYPE"/>
+      <column name="OBJECT_ROWID"/>
+    </createIndex>
+    <createIndex indexName="IDX_HASDUPLICATE_OBJECT_ROWID" tableName="HASDUPLICATE">
+      <column name="OBJECT_ROWID"/>
+    </createIndex>
+  </changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2021.0.3/Duplicate/drop_duplicateclusters.xml b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/drop_duplicateclusters.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b61e7cb651dec4c502d4956f3caf44b7640bbb1c
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/drop_duplicateclusters.xml
@@ -0,0 +1,6 @@
+<?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="p.neub" id="45db014f-922d-4619-b69f-9bf3a36285f4">
+    <dropTable tableName="DUPLICATECLUSTERS"/>
+  </changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2021.0.3/Duplicate/drop_duplicatescannerresultfieldconfig.xml b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/drop_duplicatescannerresultfieldconfig.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6804c4345d4c745de74f6850985649c4329e11bb
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/drop_duplicatescannerresultfieldconfig.xml
@@ -0,0 +1,6 @@
+<?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="p.neub" id="fcf592c4-e07c-4919-bfba-0bf99db161ec">
+    <dropTable tableName="DUPLICATESCANNERRESULTFIELDCONFIG"/>
+  </changeSet>
+</databaseChangeLog>
diff --git a/.liquibase/Data_alias/basic/2021.0.3/Duplicate/migrate_unrelatedduplicates.xml b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/migrate_unrelatedduplicates.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ac72a09e145674f5a0774b07bd80a1d1b7db5d50
--- /dev/null
+++ b/.liquibase/Data_alias/basic/2021.0.3/Duplicate/migrate_unrelatedduplicates.xml
@@ -0,0 +1,23 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<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="p.neub" id="587e1ed7-b7c8-46f0-9058-01521ed97fd5">
+        <update tableName="UNRELATEDDUPLICATES">
+            <column name="DUPLICATETYPE" value="Person_entity"/>
+            <where>
+                DUPLICATETYPE is null and
+                (select PERSON_ID from CONTACT where CONTACTID = SOURCEDUPLICATEID)
+                is not null
+            </where>
+        </update>
+        <update tableName="UNRELATEDDUPLICATES">
+            <column name="DUPLICATETYPE" value="Organisation_entity"/>
+            <where>
+                DUPLICATETYPE is null and
+                (select PERSON_ID from CONTACT where CONTACTID = SOURCEDUPLICATEID)
+                is null
+            </where>
+        </update>
+    </changeSet>
+</databaseChangeLog>
\ No newline at end of file
diff --git a/.liquibase/Data_alias/basic/2021.0.3/changelog.xml b/.liquibase/Data_alias/basic/2021.0.3/changelog.xml
index 2c2fee9f8764ff778599efbc23b6f9aa499df6eb..887abd39115340a861cfcd8a4b9c9cdb09c74cda 100644
--- a/.liquibase/Data_alias/basic/2021.0.3/changelog.xml
+++ b/.liquibase/Data_alias/basic/2021.0.3/changelog.xml
@@ -9,4 +9,5 @@
     <include relativeToChangelogFile="true" file="Checklists/changelog.xml"/>
     <include relativeToChangelogFile="true" file="Planning/changelog.xml"/>
     <include relativeToChangelogFile="true" file="alter_origin_attribute.xml"/>
+    <include relativeToChangelogFile="true" file="Duplicate/changelog.xml"/>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/aliasDefinition/Data_alias/Data_alias.aod b/aliasDefinition/Data_alias/Data_alias.aod
index 8b751faf53e63dcb050f7de37e2146edf319454f..5943721355fd27f1c045dd4b6278fb3daa8604cb 100644
--- a/aliasDefinition/Data_alias/Data_alias.aod
+++ b/aliasDefinition/Data_alias/Data_alias.aod
@@ -12176,82 +12176,6 @@
               </entityFieldDb>
             </entityFields>
           </entityDb>
-          <entityDb>
-            <name>DUPLICATECLUSTERS</name>
-            <dbName></dbName>
-            <idColumn>ID</idColumn>
-            <idGeneratorType v="0" />
-            <idGeneratorInterval v="1" />
-            <documentation></documentation>
-            <title></title>
-            <description></description>
-            <auditSyncConfig>
-              <name>auditSyncConfig</name>
-              <auditMode v="0" />
-              <syncActive v="false" />
-              <syncComplete v="true" />
-              <syncDirection v="1" />
-              <syncIds></syncIds>
-            </auditSyncConfig>
-            <entityFields>
-              <entityFieldDb>
-                <name>DUPLICATEID</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="1" />
-                <size v="36" />
-                <scale v="0" />
-                <notNull v="true" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>CLUSTERID</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="1" />
-                <size v="36" />
-                <scale v="0" />
-                <notNull v="true" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>ID</name>
-                <dbName></dbName>
-                <primaryKey v="true" />
-                <columnType v="1" />
-                <size v="36" />
-                <scale v="0" />
-                <notNull v="true" />
-                <isUnique v="true" />
-                <index v="true" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>TARGET_ENTITY</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="12" />
-                <size v="200" />
-                <scale v="0" />
-                <notNull v="false" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-            </entityFields>
-          </entityDb>
           <entityDb>
             <name>UNRELATEDDUPLICATES</name>
             <dbName></dbName>
@@ -12313,136 +12237,11 @@
                 <description></description>
               </entityFieldDb>
               <entityFieldDb>
-                <name>CLUSTERID</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="1" />
-                <size v="36" />
-                <scale v="0" />
-                <notNull v="false" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-            </entityFields>
-          </entityDb>
-          <entityDb>
-            <name>DUPLICATESCANNERRESULTFIELDCONFIG</name>
-            <dbName></dbName>
-            <idColumn>ID</idColumn>
-            <idGeneratorType v="0" />
-            <idGeneratorInterval v="1" />
-            <documentation></documentation>
-            <title></title>
-            <description></description>
-            <auditSyncConfig>
-              <name>auditSyncConfig</name>
-              <auditMode v="0" />
-              <syncActive v="false" />
-              <syncComplete v="true" />
-              <syncDirection v="1" />
-              <syncIds></syncIds>
-            </auditSyncConfig>
-            <entityFields>
-              <entityFieldDb>
-                <name>DATE_EDIT</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="93" />
-                <size v="29" />
-                <scale v="9" />
-                <notNull v="false" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>DUPLICATESCANNER_ID</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="1" />
-                <size v="36" />
-                <scale v="0" />
-                <notNull v="true" />
-                <isUnique v="false" />
-                <index v="true" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-                <dependencies>
-                  <entityDependency>
-                    <name>9b123a17-2f41-49f8-9492-f386ece46f7c</name>
-                    <entityName>DUPLICATESCANNER</entityName>
-                    <fieldName>ID</fieldName>
-                  </entityDependency>
-                </dependencies>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>DATE_NEW</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="93" />
-                <size v="29" />
-                <scale v="9" />
-                <notNull v="true" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>ID</name>
-                <dbName></dbName>
-                <primaryKey v="true" />
-                <columnType v="1" />
-                <size v="36" />
-                <scale v="0" />
-                <notNull v="true" />
-                <isUnique v="true" />
-                <index v="true" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>USER_NEW</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="12" />
-                <size v="50" />
-                <scale v="0" />
-                <notNull v="true" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>ENTITY_FIELD_NAME</name>
+                <name>DUPLICATETYPE</name>
                 <dbName></dbName>
                 <primaryKey v="false" />
                 <columnType v="12" />
-                <size v="100" />
-                <scale v="0" />
-                <notNull v="false" />
-                <isUnique v="false" />
-                <index v="false" />
-                <documentation></documentation>
-                <title></title>
-                <description></description>
-              </entityFieldDb>
-              <entityFieldDb>
-                <name>USER_EDIT</name>
-                <dbName></dbName>
-                <primaryKey v="false" />
-                <columnType v="12" />
-                <size v="50" />
+                <size v="63" />
                 <scale v="0" />
                 <notNull v="false" />
                 <isUnique v="false" />
@@ -18533,6 +18332,82 @@
               </entityFieldDb>
             </entityFields>
           </entityDb>
+          <entityDb>
+            <name>HASDUPLICATE</name>
+            <dbName></dbName>
+            <idColumn>HASDUPLICATEID</idColumn>
+            <idGeneratorType v="0" />
+            <idGeneratorInterval v="1" />
+            <documentation></documentation>
+            <title></title>
+            <description></description>
+            <auditSyncConfig>
+              <name>auditSyncConfig</name>
+              <auditMode v="0" />
+              <syncActive v="false" />
+              <syncComplete v="true" />
+              <syncDirection v="1" />
+              <syncIds></syncIds>
+            </auditSyncConfig>
+            <entityFields>
+              <entityFieldDb>
+                <name>OBJECT_ROWID</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="1" />
+                <size v="36" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>OBJECT_TYPE</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="12" />
+                <size v="63" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>DUPLICATECOUNT</name>
+                <dbName></dbName>
+                <primaryKey v="false" />
+                <columnType v="4" />
+                <size v="10" />
+                <scale v="0" />
+                <notNull v="false" />
+                <isUnique v="false" />
+                <index v="false" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+              <entityFieldDb>
+                <name>HASDUPLICATEID</name>
+                <dbName></dbName>
+                <primaryKey v="true" />
+                <columnType v="1" />
+                <size v="36" />
+                <scale v="0" />
+                <notNull v="true" />
+                <isUnique v="true" />
+                <index v="true" />
+                <documentation></documentation>
+                <title></title>
+                <description></description>
+              </entityFieldDb>
+            </entityFields>
+          </entityDb>
           <entityDb>
             <name>AB_SYNCCONTACT</name>
             <dbName></dbName>
diff --git a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
index 1a320de850c8f403f718f35e8b8e7f72857f1f8e..70f6ccdb13ba5c645c402c818b42d9e954b3aa69 100644
--- a/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
+++ b/application/_____SYSTEM_APPLICATION_NEON/_____SYSTEM_APPLICATION_NEON.aod
@@ -330,11 +330,6 @@
                 <kind v="10077" />
                 <title></title>
               </entityNode>
-              <entityNode>
-                <name>Duplicates</name>
-                <kind v="10077" />
-                <title></title>
-              </entityNode>
               <entityNode>
                 <name>AuditLogHistory</name>
                 <kind v="10077" />
diff --git a/entity/Contact_entity/recordcontainers/db/onDBDelete.js b/entity/Contact_entity/recordcontainers/db/onDBDelete.js
index 61afa46ba950988b60515de3cae0e732553cfe69..c7b08f7110800f03efb3ca755622080493d3fd48 100644
--- a/entity/Contact_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Contact_entity/recordcontainers/db/onDBDelete.js
@@ -5,7 +5,8 @@ import("system.vars");
 import("DuplicateScanner_lib");
 
 var contactId = vars.get("$field.CONTACTID");
-DuplicateScannerUtils.deleteCachedDuplicate(contactId);
+DuplicateScannerUtils.deleteHasDuplicateEntries("Person_entity", [contactId]);
+DuplicateScannerUtils.deleteHasDuplicateEntries("Organisation_entity", [contactId]);
 
 new AttributeRelationQuery(contactId, null, "Person")
     .deleteAllAttributes();
diff --git a/entity/DuplicateOrganisation_entity/DuplicateOrganisation_entity.aod b/entity/DuplicateOrganisation_entity/DuplicateOrganisation_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..eb3318d1aad761ad8f944dd5596c80d20a8999b3
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/DuplicateOrganisation_entity.aod
@@ -0,0 +1,241 @@
+<?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>DuplicateOrganisation_entity</name>
+  <title>Duplicate</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <grantCreate v="false" />
+  <grantUpdate v="false" />
+  <grantDelete v="false" />
+  <initFilterProcess>%aditoprj%/entity/DuplicateOrganisation_entity/initFilterProcess.js</initFilterProcess>
+  <titlePlural>Duplicates</titlePlural>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+      <targetContextField>targetContext</targetContextField>
+      <targetIdField>CONTACTID</targetIdField>
+      <dependencies>
+        <entityDependency>
+          <name>a666bb24-2875-481a-879e-86b8e8517c1e</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>Duplicates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+    </entityProvider>
+    <entityProvider>
+      <name>#PROVIDER_AGGREGATES</name>
+      <useAggregates v="true" />
+    </entityProvider>
+    <entityField>
+      <name>CONTACTID</name>
+      <linkedContext>Organisation</linkedContext>
+    </entityField>
+    <entityField>
+      <name>ORGNAME</name>
+      <title>Name</title>
+      <linkedContext>Organisation</linkedContext>
+    </entityField>
+    <entityParameter>
+      <name>Id_param</name>
+      <valueProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/id_param/valueProcess.js</valueProcess>
+      <mandatory v="true" />
+    </entityParameter>
+    <entityParameter>
+      <name>Obj_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+      <description>Contains a name value object of all variables that can be used to scan for duplicates</description>
+    </entityParameter>
+    <entityActionGroup>
+      <name>filterActions</name>
+      <children>
+        <entityActionField>
+          <name>ignoreDuplicates</name>
+          <title>${IGNORE_DUPLICATE}</title>
+          <onActionProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/ignoreduplicates/onActionProcess.js</onActionProcess>
+          <isObjectAction v="false" />
+          <isSelectionAction v="true" />
+          <iconId>VAADIN:CLOSE</iconId>
+          <titleProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/ignoreduplicates/titleProcess.js</titleProcess>
+        </entityActionField>
+        <entityActionField>
+          <name>mergeselectedintocurrent</name>
+          <title>Integrate selected into current contact</title>
+          <onActionProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/mergeselectedintocurrent/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+          <iconId>NEON:IMPORT</iconId>
+        </entityActionField>
+        <entityActionField>
+          <name>mergecurrentintoselected</name>
+          <title>Integrate current into selected contact</title>
+          <onActionProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/mergecurrentintoselected/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+          <iconId>NEON:EXPORT</iconId>
+        </entityActionField>
+      </children>
+    </entityActionGroup>
+    <entityField>
+      <name>STATUS</name>
+      <title>Status</title>
+      <consumer>KeywordContactStates</consumer>
+    </entityField>
+    <entityField>
+      <name>CUSTOMERCODE</name>
+      <title>Customercode</title>
+    </entityField>
+    <entityConsumer>
+      <name>KeywordContactStates</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/keywordcontactstates/children/containername_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>TYPE</name>
+      <title>Type</title>
+      <consumer>KeywordOrganisationTypes</consumer>
+    </entityField>
+    <entityField>
+      <name>STANDARD_EMAIL_COMMUNICATION</name>
+      <title>E-Mail</title>
+    </entityField>
+    <entityField>
+      <name>STANDARD_PHONE_COMMUNICATION</name>
+      <title>Phone</title>
+    </entityField>
+    <entityField>
+      <name>STANDARD_ADDRESS</name>
+      <title>Address</title>
+    </entityField>
+    <entityConsumer>
+      <name>KeywordOrganisationTypes</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/keywordorganisationtypes/children/containername_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>targetContext</name>
+      <valueProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/targetcontext/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>DUPLICATE</name>
+      <title>Duplicate</title>
+      <contentType>BOOLEAN</contentType>
+    </entityField>
+    <entityField>
+      <name>PICTURE</name>
+      <title>Picture</title>
+      <contentType>IMAGE</contentType>
+      <displayValueProcess>%aditoprj%/entity/DuplicateOrganisation_entity/entityfields/picture/displayValueProcess.js</displayValueProcess>
+    </entityField>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <isReadOnly v="true" />
+      <fromClauseProcess>%aditoprj%/entity/DuplicateOrganisation_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
+      <conditionProcess>%aditoprj%/entity/DuplicateOrganisation_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <alias>Data_alias</alias>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>CONTACTID.value</name>
+          <recordfield>CONTACT.CONTACTID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ORGNAME.value</name>
+          <recordfield>CONTACT.CONTACTID</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ORGNAME.displayValue</name>
+          <recordfield>ORGANISATION.NAME</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>CUSTOMERCODE.value</name>
+          <recordfield>ORGANISATION.CUSTOMERCODE</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STATUS.value</name>
+          <recordfield>CONTACT.STATUS</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STATUS.displayValue</name>
+          <expression>%aditoprj%/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STANDARD_EMAIL_COMMUNICATION.value</name>
+          <expression>%aditoprj%/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js</expression>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STANDARD_PHONE_COMMUNICATION.value</name>
+          <expression>%aditoprj%/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STANDARD_ADDRESS.value</name>
+          <recordfield>ADDRESS.ADDRESS</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>TYPE.value</name>
+          <recordfield>ORGANISATION.KIND</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>TYPE.displayValue</name>
+          <expression>%aditoprj%/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/type.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DUPLICATE.value</name>
+          <expression>%aditoprj%/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/duplicate.value/expression.js</expression>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>PICTURE.value</name>
+          <recordfield>ORGANISATION.PICTURE</recordfield>
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+      <linkInformation>
+        <linkInformation>
+          <name>49ea0faa-d04e-4d9d-b489-5a7b815e9e89</name>
+          <tableName>ORGANISATION</tableName>
+          <primaryKey>ORGANISATIONID</primaryKey>
+          <isUIDTable v="false" />
+          <readonly v="true" />
+        </linkInformation>
+        <linkInformation>
+          <name>523f6891-14ee-49ba-952d-7d5981e14b0c</name>
+          <tableName>CONTACT</tableName>
+          <primaryKey>CONTACTID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="true" />
+        </linkInformation>
+        <linkInformation>
+          <name>6b73b998-a194-4fb6-8659-42eac09e20cc</name>
+          <tableName>ADDRESS</tableName>
+          <primaryKey>ADDRESSID</primaryKey>
+          <isUIDTable v="false" />
+          <readonly v="true" />
+        </linkInformation>
+      </linkInformation>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/ignoreduplicates/onActionProcess.js b/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/ignoreduplicates/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..a070181a8e991188f1a7ff62ab87423364cdb5a6
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/ignoreduplicates/onActionProcess.js
@@ -0,0 +1,7 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("DuplicateScanner_lib");
+
+DuplicateScannerUtils.updateIgnored("Organisation_entity", vars.get("$param.Id_param"), vars.get("$sys.selection"), parseInt(vars.get("$field.DUPLICATE")));
+neon.refreshAll(); // Update the rows, because UNRELATEDDUPLICATES wont trigger a refresh even with write entities
diff --git a/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/ignoreduplicates/titleProcess.js b/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/ignoreduplicates/titleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c5ccfffeb0e7b5efc940eba237fbdc99ab9b603
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/ignoreduplicates/titleProcess.js
@@ -0,0 +1,9 @@
+import("system.translate");
+import("system.vars");
+import("system.result");
+
+result.string(
+    parseInt(vars.get("$field.DUPLICATE")) ?
+    translate.text("${IGNORE_DUPLICATE}") :
+    translate.text("${UNIGNORE_DUPLICATE}")
+);
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js b/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/mergecurrentintoselected/onActionProcess.js
similarity index 51%
rename from entity/Organisation_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js
rename to entity/DuplicateOrganisation_entity/entityfields/filteractions/children/mergecurrentintoselected/onActionProcess.js
index 29dab7b72c8898044cfabd79426552733f9f7dc4..b23396c01c1214f15be0e2bae435e1e9da91c702 100644
--- a/entity/Organisation_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js
+++ b/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/mergecurrentintoselected/onActionProcess.js
@@ -1,20 +1,29 @@
+import("system.translate");
+import("system.question");
 import("Employee_lib");
 import("system.vars");
 import("system.neon");
-import("DuplicateScanner_lib");
+import("DuplicateMerge_lib");
 
-let sourceContactId = vars.get("$param.DuplicateCurrentContactId_param");
+if(vars.get("$sys.selection").length == 1)
+{
+let sourceContactId = vars.get("$param.Id_param");
 let targetContactId = vars.get("$sys.selection")[0];
 
 //todo the actual merge ought to happen in a separate view where the contact infos can be merged manually by the user.
-let mergeSuccess = DuplicateScannerUtils.mergeOrganisation(sourceContactId, targetContactId);
+let mergeSuccess = DuplicateMergeUtils.mergeOrganisation(sourceContactId, targetContactId);
 
 if(mergeSuccess)
 {
     let currentContactId = EmployeeUtils.getCurrentContactId();
     if(currentContactId == null)
         currentContactId = "";
-    DuplicateScannerUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Organisation");
+    DuplicateMergeUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Organisation");
     
     neon.openContext("Organisation", "OrganisationMain_view", [targetContactId], neon.OPERATINGSTATE_VIEW, null)
-}
\ No newline at end of file
+}
+}
+else
+{
+    question.showMessage(translate.text("Please select only one element"));
+}
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js b/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/mergeselectedintocurrent/onActionProcess.js
similarity index 61%
rename from entity/Organisation_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js
rename to entity/DuplicateOrganisation_entity/entityfields/filteractions/children/mergeselectedintocurrent/onActionProcess.js
index 5ac58579f1326724bf4e6340a751ee86b12850b4..ac1a9260b226c00b472e5222a97c0c4f8286bfad 100644
--- a/entity/Organisation_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js
+++ b/entity/DuplicateOrganisation_entity/entityfields/filteractions/children/mergeselectedintocurrent/onActionProcess.js
@@ -1,22 +1,31 @@
+import("system.translate");
+import("system.question");
 import("Employee_lib");
 import("system.vars");
 import("system.neon");
-import("DuplicateScanner_lib");
+import("DuplicateMerge_lib");
 
-let targetContactId = vars.get("$param.DuplicateCurrentContactId_param");
+if(vars.get("$sys.selection").length == 1)
+{
+let targetContactId = vars.get("$param.Id_param");
 let sourceContactId = vars.get("$sys.selection")[0];
 
 //todo the actual merge ought to happen in a separate view where the contact infos can be merged manually by the user.
-let mergeSuccess = DuplicateScannerUtils.mergeOrganisation(sourceContactId, targetContactId);
+let mergeSuccess = DuplicateMergeUtils.mergeOrganisation(sourceContactId, targetContactId);
 
 if(mergeSuccess)
 {
     let currentContactId = EmployeeUtils.getCurrentContactId();
     if(currentContactId == null)
         currentContactId = "";
-    DuplicateScannerUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Organisation");
+    DuplicateMergeUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Organisation");
     //neon.refresh() with no fields will refresh the current image (and all sub images) but NOT the preview. neon.refreshAll() would refresh both,
     //why it would lead to an error because it's trying to load the already opened preview of the duplicateContact which just got deleted 
     //and does not exist any more which results in an exception
     neon.refresh();
-}
\ No newline at end of file
+}
+}
+else
+{
+    question.showMessage(translate.text("Please select only one element"));
+}
diff --git a/entity/DuplicateOrganisation_entity/entityfields/id_param/valueProcess.js b/entity/DuplicateOrganisation_entity/entityfields/id_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..bffe18eb097c82b9fa662880ad23d5d1ee32f7ff
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/entityfields/id_param/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("system.vars");
+
+var jsonObj = JSON.parse(vars.get("$param.Obj_param"));
+result.string(jsonObj["CONTACTID"]);
diff --git a/entity/DuplicateOrganisation_entity/entityfields/keywordcontactstates/children/containername_param/valueProcess.js b/entity/DuplicateOrganisation_entity/entityfields/keywordcontactstates/children/containername_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..43e8d27c6a6cdd11f092f8b404a97dc237577a38
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/entityfields/keywordcontactstates/children/containername_param/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+result.string($KeywordRegistry.contactStatus());
diff --git a/entity/DuplicateOrganisation_entity/entityfields/keywordorganisationtypes/children/containername_param/valueProcess.js b/entity/DuplicateOrganisation_entity/entityfields/keywordorganisationtypes/children/containername_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..9f418ef99a76f73e9ce0e06b98eb299c5431d63c
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/entityfields/keywordorganisationtypes/children/containername_param/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+result.string($KeywordRegistry.organisationType());
diff --git a/entity/DuplicateOrganisation_entity/entityfields/picture/displayValueProcess.js b/entity/DuplicateOrganisation_entity/entityfields/picture/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..aa69acba15ba5aa0635f9e0a4a391a04c5819c2f
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/entityfields/picture/displayValueProcess.js
@@ -0,0 +1,11 @@
+import("system.result");
+import("system.vars");
+
+if (vars.get("$field.PICTURE"))
+{
+    result.string(vars.get("$field.PICTURE"));
+}
+else
+{
+    result.string("TEXT:" + vars.getString("$field.ORGNAME.displayValue").trim());
+}
diff --git a/entity/DuplicateOrganisation_entity/entityfields/targetcontext/valueProcess.js b/entity/DuplicateOrganisation_entity/entityfields/targetcontext/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..84e4b61c2566393178456e74db7e36eb6abdaf80
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/entityfields/targetcontext/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Context_lib");
+
+result.string(ContextUtils.getContextName("Organisation"));
diff --git a/entity/DuplicateOrganisation_entity/initFilterProcess.js b/entity/DuplicateOrganisation_entity/initFilterProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..92797e84dbb193011bf821bb4ecc828681a2d414
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/initFilterProcess.js
@@ -0,0 +1,15 @@
+import("system.translate");
+import("system.result");
+
+result.string(JSON.stringify({
+    type: "group",
+    operator: "AND",
+    childs: [{
+        type: "row",
+        name: "DUPLICATE",
+        operator: "EQUAL",
+        contenttype: "BOOLEAN",
+        key: "1",
+        value: translate.text("Yes")
+    }]
+}));
diff --git a/entity/DuplicateOrganisation_entity/recordcontainers/db/conditionProcess.js b/entity/DuplicateOrganisation_entity/recordcontainers/db/conditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e53fabe5b3f46c2048bdb6500df6f37ca9300d61
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/recordcontainers/db/conditionProcess.js
@@ -0,0 +1,8 @@
+import("system.vars");
+import("Sql_lib");
+import("DuplicateScanner_lib");
+import("system.result");
+
+var duplicateIds = DuplicateScannerUtils.getDuplicateIdsByEntityObj("Organisation_entity", JSON.parse(vars.get("$param.Obj_param")));
+duplicateIds.push("-"); // workaround empty arrays
+result.string(newWhere("CONTACT.CONTACTID", duplicateIds, SqlBuilder.IN()).toString());
diff --git a/entity/DuplicateOrganisation_entity/recordcontainers/db/fromClauseProcess.js b/entity/DuplicateOrganisation_entity/recordcontainers/db/fromClauseProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..5412501fe024b394c16299840fb75b9997368d1f
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/recordcontainers/db/fromClauseProcess.js
@@ -0,0 +1,14 @@
+import("Sql_lib");
+import("system.vars");
+import("system.result");
+
+var unrelatedCondition = newWhere("UNRELATEDDUPLICATES.DUPLICATETYPE", "Organisation_entity")
+    .and("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", vars.get("$param.Id_param"))
+    .and("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID = CONTACT.CONTACTID");
+
+result.string(
+    "ORGANISATION " +
+    "join CONTACT on (ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID) " +
+    "left join ADDRESS on (ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID) " +
+    "left join UNRELATEDDUPLICATES on " + unrelatedCondition.toString()
+);
diff --git a/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/duplicate.value/expression.js b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/duplicate.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..8f7063b2ac8e637e6618ccc1ff745653daf0b339
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/duplicate.value/expression.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("Sql_lib");
+
+var statement = SqlBuilder.caseStatement()
+    .when("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID is not null")
+    .thenString("0").elseString("1");
+result.string(statement);
diff --git a/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..5827c59c416c332ba9281a60756f919fcb75c0a2
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Communication_lib");
+
+result.string(CommUtil.getStandardSubSqlMail());
diff --git a/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f438c2535b21180c5ad03637de90f577f2c736e
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Communication_lib");
+
+result.string(CommUtil.getStandardSubSqlPhone());
diff --git a/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..b63b2d57742bc29e8f35acd8bae539ec0a560c9c
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var sql = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.contactStatus(), "CONTACT.STATUS");
+result.string(sql);
diff --git a/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/type.displayvalue/expression.js b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/type.displayvalue/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..7ab8eb06526a4f6be6502246408fe7891c4dc46d
--- /dev/null
+++ b/entity/DuplicateOrganisation_entity/recordcontainers/db/recordfieldmappings/type.displayvalue/expression.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+var sql = KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.organisationType(), "ORGANISATION.KIND");
+result.string(sql);
diff --git a/entity/DuplicatePerson_entity/DuplicatePerson_entity.aod b/entity/DuplicatePerson_entity/DuplicatePerson_entity.aod
new file mode 100644
index 0000000000000000000000000000000000000000..2d5dd73d048c99ae42a4b422275198df818f39d1
--- /dev/null
+++ b/entity/DuplicatePerson_entity/DuplicatePerson_entity.aod
@@ -0,0 +1,270 @@
+<?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>DuplicatePerson_entity</name>
+  <title>Duplicate</title>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <grantCreate v="false" />
+  <grantUpdate v="false" />
+  <grantDelete v="false" />
+  <initFilterProcess>%aditoprj%/entity/DuplicatePerson_entity/initFilterProcess.js</initFilterProcess>
+  <titlePlural>Duplicates</titlePlural>
+  <recordContainer>db</recordContainer>
+  <entityFields>
+    <entityProvider>
+      <name>#PROVIDER</name>
+      <targetContextField>parentContext</targetContextField>
+      <targetIdField>CONTACTID</targetIdField>
+      <dependencies>
+        <entityDependency>
+          <name>7f8210c4-644f-4c45-a571-e232582f8d34</name>
+          <entityName>Person_entity</entityName>
+          <fieldName>Duplicates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>fd3253c7-f3f8-483f-8f49-6192f4e75979</name>
+          <entityName>Person_entity</entityName>
+          <fieldName>Duplicates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+      </dependencies>
+    </entityProvider>
+    <entityProvider>
+      <name>#PROVIDER_AGGREGATES</name>
+      <useAggregates v="true" />
+    </entityProvider>
+    <entityParameter>
+      <name>Obj_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+      <description>Contains a name value object of all variables that can be used to scan for duplicates</description>
+    </entityParameter>
+    <entityActionGroup>
+      <name>filterActions</name>
+      <children>
+        <entityActionField>
+          <name>ignoreDuplicates</name>
+          <title>${IGNORE_DUPLICATE}</title>
+          <onActionProcess>%aditoprj%/entity/DuplicatePerson_entity/entityfields/filteractions/children/ignoreduplicates/onActionProcess.js</onActionProcess>
+          <isObjectAction v="false" />
+          <isSelectionAction v="true" />
+          <iconId>VAADIN:CLOSE</iconId>
+          <titleProcess>%aditoprj%/entity/DuplicatePerson_entity/entityfields/filteractions/children/ignoreduplicates/titleProcess.js</titleProcess>
+        </entityActionField>
+        <entityActionField>
+          <name>mergeselectedintocurrent</name>
+          <title>Integrate selected into current contact</title>
+          <onActionProcess>%aditoprj%/entity/DuplicatePerson_entity/entityfields/filteractions/children/mergeselectedintocurrent/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+          <iconId>NEON:IMPORT</iconId>
+        </entityActionField>
+        <entityActionField>
+          <name>mergecurrentintoselected</name>
+          <title>Integrate current into selected contact</title>
+          <onActionProcess>%aditoprj%/entity/DuplicatePerson_entity/entityfields/filteractions/children/mergecurrentintoselected/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+          <iconId>NEON:EXPORT</iconId>
+        </entityActionField>
+      </children>
+    </entityActionGroup>
+    <entityField>
+      <name>CONTACTID</name>
+      <linkedContext>Person</linkedContext>
+    </entityField>
+    <entityParameter>
+      <name>Id_param</name>
+      <valueProcess>%aditoprj%/entity/DuplicatePerson_entity/entityfields/id_param/valueProcess.js</valueProcess>
+      <mandatory v="true" />
+    </entityParameter>
+    <entityField>
+      <name>FIRSTNAME</name>
+      <title>Firstname</title>
+    </entityField>
+    <entityField>
+      <name>LASTNAME</name>
+      <title>Lastname</title>
+      <linkedContext>Person</linkedContext>
+    </entityField>
+    <entityField>
+      <name>MIDDLENAME</name>
+      <title>Middlename</title>
+    </entityField>
+    <entityField>
+      <name>LETTERSALUTATION</name>
+      <title>Salutation</title>
+    </entityField>
+    <entityField>
+      <name>TITLE</name>
+      <title>Title</title>
+    </entityField>
+    <entityField>
+      <name>PICTURE</name>
+      <title>Picture</title>
+      <contentType>IMAGE</contentType>
+      <displayValueProcess>%aditoprj%/entity/DuplicatePerson_entity/entityfields/picture/displayValueProcess.js</displayValueProcess>
+    </entityField>
+    <entityField>
+      <name>STANDARD_EMAIL_COMMUNICATION</name>
+      <title>E-Mail</title>
+    </entityField>
+    <entityField>
+      <name>STANDARD_PHONE_COMMUNICATION</name>
+      <title>Phone</title>
+    </entityField>
+    <entityField>
+      <name>ORGANISATION_ID</name>
+      <title>Company</title>
+      <consumer>Organisations</consumer>
+      <linkedContext>Organisation</linkedContext>
+    </entityField>
+    <entityConsumer>
+      <name>Organisations</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Organisation_entity</entityName>
+        <fieldName>Organisations</fieldName>
+      </dependency>
+    </entityConsumer>
+    <entityField>
+      <name>STATUS</name>
+      <title>Status</title>
+      <consumer>KeywordContactStates</consumer>
+    </entityField>
+    <entityConsumer>
+      <name>KeywordContactStates</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>KeywordEntry_entity</entityName>
+        <fieldName>SpecificContainerKeywords</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>ContainerName_param</name>
+          <valueProcess>%aditoprj%/entity/DuplicatePerson_entity/entityfields/keywordcontactstates/children/containername_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityField>
+      <name>STANDARD_ADDRESS</name>
+      <title>Address</title>
+    </entityField>
+    <entityField>
+      <name>parentContext</name>
+      <valueProcess>%aditoprj%/entity/DuplicatePerson_entity/entityfields/parentcontext/valueProcess.js</valueProcess>
+    </entityField>
+    <entityField>
+      <name>DUPLICATE</name>
+      <title>Duplicate</title>
+      <contentType>BOOLEAN</contentType>
+    </entityField>
+  </entityFields>
+  <recordContainers>
+    <dbRecordContainer>
+      <name>db</name>
+      <isReadOnly v="true" />
+      <fromClauseProcess>%aditoprj%/entity/DuplicatePerson_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
+      <conditionProcess>%aditoprj%/entity/DuplicatePerson_entity/recordcontainers/db/conditionProcess.js</conditionProcess>
+      <alias>Data_alias</alias>
+      <recordFieldMappings>
+        <dbRecordFieldMapping>
+          <name>CONTACTID.value</name>
+          <recordfield>CONTACT.CONTACTID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>MIDDLENAME.value</name>
+          <recordfield>PERSON.MIDDLENAME</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>LASTNAME.value</name>
+          <recordfield>CONTACT.CONTACTID</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>FIRSTNAME.value</name>
+          <recordfield>PERSON.FIRSTNAME</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>LETTERSALUTATION.value</name>
+          <recordfield>PERSON.SALUTATION</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>LASTNAME.displayValue</name>
+          <recordfield>PERSON.LASTNAME</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>TITLE.value</name>
+          <recordfield>PERSON.TITLE</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>PICTURE.value</name>
+          <recordfield>PERSON.PICTURE</recordfield>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STANDARD_PHONE_COMMUNICATION.value</name>
+          <expression>%aditoprj%/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js</expression>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STANDARD_EMAIL_COMMUNICATION.value</name>
+          <expression>%aditoprj%/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js</expression>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ORGANISATION_ID.value</name>
+          <expression>%aditoprj%/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/organisation_id.value/expression.js</expression>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STATUS.value</name>
+          <recordfield>CONTACT.STATUS</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STATUS.displayValue</name>
+          <expression>%aditoprj%/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>STANDARD_ADDRESS.value</name>
+          <recordfield>ADDRESS.ADDRESS</recordfield>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>ORGANISATION_ID.displayValue</name>
+          <expression>%aditoprj%/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/organisation_id.displayvalue/expression.js</expression>
+        </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DUPLICATE.value</name>
+          <expression>%aditoprj%/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/duplicate.value/expression.js</expression>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
+      </recordFieldMappings>
+      <linkInformation>
+        <linkInformation>
+          <name>93f86a28-8c69-491e-8f62-79f5840e23a5</name>
+          <tableName>PERSON</tableName>
+          <primaryKey>PERSONID</primaryKey>
+          <isUIDTable v="false" />
+          <readonly v="true" />
+        </linkInformation>
+        <linkInformation>
+          <name>c989f19d-d211-4f54-9ea5-ddf16e5a13a0</name>
+          <tableName>CONTACT</tableName>
+          <primaryKey>CONTACTID</primaryKey>
+          <isUIDTable v="true" />
+          <readonly v="true" />
+        </linkInformation>
+        <linkInformation>
+          <name>7ff69154-f1ff-4e33-8cd4-5a88e3b18269</name>
+          <tableName>ADDRESS</tableName>
+          <primaryKey>ADDRESSID</primaryKey>
+          <isUIDTable v="false" />
+          <readonly v="true" />
+        </linkInformation>
+      </linkInformation>
+    </dbRecordContainer>
+  </recordContainers>
+</entity>
diff --git a/entity/DuplicatePerson_entity/entityfields/filteractions/children/ignoreduplicates/onActionProcess.js b/entity/DuplicatePerson_entity/entityfields/filteractions/children/ignoreduplicates/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..69c03d7bc979275e8276e8bc9700787e0e513f13
--- /dev/null
+++ b/entity/DuplicatePerson_entity/entityfields/filteractions/children/ignoreduplicates/onActionProcess.js
@@ -0,0 +1,7 @@
+import("system.neon");
+import("system.vars");
+import("system.result");
+import("DuplicateScanner_lib");
+
+DuplicateScannerUtils.updateIgnored("Person_entity", vars.get("$param.Id_param"), vars.get("$sys.selection"), parseInt(vars.get("$field.DUPLICATE")));
+neon.refreshAll(); // Update the rows, because UNRELATEDDUPLICATES wont trigger a refresh even with write entities
diff --git a/entity/DuplicatePerson_entity/entityfields/filteractions/children/ignoreduplicates/titleProcess.js b/entity/DuplicatePerson_entity/entityfields/filteractions/children/ignoreduplicates/titleProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c5ccfffeb0e7b5efc940eba237fbdc99ab9b603
--- /dev/null
+++ b/entity/DuplicatePerson_entity/entityfields/filteractions/children/ignoreduplicates/titleProcess.js
@@ -0,0 +1,9 @@
+import("system.translate");
+import("system.vars");
+import("system.result");
+
+result.string(
+    parseInt(vars.get("$field.DUPLICATE")) ?
+    translate.text("${IGNORE_DUPLICATE}") :
+    translate.text("${UNIGNORE_DUPLICATE}")
+);
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js b/entity/DuplicatePerson_entity/entityfields/filteractions/children/mergecurrentintoselected/onActionProcess.js
similarity index 60%
rename from entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js
rename to entity/DuplicatePerson_entity/entityfields/filteractions/children/mergecurrentintoselected/onActionProcess.js
index d5f864db525910dd0635ee2ab84279e3346599b6..8e96e7fcea38ebc093da5fceaaa9ad34a9a5c7a9 100644
--- a/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js
+++ b/entity/DuplicatePerson_entity/entityfields/filteractions/children/mergecurrentintoselected/onActionProcess.js
@@ -1,14 +1,18 @@
+import("system.translate");
+import("system.question");
 import("system.tools");
 import("Employee_lib");
 import("system.vars");
 import("system.neon");
-import("DuplicateScanner_lib");
+import("DuplicateMerge_lib");
 
-var sourceContactId = vars.get("$param.DuplicateCurrentContactId_param");
+if(vars.get("$sys.selection").length == 1)
+{
+var sourceContactId = vars.get("$param.Id_param");
 var targetContactId = vars.get("$sys.selection")[0];
 
 //todo the actual merge ought to happen in a separate view where the contact infos can be merged manually by the user.
-var mergeSuccess = DuplicateScannerUtils.mergePerson(sourceContactId, targetContactId);
+var mergeSuccess = DuplicateMergeUtils.mergePerson(sourceContactId, targetContactId);
 
 if(mergeSuccess)
 {
@@ -21,7 +25,12 @@ if(mergeSuccess)
     var currentContactId = EmployeeUtils.getCurrentContactId();
     if(currentContactId == null)
         currentContactId = "";
-    DuplicateScannerUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Person");
+    DuplicateMergeUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Person");
 
     neon.openContext("Person", "PersonMain_view", [targetContactId], neon.OPERATINGSTATE_VIEW, null)
-}
\ No newline at end of file
+}
+}
+else
+{
+    question.showMessage(translate.text("Please select only one element"));
+}
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js b/entity/DuplicatePerson_entity/entityfields/filteractions/children/mergeselectedintocurrent/onActionProcess.js
similarity index 70%
rename from entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js
rename to entity/DuplicatePerson_entity/entityfields/filteractions/children/mergeselectedintocurrent/onActionProcess.js
index 6a9f2ac39a7238d7dd5fbaec53e41c57eabec241..30d97b1c8023db93074e3cee7b3f30487e920aad 100644
--- a/entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js
+++ b/entity/DuplicatePerson_entity/entityfields/filteractions/children/mergeselectedintocurrent/onActionProcess.js
@@ -1,3 +1,5 @@
+import("system.translate");
+import("system.question");
 import("system.tools");
 import("system.db");
 import("Employee_lib");
@@ -5,14 +7,16 @@ import("KeywordRegistry_basic");
 import("ActivityTask_lib");
 import("system.vars");
 import("system.neon");
-import("DuplicateScanner_lib");
+import("DuplicateMerge_lib");
 
-var targetContactId = vars.get("$param.DuplicateCurrentContactId_param");
+if(vars.get("$sys.selection").length == 1)
+{
+var targetContactId = vars.get("$param.Id_param");
 var sourceContactIdArray = vars.get("$sys.selection");
 var sourceContactId = sourceContactIdArray[0];
 
 //todo the actual merge ought to happen in a separate view where the contact infos can be merged manually by the user.
-var mergeSuccess = DuplicateScannerUtils.mergePerson(sourceContactId, targetContactId);
+var mergeSuccess = DuplicateMergeUtils.mergePerson(sourceContactId, targetContactId);
 
 if(mergeSuccess)
 {
@@ -25,9 +29,14 @@ if(mergeSuccess)
     var currentContactId = EmployeeUtils.getCurrentContactId();
     if(currentContactId == null)
         currentContactId = "";
-    DuplicateScannerUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Person");
+    DuplicateMergeUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Person");
     //neon.refresh() with no fields will refresh the current image (and all sub images) but NOT the preview. neon.refreshAll() would refresh both,
     //why it would lead to an error because it's trying to load the already opened preview of the duplicateContact which just got deleted 
     //and does not exist any more which results in an exception
     neon.refresh();
-}
\ No newline at end of file
+}
+}
+else
+{
+    question.showMessage(translate.text("Please select only one element"));
+}
diff --git a/entity/DuplicatePerson_entity/entityfields/id_param/valueProcess.js b/entity/DuplicatePerson_entity/entityfields/id_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..bffe18eb097c82b9fa662880ad23d5d1ee32f7ff
--- /dev/null
+++ b/entity/DuplicatePerson_entity/entityfields/id_param/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("system.vars");
+
+var jsonObj = JSON.parse(vars.get("$param.Obj_param"));
+result.string(jsonObj["CONTACTID"]);
diff --git a/entity/DuplicatePerson_entity/entityfields/keywordcontactstates/children/containername_param/valueProcess.js b/entity/DuplicatePerson_entity/entityfields/keywordcontactstates/children/containername_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..43e8d27c6a6cdd11f092f8b404a97dc237577a38
--- /dev/null
+++ b/entity/DuplicatePerson_entity/entityfields/keywordcontactstates/children/containername_param/valueProcess.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+result.string($KeywordRegistry.contactStatus());
diff --git a/entity/DuplicatePerson_entity/entityfields/parentcontext/valueProcess.js b/entity/DuplicatePerson_entity/entityfields/parentcontext/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..f7baa76a6be6f585b2829869961b69b1ca4a5e15
--- /dev/null
+++ b/entity/DuplicatePerson_entity/entityfields/parentcontext/valueProcess.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Context_lib");
+
+result.string(ContextUtils.getContextName("Person"));
diff --git a/entity/DuplicatePerson_entity/entityfields/picture/displayValueProcess.js b/entity/DuplicatePerson_entity/entityfields/picture/displayValueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e09fa2ae490ce0756966fd490af0150cc05e726f
--- /dev/null
+++ b/entity/DuplicatePerson_entity/entityfields/picture/displayValueProcess.js
@@ -0,0 +1,11 @@
+import("system.result");
+import("system.vars");
+
+if (vars.get("$field.PICTURE"))
+{
+    result.string(vars.get("$field.PICTURE"));
+}
+else
+{
+    result.string("TEXT:" + (vars.getString("$field.FIRSTNAME") + " " + vars.getString("$field.LASTNAME")).trim());
+}
diff --git a/entity/DuplicatePerson_entity/initFilterProcess.js b/entity/DuplicatePerson_entity/initFilterProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..92797e84dbb193011bf821bb4ecc828681a2d414
--- /dev/null
+++ b/entity/DuplicatePerson_entity/initFilterProcess.js
@@ -0,0 +1,15 @@
+import("system.translate");
+import("system.result");
+
+result.string(JSON.stringify({
+    type: "group",
+    operator: "AND",
+    childs: [{
+        type: "row",
+        name: "DUPLICATE",
+        operator: "EQUAL",
+        contenttype: "BOOLEAN",
+        key: "1",
+        value: translate.text("Yes")
+    }]
+}));
diff --git a/entity/DuplicatePerson_entity/recordcontainers/db/conditionProcess.js b/entity/DuplicatePerson_entity/recordcontainers/db/conditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..658b1af578f9b7fb2d68728d73cef7393c3a7740
--- /dev/null
+++ b/entity/DuplicatePerson_entity/recordcontainers/db/conditionProcess.js
@@ -0,0 +1,8 @@
+import("system.vars");
+import("Sql_lib");
+import("DuplicateScanner_lib");
+import("system.result");
+
+var duplicateIds = DuplicateScannerUtils.getDuplicateIdsByEntityObj("Person_entity", JSON.parse(vars.get("$param.Obj_param")));
+duplicateIds.push("-"); // workaround empty arrays
+result.string(newWhere("CONTACT.CONTACTID", duplicateIds, SqlBuilder.IN()).toString());
diff --git a/entity/DuplicatePerson_entity/recordcontainers/db/fromClauseProcess.js b/entity/DuplicatePerson_entity/recordcontainers/db/fromClauseProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..2205f0c5af7cbe0439abdf3017bae42b6e9be2cd
--- /dev/null
+++ b/entity/DuplicatePerson_entity/recordcontainers/db/fromClauseProcess.js
@@ -0,0 +1,14 @@
+import("Sql_lib");
+import("system.vars");
+import("system.result");
+
+var unrelatedCondition = newWhere("UNRELATEDDUPLICATES.DUPLICATETYPE", "Person_entity")
+    .and("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", vars.get("$param.Id_param"))
+    .and("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID = CONTACT.CONTACTID");
+
+result.string(
+    "PERSON " +
+    "join CONTACT on (PERSON.PERSONID = CONTACT.PERSON_ID) " +
+    "left join ADDRESS on (ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID) " +
+    "left join UNRELATEDDUPLICATES on " + unrelatedCondition.toString()
+);
diff --git a/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/duplicate.value/expression.js b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/duplicate.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..8f7063b2ac8e637e6618ccc1ff745653daf0b339
--- /dev/null
+++ b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/duplicate.value/expression.js
@@ -0,0 +1,7 @@
+import("system.result");
+import("Sql_lib");
+
+var statement = SqlBuilder.caseStatement()
+    .when("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID is not null")
+    .thenString("0").elseString("1");
+result.string(statement);
diff --git a/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/organisation_id.displayvalue/expression.js b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/organisation_id.displayvalue/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..64f71be666b2bbb3421d182e2fe8b25d989a3316
--- /dev/null
+++ b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/organisation_id.displayvalue/expression.js
@@ -0,0 +1,5 @@
+import("Sql_lib");
+import("system.result");
+
+result.string(newSelect("ORGANISATION.NAME").from("ORGANISATION")
+    .where("ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID").toString());
diff --git a/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/organisation_id.value/expression.js b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/organisation_id.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..e37273248e57bcb47a83af87693aa9cca2ed5636
--- /dev/null
+++ b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/organisation_id.value/expression.js
@@ -0,0 +1,6 @@
+import("system.result");
+import("Sql_lib");
+
+result.string(newSelect("c.CONTACTID").from("CONTACT as c")
+    .where("c.ORGANISATION_ID = CONTACT.ORGANISATION_ID")
+    .and("c.PERSON_ID is null").toString());
diff --git a/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..5827c59c416c332ba9281a60756f919fcb75c0a2
--- /dev/null
+++ b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Communication_lib");
+
+result.string(CommUtil.getStandardSubSqlMail());
diff --git a/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f438c2535b21180c5ad03637de90f577f2c736e
--- /dev/null
+++ b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js
@@ -0,0 +1,4 @@
+import("system.result");
+import("Communication_lib");
+
+result.string(CommUtil.getStandardSubSqlPhone());
diff --git a/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..50433a35e5f298cf550485a4d9ea33ac405a6ebd
--- /dev/null
+++ b/entity/DuplicatePerson_entity/recordcontainers/db/recordfieldmappings/status.displayvalue/expression.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Keyword_lib");
+import("KeywordRegistry_basic");
+
+result.string(KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.contactStatus(), "CONTACT.STATUS"));
diff --git a/entity/DuplicateScannerPrefilterConfig_entity/recordcontainers/dbrecordcontainer/conditionProcess.js b/entity/DuplicateScannerPrefilterConfig_entity/recordcontainers/dbrecordcontainer/conditionProcess.js
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/entity/DuplicateScannerResultFieldConfig_entity/DuplicateScannerResultFieldConfig_entity.aod b/entity/DuplicateScannerResultFieldConfig_entity/DuplicateScannerResultFieldConfig_entity.aod
deleted file mode 100644
index b336a59f809d6d5834741fc16f8a6034815597b2..0000000000000000000000000000000000000000
--- a/entity/DuplicateScannerResultFieldConfig_entity/DuplicateScannerResultFieldConfig_entity.aod
+++ /dev/null
@@ -1,104 +0,0 @@
-<?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>DuplicateScannerResultFieldConfig_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <recordContainer>recordContainer</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>UID</name>
-    </entityField>
-    <entityField>
-      <name>ENTITY_FIELD_NAME</name>
-      <title>Entity field name</title>
-    </entityField>
-    <entityField>
-      <name>DATE_EDIT</name>
-      <valueProcess>%aditoprj%/entity/DuplicateScannerResultFieldConfig_entity/entityfields/date_edit/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>DATE_NEW</name>
-      <valueProcess>%aditoprj%/entity/DuplicateScannerResultFieldConfig_entity/entityfields/date_new/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>USER_NEW</name>
-      <valueProcess>%aditoprj%/entity/DuplicateScannerResultFieldConfig_entity/entityfields/user_new/valueProcess.js</valueProcess>
-    </entityField>
-    <entityField>
-      <name>USER_EDIT</name>
-      <valueProcess>%aditoprj%/entity/DuplicateScannerResultFieldConfig_entity/entityfields/user_edit/valueProcess.js</valueProcess>
-    </entityField>
-    <entityParameter>
-      <name>DuplicateScannerId_param</name>
-      <expose v="true" />
-      <mandatory v="true" />
-    </entityParameter>
-    <entityProvider>
-      <name>ScannerResultFieldConfigProvider</name>
-      <dependencies>
-        <entityDependency>
-          <name>119b48a5-ce78-4169-bd31-76e524cece99</name>
-          <entityName>DuplicateScanner_entity</entityName>
-          <fieldName>ScannerResultFieldsConfig_Consumer</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-    </entityProvider>
-    <entityField>
-      <name>DUPLICATESCANNER_ID</name>
-      <valueProcess>%aditoprj%/entity/DuplicateScannerResultFieldConfig_entity/entityfields/duplicatescanner_id/valueProcess.js</valueProcess>
-    </entityField>
-    <entityProvider>
-      <name>#PROVIDER_AGGREGATES</name>
-      <useAggregates v="true" />
-    </entityProvider>
-  </entityFields>
-  <recordContainers>
-    <dbRecordContainer>
-      <name>recordContainer</name>
-      <conditionProcess>%aditoprj%/entity/DuplicateScannerResultFieldConfig_entity/recordcontainers/recordcontainer/conditionProcess.js</conditionProcess>
-      <alias>Data_alias</alias>
-      <recordFieldMappings>
-        <dbRecordFieldMapping>
-          <name>DATE_EDIT.value</name>
-          <recordfield>DUPLICATESCANNERRESULTFIELDCONFIG.DATE_EDIT</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DATE_NEW.value</name>
-          <recordfield>DUPLICATESCANNERRESULTFIELDCONFIG.DATE_NEW</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>ENTITY_FIELD_NAME.value</name>
-          <recordfield>DUPLICATESCANNERRESULTFIELDCONFIG.ENTITY_FIELD_NAME</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>UID.value</name>
-          <recordfield>DUPLICATESCANNERRESULTFIELDCONFIG.ID</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>USER_EDIT.value</name>
-          <recordfield>DUPLICATESCANNERRESULTFIELDCONFIG.USER_EDIT</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>USER_NEW.value</name>
-          <recordfield>DUPLICATESCANNERRESULTFIELDCONFIG.USER_NEW</recordfield>
-        </dbRecordFieldMapping>
-        <dbRecordFieldMapping>
-          <name>DUPLICATESCANNER_ID.value</name>
-          <recordfield>DUPLICATESCANNERRESULTFIELDCONFIG.DUPLICATESCANNER_ID</recordfield>
-        </dbRecordFieldMapping>
-      </recordFieldMappings>
-      <linkInformation>
-        <linkInformation>
-          <name>f7126f94-9e4c-46a0-8dc9-9e52fda1c7c0</name>
-          <tableName>DUPLICATESCANNERRESULTFIELDCONFIG</tableName>
-          <primaryKey>ID</primaryKey>
-          <isUIDTable v="false" />
-          <readonly v="false" />
-        </linkInformation>
-      </linkInformation>
-    </dbRecordContainer>
-  </recordContainers>
-</entity>
diff --git a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/date_edit/valueProcess.js b/entity/DuplicateScannerResultFieldConfig_entity/entityfields/date_edit/valueProcess.js
deleted file mode 100644
index 5e6ef059738e0c724a468685333a5e257ac228ce..0000000000000000000000000000000000000000
--- a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/date_edit/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.util");
-import("system.result");
-import("system.neon");
-import("system.vars");
-
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
-    result.string(vars.get("$sys.date"));
\ No newline at end of file
diff --git a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/date_new/valueProcess.js b/entity/DuplicateScannerResultFieldConfig_entity/entityfields/date_new/valueProcess.js
deleted file mode 100644
index a72892783bf2bd04fe353c47f1be0cb570bbb323..0000000000000000000000000000000000000000
--- a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/date_new/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.util");
-import("system.result");
-import("system.neon");
-import("system.vars");
-
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
-    result.string(vars.get("$sys.date"));
\ No newline at end of file
diff --git a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/duplicatescanner_id/valueProcess.js b/entity/DuplicateScannerResultFieldConfig_entity/entityfields/duplicatescanner_id/valueProcess.js
deleted file mode 100644
index b8c682ad670116ff553d3774001f92eeec9478ce..0000000000000000000000000000000000000000
--- a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/duplicatescanner_id/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.result");
-import("system.vars");
-
-if(vars.get("$this.value") == null || vars.get("$this.value") == "")
-{
-    result.string(vars.get("$param.DuplicateScannerId_param"));
-}
\ No newline at end of file
diff --git a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/user_edit/valueProcess.js b/entity/DuplicateScannerResultFieldConfig_entity/entityfields/user_edit/valueProcess.js
deleted file mode 100644
index 6af880ae3e0e2b89b4eee8327ed49f1eefe458af..0000000000000000000000000000000000000000
--- a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/user_edit/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.util");
-import("system.result");
-import("system.neon");
-import("system.vars");
-
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_EDIT)
-    result.string(vars.get("$sys.user"));
\ No newline at end of file
diff --git a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/user_new/valueProcess.js b/entity/DuplicateScannerResultFieldConfig_entity/entityfields/user_new/valueProcess.js
deleted file mode 100644
index e518bc75a9494e53a83613dedd943106e74fc00a..0000000000000000000000000000000000000000
--- a/entity/DuplicateScannerResultFieldConfig_entity/entityfields/user_new/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.util");
-import("system.result");
-import("system.neon");
-import("system.vars");
-
-if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
-    result.string(vars.get("$sys.user"));
\ No newline at end of file
diff --git a/entity/DuplicateScannerResultFieldConfig_entity/recordcontainers/recordcontainer/conditionProcess.js b/entity/DuplicateScannerResultFieldConfig_entity/recordcontainers/recordcontainer/conditionProcess.js
deleted file mode 100644
index b9bff609c91222abb6c3b0292492600907585487..0000000000000000000000000000000000000000
--- a/entity/DuplicateScannerResultFieldConfig_entity/recordcontainers/recordcontainer/conditionProcess.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import("system.vars");
-import("system.result");
-
-if (vars.get("$param.DuplicateScannerId_param"))
-    result.string(newWhere("DUPLICATESCANNERRESULTFIELDCONFIG.DUPLICATESCANNER_ID", "$param.DuplicateScannerId_param").toString());
\ No newline at end of file
diff --git a/entity/DuplicateScanner_entity/DuplicateScanner_entity.aod b/entity/DuplicateScanner_entity/DuplicateScanner_entity.aod
index 34fb0577dfe0c9ee42cc2f58458267359bd8f094..220ca8da86b7ff352ba94fa259602a9f004e9585 100644
--- a/entity/DuplicateScanner_entity/DuplicateScanner_entity.aod
+++ b/entity/DuplicateScanner_entity/DuplicateScanner_entity.aod
@@ -33,16 +33,6 @@
       <contentType>BOOLEAN</contentType>
       <valueProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/external_service_usage_allowed/valueProcess.js</valueProcess>
     </entityField>
-    <entityActionGroup>
-      <name>TestActionGroup</name>
-      <children>
-        <entityActionField>
-          <name>TestDuplicateScanner</name>
-          <title>Test DuplicateSearch</title>
-          <onActionProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/testactiongroup/children/testduplicatescanner/onActionProcess.js</onActionProcess>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
     <entityField>
       <name>USER_NEW</name>
       <valueProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/user_new/valueProcess.js</valueProcess>
@@ -71,40 +61,36 @@
       <state>AUTO</state>
       <stateProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/scan_pattern/stateProcess.js</stateProcess>
     </entityField>
-    <entityConsumer>
-      <name>ScannerResultFieldsConfig_Consumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>DuplicateScannerResultFieldConfig_entity</entityName>
-        <fieldName>ScannerResultFieldConfigProvider</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>DuplicateScannerId_param</name>
-          <valueProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/scannerresultfieldsconfig_consumer/children/duplicatescannerid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
+    <entityProvider>
+      <name>#PROVIDER_AGGREGATES</name>
+      <useAggregates v="true" />
+    </entityProvider>
     <entityActionGroup>
-      <name>RunActionGroup</name>
-      <documentation>%aditoprj%/entity/DuplicateScanner_entity/entityfields/runactiongroup/documentation.adoc</documentation>
+      <name>FilterActions</name>
       <children>
         <entityActionField>
-          <name>RebuildPersonDuplicatesCache</name>
-          <title>Rebuild Person duplicates cache</title>
-          <onActionProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildpersonduplicatescache/onActionProcess.js</onActionProcess>
+          <name>rebuild</name>
+          <title>Rebuild selected entries</title>
+          <onActionProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/filteractions/children/rebuild/onActionProcess.js</onActionProcess>
+          <isObjectAction v="false" />
+          <isSelectionAction v="true" />
+          <iconId>VAADIN:CALC</iconId>
+          <tooltip>Rebuild all duplicates from the selected scanners</tooltip>
         </entityActionField>
         <entityActionField>
-          <name>RebuildOrganisationDuplicatesCache</name>
-          <title>Rebuild Organisation duplicates cache</title>
-          <onActionProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildorganisationduplicatescache/onActionProcess.js</onActionProcess>
+          <name>viewDuplicates</name>
+          <title>View duplicates</title>
+          <onActionProcess>%aditoprj%/entity/DuplicateScanner_entity/entityfields/filteractions/children/viewduplicates/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+          <iconId>VAADIN:TABLE</iconId>
+          <tooltip>View all duplicates from this scanner</tooltip>
         </entityActionField>
       </children>
     </entityActionGroup>
-    <entityProvider>
-      <name>#PROVIDER_AGGREGATES</name>
-      <useAggregates v="true" />
-    </entityProvider>
+    <entityField>
+      <name>DUPLICATECOUNT</name>
+      <title>Count</title>
+    </entityField>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
@@ -154,6 +140,11 @@
           <name>SCAN_PATTERN.value</name>
           <recordfield>DUPLICATESCANNER.SCAN_PATTERN</recordfield>
         </dbRecordFieldMapping>
+        <dbRecordFieldMapping>
+          <name>DUPLICATECOUNT.value</name>
+          <expression>%aditoprj%/entity/DuplicateScanner_entity/recordcontainers/dbrecordcontainer/recordfieldmappings/duplicatecount.value/expression.js</expression>
+          <isFilterable v="true" />
+        </dbRecordFieldMapping>
       </recordFieldMappings>
       <linkInformation>
         <linkInformation>
diff --git a/entity/DuplicateScanner_entity/entityfields/filteractions/children/rebuild/onActionProcess.js b/entity/DuplicateScanner_entity/entityfields/filteractions/children/rebuild/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..fc6ae65d2d318b7ba951ae069442ed54db022857
--- /dev/null
+++ b/entity/DuplicateScanner_entity/entityfields/filteractions/children/rebuild/onActionProcess.js
@@ -0,0 +1,34 @@
+import("system.process");
+import("system.logging");
+import("system.entities");
+import("system.vars");
+import("DuplicateScanner_lib");
+
+var selectedIds = vars.get("$sys.selection");
+var loadConfig = entities.createConfigForLoadingRows()
+    .entity("DuplicateScanner_entity")
+    .uids(selectedIds)
+    .fields(["FILTER_NAME", "ENTITY_TO_SCAN_NAME", "ID_FIELD_NAME", "SCAN_PATTERN"]);
+var selectedEntries = entities.getRows(loadConfig);
+logging.log("Rebuilding " + selectedEntries.length + " entries");
+
+selectedEntries.forEach(function(currEntry)
+{
+    var filterName = currEntry["FILTER_NAME"];
+    var targetEntity = currEntry["ENTITY_TO_SCAN_NAME"];
+    var targetIdField = currEntry["ID_FIELD_NAME"];
+    var filter = JSON.parse(currEntry["SCAN_PATTERN"]);
+    
+    var startConfig = process.createStartAsyncConfig()
+    .setName("rebuildDuplicates_serverProcess")
+    .setShowErrorDialog(true)
+    .setLocalVariables({
+        filterName: filterName,
+        targetEntity: targetEntity,
+        targetIdField: targetIdField,
+        filter: JSON.stringify(filter.filter)
+    })
+    .setUser(vars.get("$sys.user"))
+    .setTimerType(process.TIMERTYPE_SERVER);
+    process.startAsync(startConfig);
+});
diff --git a/entity/DuplicateScanner_entity/entityfields/filteractions/children/viewduplicates/onActionProcess.js b/entity/DuplicateScanner_entity/entityfields/filteractions/children/viewduplicates/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..064e1f6c17fd9f84dc46723d329baf5a181ddc6d
--- /dev/null
+++ b/entity/DuplicateScanner_entity/entityfields/filteractions/children/viewduplicates/onActionProcess.js
@@ -0,0 +1,35 @@
+import("system.translate");
+import("system.question");
+import("system.vars");
+import("system.neon");
+import("system.entities");
+import("Context_lib");
+
+if(vars.get("$sys.selection").length == 1)
+{
+    var config = entities.createConfigForLoadingRows()
+        .entity("DuplicateScanner_entity")
+        .uid(vars.get("$sys.selection")[0])
+        .fields(["ENTITY_TO_SCAN_NAME"]);
+    var scanner = entities.getRow(config);
+    var contextId = ContextUtils.getContextName(ContextUtils.getContextId(scanner["ENTITY_TO_SCAN_NAME"]));
+
+    neon.openContext(contextId, null, null, neon.OPERATINGSTATE_SEARCH, {
+        FilterPreSet_param: JSON.stringify({
+            type: "group",
+            operator: "AND",
+            childs: [{
+                type: "row",
+                name: "#EXTENSION.Duplicates_filter.Duplicates_filter#NUMBER",
+                operator: "GREATER",
+                value: "All Duplicates",
+                key: "0",
+                contenttype: "NUMBER"
+            }]
+        })
+    });
+}
+else
+{
+    question.showMessage(translate.text("Please select only one element"));
+}
diff --git a/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildorganisationduplicatescache/onActionProcess.js b/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildorganisationduplicatescache/onActionProcess.js
deleted file mode 100644
index e391b4c1938da96eddca596f8fb2211dd3d681ab..0000000000000000000000000000000000000000
--- a/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildorganisationduplicatescache/onActionProcess.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import("system.logging");
-import("system.logging");
-import("DuplicateScanner_lib");
-
-var filterName = "OrganisationDuplicates";
-var targetEntity = "Organisation_entity";
-var recordBlockSize = DuplicateScannerUtils.getBlockSize();
-
-logging.log(filterName + ": Delete duplicates -> ");
-DuplicateScannerUtils.deleteClustersByTargetEntity(targetEntity);
-
-logging.log(filterName + ": Recalculate duplicates -> ");
-DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, recordBlockSize, null);
-
-logging.log(filterName + ": Refresh unrelated duplicates -> ");
-DuplicateScannerUtils.refreshUnrelatedDuplicateRelations(targetEntity);
-
-logging.log(filterName + ": Done rebuilding ");
\ No newline at end of file
diff --git a/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildpersonduplicatescache/onActionProcess.js b/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildpersonduplicatescache/onActionProcess.js
deleted file mode 100644
index cad8736382338846edff77ef164f85488513731d..0000000000000000000000000000000000000000
--- a/entity/DuplicateScanner_entity/entityfields/runactiongroup/children/rebuildpersonduplicatescache/onActionProcess.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import("system.project");
-import("system.logging");
-import("DuplicateScanner_lib");
-
-var filterName = "PersonDuplicates";
-var targetEntity = "Person_entity";
-var recordBlockSize = DuplicateScannerUtils.getBlockSize();
-
-logging.log(filterName + ": Delete duplicates -> ");
-DuplicateScannerUtils.deleteClustersByTargetEntity(targetEntity);
-
-logging.log(filterName + ": Recalculate duplicates -> ");
-DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, recordBlockSize, null);
-
-logging.log(filterName + ": Refresh unrelated duplicates -> ");
-DuplicateScannerUtils.refreshUnrelatedDuplicateRelations(targetEntity);
-
-logging.log(filterName + ": Done rebuilding ");
\ No newline at end of file
diff --git a/entity/DuplicateScanner_entity/entityfields/runactiongroup/documentation.adoc b/entity/DuplicateScanner_entity/entityfields/runactiongroup/documentation.adoc
deleted file mode 100644
index f998dfcc78c6497f121cd16b294c8d01e6e1c1c7..0000000000000000000000000000000000000000
--- a/entity/DuplicateScanner_entity/entityfields/runactiongroup/documentation.adoc
+++ /dev/null
@@ -1 +0,0 @@
-Since duplicate caching is disabled there is no need  to show this action group within views at the moment.
\ No newline at end of file
diff --git a/entity/DuplicateScanner_entity/entityfields/scannerresultfieldsconfig_consumer/children/duplicatescannerid_param/valueProcess.js b/entity/DuplicateScanner_entity/entityfields/scannerresultfieldsconfig_consumer/children/duplicatescannerid_param/valueProcess.js
deleted file mode 100644
index 3c559d42002c59103607e03f79eb792d99d74d31..0000000000000000000000000000000000000000
--- a/entity/DuplicateScanner_entity/entityfields/scannerresultfieldsconfig_consumer/children/duplicatescannerid_param/valueProcess.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import("system.vars");
-import("system.result");
-result.string(vars.get("$field.UID"));
\ No newline at end of file
diff --git a/entity/DuplicateScanner_entity/entityfields/testactiongroup/children/testduplicatescanner/onActionProcess.js b/entity/DuplicateScanner_entity/entityfields/testactiongroup/children/testduplicatescanner/onActionProcess.js
deleted file mode 100644
index af7cd56a2472c2305bf914b22fc59c89a7ba03a8..0000000000000000000000000000000000000000
--- a/entity/DuplicateScanner_entity/entityfields/testactiongroup/children/testduplicatescanner/onActionProcess.js
+++ /dev/null
@@ -1,432 +0,0 @@
-import("system.process");
-import("KeywordRegistry_basic");
-import("system.db");
-import("ActivityTask_lib");
-import("Employee_lib");
-import("system.util");
-import("system.notification");
-import("system.notificationtypes");
-import("system.entities");
-import("system.project");
-import("system.indexsearch");
-import("system.question");
-import("system.logging");
-import("DuplicateScanner_lib");
-import("JditoFilter_lib");
-
-//let testFields = [];
-//let filters = DuplicateScannerUtils.loadFilters("PersonDuplicates", "Person_entity")
-//logging.log("filters -> " + filters);
-//
-//for (let i = 0; i < filters.length; i++) 
-//{
-//    logging.log("filters[i] -> " + filters[i]);
-//    let filter = JSON.parse(filters[i][0]).filter;
-//    let fields = JditoFilterUtils.getFilterFields(filter.childs);
-//    testFields = testFields.concat(fields);
-//}
-//logging.log("testFields -> " + testFields);
-
-
-//##############################Test Duplicate Scan######################################################
-
-//var filterName = "PersonDuplicates";
-//var targetEntity = "Person_entity";
-//var resultFieldsIdFieldName = "CONTACTID";
-//
-//var tmpFieldsInFilterRay = ["CONTACTID", "FIRSTNAME", "LASTNAME", "GENDER"];
-//var queryPersonContactIds = "select CONTACTID, FIRSTNAME, LASTNAME, GENDER from CONTACT"
-//                            + " join PERSON on PERSONID = PERSON_ID";
-//
-//
-//var filterFieldValueRays = [["CONTACTID", "29271db0-4253-46c9-b7c2-5e25376b9d19"], ["FIRSTNAME", "Narkus"], ["LASTNAME", "Bltinger"], ["GENDER", "m"]];
-//
-////DuplicateScannerUtils.ScanForDuplicatesIndex = function(pFilterName, pTargetEntity, pFilterFieldValueRays,
-////pTargetEntityResultFields, pRecordIdFieldToIgnore, pRecordIdValueToIgnore)
-//
-///* 
-// * 
-// */
-//
-//
-//
-//let duplicateFieldsConfig = DuplicateScannerUtils.LoadDuplicateIndexFieldsConfiguration(filterName, targetEntity);
-//
-//let querySelectFields = "";
-//for (let i = 0; i < duplicateFieldsConfig.length; i++) 
-//{
-//    querySelectFields += duplicateFieldsConfig[i][0];
-//    
-//    if(i < duplicateFieldsConfig.length)
-//        querySelectFields += ", ";
-//}
-//
-//let queryPersonFieldData = "select " + querySelectFields + " from CONTACT"
-//                            + " join PERSON on PERSONID = PERSON_ID";
-//
-//DuplicateScannerUtils.GetEntityFieldNameValueMap(duplicateFieldsConfig);
-//
-//DuplicateScannerUtils.ScanForDuplicatesIndex(filterName, targetEntity, 
-//filterFieldValueRays, [], resultFieldsIdFieldName, "29271db0-4253-46c9-b7c2-5e25376b9d19");
-
-
-//##############################ANs Beispiel######################################################
-
-
-//logging.log("TEST INDEX API with Entities");
-//logging.log(indexsearch.lookupIndexField("Person_entity", "FIRSTNAME"));
-//logging.log(indexsearch.lookupIndexField("Person_entity", "FIRSTNAME.value"));
-//logging.log(indexsearch.lookupIndexField("Person_entity", "PersAddresses.CITY"));
-//logging.log(indexsearch.lookupIndexField("Person_entity", "PersAddresses.CITY.value"));
-//logging.log(indexsearch.lookupIndexField(null, "Person_entity.FIRSTNAME.value"));
-//logging.log(indexsearch.lookupIndexField(null, "Person_entity.PersAddresses.CITY.value"));
-//var json = '{"entity":"Person_entity","filter":{"type":"group","operator":"AND","childs":[{"type":"row","name":"FIRSTNAME","operator":"STARTSWITH","value":"asd","key":"","contenttype":"TEXT"},{"type":"group","operator":"OR","childs":[{"type":"row","name":"LASTNAME","operator":"STARTSWITH","value":"L","key":"","contenttype":"TEXT"}]}]}}';
-//logging.log(indexsearch.buildQueryFromSearchCondition(json));
-//
-//var t1 = indexsearch.createTerm("lisa").setEntityField("Person_entity.FIRSTNAME");
-//var t2 = indexsearch.createTerm("sommer").setEntityField("Person_entity.LASTNAME");
-//var t3 = indexsearch.createWildcardTerm("L").setEntityField("Person_entity.PersAddresses.CITY");
-//
-//var patternConf = indexsearch.createPatternConfig().or(t1).or(t2).or(t3);
-//var pattern = indexsearch.buildPatternString(patternConf);
-//logging.log(pattern); 
-//
-//var query = indexsearch.createIndexQuery()
-//.setPattern(pattern)
-//.setEntities("Person_entity")
-////.addResultIndexFields(indexsearch.FIELD_ID)
-//.addResultFields("Person_entity.FIRSTNAME")
-//.addSearchFields("Person_entity.FIRSTNAME", "Person_entity.LASTNAME");
-//
-//var res = indexsearch.searchIndex(query);
-//logging.log("" + res);
-
-
-
-//######################################Demosuche nach Datensatz##############################################
-
-
-
-
-//
-//let indexQuery = indexsearch.createIndexQuery()
-//                            .setPattern("(+(-contactid_value:(29271db0-4253-46c9-b7c2-5e25376b9d19)) +gender_value:m*)")
-//                            .setEntities(["Person_entity"])
-//                            .addResultFields("Person_entity.FIRSTNAME")
-//                            .setRows(50);
-//
-//
-//let filterTerm1 = indexsearch.createTerm("Barkus")
-//                            .setIndexField("firstname_value")
-//                            .setFuzzySearchFactor(0);
-////let filterTerm2 = indexsearch.createTerm("Altinger")
-////                            .setIndexField("lastname_value")
-////                            .setFuzzySearchFactor(0);
-//
-//let filterPatternConfig = indexsearch.createPatternConfig().and(filterTerm1);
-//
-//let filterPatternString = indexsearch.buildPatternString(filterPatternConfig);
-//logging.log("Hauptsuche filterPatternString -> " + filterPatternString);
-//indexQuery = indexQuery.addFilter(filterPatternString);
-//
-//let searchResult = indexsearch.searchIndex(indexQuery);
-//logging.log("searchResult -> " + searchResult);
-//
-//logging.log("searchResults hits length -> " + searchResult[indexsearch.HITS].length);
-//
-//for (let i = 0; i < searchResult[indexsearch.HITS].length; i++) 
-//{
-//    logging.log("Treffer Nr -> " + i);
-//    //searchResults hits 0 -> {#ADITO_SEARCH_ID=1868bd3a-05af-4b7f-a633-e3aec50ac45c, _index_group_=Person, #ADITO_SEARCH_TYPE=Person, firstname_value=Peter, _local_id_=1868bd3a-05af-4b7f-a633-e3aec50ac45c}
-//    let localId = searchResult[indexsearch.HITS][i]["_local_id_"];
-//    let firstname = searchResult[indexsearch.HITS][i]["firstname_value"];
-//    let indexGroup = searchResult[indexsearch.HITS][i]["_index_group_"];
-//    logging.log("localId -> " + localId);
-//    logging.log("firstname -> " + firstname);
-//    logging.log("indexGroup -> " + indexGroup);
-//}
-
-
-
-
-
-//####################################################################################
-
-
-//
-//var filterName = "PersonDuplicates";
-//var targetEntity = "Person_entity";
-//var resultFieldsIdFieldName = "CONTACTID";
-//var queryPersonContactIds = "select CONTACTID, FIRSTNAME, LASTNAME, GENDER from CONTACT"
-//                            + " join PERSON on PERSONID = PERSON_ID";
-//var tmpFieldsInFilterRay = ["CONTACTID", "FIRSTNAME", "LASTNAME", "GENDER"];
-//
-//logging.log("Löschen von PERSON Dubletten -> ");
-//DuplicateScannerUtils.deleteClustersByTargetEntity("Person_entity");
-//
-//logging.log("Neu berechnen von PERSON Dubletten -> ");
-//DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, queryPersonContactIds,
-//tmpFieldsInFilterRay, resultFieldsIdFieldName);
-//
-//DuplicateScannerUtils.refreshUnrelatedDuplicateRelations(targetEntity);
-
-//##############################################################################
-
-//filterName = "OrganisationDuplicates";
-//targetEntity = "Organisation_entity";
-//resultFieldsIdFieldName = "CONTACTID";
-//queryPersonContactIds = "select CONTACTID, ORGANISATION.NAME from ORGANISATION"
-//                            + " join CONTACT on CONTACT.CONTACTID = ORGANISATION.ORGANISATIONID"
-//                            + " where CONTACTID != '0'";
-//tmpFieldsInFilterRay = ["CONTACTID", "NAME"];
-//
-//
-//logging.log("Löschen von ORGANISATION Dubletten -> ");
-//DuplicateScannerUtils.deleteClustersByTargetEntity(targetEntity)
-//
-//logging.log("Neu berechnen von ORGANISATION Dubletten -> ");
-//DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, queryPersonContactIds,
-//tmpFieldsInFilterRay, resultFieldsIdFieldName);
-//
-//DuplicateScannerUtils.refreshUnrelatedDuplicateRelations(targetEntity);
-
-
-//####################################Rebuild person duplicates##########################################
-
-//var filterName = "PersonDuplicates";
-//var targetEntity = "Person_entity";
-//
-//let duplicateFieldsConfig = DuplicateScannerUtils.LoadIndexFieldsConfiguration(filterName, targetEntity);
-//let resultFields = DuplicateScannerUtils.getResultFields(filterName, targetEntity);
-//
-//logging.log("duplicateFieldsConfig -> " + duplicateFieldsConfig);
-//logging.log("resultFields -> " + resultFields);
-//
-//let querySelectFields = DuplicateScannerUtils.BuildSqlSelectFieldsFromFieldConfig(duplicateFieldsConfig);
-//logging.log("querySelectFields -> " + querySelectFields);
-//
-//let queryPersonFieldData = "select " + querySelectFields + " from CONTACT"
-//                            + " join PERSON on PERSONID = PERSON_ID"
-//                            + " left join ADDRESS on ADDRESS.CONTACT_ID = CONTACT.CONTACTID";
-//
-//logging.log("Löschen von PERSON Dubletten -> ");
-//DuplicateScannerUtils.deleteClustersByTargetEntity(targetEntity);
-//
-//let formatToJsonAndCallWsCallback = function(pPossibleDuplicatesRay)
-//{
-//    let indexResultFields = DuplicateScannerUtils.translateEntityToIndexFields(targetEntity, resultFields)
-//
-//    //Run thru every duplicate result an read out the resultfields
-//    for (let i = 0; i < pPossibleDuplicatesRay.length; i++)
-//    {
-//        for (let b = 0; b < resultFields.length; b++)
-//        {
-//            let entityFieldName = resultFields[b];
-//            let indexFieldName = indexResultFields[entityFieldName];
-//            //logging.log("Entity Field -> "+ pPossibleDuplicatesRay[i][indexFieldName]);
-//            //format values
-//        }
-//    }
-//    //call webservice
-//    //reformat results to same structure as before
-//    return pPossibleDuplicatesRay;
-//};
-//
-//logging.log("Neu berechnen von PERSON Dubletten -> ");
-//DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, queryPersonFieldData,
-//duplicateFieldsConfig, resultFields, formatToJsonAndCallWsCallback);
-//
-//DuplicateScannerUtils.refreshUnrelatedDuplicateRelations(targetEntity);
-
-
-
-
-
-//##################################single scanForDuplicates#######################################################################
-
-
-//var filterName = "PersonDuplicates";
-//var targetEntity = "Person_entity";
-//
-////Values to check, the same fields as configured
-//let valuesToCheck = {};
-//valuesToCheck["CONTACTID"] = "c7ddf982-0e58-4152-b82b-8f5673b0b729";
-//valuesToCheck["FIRSTNAME"] = "Tim";
-//valuesToCheck["GENDER"] = "m                                   ";
-//
-////The result values can be accessed as seen above in "formatToJsonAndCallWsCallback"
-//let pPossibleDuplicatesRay = DuplicateScannerUtils.scanForDuplicates(filterName, targetEntity, valuesToCheck, null);
-//
-//logging.log(" pPossibleDuplicatesRay-> " + pPossibleDuplicatesRay);
-//
-//for (let i = 0; i < pPossibleDuplicatesRay.length; i++) 
-//{
-//    logging.log("pPossibleDuplicatesRay[i] -> " + pPossibleDuplicatesRay[i]);
-//}
-//
-
-
-//################################ entity structure auslesen ##############################################
-
-
-//var model = project.getEntityStructure("Person_entity"); 
-//logging.log("Name: " + model.name); 
-//logging.log("Title: " + model.title); 
-//logging.log("Description: " + model.description); 
-//logging.log("UsePermissions: " + model.usePermissions); 
-//
-//for (fieldname in model.fields) 
-//{ 
-//    field = model.fields[fieldname]; 
-//    if(field.fieldType == project.ENTITYFIELDTYPE_FIELD)
-//    {
-//        logging.log(" Name: " + field.name); 
-//        logging.log(" Type: " + field.fieldType); 
-//        logging.log(" Title: " + field.title); 
-//        logging.log(" Description: " + field.description); 
-//        logging.log(" UsePermissions: " + field.usePermissions); 
-//        logging.log("###################### -> ");
-//    }
-//    if(field.fieldType == project.ENTITYFIELDTYPE_CONSUMER)
-//    {
-//        let consumerEntity = field.entityName;
-//        
-//        if(consumerEntity == null || consumerEntity == "")
-//            continue;
-//        
-//        let consumerEntityFields = project.getEntityStructure(consumerEntity);
-//        for (consumerEntityFieldname in consumerEntityFields.fields) 
-//        { 
-//            consumerField = consumerEntityFields.fields[consumerEntityFieldname]; 
-//            if(consumerField.fieldType == project.ENTITYFIELDTYPE_FIELD)
-//            {
-//                logging.log(" Name: " + consumerField.name); 
-//                logging.log(" Type: " + consumerField.fieldType); 
-//                logging.log(" Title: " + consumerField.title); 
-//                logging.log(" Description: " + consumerField.description); 
-//                logging.log(" UsePermissions: " + consumerField.usePermissions); 
-//                logging.log("###################### -> ");
-//            }
-//        }
-//    }
-//}
-
-//##############################################################################
-
-//var model = project.getEntityStructure("Person_entity"); 
-//let duplicateFieldsConfig = DuplicateScannerUtils.LoadIndexFieldsConfiguration(filterName, targetEntity);
-//
-//let combinedData = []
-//let entityFieldsToLoad = [];
-//for (field in duplicateFieldsConfig) 
-//{
-//    let entityFieldName = duplicateFieldsConfig[field][0];
-//    let isIdField = duplicateFieldsConfig[field][1];
-//    let useForIndexSearch = duplicateFieldsConfig[field][2];
-//    let entityFieldData = model[entiyFieldName];
-//    combinedData.push(entityFieldName, isIdField, useForIndexSearch, entityFieldData);
-//}
-//
-//var filterName = "PersonDuplicates";
-//var targetEntity = "Person_entity";
-//DuplicateScannerUtils.getEntityRecords(targetEntity, entityFieldsToLoad, 0, 50);
-
-//Beispiel 1: 
-//Feld mit verknüpftem Consumer
-
-//[entity, feldname, consumerName, ProviderName]
-//let test = ["Communication_entity", "STANDARD_EMAIL_COMMUNICATION", "EmailCommunications", "EmailCommunications"];
-//
-//let testrow = entities.createConfigForLoadingRows()
-//                        .fields([test[1]])
-//                        .entity(test[0])
-//                        .provider(test[3])
-//                        .addParameter("ContactId_param", "d4c1bec3-656f-45ec-ae03-1c4d729d99fe")
-//                        //.uid()
-//let resultTest = entities.getRows(testrow);
-//logging.log("resultTest -> " + JSON.stringify(resultTest));
-
-
-
-//Beispiel 2: 
-//Feld direkt von anderem Entity
-//let testrow = entities.createConfigForLoadingRows()
-//                        .fields(["ZIP"])
-//                        .entity("Address_entity")
-//                        .uid("1a67eaa7-21da-4a18-97ab-755ac5cb74f7")
-//
-//let resultTest = entities.getRows(testrow);
-//logging.log("resultTest Beispiel 2 -> " + JSON.stringify(resultTest));
-
-
-//indexsearch.runIndexer(["Person"]);
-
-
-
-
-//let resultClusterId = DuplicateScannerUtils.GetClusterWithDuplicates(["7a34d9d0-04c7-478c-a8e2-f584fe625c45", "c7ddf982-0e58-4152-b82b-8f5673b0b729"]);
-//logging.log("resultClusterId -> " + resultClusterId);
-
-
-//
-//var filterName = "PersonDuplicates";
-//var targetEntity = "Person_entity";
-//var recordBlockSize = DuplicateScannerUtils.GetBlockSizeForScanner(filterName, targetEntity);
-//
-//logging.log("recordBlockSize -> " + recordBlockSize);
-
-//try 
-//{
-//    let sourceContactId = "sourceContactId";
-//    let targetContactId = "targetContactId";
-//    
-//    var activityDataForInsert = {
-//        subject: "Es wurde ein Personendatensatz in diesen integriert",
-//        content: "Person mit ID " + sourceContactId + " wurde in Person mit ID " + targetContactId + " integriert",
-//        //categoryKeywordId: $KeywordRegistry.ac
-//        directionKeywordId: "x",
-//        responsibleContactId: EmployeeUtils.getCurrentContactId()
-//    };
-//    
-//    var activityLinks = [["Person", "6e667085-bb97-4039-8dfe-2230002985e0"]]
-//
-//    //activityLinks = ArrayUtils.distinct2d(activityLinks);//TODO: better check before adding the elements into the array if it already exists there
-//    
-//    var activityRes = ActivityUtils.insertNewActivity(activityDataForInsert, activityLinks, null, db.getCurrentAlias());
-//} 
-//catch (exception) 
-//{ 
-//    logging.log("exception -> " + exception);
-//}
-
-////notification.addNotification(util.getNewUUID(), null, null, null, notification., notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [user], message, description);
-
-
-//let currentContactId = EmployeeUtils.getCurrentContactId();
-//DuplicateScannerUtils.CreateMergeSuccessActivity("a2e084e2-d68a-4f1e-a1bb-f8d46ad6293d", "6e667085-bb97-4039-8dfe-2230002985e0", currentContactId, "Person");
-
-
-//logging.log("$KeywordRegistry.activityDirection$internal() -> " + $KeywordRegistry.activityDirection$internal());
-
-
-
-//let processParameters = {
-//    filterName: "PersonDuplicates",
-//    targetEntity: "Person_entity" //process.execute is only able to handle strings
-//}
-//let userId = EmployeeUtils.getCurrentUserId();
-//if(userId == null)
-//    userId == "";
-//try 
-//{
-//    let processId = "manualrun_rebuild_duplicatecache_" + util.getNewUUID();
-//    process.executeTimer(processId, "RebuildAllDuplicatesCache_serverProcess", 0, true, false, process.TIMERTYPE_SERVER_RUN, userId, false, process.THREADPRIORITY_LOW)
-//    process.stopTimer(processId);
-//    logging.log("test -> ");
-//    process.executeAsync("RebuildAllDuplicateCaches_serverProcess", processParameters, false, userId, process.THREADPRIORITY_LOW)
-//    logging.log("test2 -> ");
-//} 
-//catch (exception) 
-//{ 
-//    logging.log(" exception-> " + exception);
-//}
diff --git a/entity/DuplicateScanner_entity/recordcontainers/dbrecordcontainer/recordfieldmappings/duplicatecount.value/expression.js b/entity/DuplicateScanner_entity/recordcontainers/dbrecordcontainer/recordfieldmappings/duplicatecount.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..a49f1a0db948473f671384d79a28219c3a23cd17
--- /dev/null
+++ b/entity/DuplicateScanner_entity/recordcontainers/dbrecordcontainer/recordfieldmappings/duplicatecount.value/expression.js
@@ -0,0 +1,13 @@
+import("system.result");
+import("Sql_lib");
+
+var subselect = newSelect("count(*)").from("UNRELATEDDUPLICATES")
+.where("UNRELATEDDUPLICATES.DUPLICATETYPE = HASDUPLICATE.OBJECT_TYPE")
+.and("UNRELATEDDUPLICATES.SOURCEDUPLICATEID = HASDUPLICATE.OBJECT_ROWID");
+result.string(
+    newSelect("count(*)")
+    .from("HASDUPLICATE")
+    .where("HASDUPLICATE.OBJECT_TYPE = DUPLICATESCANNER.ENTITY_TO_SCAN_NAME")
+    .and("(HASDUPLICATE.DUPLICATECOUNT - (" + subselect.toString() + ")) > 0")
+    .toString()
+);
diff --git a/entity/DuplicatesUnrelated_entity/DuplicatesUnrelated_entity.aod b/entity/DuplicatesUnrelated_entity/DuplicatesUnrelated_entity.aod
deleted file mode 100644
index 7d2241b72c2014a236b28f81f3f8a49060a1f768..0000000000000000000000000000000000000000
--- a/entity/DuplicatesUnrelated_entity/DuplicatesUnrelated_entity.aod
+++ /dev/null
@@ -1,91 +0,0 @@
-<?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>DuplicatesUnrelated_entity</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/DuplicatesUnrelated_entity/documentation.adoc</documentation>
-  <siblings>
-    <element>Duplicates_entity</element>
-  </siblings>
-  <recordContainer>jditoRecordContainer</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityProvider>
-      <name>UnrelatedPersonsProvider</name>
-      <titlePlural>Unrelated person duplicates</titlePlural>
-      <children>
-        <entityParameter>
-          <name>TargetEntity</name>
-          <expose v="true" />
-          <mandatory v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>ClusterId_param</name>
-          <expose v="true" />
-          <mandatory v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityParameter>
-      <name>TargetEntity</name>
-      <expose v="true" />
-      <mandatory v="true" />
-    </entityParameter>
-    <entityProvider>
-      <name>UnrelatedOrganisationsProvider</name>
-      <titlePlural>Unrelated organisations duplicates</titlePlural>
-      <children>
-        <entityParameter>
-          <name>TargetEntity</name>
-          <expose v="true" />
-          <mandatory v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>ClusterId_param</name>
-          <expose v="true" />
-          <mandatory v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityField>
-      <name>SourceDuplicateDescription</name>
-      <title>Source duplicate</title>
-    </entityField>
-    <entityField>
-      <name>UnrelatedDuplicateDescription</name>
-      <title>Unrelated duplicate</title>
-    </entityField>
-    <entityField>
-      <name>UID</name>
-    </entityField>
-    <entityParameter>
-      <name>ClusterId_param</name>
-      <expose v="true" />
-      <mandatory v="true" />
-    </entityParameter>
-    <entityProvider>
-      <name>#PROVIDER_AGGREGATES</name>
-      <useAggregates v="true" />
-    </entityProvider>
-  </entityFields>
-  <recordContainers>
-    <jDitoRecordContainer>
-      <name>jditoRecordContainer</name>
-      <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
-      <contentProcess>%aditoprj%/entity/DuplicatesUnrelated_entity/recordcontainers/jditorecordcontainer/contentProcess.js</contentProcess>
-      <onDelete>%aditoprj%/entity/DuplicatesUnrelated_entity/recordcontainers/jditorecordcontainer/onDelete.js</onDelete>
-      <recordFieldMappings>
-        <jDitoRecordFieldMapping>
-          <name>UID.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>SourceDuplicateDescription.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>UnrelatedDuplicateDescription.value</name>
-        </jDitoRecordFieldMapping>
-      </recordFieldMappings>
-    </jDitoRecordContainer>
-  </recordContainers>
-</entity>
diff --git a/entity/DuplicatesUnrelated_entity/documentation.adoc b/entity/DuplicatesUnrelated_entity/documentation.adoc
deleted file mode 100644
index 06d0fa27494b89bf6d02bef96f9872cb1409c379..0000000000000000000000000000000000000000
--- a/entity/DuplicatesUnrelated_entity/documentation.adoc
+++ /dev/null
@@ -1,3 +0,0 @@
-=DuplicateUnrelated_entity
-
-These Duplicates not related to another Entity.
\ No newline at end of file
diff --git a/entity/DuplicatesUnrelated_entity/recordcontainers/jditorecordcontainer/contentProcess.js b/entity/DuplicatesUnrelated_entity/recordcontainers/jditorecordcontainer/contentProcess.js
deleted file mode 100644
index 7f6beb6cd3e8fff07df2f33aa29835976eedc12d..0000000000000000000000000000000000000000
--- a/entity/DuplicatesUnrelated_entity/recordcontainers/jditorecordcontainer/contentProcess.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import("system.result");
-import("system.vars");
-import("system.db");
-import("Sql_lib");
-
-var INDEX_ID = 0;
-var INDEX_SOURCE_INFO1 = 1;
-var INDEX_SOURCE_INFO2 = 3;
-var INDEX_UNRELATED_INFO1 = 2;
-var INDEX_UNRELATED_INFO2 = 4;
-var INDEX_SOURCE_INFO = 1;
-var INDEX_UNRELATED_INFO = 2;
-
-
-let unrelatedDuplicates = [];
-let resultUnrelatedDuplicates = [];
-let targetEntity = vars.get("$param.TargetEntity");
-let clusterId = vars.get("$param.ClusterId_param");
-let querySelect = new SqlBuilder();
-
-if(targetEntity == 'Person_entity')
-{
-    querySelect.select("ud.ID,"
-                    + " pSource.FIRSTNAME, pUnrelated.FIRSTNAME,"
-                    + " pSource.LASTNAME, pUnrelated.LASTNAME")
-                .from("UNRELATEDDUPLICATES", "ud")
-                .join("CONTACT", "cUnrelated.CONTACTID = ud.UNRELATEDDUPLICATEID", "cUnrelated")
-                .join("PERSON", "pUnrelated.PERSONID = cUnrelated.PERSON_ID", "pUnrelated")
-                .join("CONTACT", "cSource.CONTACTID = ud.SOURCEDUPLICATEID", "cSource")
-                .join("PERSON", "pSource.PERSONID = cSource.PERSON_ID", "pSource")
-                //If the clusterid parameter is present, only load the duplicates for this particular cluster
-                .whereIfSet(["UNRELATEDDUPLICATES", "CLUSTERID", "ud"], clusterId);
-
-}
-else
-{
-    querySelect.select("ud.ID,"
-                    + " oSource.\"NAME\","
-                    + " oUnrelated.\"NAME\"")
-                .from("UNRELATEDDUPLICATES", "ud")
-                .join("CONTACT", "cUnrelated.CONTACTID = ud.UNRELATEDDUPLICATEID", "cUnrelated")
-                .join("ORGANISATION", "oUnrelated.ORGANISATIONID = cUnrelated.CONTACTID", "oUnrelated")
-                .join("CONTACT", "cSource.CONTACTID = ud.SOURCEDUPLICATEID", "cSource")
-                .join("ORGANISATION", "oSource.ORGANISATIONID = cSource.CONTACTID", "oSource")
-                //If the clusterid parameter is present, only load the duplicates for this particular cluster
-                .whereIfSet(["UNRELATEDDUPLICATES", "CLUSTERID", "ud"], clusterId);
-}
-
-unrelatedDuplicates = querySelect.table();
-
-for (let i = 0; i < unrelatedDuplicates.length; i++) 
-{
-    let id = unrelatedDuplicates[i][INDEX_ID];
-    let sourceInfo = "";
-    let unrelatedInfo = "";
-    
-        let sourceInfo1 = unrelatedDuplicates[i][INDEX_SOURCE_INFO1];
-        let sourceInfo2 = unrelatedDuplicates[i][INDEX_SOURCE_INFO2];
-        let unrelatedInfo1 = unrelatedDuplicates[i][INDEX_UNRELATED_INFO1];
-        let unrelatedInfo2 = unrelatedDuplicates[i][INDEX_UNRELATED_INFO2];
-        
-        sourceInfo = sourceInfo1;
-        if(sourceInfo2 != undefined)
-            sourceInfo += " " + sourceInfo2;
-        
-        unrelatedInfo = unrelatedInfo1;
-        if(unrelatedInfo2 != undefined)
-            unrelatedInfo += " " + unrelatedInfo2;
-    
-    resultUnrelatedDuplicates.push([id, sourceInfo, unrelatedInfo]);
-}
-
-result.object(resultUnrelatedDuplicates);
\ No newline at end of file
diff --git a/entity/DuplicatesUnrelated_entity/recordcontainers/jditorecordcontainer/onDelete.js b/entity/DuplicatesUnrelated_entity/recordcontainers/jditorecordcontainer/onDelete.js
deleted file mode 100644
index 4cb5ca4f2a88d7144b24d27ecf99028f547ca144..0000000000000000000000000000000000000000
--- a/entity/DuplicatesUnrelated_entity/recordcontainers/jditorecordcontainer/onDelete.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import("Sql_lib");
-
-newWhere("UNRELATEDDUPLICATES.ID", "$local.uid").deleteData();
\ No newline at end of file
diff --git a/entity/Duplicates_entity/Duplicates_entity.aod b/entity/Duplicates_entity/Duplicates_entity.aod
deleted file mode 100644
index fe9a19485083c678b01823430ae02631da122683..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/Duplicates_entity.aod
+++ /dev/null
@@ -1,234 +0,0 @@
-<?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>Duplicates_entity</name>
-  <title>Duplicates</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <documentation>%aditoprj%/entity/Duplicates_entity/documentation.adoc</documentation>
-  <siblings>
-    <element>DuplicatesUnrelated_entity</element>
-  </siblings>
-  <iconId>VAADIN:DATABASE</iconId>
-  <recordContainer>recordContainer</recordContainer>
-  <entityFields>
-    <entityProvider>
-      <name>#PROVIDER</name>
-    </entityProvider>
-    <entityField>
-      <name>CLUSTER_DESCRIPTION</name>
-      <title>Cluster description</title>
-    </entityField>
-    <entityField>
-      <name>COUNT_DUPLICATES_IN_CLUSTER</name>
-      <title>Count duplicates in cluster</title>
-      <contentType>NUMBER</contentType>
-    </entityField>
-    <entityField>
-      <name>TARGET_ENTITY</name>
-    </entityField>
-    <entityField>
-      <name>UID</name>
-    </entityField>
-    <entityProvider>
-      <name>SelfPersonDuplicatesProvider</name>
-      <titlePluralProcess>%aditoprj%/entity/Duplicates_entity/entityfields/selfpersonduplicatesprovider/titlePluralProcess.js</titlePluralProcess>
-      <titlePlural>Person duplicates</titlePlural>
-      <children>
-        <entityParameter>
-          <name>TargetEntity</name>
-          <expose v="true" />
-          <mandatory v="true" />
-        </entityParameter>
-      </children>
-    </entityProvider>
-    <entityConsumer>
-      <name>SelfPersonDuplicatesConsumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Duplicates_entity</entityName>
-        <fieldName>SelfPersonDuplicatesProvider</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>TargetEntity</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/selfpersonduplicatesconsumer/children/targetentity/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>ClusterId_param</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/selfpersonduplicatesconsumer/children/clusterid_param/valueProcess.js</valueProcess>
-          <title></title>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityParameter>
-      <name>TargetEntity</name>
-      <expose v="true" />
-      <mandatory v="true" />
-    </entityParameter>
-    <entityConsumer>
-      <name>SelfOrganisationDuplicatesConsumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Duplicates_entity</entityName>
-        <fieldName>SelfOrganisationDuplicatesProvider</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>TargetEntity</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/selforganisationduplicatesconsumer/children/targetentity/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>ClusterId_param</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/selforganisationduplicatesconsumer/children/clusterid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityProvider>
-      <name>SelfOrganisationDuplicatesProvider</name>
-      <titlePlural>Organisation duplicates</titlePlural>
-    </entityProvider>
-    <entityConsumer>
-      <name>DuplicatesUnrelatedPersonConsumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>DuplicatesUnrelated_entity</entityName>
-        <fieldName>UnrelatedPersonsProvider</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>TargetEntity</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicatesunrelatedpersonconsumer/children/targetentity/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>ClusterId_param</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicatesunrelatedpersonconsumer/children/clusterid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityField>
-      <name>CLUSTER_ID</name>
-    </entityField>
-    <entityConsumer>
-      <name>DuplicatePersonsConsumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Person_entity</entityName>
-        <fieldName>NonselfDuplicates</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>OnlyShowContactIds_param</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicatepersonsconsumer/children/onlyshowcontactids_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicatepersonsconsumer/children/duplicateactionscontrol_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityActionGroup>
-      <name>DuplicateClusterActionGroup</name>
-      <title>Duplicate actions</title>
-      <children>
-        <entityActionField>
-          <name>IgnoreWholeCluster</name>
-          <title>Ignore whole cluster</title>
-          <onActionProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicateclusteractiongroup/children/ignorewholecluster/onActionProcess.js</onActionProcess>
-          <isSelectionAction v="true" />
-          <iconId>VAADIN:CLOSE</iconId>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
-    <entityConsumer>
-      <name>DuplicatesUnrelatedOrganisationConsumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>DuplicatesUnrelated_entity</entityName>
-        <fieldName>UnrelatedOrganisationsProvider</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>TargetEntity</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicatesunrelatedorganisationconsumer/children/targetentity/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>ClusterId_param</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicatesunrelatedorganisationconsumer/children/clusterid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityActionGroup>
-      <name>PersonOpenClusterDetailActionGroup</name>
-      <children>
-        <entityActionField>
-          <name>PersonOpenClusterDetail</name>
-          <title></title>
-          <onActionProcess>%aditoprj%/entity/Duplicates_entity/entityfields/personopenclusterdetailactiongroup/children/personopenclusterdetail/onActionProcess.js</onActionProcess>
-          <isSelectionAction v="true" />
-          <iconId>VAADIN:FOLDER_OPEN</iconId>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
-    <entityParameter>
-      <name>ClusterId_param</name>
-      <expose v="true" />
-    </entityParameter>
-    <entityActionGroup>
-      <name>OrganisationOpenClusterDetailActionGroup</name>
-      <children>
-        <entityActionField>
-          <name>OrganisationOpenClusterDetail</name>
-          <title>Open cluster detail</title>
-          <onActionProcess>%aditoprj%/entity/Duplicates_entity/entityfields/organisationopenclusterdetailactiongroup/children/organisationopenclusterdetail/onActionProcess.js</onActionProcess>
-          <isSelectionAction v="true" />
-          <iconId>VAADIN:FOLDER_OPEN</iconId>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
-    <entityConsumer>
-      <name>DuplicateOrganisationsConsumer</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Organisation_entity</entityName>
-        <fieldName>NonselfDuplicates</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicateorganisationsconsumer/children/duplicateactionscontrol_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyShowContactIds_param</name>
-          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/duplicateorganisationsconsumer/children/onlyshowcontactids_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
-    <entityProvider>
-      <name>#PROVIDER_AGGREGATES</name>
-      <useAggregates v="true" />
-    </entityProvider>
-  </entityFields>
-  <recordContainers>
-    <jDitoRecordContainer>
-      <name>recordContainer</name>
-      <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
-      <contentProcess>%aditoprj%/entity/Duplicates_entity/recordcontainers/recordcontainer/contentProcess.js</contentProcess>
-      <recordFieldMappings>
-        <jDitoRecordFieldMapping>
-          <name>UID.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>CLUSTER_DESCRIPTION.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>COUNT_DUPLICATES_IN_CLUSTER.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>TARGET_ENTITY.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>CLUSTER_ID.value</name>
-        </jDitoRecordFieldMapping>
-      </recordFieldMappings>
-    </jDitoRecordContainer>
-  </recordContainers>
-</entity>
diff --git a/entity/Duplicates_entity/documentation.adoc b/entity/Duplicates_entity/documentation.adoc
deleted file mode 100644
index aa8d46c4a31d622c6ed142e3e92422218a302ae9..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/documentation.adoc
+++ /dev/null
@@ -1,3 +0,0 @@
-=Duplicates_entity
-
-This Entity shows the Duplicates of 
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/duplicateclusteractiongroup/children/ignorewholecluster/onActionProcess.js b/entity/Duplicates_entity/entityfields/duplicateclusteractiongroup/children/ignorewholecluster/onActionProcess.js
deleted file mode 100644
index 77822dbca0461d5ffccc31af058b9a5750002a4b..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicateclusteractiongroup/children/ignorewholecluster/onActionProcess.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import("system.logging");
-import("system.neon");
-import("system.vars");
-import("DuplicateScanner_lib");
-import("system.notification");
-
-let clusterId = vars.get("$sys.selection");
-
-let duplicateContactIdsInClusterRay = DuplicateScannerUtils.getCachedDuplicatesForClusterId(clusterId)
-
-if(duplicateContactIdsInClusterRay.length > 1)
-{
-    let referenceDuplicateId = duplicateContactIdsInClusterRay[0];
-    for (let i = 1; i < duplicateContactIdsInClusterRay.length; i++) 
-    {
-        DuplicateScannerUtils.createUnrelatedDuplicateRelation(referenceDuplicateId, duplicateContactIdsInClusterRay[i], clusterId);
-    }
-    //notification.createConfig().notificationType(notification.t)
-    //neon.refresh(["$field.SelfPersonDuplicatesConsumer"])
-
-    //todo Temporary!!! In the first refresh is the record via idValue selected and gets refreshed but stays visible in the record container
-    //todo Temporary!!! on the second refresh, no selecten remains and the container loads the remaining records as expected
-    neon.refreshAll();
-    neon.refreshAll();
-}
-
-
diff --git a/entity/Duplicates_entity/entityfields/duplicateorganisationsconsumer/children/duplicateactionscontrol_param/valueProcess.js b/entity/Duplicates_entity/entityfields/duplicateorganisationsconsumer/children/duplicateactionscontrol_param/valueProcess.js
deleted file mode 100644
index 5267adbe23e51fbb6b2c1c2aa44c947c3c3e7c34..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicateorganisationsconsumer/children/duplicateactionscontrol_param/valueProcess.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import("system.result");
-result.string("2");//todo exchange with keyword
diff --git a/entity/Duplicates_entity/entityfields/duplicateorganisationsconsumer/children/onlyshowcontactids_param/valueProcess.js b/entity/Duplicates_entity/entityfields/duplicateorganisationsconsumer/children/onlyshowcontactids_param/valueProcess.js
deleted file mode 100644
index ecb8c518cd40068c5e36606b64c83765a69962f6..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicateorganisationsconsumer/children/onlyshowcontactids_param/valueProcess.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import("system.logging");
-import("system.result");
-import("system.vars");
-import("DuplicateScanner_lib");
-
-let clusterRecordId = vars.get("$field.UID");
-
-let contactIdsInCluster = DuplicateScannerUtils.getCachedDuplicatesForClusterId(clusterRecordId);
-
-/*
- * To achieve that if there are no duplicates, no contacts should be shown and therefore returned by the 
- * recordcontainer, an invalid id gets returned. It then is used in the conditionProcess to load the duplicates.
- * Because of its invalidity, no records are shown.
-*/
-if(contactIdsInCluster.length == 0)
-    result.string(JSON.stringify(["nodata"]));
-else
-    result.string(JSON.stringify(contactIdsInCluster));
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/duplicatepersonsconsumer/children/duplicateactionscontrol_param/valueProcess.js b/entity/Duplicates_entity/entityfields/duplicatepersonsconsumer/children/duplicateactionscontrol_param/valueProcess.js
deleted file mode 100644
index 5267adbe23e51fbb6b2c1c2aa44c947c3c3e7c34..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicatepersonsconsumer/children/duplicateactionscontrol_param/valueProcess.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import("system.result");
-result.string("2");//todo exchange with keyword
diff --git a/entity/Duplicates_entity/entityfields/duplicatepersonsconsumer/children/onlyshowcontactids_param/valueProcess.js b/entity/Duplicates_entity/entityfields/duplicatepersonsconsumer/children/onlyshowcontactids_param/valueProcess.js
deleted file mode 100644
index ecb8c518cd40068c5e36606b64c83765a69962f6..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicatepersonsconsumer/children/onlyshowcontactids_param/valueProcess.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import("system.logging");
-import("system.result");
-import("system.vars");
-import("DuplicateScanner_lib");
-
-let clusterRecordId = vars.get("$field.UID");
-
-let contactIdsInCluster = DuplicateScannerUtils.getCachedDuplicatesForClusterId(clusterRecordId);
-
-/*
- * To achieve that if there are no duplicates, no contacts should be shown and therefore returned by the 
- * recordcontainer, an invalid id gets returned. It then is used in the conditionProcess to load the duplicates.
- * Because of its invalidity, no records are shown.
-*/
-if(contactIdsInCluster.length == 0)
-    result.string(JSON.stringify(["nodata"]));
-else
-    result.string(JSON.stringify(contactIdsInCluster));
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/duplicatesunrelatedorganisationconsumer/children/clusterid_param/valueProcess.js b/entity/Duplicates_entity/entityfields/duplicatesunrelatedorganisationconsumer/children/clusterid_param/valueProcess.js
deleted file mode 100644
index 152dfe0324a75ddba53552148d86b4af97acc6dd..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicatesunrelatedorganisationconsumer/children/clusterid_param/valueProcess.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import("system.vars");
-import("system.result");
-
-let clusterId = vars.get("$field.UID");
-result.string(clusterId);
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/duplicatesunrelatedorganisationconsumer/children/targetentity/valueProcess.js b/entity/Duplicates_entity/entityfields/duplicatesunrelatedorganisationconsumer/children/targetentity/valueProcess.js
deleted file mode 100644
index ea14ae6b612db05a0e3a34e900ca16547f9ed208..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicatesunrelatedorganisationconsumer/children/targetentity/valueProcess.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.vars");
-import("system.result");
-
-result.string("Organisation_entity");
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/duplicatesunrelatedpersonconsumer/children/clusterid_param/valueProcess.js b/entity/Duplicates_entity/entityfields/duplicatesunrelatedpersonconsumer/children/clusterid_param/valueProcess.js
deleted file mode 100644
index 03d5df5be8044683b94f306002bcbeada25b8737..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicatesunrelatedpersonconsumer/children/clusterid_param/valueProcess.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import("system.vars");
-import("system.result");
-
-//let clusterId = vars.get("$field.UID");
-let clusterId = vars.get("$param.ClusterId_param");
-result.string(clusterId);
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/duplicatesunrelatedpersonconsumer/children/targetentity/valueProcess.js b/entity/Duplicates_entity/entityfields/duplicatesunrelatedpersonconsumer/children/targetentity/valueProcess.js
deleted file mode 100644
index f8b07f56abc4e6b2df8800916a77fa58b50e99bf..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/duplicatesunrelatedpersonconsumer/children/targetentity/valueProcess.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import("system.vars");
-import("system.result");
-
-result.string("Person_entity");
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/organisationopenclusterdetailactiongroup/children/organisationopenclusterdetail/onActionProcess.js b/entity/Duplicates_entity/entityfields/organisationopenclusterdetailactiongroup/children/organisationopenclusterdetail/onActionProcess.js
deleted file mode 100644
index f599915bdc2dbbb45a9b52bb92e7de622c74f618..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/organisationopenclusterdetailactiongroup/children/organisationopenclusterdetail/onActionProcess.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-
-let contextName = "Duplicates";
-let viewName = "OrganisationClusterMain_view";
-
-var params = {};
-params["ClusterId_param"] = vars.get("$sys.selection")[0];
-params["TargetEntity"] = "Organisation_entity";
-
-neon.openContext(contextName, viewName, null, neon.OPERATINGSTATE_VIEW, params);
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/personopenclusterdetailactiongroup/children/personopenclusterdetail/onActionProcess.js b/entity/Duplicates_entity/entityfields/personopenclusterdetailactiongroup/children/personopenclusterdetail/onActionProcess.js
deleted file mode 100644
index 9d5cf8d6da175cc02200a6874c07f460589f6745..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/personopenclusterdetailactiongroup/children/personopenclusterdetail/onActionProcess.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-
-let contextName = "Duplicates";
-let viewName = "PersonClusterMain_view";
-
-var params = {};
-params["ClusterId_param"] = vars.get("$sys.selection")[0];
-params["TargetEntity"] = "Person_entity";
-
-neon.openContext(contextName, viewName, null, neon.OPERATINGSTATE_VIEW, params);
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/selforganisationduplicatesconsumer/children/clusterid_param/valueProcess.js b/entity/Duplicates_entity/entityfields/selforganisationduplicatesconsumer/children/clusterid_param/valueProcess.js
deleted file mode 100644
index 8ef7b768764a4f534b886492c99ec2e9408c00e5..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/selforganisationduplicatesconsumer/children/clusterid_param/valueProcess.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import("system.vars");
-import("system.result");
-
-let clusterId = vars.get("$param.ClusterId_param");
-result.string(clusterId);
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/selforganisationduplicatesconsumer/children/targetentity/valueProcess.js b/entity/Duplicates_entity/entityfields/selforganisationduplicatesconsumer/children/targetentity/valueProcess.js
deleted file mode 100644
index e781fb72fd248164b8b63a98008094744aee7460..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/selforganisationduplicatesconsumer/children/targetentity/valueProcess.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import("system.result");
-result.string("Organisation_entity");
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/selfpersonduplicatesconsumer/children/clusterid_param/valueProcess.js b/entity/Duplicates_entity/entityfields/selfpersonduplicatesconsumer/children/clusterid_param/valueProcess.js
deleted file mode 100644
index 258d52e236265f259b354a56fd04b1a3d2fcb566..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/selfpersonduplicatesconsumer/children/clusterid_param/valueProcess.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import("system.vars");
-import("system.result");
-
-//let clusterId = vars.get("$sys.selection");
-let clusterId = vars.get("$param.ClusterId_param");
-result.string(clusterId);
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/selfpersonduplicatesconsumer/children/targetentity/valueProcess.js b/entity/Duplicates_entity/entityfields/selfpersonduplicatesconsumer/children/targetentity/valueProcess.js
deleted file mode 100644
index 0f7bee25ea3bd34aeeceff7f47f7f9118e69b7ba..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/selfpersonduplicatesconsumer/children/targetentity/valueProcess.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import("system.result");
-result.string("Person_entity");
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/selfpersonduplicatesprovider/titlePluralProcess.js b/entity/Duplicates_entity/entityfields/selfpersonduplicatesprovider/titlePluralProcess.js
deleted file mode 100644
index b213a20410d97225b6a299a51857dcf0057ba50c..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/entityfields/selfpersonduplicatesprovider/titlePluralProcess.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import("system.result");
-import("system.translate");
-result.string(translate.text("Person duplicates"));
\ No newline at end of file
diff --git a/entity/Duplicates_entity/recordcontainers/recordcontainer/contentProcess.js b/entity/Duplicates_entity/recordcontainers/recordcontainer/contentProcess.js
deleted file mode 100644
index fc29941db97b09cd069a88b166304eb2be952b1e..0000000000000000000000000000000000000000
--- a/entity/Duplicates_entity/recordcontainers/recordcontainer/contentProcess.js
+++ /dev/null
@@ -1,121 +0,0 @@
-import("Sql_lib");
-import("system.logging");
-import("system.db");
-import("system.vars");
-import("system.result");
-
-var INDEX_CLUSTERID = 0;
-var INDEX_FIRSTNAME = 1;
-var INDEX_LASTNAME = 2;
-var INDEX_ORGNAME = 1;
-
-let targetEntity = vars.get("$param.TargetEntity");
-let duplicates = [];
-
-let selectedClusterId = vars.get("$param.ClusterId_param");
-    
-let duplicateInfosQuery = new SqlBuilder();
-
-let selectedId = vars.get("$local.idvalues");
-
-if(selectedId)
-{
-    /* 
-     * Definitely a todo.
-     * Support for the action "Ignore whole cluster"
-     * If this action is used two times in a row, an error occurs on the second time.
-     * Although the selected record isn't present in the recordcontainer any more, the core tries to load a record with the same id.
-     * As a result an error gets thrown. If a dummy record gets returned here, it plays along with the current internal logic and doesn't throw an error.
-     * If a preview should be shown, this part of the container has to be extended.
-     */
-    duplicates.push([selectedId, "", "", "", ""]);
-    result.object(duplicates);
-}
-else
-{
-    if(targetEntity == "Person_entity")
-    {
-        duplicateInfosQuery.select("CLUSTERID, FIRSTNAME, LASTNAME")
-                           .from("DUPLICATECLUSTERS")
-                           .join("CONTACT", "CONTACT.CONTACTID = DUPLICATEID")
-                           .join("PERSON", "PERSON.PERSONID = CONTACT.PERSON_ID")
-                           .where("DUPLICATEID not in (select UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID from UNRELATEDDUPLICATES)")
-                           .andIfSet("DUPLICATECLUSTERS.CLUSTERID", selectedClusterId)
-                           .orderBy("CLUSTERID");
-    }
-    else
-    {
-        duplicateInfosQuery.select("CLUSTERID, ORGANISATION.\"NAME\"")
-                           .from("DUPLICATECLUSTERS")
-                           .join("CONTACT", "CONTACT.CONTACTID = DUPLICATEID")
-                           .join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID")
-                           .where("DUPLICATEID not in (select UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID from UNRELATEDDUPLICATES)")
-                           .andIfSet("DUPLICATECLUSTERS.CLUSTERID", vars.get("$local.idvalues"), SqlBuilder.IN())
-                           .orderBy("CLUSTERID");
-    }   
-    let duplicateInfos = duplicateInfosQuery.table();
-
-    let MAX_SHOW_CLUSTER_RECORDS = 4;
-    let recordClusterId = "";
-    let recordDescription = "";
-    let recordDuplicateInClusterCount = 0;
-
-    for (let i = 0; i < duplicateInfos.length; i++) 
-    {
-        let currentClusterId = duplicateInfos[i][INDEX_CLUSTERID];
-        let currentDescription = "";
-
-        //Build the description depending on the targetEntity
-        if(targetEntity == "Person_entity")
-            currentDescription = duplicateInfos[i][INDEX_FIRSTNAME] + " " + duplicateInfos[i][INDEX_LASTNAME];
-        else
-            currentDescription = duplicateInfos[i][INDEX_ORGNAME];
-
-        if(i == 0)
-        {
-            recordClusterId = currentClusterId;
-            recordDescription = currentDescription;
-            recordDuplicateInClusterCount = 1;
-            continue;
-        }
-
-        //If the record belongs to the same Cluster as the one before, append its value and increase the counter
-        //otherwise write the clusters record an start a new record.
-        if(recordClusterId == currentClusterId)
-        {
-            if(recordDuplicateInClusterCount < MAX_SHOW_CLUSTER_RECORDS)
-                recordDescription += ", " + currentDescription;
-            if(recordDuplicateInClusterCount == MAX_SHOW_CLUSTER_RECORDS)
-                recordDescription += ", ..."
-            recordDuplicateInClusterCount++;
-
-            /*
-             * Finish the current record if its the last duplicate.
-             * It has to be checked wether or not more than one element is currently in the cluster:
-             * Normally, there are always at least 2 elements in a cluster. If then a duplicate relation
-             * is beign ignored, there's only one record left in this particluar cluster. 
-             * As there are then no interactions possible (and a cluster of one is no cluster), this cluster musn't be shown in the list.
-             */
-            if(i == duplicateInfos.length-1 && recordDuplicateInClusterCount > 1)
-                duplicates.push([recordClusterId, recordDescription, recordDuplicateInClusterCount, targetEntity, recordClusterId]);
-        }
-        else
-        {
-            /*
-             * Finish the current record if its the next cluster.
-             * It has to be checked wether or not more than one element is currently in the cluster:
-             * Normally, there are always at least 2 elements in a cluster. If then a duplicate relation
-             * is beign ignored, there's only one record left in this particluar cluster. 
-             * As there would be no interactions possible (and a cluster of one is no cluster), this cluster musn't be shown in the list.
-             */
-            if(recordDuplicateInClusterCount > 1)
-                duplicates.push([recordClusterId, recordDescription, recordDuplicateInClusterCount, targetEntity, recordClusterId]);
-
-            recordClusterId = currentClusterId
-            recordDescription = currentDescription
-            recordDuplicateInClusterCount = 1;
-        }
-    }
-
-    result.object(duplicates);
-}
diff --git a/entity/KeywordEntry_entity/KeywordEntry_entity.aod b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
index 39bcb0a4581d7af2ee3b4a472d718ba09173abe5..125241142e38eac39484efca2261f07e5538ce81 100644
--- a/entity/KeywordEntry_entity/KeywordEntry_entity.aod
+++ b/entity/KeywordEntry_entity/KeywordEntry_entity.aod
@@ -637,6 +637,24 @@
           <fieldName>KeywordPhases</fieldName>
           <isConsumer v="false" />
         </entityDependency>
+        <entityDependency>
+          <name>414ad662-727b-4e9f-9e86-0659d92ec60d</name>
+          <entityName>DuplicatePerson_entity</entityName>
+          <fieldName>KeywordContactStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>0f8f9bfc-379c-4f05-8364-8270e718fe9a</name>
+          <entityName>DuplicateOrganisation_entity</entityName>
+          <fieldName>KeywordContactStates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
+        <entityDependency>
+          <name>b78c0dd7-a35c-4d9b-9a23-1a20e7e41464</name>
+          <entityName>DuplicateOrganisation_entity</entityName>
+          <fieldName>KeywordOrganisationTypes</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
         <entityDependency>
           <name>98608b12-9927-4197-adfe-1398a388bcb0</name>
           <entityName>WebtrackingTag_entity</entityName>
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index be40c333adc19fbc28ccd8715d0596b2f151a47f..b0b919e690ff43f4ff5aafc1723cb375a3b0a56f 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -186,6 +186,12 @@
           <fieldName>OrganisationConsumer</fieldName>
           <isConsumer v="false" />
         </entityDependency>
+        <entityDependency>
+          <name>fa1b6124-1e00-4fa0-8c04-debc19f58d95</name>
+          <entityName>DuplicatePerson_entity</entityName>
+          <fieldName>Organisations</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
         <entityDependency>
           <name>640a8509-1972-4dc5-980e-68832f1c03c5</name>
           <entityName>Planning_entity</entityName>
@@ -226,14 +232,6 @@
           <name>AttributeId_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
         <entityParameter>
           <name>MapViewAdditionalFeatures_param</name>
           <expose v="false" />
@@ -699,14 +697,6 @@
           <name>ExcludedContactIds_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
         <entityParameter>
           <name>MapViewAdditionalFeatures_param</name>
           <expose v="false" />
@@ -770,14 +760,6 @@
           <name>ExcludedContactIds_param</name>
           <expose v="true" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
         <entityParameter>
           <name>MapViewAdditionalFeatures_param</name>
           <expose v="false" />
@@ -955,65 +937,10 @@
       <colorProcess>%aditoprj%/entity/Organisation_entity/entityfields/lastactivity/colorProcess.js</colorProcess>
       <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/lastactivity/valueProcess.js</valueProcess>
     </entityField>
-    <entityProvider>
-      <name>SelfDuplicates</name>
-      <documentation>%aditoprj%/entity/Organisation_entity/entityfields/selfduplicates/documentation.adoc</documentation>
-      <titlePlural>Duplicates</titlePlural>
-      <children>
-        <entityParameter>
-          <name>AttributeId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>AttributeKeyId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>FilterPreSet_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>OrganisationType_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>WithPrivate_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyOwnSupervised_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>ExcludeOrganisationsByPersonId</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>MapViewAdditionalFeatures_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>MapViewCenterLat_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>MapViewCenterLon_param</name>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
     <entityParameter>
       <name>OnlyShowContactIds_param</name>
       <expose v="true" />
     </entityParameter>
-    <entityParameter>
-      <name>DuplicateActionsControl_param</name>
-      <expose v="true" />
-    </entityParameter>
-    <entityParameter>
-      <name>DuplicateCurrentContactId_param</name>
-      <expose v="true" />
-    </entityParameter>
     <entityField>
       <name>STANDARD_COUNTRY</name>
       <title>Standard Country</title>
@@ -1023,33 +950,6 @@
       <name>OnlyOwnSupervised_param</name>
       <expose v="true" />
     </entityParameter>
-    <entityConsumer>
-      <name>SelfDuplicatesUncached</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Organisation_entity</entityName>
-        <fieldName>SelfDuplicates</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/duplicateactionscontrol_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/duplicatecurrentcontactid_param/valueProcess.js</valueProcess>
-          <title></title>
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyShowContactIds_param</name>
-          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/onlyshowcontactids_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>ExcludedContactIds_param</name>
-          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/excludedcontactids_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
     <entityConsumer>
       <name>CommRestrictions</name>
       <dependency>
@@ -1153,14 +1053,6 @@
           <name>AttributeKeyId_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
         <entityParameter>
           <name>ExcludedContactIds_param</name>
           <expose v="false" />
@@ -1226,10 +1118,6 @@
           <name>OnlyShowContactIds_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
         <entityParameter>
           <name>ExcludeOrganisationsByPersonId</name>
           <expose v="false" />
@@ -1282,52 +1170,6 @@
       <name>FilterPreSet_param</name>
       <expose v="true" />
     </entityParameter>
-    <entityProvider>
-      <name>NonselfDuplicates</name>
-      <documentation>%aditoprj%/entity/Organisation_entity/entityfields/nonselfduplicates/documentation.adoc</documentation>
-      <dependencies>
-        <entityDependency>
-          <name>2e410b9e-5ebc-48ea-9562-da386202d7e8</name>
-          <entityName>Duplicates_entity</entityName>
-          <fieldName>DuplicateOrganisationsConsumer</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>AttributeKeyId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>ExcludedContactIds_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyShowContactIds_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyOwnSupervised_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>MapViewAdditionalFeatures_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>MapViewCenterLon_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>MapViewCenterLat_param</name>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
     <entityConsumer>
       <name>AttributesFilter</name>
       <dependency>
@@ -1526,52 +1368,6 @@
       <iconId>VAADIN:ENVELOPE</iconId>
       <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/newletter/stateProcess.js</stateProcess>
     </entityActionField>
-    <entityActionGroup>
-      <name>DuplicateActions</name>
-      <title>Duplicate actions</title>
-      <state>AUTO</state>
-      <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/stateProcess.js</stateProcess>
-      <children>
-        <entityActionField>
-          <name>IntegrateSelectedIntoCurrentAction</name>
-          <title>Integrate selected into current contact</title>
-          <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js</onActionProcess>
-          <isMenuAction v="true" />
-          <isObjectAction v="false" />
-          <isSelectionAction v="true" />
-          <iconId>NEON:IMPORT</iconId>
-          <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/stateProcess.js</stateProcess>
-        </entityActionField>
-        <entityActionField>
-          <name>IntegrateCurrentIntoSelectedAction</name>
-          <title>Integrate current into selected contact</title>
-          <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js</onActionProcess>
-          <isMenuAction v="true" />
-          <isObjectAction v="false" />
-          <isSelectionAction v="true" />
-          <iconId>NEON:EXPORT</iconId>
-          <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/stateProcess.js</stateProcess>
-        </entityActionField>
-        <entityActionField>
-          <name>IgnoreDuplicate</name>
-          <title>Ignore Duplicate</title>
-          <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/children/ignoreduplicate/onActionProcess.js</onActionProcess>
-          <isMenuAction v="true" />
-          <isObjectAction v="false" />
-          <isSelectionAction v="true" />
-          <iconId>VAADIN:CLOSE</iconId>
-          <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/children/ignoreduplicate/stateProcess.js</stateProcess>
-        </entityActionField>
-        <entityActionField>
-          <name>IgnoreWholeCluster</name>
-          <title>Ignore whole Cluster</title>
-          <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/children/ignorewholecluster/onActionProcess.js</onActionProcess>
-          <isObjectAction v="false" />
-          <iconId>VAADIN:CLOSE</iconId>
-          <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicateactions/children/ignorewholecluster/stateProcess.js</stateProcess>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
     <entityActionField>
       <name>startWorkflow</name>
       <title>Start workflow</title>
@@ -1629,6 +1425,22 @@
       <iconId>VAADIN:CURLY_BRACKETS</iconId>
       <stateProcess>%aditoprj%/entity/Organisation_entity/entityfields/openadminview/stateProcess.js</stateProcess>
     </entityActionField>
+    <entityConsumer>
+      <name>Duplicates</name>
+      <selectionMode>MULTI</selectionMode>
+      <selectionModeProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicates/selectionModeProcess.js</selectionModeProcess>
+      <dependency>
+        <name>dependency</name>
+        <entityName>DuplicateOrganisation_entity</entityName>
+        <fieldName>#PROVIDER</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>Obj_param</name>
+          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/duplicates/children/obj_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
     <entityConsumer>
       <name>Plannings</name>
       <dependency>
@@ -1787,11 +1599,13 @@
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>STANDARD_EMAIL_COMMUNICATION.value</name>
+          <expression>%aditoprj%/entity/Organisation_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js</expression>
           <isFilterable v="false" />
           <isLookupFilter v="false" />
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>STANDARD_PHONE_COMMUNICATION.value</name>
+          <expression>%aditoprj%/entity/Organisation_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js</expression>
           <isFilterable v="false" />
           <isLookupFilter v="false" />
         </dbRecordFieldMapping>
@@ -1943,6 +1757,13 @@
           <filterConditionProcess>%aditoprj%/entity/Organisation_entity/recordcontainers/db/filterextensions/responsibleassignment/filterConditionProcess.js</filterConditionProcess>
           <filtertype>EXTENDED</filtertype>
         </filterExtension>
+        <filterExtension>
+          <name>Duplicates_filter</name>
+          <title>Duplicates</title>
+          <contentType>NUMBER</contentType>
+          <filterConditionProcess>%aditoprj%/entity/Organisation_entity/recordcontainers/db/filterextensions/duplicates_filter/filterConditionProcess.js</filterConditionProcess>
+          <filtertype>BASIC</filtertype>
+        </filterExtension>
         <filterExtension>
           <name>Communication_Mail_filter</name>
           <title>Communication: Mail</title>
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/children/ignoreduplicate/onActionProcess.js b/entity/Organisation_entity/entityfields/duplicateactions/children/ignoreduplicate/onActionProcess.js
deleted file mode 100644
index c9289cbd0ef896d7dbcf5eae668bac8a87e861da..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/duplicateactions/children/ignoreduplicate/onActionProcess.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import("system.neon");
-import("system.vars");
-import("DuplicateScanner_lib");
-
-let sourceContactId = vars.get("$param.DuplicateCurrentContactId_param");
-let selectedContactId = vars.get("$sys.selection");
-let clusterId = DuplicateScannerUtils.getClusterId(sourceContactId);
-DuplicateScannerUtils.createUnrelatedDuplicateRelation(sourceContactId, selectedContactId, clusterId);
-
-neon.refreshAll();
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/children/ignoreduplicate/stateProcess.js b/entity/Organisation_entity/entityfields/duplicateactions/children/ignoreduplicate/stateProcess.js
deleted file mode 100644
index b736eb15f5b18e779e37281fe216c9297ca86191..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/duplicateactions/children/ignoreduplicate/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState != null && actionState != "1")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/children/ignorewholecluster/onActionProcess.js b/entity/Organisation_entity/entityfields/duplicateactions/children/ignorewholecluster/onActionProcess.js
deleted file mode 100644
index 99d7f55925b3fed54dc2d5e20604793b6e9fd862..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/duplicateactions/children/ignorewholecluster/onActionProcess.js
+++ /dev/null
@@ -1,21 +0,0 @@
-import("system.logging");
-import("system.neon");
-import("system.vars");
-import("DuplicateScanner_lib");
-import("system.notification");
-
-let contactId = vars.get("$field.CONTACTID");
-let clusterId = DuplicateScannerUtils.getClusterId(contactId);
-
-let duplicateContactIdsInClusterRay = DuplicateScannerUtils.getCachedDuplicatesForClusterId(clusterId)
-
-if(duplicateContactIdsInClusterRay.length > 1)
-{
-    let referenceDuplicateId = duplicateContactIdsInClusterRay[0];
-    for (let i = 1; i < duplicateContactIdsInClusterRay.length; i++) 
-    {
-        DuplicateScannerUtils.createUnrelatedDuplicateRelation(referenceDuplicateId, duplicateContactIdsInClusterRay[i], clusterId);
-    }
-}
-
-
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/children/ignorewholecluster/stateProcess.js b/entity/Organisation_entity/entityfields/duplicateactions/children/ignorewholecluster/stateProcess.js
deleted file mode 100644
index fdd913ad06bf2815da3127d405d21b258c4ad795..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/duplicateactions/children/ignorewholecluster/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState != null && actionState != "2")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/stateProcess.js b/entity/Organisation_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/stateProcess.js
deleted file mode 100644
index b736eb15f5b18e779e37281fe216c9297ca86191..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState != null && actionState != "1")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/stateProcess.js b/entity/Organisation_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/stateProcess.js
deleted file mode 100644
index b736eb15f5b18e779e37281fe216c9297ca86191..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState != null && actionState != "1")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/duplicateactions/stateProcess.js b/entity/Organisation_entity/entityfields/duplicateactions/stateProcess.js
deleted file mode 100644
index 5b8b24021ddfcba34a258bf7af7d4ec5ec65852a..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/duplicateactions/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState == null || actionState == "0")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/duplicates/children/obj_param/valueProcess.js b/entity/Organisation_entity/entityfields/duplicates/children/obj_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..39bdfae5361be160d838627fc4e4de2d45eb9b82
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/duplicates/children/obj_param/valueProcess.js
@@ -0,0 +1,20 @@
+import("system.vars");
+import("system.result");
+
+result.string(JSON.stringify({
+    CONTACTID: vars.get("$field.CONTACTID"),
+    NAME: vars.get("$field.NAME"),
+    ADDRESS_ID: vars.get("$field.ADDRESS_ID"),
+    CUSTOMERCODE: vars.get("$field.CUSTOMERCODE"),
+    LANGUAGE: vars.get("$field.LANGUAGE"),
+    TYPE: vars.get("$field.TYPE"),
+    STATUS: vars.get("$field.STATUS"),
+    STANDARD_ADDRESS: vars.get("$field.STANDARD_ADDRESS"),
+    STANDARD_CITY: vars.get("$field.STANDARD_CITY"),
+    STANDARD_COUNTRY: vars.get("$field.STANDARD_COUNTRY"),
+    STANDARD_EMAIL_COMMUNICATION: vars.get("$field.STANDARD_EMAIL_COMMUNICATION"),
+    STANDARD_LAT: vars.get("$field.STANDARD_LAT"),
+    STANDARD_LON: vars.get("$field.STANDARD_LON"),
+    STANDARD_PHONE_COMMUNICATION: vars.get("$field.STANDARD_PHONE_COMMUNICATION"),
+    STANDARD_ZIP: vars.get("$field.STANDARD_ZIP")
+}));
diff --git a/entity/Organisation_entity/entityfields/duplicates/selectionModeProcess.js b/entity/Organisation_entity/entityfields/duplicates/selectionModeProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c92317456ba1a7476401171e875526c8eff6fa76
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/duplicates/selectionModeProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("system.vars");
+import("system.neon");
+
+result.string(
+    vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW ||
+        vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT ?
+    "NONE" : "MULTI"
+);
diff --git a/entity/Organisation_entity/entityfields/nonselfduplicates/documentation.adoc b/entity/Organisation_entity/entityfields/nonselfduplicates/documentation.adoc
deleted file mode 100644
index dc35980c12405163da2417e0472197dd9e3c7285..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/nonselfduplicates/documentation.adoc
+++ /dev/null
@@ -1,3 +0,0 @@
-Provides organisation duplicate-records without the `Organisation_entity` scope, for example for the `Duplicates_entity`.
-
-The provider is named `NonselfDuplicates` to differentiate this provider and the `SelfDuplicates`-provider.
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/selfduplicates/documentation.adoc b/entity/Organisation_entity/entityfields/selfduplicates/documentation.adoc
deleted file mode 100644
index 396162acb9e2db72c8c1090f4fdda9eb84a95738..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/selfduplicates/documentation.adoc
+++ /dev/null
@@ -1 +0,0 @@
-Provides organisation duplicate-records within the `Organisation_entity` scope itself.
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/duplicateactionscontrol_param/valueProcess.js b/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/duplicateactionscontrol_param/valueProcess.js
deleted file mode 100644
index 81570217c3ecd3cf76deb5e14d7ac0a6121a59bb..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/duplicateactionscontrol_param/valueProcess.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import("system.result");
-result.string("1");//todo use keyword
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/duplicatecurrentcontactid_param/valueProcess.js b/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/duplicatecurrentcontactid_param/valueProcess.js
deleted file mode 100644
index 821415ae694dd9c3d98a7703f4c59b81a37f524b..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/duplicatecurrentcontactid_param/valueProcess.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import("system.vars");
-import("system.result");
-result.string(vars.get("$field.CONTACTID"));
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/excludedcontactids_param/valueProcess.js b/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/excludedcontactids_param/valueProcess.js
deleted file mode 100644
index 849632882bbabd4e65dfb25c7dc984366bde5116..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/excludedcontactids_param/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.result");
-import("DuplicateScanner_lib");
-
-let unrelatedIds = DuplicateScannerUtils.getUnrelatedRelationsForDuplicate(vars.get("$field.CONTACTID"));
-result.string(JSON.stringify(unrelatedIds));
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/onlyshowcontactids_param/valueProcess.js b/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/onlyshowcontactids_param/valueProcess.js
deleted file mode 100644
index 77f449d52a0995e5bb7e8ba94746a1659bf36001..0000000000000000000000000000000000000000
--- a/entity/Organisation_entity/entityfields/selfduplicatesuncached/children/onlyshowcontactids_param/valueProcess.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import("system.project");
-import("system.indexsearch");
-import("system.vars");
-import("DuplicateScanner_lib");
-import("system.result");
-
-var scannerName = "OrganisationDuplicates";
-var targetEntity = "Organisation_entity";
-var valuesToCheck = {};
-var entityFieldsToLoad = DuplicateScannerUtils.getEntityFieldObjectFromConfig(scannerName, targetEntity);
-
-var idsForEmptyResult = JSON.stringify(["nodata"]);
-
-if (entityFieldsToLoad == null)
-    result.string(idsForEmptyResult);
-else
-{
-    //Read the values of all available entity fields and write the fieldname7value combination
-    //as key/value pairs into an object. This is used to trigger the scan for duplicates
-
-    vars.get("$field.NAME")
-    vars.get("$field.STANDARD_CITY");
-    vars.get("$field.STANDARD_ZIP");
-    vars.get("$field.STANDARD_ADDRESS");
-    
-    var allFieldsToLoad = entityFieldsToLoad.entityFields.concat(entityFieldsToLoad.entityIdField);
-    allFieldsToLoad.forEach(function (field)
-    {
-        var fieldValue = vars.get("$field." + field);
-        if (fieldValue)
-            valuesToCheck[field] = fieldValue;
-    });
-    
-    var scanResults = [];
-    
-    //don't search if only the id field has a value
-    var fieldsToCheck = Object.keys(valuesToCheck);
-    if (!(fieldsToCheck.length === 0 || (fieldsToCheck.length === 1 && entityFieldsToLoad.entityIdField in valuesToCheck)))
-        scanResults = DuplicateScannerUtils.scanForDuplicates(scannerName, targetEntity, valuesToCheck, null) || [];
-    
-    var duplicateIds = scanResults.map(function (scanResult)
-    {
-        return scanResult[indexsearch.FIELD_ID];
-    });
-
-    /*
-     * To achieve that if there are no duplicates, no contacts should be shown and therefore returned by the 
-     * recordcontainer, an invalid id gets returned. It then is used in the conditionProcess to load the duplicates.
-     * Because of its invalidity, no records are shown.
-     */
-    if (duplicateIds.length == 0)
-        result.string(idsForEmptyResult);
-    else
-        result.string(JSON.stringify(duplicateIds));
-}
\ No newline at end of file
diff --git a/entity/Organisation_entity/initFilterProcess.js b/entity/Organisation_entity/initFilterProcess.js
index 936a623f599055fc4fb5fa81c850fc7d323bff22..afecc1ede02d6f412681545610696b1efa17dc90 100644
--- a/entity/Organisation_entity/initFilterProcess.js
+++ b/entity/Organisation_entity/initFilterProcess.js
@@ -5,15 +5,10 @@ import("KeywordRegistry_basic");
 import("system.result");
 
 var filter = vars.get("$param.FilterPreSet_param");
-
-var res;
-if (filter)
-    res = filter;
-else if (vars.get("$sys.presentationmode") === neon.CONTEXT_PRESENTATIONMODE_FILTER) 
+if(!filter && vars.get("$sys.presentationmode") === neon.CONTEXT_PRESENTATIONMODE_FILTER) 
 {
     var statusInactive = $KeywordRegistry.contactStatus$inactive();
-    
-    filter = {
+    filter = JSON.stringify({
         type: "group",
         operator: "AND",
         childs: [{
@@ -24,9 +19,9 @@ else if (vars.get("$sys.presentationmode") === neon.CONTEXT_PRESENTATIONMODE_FIL
             key: statusInactive,
             value: KeywordUtils.getViewValue($KeywordRegistry.contactStatus(), statusInactive)
         }]
-    };
-    res = JSON.stringify(filter);
+    });
+}
+if(filter)
+{
+    result.string(filter);
 }
-
-if (res)
-    result.string(res);
\ No newline at end of file
diff --git a/entity/Organisation_entity/recordcontainers/db/filterextensions/duplicates_filter/filterConditionProcess.js b/entity/Organisation_entity/recordcontainers/db/filterextensions/duplicates_filter/filterConditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..96f185ae76701ab39777fe91db3d18baf328b614
--- /dev/null
+++ b/entity/Organisation_entity/recordcontainers/db/filterextensions/duplicates_filter/filterConditionProcess.js
@@ -0,0 +1,16 @@
+import("system.result");
+import("Sql_lib");
+import("system.vars");
+import("DuplicateScanner_lib");
+
+var sqlOperator = SqlUtils.getSqlConditionalOperator(vars.get("$local.operator"));
+
+result.string(newWhere(
+    "CONTACT.CONTACTID",
+    DuplicateScannerUtils.getDuplicateConditionalListSql(
+        ["Organisation_entity"],
+        vars.get("$local.rawvalue"),
+        sqlOperator, true
+    ),
+    SqlBuilder.IN()
+));
diff --git a/entity/Organisation_entity/recordcontainers/db/onDBDelete.js b/entity/Organisation_entity/recordcontainers/db/onDBDelete.js
index 00e50690d485216c4b4956f416b688ab433e68a8..320f4e3329fa4fd7195da03495b3cd7e5812a9d6 100644
--- a/entity/Organisation_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Organisation_entity/recordcontainers/db/onDBDelete.js
@@ -7,7 +7,7 @@ import("Attribute_lib");
 
 // TODO: enable when duplicate-module is finalized
 let contactId = vars.get("$field.CONTACTID");
-DuplicateScannerUtils.deleteCachedDuplicate(contactId);
+DuplicateScannerUtils.deleteHasDuplicateEntries("Organisation_entity", [contactId]);
 
 new AttributeRelationQuery(contactId, null, ContextUtils.getCurrentContextId())
     .deleteAllAttributes();
diff --git a/entity/Organisation_entity/recordcontainers/db/onDBInsert.js b/entity/Organisation_entity/recordcontainers/db/onDBInsert.js
index 60299cd7d4eda2ceed743571cec9cbda912ad318..c8db8fdecb72ba18f14ae3fd3a5bd05223ac2396 100644
--- a/entity/Organisation_entity/recordcontainers/db/onDBInsert.js
+++ b/entity/Organisation_entity/recordcontainers/db/onDBInsert.js
@@ -1,5 +1,8 @@
 import("system.vars");
 import("Workflow_lib");
+import("DuplicateScanner_lib");
+
+DuplicateScannerUtils.updateHasDuplicateEntry("Organisation_entity");
 
 //start the execution in afterOperatingState, because here the dataset is not yet inserted
 vars.set("$context.workflowQueue", {});
diff --git a/entity/Organisation_entity/recordcontainers/db/onDBUpdate.js b/entity/Organisation_entity/recordcontainers/db/onDBUpdate.js
index 9f0337793c84207f61013809345f829d1f874671..737768cc8678c59374d99e790f4956812e3661db 100644
--- a/entity/Organisation_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/Organisation_entity/recordcontainers/db/onDBUpdate.js
@@ -6,6 +6,9 @@ import("Communication_lib");
 import("Entity_lib");
 import("Workflow_lib");
 import("KeywordRegistry_basic");
+import("DuplicateScanner_lib");
+
+DuplicateScannerUtils.updateHasDuplicateEntry("Organisation_entity");
 
 // TODO: this is a workaround for missing possibility to react on changes of fields not connected to record Contqainer #1030023
 var rowdata =  vars.get("$local.rowdata");
diff --git a/entity/Organisation_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js b/entity/Organisation_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..41ef07ff58ec51eda018bed12cb5b0b2b657c348
--- /dev/null
+++ b/entity/Organisation_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Communication_lib");
+
+var res = CommUtil.getStandardSubSqlMail();
+result.string(res);
\ No newline at end of file
diff --git a/entity/Organisation_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js b/entity/Organisation_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..320ae40ad1ba794b4e759037fa0f382b9af67696
--- /dev/null
+++ b/entity/Organisation_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Communication_lib");
+
+var res = CommUtil.getStandardSubSqlPhone();
+result.string(res);
\ No newline at end of file
diff --git a/entity/Person_entity/Person_entity.aod b/entity/Person_entity/Person_entity.aod
index 87f279d514b74c7e9a02d6386c8416589874f65d..acb1ac9f267e189656e69ac475c18f3059e76dfd 100644
--- a/entity/Person_entity/Person_entity.aod
+++ b/entity/Person_entity/Person_entity.aod
@@ -162,10 +162,6 @@
           <name>OnlyActive_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
       </children>
     </entityProvider>
     <entityField>
@@ -411,14 +407,6 @@
           <name>OnlyActive_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <expose v="false" />
-        </entityParameter>
       </children>
     </entityProvider>
     <entityConsumer>
@@ -776,10 +764,6 @@
           <name>OnlyActive_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
       </children>
     </entityProvider>
     <entityConsumer>
@@ -945,46 +929,11 @@
       <displayValueProcess>%aditoprj%/entity/Person_entity/entityfields/organisation_contactid/displayValueProcess.js</displayValueProcess>
       <onValidation>%aditoprj%/entity/Person_entity/entityfields/organisation_contactid/onValidation.js</onValidation>
     </entityField>
-    <entityParameter>
-      <name>DuplicateCurrentContactId_param</name>
-      <expose v="true" />
-    </entityParameter>
-    <entityParameter>
-      <name>DuplicateActionsControl_param</name>
-      <expose v="true" />
-      <mandatory v="false" />
-    </entityParameter>
     <entityField>
       <name>STANDARD_COUNTRY</name>
       <title>Country</title>
       <groupable v="true" />
     </entityField>
-    <entityConsumer>
-      <name>SelfDuplicatesUncached</name>
-      <dependency>
-        <name>dependency</name>
-        <entityName>Person_entity</entityName>
-        <fieldName>SelfDuplicates</fieldName>
-      </dependency>
-      <children>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <valueProcess>%aditoprj%/entity/Person_entity/entityfields/selfduplicatesuncached/children/duplicateactionscontrol_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <valueProcess>%aditoprj%/entity/Person_entity/entityfields/selfduplicatesuncached/children/duplicatecurrentcontactid_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyShowContactIds_param</name>
-          <valueProcess>%aditoprj%/entity/Person_entity/entityfields/selfduplicatesuncached/children/onlyshowcontactids_param/valueProcess.js</valueProcess>
-        </entityParameter>
-        <entityParameter>
-          <name>ExcludedContactIds_param</name>
-          <valueProcess>%aditoprj%/entity/Person_entity/entityfields/selfduplicatesuncached/children/excludedcontactids_param/valueProcess.js</valueProcess>
-        </entityParameter>
-      </children>
-    </entityConsumer>
     <entityField>
       <name>LEAD_LEADID</name>
     </entityField>
@@ -1035,47 +984,12 @@
           <name>OnlyActive_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
       </children>
     </entityProvider>
     <entityParameter>
       <name>OnlyShowContactIds_param</name>
       <expose v="true" />
     </entityParameter>
-    <entityProvider>
-      <name>SelfDuplicates</name>
-      <documentation>%aditoprj%/entity/Person_entity/entityfields/selfduplicates/documentation.adoc</documentation>
-      <titlePlural>Duplicates</titlePlural>
-      <children>
-        <entityParameter>
-          <name>OnlyShowContactIds_param</name>
-          <mandatory v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyActive_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>OrgId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyOwnSupervised_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>ContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
     <entityField>
       <name>IndexCommunication</name>
     </entityField>
@@ -1124,10 +1038,6 @@
           <name>ContactId_param</name>
           <expose v="false" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <expose v="false" />
-        </entityParameter>
         <entityParameter>
           <name>OnlyOwnSupervised_param</name>
           <expose v="false" />
@@ -1144,10 +1054,6 @@
           <name>OnlyActive_param</name>
           <expose v="true" />
         </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
       </children>
     </entityProvider>
     <entityField>
@@ -1164,12 +1070,6 @@
       <name>indexP</name>
       <documentation>%aditoprj%/entity/Person_entity/entityfields/indexp/documentation.adoc</documentation>
       <recordContainer>index</recordContainer>
-      <children>
-        <entityParameter>
-          <name>DuplicateActionsControl_param</name>
-          <expose v="false" />
-        </entityParameter>
-      </children>
     </entityProvider>
     <entityField>
       <name>PERSON_OBJECTTYPE</name>
@@ -1195,40 +1095,6 @@
         </entityParameter>
       </children>
     </entityConsumer>
-    <entityProvider>
-      <name>NonselfDuplicates</name>
-      <documentation>%aditoprj%/entity/Person_entity/entityfields/nonselfduplicates/documentation.adoc</documentation>
-      <dependencies>
-        <entityDependency>
-          <name>3a4352e2-9686-4c52-9d01-dbfad8c68ea7</name>
-          <entityName>Duplicates_entity</entityName>
-          <fieldName>DuplicatePersonsConsumer</fieldName>
-          <isConsumer v="false" />
-        </entityDependency>
-      </dependencies>
-      <children>
-        <entityParameter>
-          <name>ContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>DuplicateCurrentContactId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyShowContactIds_param</name>
-          <expose v="true" />
-        </entityParameter>
-        <entityParameter>
-          <name>OrgId_param</name>
-          <expose v="false" />
-        </entityParameter>
-        <entityParameter>
-          <name>OnlyOwnSupervised_param</name>
-          <expose v="false" />
-        </entityParameter>
-      </children>
-    </entityProvider>
     <entityConsumer>
       <name>DistrictResponsibles</name>
       <state>INVISIBLE</state>
@@ -1395,52 +1261,6 @@
         </entityActionField>
       </children>
     </entityActionGroup>
-    <entityActionGroup>
-      <name>DuplicateActions</name>
-      <title>Duplicate actions</title>
-      <state>AUTO</state>
-      <stateProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/stateProcess.js</stateProcess>
-      <children>
-        <entityActionField>
-          <name>IntegrateSelectedIntoCurrentAction</name>
-          <title>Integrate selected into current contact</title>
-          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js</onActionProcess>
-          <isMenuAction v="true" />
-          <isObjectAction v="false" />
-          <isSelectionAction v="true" />
-          <iconId>NEON:IMPORT</iconId>
-          <stateProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/stateProcess.js</stateProcess>
-        </entityActionField>
-        <entityActionField>
-          <name>IntegrateCurrentIntoSelectedAction</name>
-          <title>Integrate current into selected contact</title>
-          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js</onActionProcess>
-          <isMenuAction v="true" />
-          <isObjectAction v="false" />
-          <isSelectionAction v="true" />
-          <iconId>NEON:EXPORT</iconId>
-          <stateProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/stateProcess.js</stateProcess>
-        </entityActionField>
-        <entityActionField>
-          <name>IgnoreDuplicate</name>
-          <title>Ignore Duplicate</title>
-          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/children/ignoreduplicate/onActionProcess.js</onActionProcess>
-          <isMenuAction v="true" />
-          <isObjectAction v="false" />
-          <isSelectionAction v="true" />
-          <iconId>VAADIN:CLOSE</iconId>
-          <stateProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/children/ignoreduplicate/stateProcess.js</stateProcess>
-        </entityActionField>
-        <entityActionField>
-          <name>IgnoreWholeCluster</name>
-          <title>Ignore whole cluster</title>
-          <onActionProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/children/ignorewholecluster/onActionProcess.js</onActionProcess>
-          <isObjectAction v="false" />
-          <iconId>VAADIN:CLOSE</iconId>
-          <stateProcess>%aditoprj%/entity/Person_entity/entityfields/duplicateactions/children/ignorewholecluster/stateProcess.js</stateProcess>
-        </entityActionField>
-      </children>
-    </entityActionGroup>
     <entityActionField>
       <name>newEmail</name>
       <title>Write email</title>
@@ -1499,6 +1319,26 @@
       <iconId>VAADIN:CURLY_BRACKETS</iconId>
       <stateProcess>%aditoprj%/entity/Person_entity/entityfields/openadminview/stateProcess.js</stateProcess>
     </entityActionField>
+    <entityParameter>
+      <name>FilterPreSet_param</name>
+      <expose v="true" />
+    </entityParameter>
+    <entityConsumer>
+      <name>Duplicates</name>
+      <selectionMode>MULTI</selectionMode>
+      <selectionModeProcess>%aditoprj%/entity/Person_entity/entityfields/duplicates/selectionModeProcess.js</selectionModeProcess>
+      <dependency>
+        <name>dependency</name>
+        <entityName>DuplicatePerson_entity</entityName>
+        <fieldName>#PROVIDER</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>Obj_param</name>
+          <valueProcess>%aditoprj%/entity/Person_entity/entityfields/duplicates/children/obj_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
     <entityConsumer>
       <name>ContactCommunicationSettings</name>
       <refreshParent v="true" />
@@ -1703,11 +1543,13 @@
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>STANDARD_EMAIL_COMMUNICATION.value</name>
+          <expression>%aditoprj%/entity/Person_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js</expression>
           <isFilterable v="false" />
           <isLookupFilter v="false" />
         </dbRecordFieldMapping>
         <dbRecordFieldMapping>
           <name>STANDARD_PHONE_COMMUNICATION.value</name>
+          <expression>%aditoprj%/entity/Person_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js</expression>
           <isFilterable v="false" />
           <isLookupFilter v="false" />
         </dbRecordFieldMapping>
@@ -1857,6 +1699,13 @@
           <filterConditionProcess>%aditoprj%/entity/Person_entity/recordcontainers/db/filterextensions/supervisorassignment/filterConditionProcess.js</filterConditionProcess>
           <filtertype>BASIC</filtertype>
         </filterExtension>
+        <filterExtension>
+          <name>Duplicates_filter</name>
+          <title>Duplicates</title>
+          <contentType>NUMBER</contentType>
+          <filterConditionProcess>%aditoprj%/entity/Person_entity/recordcontainers/db/filterextensions/duplicates_filter/filterConditionProcess.js</filterConditionProcess>
+          <filtertype>BASIC</filtertype>
+        </filterExtension>
         <filterExtension>
           <name>Communication_Mail_filter</name>
           <title>Communication: Mail</title>
diff --git a/entity/Person_entity/entityfields/deletefunction/onActionProcess.js b/entity/Person_entity/entityfields/deletefunction/onActionProcess.js
index 083e2d8b0d3d0649e0984e06b3947a6ae709fd3e..324c438c9d7953e5177748efa8679fe55ab0e8f6 100644
--- a/entity/Person_entity/entityfields/deletefunction/onActionProcess.js
+++ b/entity/Person_entity/entityfields/deletefunction/onActionProcess.js
@@ -21,7 +21,7 @@ if(contactIds > 1)
     
     entities.deleteRow(config);
     
-    DuplicateScannerUtils.deleteCachedDuplicate(contactId);
+    DuplicateScannerUtils.deleteHasDuplicateEntries("Person_entity", [contactId]);
 
     new AttributeRelationQuery(contactId, null, ContextUtils.getCurrentContextId())
         .deleteAllAttributes();
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/ignoreduplicate/onActionProcess.js b/entity/Person_entity/entityfields/duplicateactions/children/ignoreduplicate/onActionProcess.js
deleted file mode 100644
index c9289cbd0ef896d7dbcf5eae668bac8a87e861da..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/duplicateactions/children/ignoreduplicate/onActionProcess.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import("system.neon");
-import("system.vars");
-import("DuplicateScanner_lib");
-
-let sourceContactId = vars.get("$param.DuplicateCurrentContactId_param");
-let selectedContactId = vars.get("$sys.selection");
-let clusterId = DuplicateScannerUtils.getClusterId(sourceContactId);
-DuplicateScannerUtils.createUnrelatedDuplicateRelation(sourceContactId, selectedContactId, clusterId);
-
-neon.refreshAll();
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/ignoreduplicate/stateProcess.js b/entity/Person_entity/entityfields/duplicateactions/children/ignoreduplicate/stateProcess.js
deleted file mode 100644
index b736eb15f5b18e779e37281fe216c9297ca86191..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/duplicateactions/children/ignoreduplicate/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState != null && actionState != "1")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/ignorewholecluster/onActionProcess.js b/entity/Person_entity/entityfields/duplicateactions/children/ignorewholecluster/onActionProcess.js
deleted file mode 100644
index f74997cb1d72c3baa56b1dd12a42ba77eb782769..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/duplicateactions/children/ignorewholecluster/onActionProcess.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import("system.logging");
-import("system.neon");
-import("system.vars");
-import("DuplicateScanner_lib");
-import("system.notification");
-
-let contactId = vars.get("$field.CONTACTID");
-logging.log("contactId -> " + contactId);
-let clusterId = DuplicateScannerUtils.getClusterId(contactId);
-logging.log("clusterId -> " + clusterId);
-let duplicateContactIdsInClusterRay = DuplicateScannerUtils.getCachedDuplicatesForClusterId(clusterId)
-logging.log("duplicateContactIdsInClusterRay -> " + duplicateContactIdsInClusterRay);
-if(duplicateContactIdsInClusterRay.length > 1)
-{
-    let referenceDuplicateId = duplicateContactIdsInClusterRay[0];
-    for (let i = 1; i < duplicateContactIdsInClusterRay.length; i++) 
-    {
-        DuplicateScannerUtils.createUnrelatedDuplicateRelation(referenceDuplicateId, duplicateContactIdsInClusterRay[i], clusterId);
-    }
-    neon.refreshAll();
-    
-//    var params = {};
-//    params["TargetEntity"] = "Person_entity";
-//        
-//    neon.openContext("Duplicates", "DuplicatesOverview_view", null, neon.OPERATINGSTATE_VIEW, params);
-}
-
-
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/ignorewholecluster/stateProcess.js b/entity/Person_entity/entityfields/duplicateactions/children/ignorewholecluster/stateProcess.js
deleted file mode 100644
index fdd913ad06bf2815da3127d405d21b258c4ad795..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/duplicateactions/children/ignorewholecluster/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState != null && actionState != "2")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/stateProcess.js b/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/stateProcess.js
deleted file mode 100644
index b736eb15f5b18e779e37281fe216c9297ca86191..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState != null && actionState != "1")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/stateProcess.js b/entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/stateProcess.js
deleted file mode 100644
index b736eb15f5b18e779e37281fe216c9297ca86191..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState != null && actionState != "1")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/duplicateactions/stateProcess.js b/entity/Person_entity/entityfields/duplicateactions/stateProcess.js
deleted file mode 100644
index 5b8b24021ddfcba34a258bf7af7d4ec5ec65852a..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/duplicateactions/stateProcess.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.neon");
-import("system.result");
-
-//Actions to show in the duplicates view inside the persons main view
-
-let actionState = vars.get("$param.DuplicateActionsControl_param");
-
-if(actionState == null || actionState == "0")//todo replace with keyword
-    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/duplicates/children/obj_param/valueProcess.js b/entity/Person_entity/entityfields/duplicates/children/obj_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..59dc755e2ab02e6af201c71f835676e5172180bc
--- /dev/null
+++ b/entity/Person_entity/entityfields/duplicates/children/obj_param/valueProcess.js
@@ -0,0 +1,23 @@
+import("system.vars");
+import("system.result");
+
+result.string(JSON.stringify({
+    CONTACTID: vars.get("$field.CONTACTID"),
+    FIRSTNAME: vars.get("$field.FIRSTNAME"),
+    MIDDLENAME: vars.get("$field.MIDDLENAME"),
+    LASTNAME: vars.get("$field.LASTNAME"),
+    DATEOFBIRTH: vars.get("$field.DATEOFBIRTH"),
+    GENDER: vars.get("$field.GENDER"),
+    SALUTATION: vars.get("$field.SALUTATION"),
+    TITLE: vars.get("$field.TITLE"),
+    TITLESUFFIX: vars.get("$field.TITLESUFFIX"),
+    POSITION: vars.get("$field.POSITION"),
+    STATUS: vars.get("$field.STATUS"),
+    DEPARTMENT: vars.get("$field.DEPARTMENT"),
+    STANDARD_ADDRESS: vars.get("$field.STANDARD_ADDRESS"),
+    STANDARD_CITY: vars.get("$field.STANDARD_CITY"),
+    STANDARD_COUNTRY: vars.get("$field.STANDARD_COUNTRY"),
+    STANDARD_EMAIL_COMMUNICATION: vars.get("$field.STANDARD_EMAIL_COMMUNICATION"),
+    STANDARD_PHONE_COMMUNICATION: vars.get("$field.STANDARD_PHONE_COMMUNICATION"),
+    STANDARD_ZIP: vars.get("$field.STANDARD_ZIP")
+}));
diff --git a/entity/Person_entity/entityfields/duplicates/selectionModeProcess.js b/entity/Person_entity/entityfields/duplicates/selectionModeProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..c92317456ba1a7476401171e875526c8eff6fa76
--- /dev/null
+++ b/entity/Person_entity/entityfields/duplicates/selectionModeProcess.js
@@ -0,0 +1,9 @@
+import("system.result");
+import("system.vars");
+import("system.neon");
+
+result.string(
+    vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW ||
+        vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT ?
+    "NONE" : "MULTI"
+);
diff --git a/entity/Person_entity/entityfields/nonselfduplicates/documentation.adoc b/entity/Person_entity/entityfields/nonselfduplicates/documentation.adoc
deleted file mode 100644
index d7964dadc0c8a8c7d5ea6856c3b82d07ccbcc361..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/nonselfduplicates/documentation.adoc
+++ /dev/null
@@ -1,3 +0,0 @@
-Provides contact duplicate-records without the `Person_entity` scope, for example for the `Duplicates_entity`.
-
-The provider is named `NonselfDuplicates` to differentiate this provider and the `SelfDuplicates`-provider.
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/selfduplicates/documentation.adoc b/entity/Person_entity/entityfields/selfduplicates/documentation.adoc
deleted file mode 100644
index 4f02d8b1a256bb4d0a791bab46cf0cda23790c84..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/selfduplicates/documentation.adoc
+++ /dev/null
@@ -1 +0,0 @@
-Provides contact duplicate-records within the `Person_entity` scope itself.
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/selfduplicatesuncached/children/duplicateactionscontrol_param/valueProcess.js b/entity/Person_entity/entityfields/selfduplicatesuncached/children/duplicateactionscontrol_param/valueProcess.js
deleted file mode 100644
index 81570217c3ecd3cf76deb5e14d7ac0a6121a59bb..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/selfduplicatesuncached/children/duplicateactionscontrol_param/valueProcess.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import("system.result");
-result.string("1");//todo use keyword
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/selfduplicatesuncached/children/duplicatecurrentcontactid_param/valueProcess.js b/entity/Person_entity/entityfields/selfduplicatesuncached/children/duplicatecurrentcontactid_param/valueProcess.js
deleted file mode 100644
index 821415ae694dd9c3d98a7703f4c59b81a37f524b..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/selfduplicatesuncached/children/duplicatecurrentcontactid_param/valueProcess.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import("system.vars");
-import("system.result");
-result.string(vars.get("$field.CONTACTID"));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/selfduplicatesuncached/children/excludedcontactids_param/valueProcess.js b/entity/Person_entity/entityfields/selfduplicatesuncached/children/excludedcontactids_param/valueProcess.js
deleted file mode 100644
index 849632882bbabd4e65dfb25c7dc984366bde5116..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/selfduplicatesuncached/children/excludedcontactids_param/valueProcess.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("system.result");
-import("DuplicateScanner_lib");
-
-let unrelatedIds = DuplicateScannerUtils.getUnrelatedRelationsForDuplicate(vars.get("$field.CONTACTID"));
-result.string(JSON.stringify(unrelatedIds));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/selfduplicatesuncached/children/onlyshowcontactids_param/valueProcess.js b/entity/Person_entity/entityfields/selfduplicatesuncached/children/onlyshowcontactids_param/valueProcess.js
deleted file mode 100644
index 8fa370156eae601ebddb1f7b6f024650a156de52..0000000000000000000000000000000000000000
--- a/entity/Person_entity/entityfields/selfduplicatesuncached/children/onlyshowcontactids_param/valueProcess.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import("system.indexsearch");
-import("system.project");
-import("system.logging");
-import("system.vars");
-import("DuplicateScanner_lib");
-import("system.result");
-
-var scannerName = "PersonDuplicates";
-var targetEntity = "Person_entity";
-var valuesToCheck = {};
-var entityFieldsToLoad = DuplicateScannerUtils.getEntityFieldObjectFromConfig(scannerName, targetEntity);
-
-var idsForEmptyResult = JSON.stringify(["nodata"]);
-
-if (entityFieldsToLoad == null)
-    result.string(idsForEmptyResult);
-else
-{
-    //Read the values of all available entity fields and write the fieldname7value combination
-    //as key/value pairs into an object. This is used to trigger the scan for duplicates
-
-    vars.get("$field.STANDARD_CITY");
-    vars.get("$field.STANDARD_ZIP");
-    vars.get("$field.STANDARD_ADDRESS");
-    vars.get("$field.FIRSTNAME");
-    vars.get("$field.LASTNAME");
-    vars.get("$field.PersAddresses.insertedRows")
-    vars.get("$field.PersAddresses.changedRows")
-    vars.get("$field.PersAddresses.deletedRows")
-    
-    var allFieldsToLoad = entityFieldsToLoad.entityFields.concat(entityFieldsToLoad.entityIdField);
-    allFieldsToLoad.forEach(function (field)
-    {
-        var fieldValue = vars.get("$field." + field);
-        if (fieldValue)
-            valuesToCheck[field] = fieldValue;
-    });
-    
-    var scanResults = [];
-    
-    //don't search if only the id field has a value
-    var fieldsToCheck = Object.keys(valuesToCheck);
-    if (!(fieldsToCheck.length === 0 || (fieldsToCheck.length === 1 && entityFieldsToLoad.entityIdField in valuesToCheck)))
-        scanResults = DuplicateScannerUtils.scanForDuplicates(scannerName, targetEntity, valuesToCheck, null) || [];
-    
-    var duplicateIds = scanResults.map(function (duplicate)
-    {
-        return duplicate[indexsearch.FIELD_ID];
-    });
-
-    /*
-     * To achieve that if there are no duplicates, no contacts should be shown and therefore returned by the 
-     * recordcontainer, an invalid id gets returned. It then is used in the conditionProcess to load the duplicates.
-     * Because of its invalidity, no records are shown.
-     */
-    if (duplicateIds.length == 0)
-        result.string(idsForEmptyResult);
-    else
-        result.string(JSON.stringify(duplicateIds));
-}
\ No newline at end of file
diff --git a/entity/Person_entity/initFilterProcess.js b/entity/Person_entity/initFilterProcess.js
index f64ef8977cc3f20a910f104d6196bfe90c43fc34..afecc1ede02d6f412681545610696b1efa17dc90 100644
--- a/entity/Person_entity/initFilterProcess.js
+++ b/entity/Person_entity/initFilterProcess.js
@@ -1,14 +1,14 @@
-import("system.entities");
+import("system.neon");
+import("system.vars");
 import("Keyword_lib");
 import("KeywordRegistry_basic");
 import("system.result");
-import("system.vars");
-import("system.neon");
 
-if (vars.get("$sys.presentationmode") === neon.CONTEXT_PRESENTATIONMODE_FILTER) 
+var filter = vars.get("$param.FilterPreSet_param");
+if(!filter && vars.get("$sys.presentationmode") === neon.CONTEXT_PRESENTATIONMODE_FILTER) 
 {
     var statusInactive = $KeywordRegistry.contactStatus$inactive();
-    var filter = {
+    filter = JSON.stringify({
         type: "group",
         operator: "AND",
         childs: [{
@@ -19,7 +19,9 @@ if (vars.get("$sys.presentationmode") === neon.CONTEXT_PRESENTATIONMODE_FILTER)
             key: statusInactive,
             value: KeywordUtils.getViewValue($KeywordRegistry.contactStatus(), statusInactive)
         }]
-    };
-
-    result.string(JSON.stringify(filter));
-}
\ No newline at end of file
+    });
+}
+if(filter)
+{
+    result.string(filter);
+}
diff --git a/entity/Person_entity/recordcontainers/db/filterextensions/duplicates_filter/filterConditionProcess.js b/entity/Person_entity/recordcontainers/db/filterextensions/duplicates_filter/filterConditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..6a53c389f9916191793616c6e838f781cd140e7c
--- /dev/null
+++ b/entity/Person_entity/recordcontainers/db/filterextensions/duplicates_filter/filterConditionProcess.js
@@ -0,0 +1,16 @@
+import("system.result");
+import("Sql_lib");
+import("system.vars");
+import("DuplicateScanner_lib");
+
+var sqlOperator = SqlUtils.getSqlConditionalOperator(vars.get("$local.operator"));
+
+result.string(newWhere(
+    "CONTACT.CONTACTID",
+    DuplicateScannerUtils.getDuplicateConditionalListSql(
+        ["Person_entity"],
+        vars.get("$local.rawvalue"),
+        sqlOperator, true
+    ),
+    SqlBuilder.IN()
+));
diff --git a/entity/Person_entity/recordcontainers/db/onDBDelete.js b/entity/Person_entity/recordcontainers/db/onDBDelete.js
index 56d4461823493222635f99ab42de361ec497f838..26d095805ed1fc2a0f944c3a99c4f7e49475057a 100644
--- a/entity/Person_entity/recordcontainers/db/onDBDelete.js
+++ b/entity/Person_entity/recordcontainers/db/onDBDelete.js
@@ -6,7 +6,7 @@ import("system.vars");
 import("DuplicateScanner_lib");
 
 var contactId = vars.get("$field.CONTACTID");
-DuplicateScannerUtils.deleteCachedDuplicate(contactId);
+DuplicateScannerUtils.deleteHasDuplicateEntries("Person_entity", [contactId]);
 
 new AttributeRelationQuery(contactId, null, ContextUtils.getCurrentContextId())
     .deleteAllAttributes();
diff --git a/entity/Person_entity/recordcontainers/db/onDBInsert.js b/entity/Person_entity/recordcontainers/db/onDBInsert.js
index 3385c553d10f5332ad4c946ea239bf7bcdf4b6bc..8d1c5ddea0bed7f36862a8423508f130794a3a07 100644
--- a/entity/Person_entity/recordcontainers/db/onDBInsert.js
+++ b/entity/Person_entity/recordcontainers/db/onDBInsert.js
@@ -4,6 +4,9 @@ import("Sql_lib");
 import("system.db");
 import("DataPrivacy_lib");
 import("system.vars");
+import("DuplicateScanner_lib");
+
+DuplicateScannerUtils.updateHasDuplicateEntry("Person_entity");
 
 //let targetEntity = "Person_entity";
 let contactId = vars.get("$local.uid");
diff --git a/entity/Person_entity/recordcontainers/db/onDBUpdate.js b/entity/Person_entity/recordcontainers/db/onDBUpdate.js
index 0c29899fd4393c2528219ef9dc213eb151d10b18..100f1f714f83179a745ab4c332591ab988c0e60b 100644
--- a/entity/Person_entity/recordcontainers/db/onDBUpdate.js
+++ b/entity/Person_entity/recordcontainers/db/onDBUpdate.js
@@ -8,6 +8,9 @@ import("Person_lib");
 import("Communication_lib");
 import("Entity_lib");
 import("StandardObject_lib");
+import("DuplicateScanner_lib");
+
+DuplicateScannerUtils.updateHasDuplicateEntry("Person_entity");
 
 var localChanged = vars.get("$local.changed");
 var orgChanged = false;
diff --git a/entity/Person_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js b/entity/Person_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..41ef07ff58ec51eda018bed12cb5b0b2b657c348
--- /dev/null
+++ b/entity/Person_entity/recordcontainers/db/recordfieldmappings/standard_email_communication.value/expression.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Communication_lib");
+
+var res = CommUtil.getStandardSubSqlMail();
+result.string(res);
\ No newline at end of file
diff --git a/entity/Person_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js b/entity/Person_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js
new file mode 100644
index 0000000000000000000000000000000000000000..320ae40ad1ba794b4e759037fa0f382b9af67696
--- /dev/null
+++ b/entity/Person_entity/recordcontainers/db/recordfieldmappings/standard_phone_communication.value/expression.js
@@ -0,0 +1,5 @@
+import("system.result");
+import("Communication_lib");
+
+var res = CommUtil.getStandardSubSqlPhone();
+result.string(res);
\ No newline at end of file
diff --git a/entity/QuickEntry_entity/QuickEntry_entity.aod b/entity/QuickEntry_entity/QuickEntry_entity.aod
index 9ce66331b3242cbbba9001036cd3e65dc920d156..2c460f59b8748cc6d79d1046db867b5d3614130c 100644
--- a/entity/QuickEntry_entity/QuickEntry_entity.aod
+++ b/entity/QuickEntry_entity/QuickEntry_entity.aod
@@ -237,6 +237,7 @@
         <entityParameter>
           <name>ContactIds_param</name>
           <valueProcess>%aditoprj%/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/valueProcess.js</valueProcess>
+          <documentation>%aditoprj%/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/documentation.adoc</documentation>
         </entityParameter>
         <entityParameter>
           <name>WithPrivatePersons_param</name>
diff --git a/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/documentation.adoc b/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/documentation.adoc
new file mode 100644
index 0000000000000000000000000000000000000000..667cdd59e70d81d319b110ff44e24478616dae1d
--- /dev/null
+++ b/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/documentation.adoc
@@ -0,0 +1,2 @@
+returns a list of duplicate ids
+the index will be searched via the values entered in the edit frame
\ No newline at end of file
diff --git a/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/valueProcess.js b/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/valueProcess.js
index 68ef6879ab48622e909ec092bb0314156746f96e..98b27caa01f480c5b39a7c62f68970a13519812b 100644
--- a/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/valueProcess.js
+++ b/entity/QuickEntry_entity/entityfields/organdpersduplicates/children/contactids_param/valueProcess.js
@@ -2,6 +2,7 @@ import("system.indexsearch");
 import("system.vars");
 import("DuplicateScanner_lib");
 import("system.result");
+import("IndexSearch_lib");
 
 //trigger refresh
 vars.get("$field.FIRSTNAME");
@@ -11,11 +12,11 @@ var uid = vars.get("$field.UID");
 var idsForEmptyResult = JSON.stringify(["nodata"]);
 var duplicateScans = [];
 
-duplicateScans.push(["PersonDuplicates", "Person_entity", {"CONTACTID" : uid}]);
+duplicateScans.push(["Person_entity", {"CONTACTID" : uid}]);
 
 vars.get("$field.Contacts.insertedRows").forEach(function (contact)
 {
-    duplicateScans.push(["PersonDuplicates", "Person_entity", contact]);
+    duplicateScans.push(["Person_entity", contact]);
 });
 
 var organisationName = vars.get("$field.ORGANISATION_NAME");
@@ -34,7 +35,7 @@ if (organisationName || firstOrganisationAddress)
         address = firstOrganisationAddress["ADDRESS"];
     }
     
-    duplicateScans.push(["OrganisationDuplicates", "Organisation_entity", {
+    duplicateScans.push(["Organisation_entity", {
         "CONTACTID" : uid,
         "NAME" : organisationName,
         "STANDARD_CITY" : city,
@@ -43,9 +44,9 @@ if (organisationName || firstOrganisationAddress)
     }]);
 }
 
-var duplicates = duplicateScans.reduce(function (duplicateArr, [scannerName, entity, fieldValues])
+var duplicates = duplicateScans.reduce(function (duplicateArr, [entity, fieldValues])
 {
-    return duplicateArr.concat(_getDuplicates(scannerName, entity, fieldValues));
+    return duplicateArr.concat(_getDuplicates(entity, fieldValues));
 }, []);
 
 if (duplicates.length === 0)
@@ -54,34 +55,22 @@ else
     result.string(JSON.stringify(duplicates));
 
 
-function _getDuplicates (pScannerName, pEntity, pEntityFieldValues)
+function _getDuplicates(pEntity, pEntityFieldValues)
 {
-    var fieldsToLoad = DuplicateScannerUtils.getEntityFieldObjectFromConfig(pScannerName, pEntity);
-    if (fieldsToLoad == null)
-        return [];
+    var scanner = DuplicateScannerUtils.getScannerByEntity(pEntity);
+    var indexsearchFilter = IndexsearchFilterUtils.fromFilter(scanner.filter);
+    var entityFields = indexsearchFilter.getFields();
+    entityFields.add(scanner.idField);
     
     var valuesToCheck = {};
-    
-    var allFieldsToLoad = fieldsToLoad.entityFields.concat(fieldsToLoad.entityIdField);
-    allFieldsToLoad.forEach(function (field)
-    {
+    entityFields.forEach(function(field) {
         var fieldValue = field in pEntityFieldValues
             ? pEntityFieldValues[field]
-            : vars.get("$field." + field);
-        if (fieldValue)
-            valuesToCheck[field] = fieldValue;
-    });
-    
-    //don't search if only the id field has a value
-    var fieldsToCheck = Object.keys(valuesToCheck);
-    if (fieldsToCheck.length === 0 || (fieldsToCheck.length === 1 && fieldsToLoad.entityIdField in valuesToCheck))
-        return [];
-    
-    var scanResults = DuplicateScannerUtils.scanForDuplicates(pScannerName, pEntity, valuesToCheck, null) || [];
-    var duplicateIds = scanResults.map(function (duplicate)
-    {
-        return duplicate[indexsearch.FIELD_ID];
+            : vars.exists("$field." + field) ? vars.get("$field." + field) : "";
+        valuesToCheck[field] = fieldValue || "";
     });
 
-    return duplicateIds;
+    var indexPattern = indexsearchFilter.buildQuery(valuesToCheck);
+    var duplicateIds = DuplicateScannerUtils.getDuplicateIds(pEntity, indexPattern, valuesToCheck[scanner.idField]);
+    return DuplicateScannerUtils.filterIgnored(pEntity, valuesToCheck[scanner.idField], duplicateIds);
 }
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index 1fc9a21e9d608dff16a653d76fef388a63123cab..1cf98cfdedf9bc9697cc8ae637205adb68bc21b2 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -8076,6 +8076,12 @@
     <entry>
       <key>EML files can't be edited here. You can download, edit and reupload the template to change the content.</key>
     </entry>
+    <entry>
+      <key>The duplicate row corrosponding to %0 has been rebuild</key>
+    </entry>
+    <entry>
+      <key>Duplicaterow rebuild</key>
+    </entry>
     <entry>
       <key>Edit HTML</key>
     </entry>
@@ -8406,6 +8412,28 @@
     <entry>
       <key>Redirect needs a full Url with http/https</key>
     </entry>
+    <entry>
+      <key>${IGNORE_DUPLICATE}</key>
+    </entry>
+    <entry>
+      <key>${UNIGNORE_DUPLICATE}</key>
+    </entry>
+    <entry>
+      <key>View all duplicates from this scanner</key>
+    </entry>
+    <entry>
+      <key>Rebuild all duplicates from the selected scanners</key>
+    </entry>
+    <entry>
+      <key>View duplicates</key>
+    </entry>
+    <entry>
+      <key>Rebuild selected entries</key>
+    </entry>
+    <entry>
+      <key>Ignored</key>
+      <value>Ignoriert</value>
+    </entry>
     <entry>
       <key>Not enough room in campaignstep</key>
     </entry>
diff --git a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
index 3a6dbc11f1f96b584186cc24f0c6b29d832e1b0c..c239d448334a65386356e07724d1066007037fb4 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -10984,6 +10984,14 @@ Bitte Datumseingabe prüfen</value>
     <entry>
       <key>Calendar week</key>
     </entry>
+    <entry>
+      <key>Duplicaterow rebuild</key>
+      <value>Dubletten neu berechnet</value>
+    </entry>
+    <entry>
+      <key>The duplicate row corrosponding to %0 has been rebuild</key>
+      <value>Die Dupletten des %0 filters wurden neu berechnet</value>
+    </entry>
     <entry>
       <key>HTML Editor</key>
     </entry>
@@ -11035,6 +11043,34 @@ Bitte Datumseingabe prüfen</value>
       <key>Internal responsible</key>
       <value>Intern: Gebietsverantwortlich</value>
     </entry>
+    <entry>
+      <key>${IGNORE_DUPLICATE}</key>
+      <value>Datensatz ist keine Dublette</value>
+    </entry>
+    <entry>
+      <key>${UNIGNORE_DUPLICATE}</key>
+      <value>Datensatz ist eine Dublette</value>
+    </entry>
+    <entry>
+      <key>Rebuild selected entries</key>
+      <value>Ausgewählte Einträge neu aufbauen</value>
+    </entry>
+    <entry>
+      <key>Rebuild all duplicates from the selected scanners</key>
+      <value>Ausgewählte Einträge neu aufbauen</value>
+    </entry>
+    <entry>
+      <key>View duplicates</key>
+      <value>Dubletten anzeigen</value>
+    </entry>
+    <entry>
+      <key>View all duplicates from this scanner</key>
+      <value>Alle Duplikate dieses Scanners anzeigen</value>
+    </entry>
+    <entry>
+      <key>Ignored</key>
+      <value>Ignoriert</value>
+    </entry>
     <entry>
       <key>Invalid attribute count</key>
       <value>Unzulässige Attributanzahl</value>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index 775c68dacdaa8027b09cc035d8132b22dd07b3d7..4f213025460dede50cbccfd744b40eaa5a74b697 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -8325,6 +8325,9 @@
     <entry>
       <key>Invalid value</key>
     </entry>
+    <entry>
+      <key>Object not found</key>
+    </entry>
     <entry>
       <key>Value is too big, the maximum is %0</key>
     </entry>
@@ -8490,6 +8493,29 @@
     <entry>
       <key>Redirect needs a full Url with http/https</key>
     </entry>
+    <entry>
+      <key>${IGNORE_DUPLICATE}</key>
+      <value>Record is not a duplicate</value>
+    </entry>
+    <entry>
+      <key>${UNIGNORE_DUPLICATE}</key>
+      <value>Record is a duplicate</value>
+    </entry>
+    <entry>
+      <key>View all duplicates from this scanner</key>
+    </entry>
+    <entry>
+      <key>Rebuild all duplicates from the selected scanners</key>
+    </entry>
+    <entry>
+      <key>View duplicates</key>
+    </entry>
+    <entry>
+      <key>Rebuild selected entries</key>
+    </entry>
+    <entry>
+      <key>Ignored</key>
+    </entry>
     <entry>
       <key>Not enough room in campaignstep</key>
     </entry>
diff --git a/neonContext/DuplicateOrganisation/DuplicateOrganisation.aod b/neonContext/DuplicateOrganisation/DuplicateOrganisation.aod
new file mode 100644
index 0000000000000000000000000000000000000000..180a84c994ec66d9360520047ed577612fce6b84
--- /dev/null
+++ b/neonContext/DuplicateOrganisation/DuplicateOrganisation.aod
@@ -0,0 +1,24 @@
+<?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>DuplicateOrganisation</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <previewView>DuplicateOrganisationPreview_view</previewView>
+  <entity>DuplicateOrganisation_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>c62620c2-33e3-4b76-bd76-0c1be1d516eb</name>
+      <view>DuplicateOrganisationFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>512ef5c4-dc95-4ef1-81e0-d45479249c2e</name>
+      <view>DuplicateOrganisationEdit_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>07bbb126-8b4b-4f3c-a2c8-30409e0ee826</name>
+    </neonViewReference>
+    <neonViewReference>
+      <name>2e59d859-6b5f-4bb5-a47b-1225164140ed</name>
+      <view>DuplicateOrganisationPreview_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/DuplicatePerson/DuplicatePerson.aod b/neonContext/DuplicatePerson/DuplicatePerson.aod
new file mode 100644
index 0000000000000000000000000000000000000000..6d8e12f75aafc815feb17c94b9165e142be633e6
--- /dev/null
+++ b/neonContext/DuplicatePerson/DuplicatePerson.aod
@@ -0,0 +1,27 @@
+<?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>DuplicatePerson</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <previewView>DuplicatePersonPreview_view</previewView>
+  <entity>DuplicatePerson_entity</entity>
+  <references>
+    <neonViewReference>
+      <name>930c8a65-e92e-4222-9ca7-cbc663ebf274</name>
+      <view>DuplicatePersonFilter_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>f54e544a-2279-41ec-a7b3-44e11989a736</name>
+      <view>DuplicatePersonEdit_view</view>
+    </neonViewReference>
+    <neonViewReference>
+      <name>88155af6-074d-4683-b27e-20a8ef75dd8a</name>
+    </neonViewReference>
+    <neonViewReference>
+      <name>fb801ec5-ec73-4d6d-be3e-f2d78a57716f</name>
+    </neonViewReference>
+    <neonViewReference>
+      <name>596cd813-22e1-4ba6-96d5-fefefbb800cf</name>
+      <view>DuplicatePersonPreview_view</view>
+    </neonViewReference>
+  </references>
+</neonContext>
diff --git a/neonContext/DuplicateScannerResultFieldConfig/DuplicateScannerResultFieldConfig.aod b/neonContext/DuplicateScannerResultFieldConfig/DuplicateScannerResultFieldConfig.aod
deleted file mode 100644
index 79d97363fbb75d25de88168f1dbd76713df82073..0000000000000000000000000000000000000000
--- a/neonContext/DuplicateScannerResultFieldConfig/DuplicateScannerResultFieldConfig.aod
+++ /dev/null
@@ -1,12 +0,0 @@
-<?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>DuplicateScannerResultFieldConfig</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <entity>DuplicateScannerResultFieldConfig_entity</entity>
-  <references>
-    <neonViewReference>
-      <name>4bab12e9-c4c3-450f-bfcf-8ecbec1f994c</name>
-      <view>DuplicateScannerResultFieldConfigEdit_view</view>
-    </neonViewReference>
-  </references>
-</neonContext>
diff --git a/neonContext/Duplicates/Duplicates.aod b/neonContext/Duplicates/Duplicates.aod
deleted file mode 100644
index 5de0f3a1913c9bb49aecba2c8ea9998e23ad1faf..0000000000000000000000000000000000000000
--- a/neonContext/Duplicates/Duplicates.aod
+++ /dev/null
@@ -1,50 +0,0 @@
-<?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>Duplicates</name>
-  <title>Duplicates</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <filterView>DuplicatesOverview_view</filterView>
-  <entity>Duplicates_entity</entity>
-  <references>
-    <neonViewReference>
-      <name>d8994f4c-3abf-4ff1-8bdb-f12e527df655</name>
-      <view>PersonDuplicatesFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>de287a3b-1d6a-435c-b65e-d833c1751edf</name>
-      <view>DuplicatesOverview_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>5bdeb931-4e69-4520-bbc9-94fb17679331</name>
-      <view>PersonDublicatesTab_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>70cb2e96-5bc1-46cb-982f-b27db5d143d2</name>
-      <view>PersonClusterMain_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>7cdb6ca7-e99d-4eb6-897a-0953157bf62f</name>
-      <view>DuplicatesUnrelatedCluster_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>4b9a1a26-e14f-4246-b474-8bfb3e3a95b0</name>
-      <view>OrganisationDuplicatesTab_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>f9b46eab-7417-4f61-b7cd-dc772c04ddc0</name>
-      <view>OrganisationDuplicatesFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>d68a425a-037a-4725-8dc1-b0afac277bdd</name>
-      <view>OrganisationUnrelatedDuplicates_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>4c1fc406-1c83-4fb6-9059-e45ff5c80756</name>
-      <view>OrganisationClusterMain_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>2400acfd-50e4-472d-b69c-368b9d25b6c6</name>
-      <view>PersonClusterPreview_view</view>
-    </neonViewReference>
-  </references>
-</neonContext>
diff --git a/neonContext/DuplicatesUnrelated/DuplicatesUnrelated.aod b/neonContext/DuplicatesUnrelated/DuplicatesUnrelated.aod
deleted file mode 100644
index 56bf4fd8574682d13f54fd2c5628fde361465b46..0000000000000000000000000000000000000000
--- a/neonContext/DuplicatesUnrelated/DuplicatesUnrelated.aod
+++ /dev/null
@@ -1,16 +0,0 @@
-<?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>DuplicatesUnrelated</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <entity>DuplicatesUnrelated_entity</entity>
-  <references>
-    <neonViewReference>
-      <name>0b5cbd31-cfa1-4ee8-8bd2-b4772ac95953</name>
-      <view>DuplicatesUnrelatedPersonFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>433a665e-63ac-4281-8f7c-08603362daf7</name>
-      <view>DuplicatesUnrelatedOrganisationFilter_view</view>
-    </neonViewReference>
-  </references>
-</neonContext>
diff --git a/neonContext/Person/Person.aod b/neonContext/Person/Person.aod
index 1e80db9a3c4e51a1331d5a9a15196dde803ed08f..bc1cf78630928ad1994e887836ce2aaba9e2ca81 100644
--- a/neonContext/Person/Person.aod
+++ b/neonContext/Person/Person.aod
@@ -61,7 +61,6 @@
     </neonViewReference>
     <neonViewReference>
       <name>2a6c44be-53e2-469e-84b3-615841bd4430</name>
-      <view>PersonDuplicateEditview_view</view>
     </neonViewReference>
     <neonViewReference>
       <name>627518cc-15b0-4f0d-b6f3-ec06172e7c4e</name>
diff --git a/neonView/PersonDuplicateEditview_view/PersonDuplicateEditview_view.aod b/neonView/DuplicateOrganisationEdit_view/DuplicateOrganisationEdit_view.aod
similarity index 55%
rename from neonView/PersonDuplicateEditview_view/PersonDuplicateEditview_view.aod
rename to neonView/DuplicateOrganisationEdit_view/DuplicateOrganisationEdit_view.aod
index b331c5900d3b446f8632159bd837bb4968b85ef4..a2d93541e4f43880901a1cf4e3caad407d2b8ea1 100644
--- a/neonView/PersonDuplicateEditview_view/PersonDuplicateEditview_view.aod
+++ b/neonView/DuplicateOrganisationEdit_view/DuplicateOrganisationEdit_view.aod
@@ -1,6 +1,6 @@
 <?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>PersonDuplicateEditview_view</name>
+  <name>DuplicateOrganisationEdit_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
     <noneLayout>
@@ -9,38 +9,38 @@
   </layout>
   <children>
     <tableViewTemplate>
-      <name>PersonDuplicateEditview_Table</name>
+      <name>table</name>
       <hideActions v="true" />
-      <hideContentSearch v="true" />
-      <iconField></iconField>
-      <entityField>#ENTITY</entityField>
-      <linkedColumns />
-      <fixedFilterFields />
-      <hideHeader v="true" />
-      <title>Duplicates</title>
+      <isCreatable v="false" />
+      <isDeletable v="false" />
+      <isEditable v="false" />
       <columns>
         <neonTableColumn>
-          <name>7e5410c5-ee05-4a5a-b168-8015d2d05834</name>
-          <entityField>#IMAGE</entityField>
+          <name>7cb9aa93-5aa1-4f52-a2a0-32723919af08</name>
+          <entityField>ORGNAME</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>ef22c1b8-1025-41b6-bb0b-99fe053e9ef9</name>
-          <entityField>FIRSTNAME</entityField>
+          <name>683fa228-8853-4def-b904-c10222136aec</name>
+          <entityField>STATUS</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>abfe3ce4-4fcc-4d61-93ec-156bd97ace3b</name>
-          <entityField>LASTNAME</entityField>
+          <name>bb6ddf6b-aa09-4b5b-814a-ae5ebf08a48a</name>
+          <entityField>CUSTOMERCODE</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>17d892a8-69fb-4bca-9629-d92ae80c72f8</name>
-          <entityField>STANDARD_PHONE_COMMUNICATION</entityField>
+          <name>a1630a4a-9989-4e9b-bb39-03a8432aef3f</name>
+          <entityField>TYPE</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>12006c11-e833-4ce1-9645-fdec0a8b6088</name>
+          <name>6295ed5c-35a8-4238-921e-65e29141883f</name>
           <entityField>STANDARD_EMAIL_COMMUNICATION</entityField>
         </neonTableColumn>
         <neonTableColumn>
-          <name>0231907e-8ae0-4f99-af1c-1bcb2f57bdb8</name>
+          <name>d6716d9e-19b7-4d2f-b7a9-61d0e3ef3ac5</name>
+          <entityField>STANDARD_PHONE_COMMUNICATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>334a97a3-cad3-4ac5-b670-de7d587e2781</name>
           <entityField>STANDARD_ADDRESS</entityField>
         </neonTableColumn>
       </columns>
diff --git a/neonView/DuplicateOrganisationFilter_view/DuplicateOrganisationFilter_view.aod b/neonView/DuplicateOrganisationFilter_view/DuplicateOrganisationFilter_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..2e4b88985d02932f1eb78ced263ceb82b88c2adf
--- /dev/null
+++ b/neonView/DuplicateOrganisationFilter_view/DuplicateOrganisationFilter_view.aod
@@ -0,0 +1,58 @@
+<?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>DuplicateOrganisationFilter_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterable v="true" />
+  <layout>
+    <groupLayout>
+      <name>layout</name>
+    </groupLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>table</name>
+      <favoriteActionGroup1>filterActions</favoriteActionGroup1>
+      <isCreatable v="false" />
+      <isDeletable v="false" />
+      <isEditable v="false" />
+      <columns>
+        <neonTableColumn>
+          <name>04253f56-c764-46a9-8795-6b7c58d9352b</name>
+          <entityField>PICTURE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>fc700556-7829-42be-b824-83d29e7dddf3</name>
+          <entityField>DUPLICATE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>6e753d4c-4f6a-4fbf-8af0-b76aa4ff8e76</name>
+          <entityField>ORGNAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>1368091a-0a65-4df6-b0fc-34031925e2bf</name>
+          <entityField>STATUS</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>d407d879-3f44-4656-a4bc-0149adcfec5e</name>
+          <entityField>CUSTOMERCODE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>166bdb5d-a822-4915-99aa-2ff1adca1bc9</name>
+          <entityField>TYPE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>4edfc696-78b0-4abd-8d03-39c02d0116da</name>
+          <entityField>STANDARD_PHONE_COMMUNICATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>e7fb62b8-4d76-46cc-bf84-00230d2e6e56</name>
+          <entityField>STANDARD_EMAIL_COMMUNICATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>93bc9275-aea3-436d-ab86-fd400a790538</name>
+          <entityField>STANDARD_ADDRESS</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/DuplicatesUnrelatedCluster_view/DuplicatesUnrelatedCluster_view.aod b/neonView/DuplicateOrganisationPreview_view/DuplicateOrganisationPreview_view.aod
similarity index 51%
rename from neonView/DuplicatesUnrelatedCluster_view/DuplicatesUnrelatedCluster_view.aod
rename to neonView/DuplicateOrganisationPreview_view/DuplicateOrganisationPreview_view.aod
index 670b2c939dc7b4c793999bf90f30c9503d4c0052..29f3a38fc42c1f47d2d21233941b8677b77ddfe7 100644
--- a/neonView/DuplicatesUnrelatedCluster_view/DuplicatesUnrelatedCluster_view.aod
+++ b/neonView/DuplicateOrganisationPreview_view/DuplicateOrganisationPreview_view.aod
@@ -1,17 +1,10 @@
 <?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>DuplicatesUnrelatedCluster_view</name>
+  <name>DuplicateOrganisationPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <noneLayout>
       <name>layout</name>
-    </boxLayout>
+    </noneLayout>
   </layout>
-  <children>
-    <neonViewReference>
-      <name>484990d0-890b-48b8-8618-6f0fab367138</name>
-      <entityField>DuplicatesUnrelatedPersonConsumer</entityField>
-      <view>DuplicatesUnrelatedPersonFilter_view</view>
-    </neonViewReference>
-  </children>
 </neonView>
diff --git a/neonView/DuplicatePersonEdit_view/DuplicatePersonEdit_view.aod b/neonView/DuplicatePersonEdit_view/DuplicatePersonEdit_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..99e36d549f4ddd5e255077197ed28f53825b0c57
--- /dev/null
+++ b/neonView/DuplicatePersonEdit_view/DuplicatePersonEdit_view.aod
@@ -0,0 +1,61 @@
+<?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>DuplicatePersonEdit_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <noneLayout>
+      <name>layout</name>
+    </noneLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>table</name>
+      <hideActions v="true" />
+      <isCreatable v="false" />
+      <isDeletable v="false" />
+      <isEditable v="false" />
+      <columns>
+        <neonTableColumn>
+          <name>fe9c534a-ba99-4805-996f-e76a6e77396e</name>
+          <entityField>LETTERSALUTATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>f8235c5b-6d13-4fd4-8522-96e38abaad1e</name>
+          <entityField>TITLE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>7b89e8a4-e9da-4d89-86cf-d35db86cf53c</name>
+          <entityField>FIRSTNAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>2b255370-1cd5-472f-8417-bde8c9f5743a</name>
+          <entityField>MIDDLENAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>a5188dac-9c63-44de-bb36-cb40689376c2</name>
+          <entityField>LASTNAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>7f0abf2a-5411-425e-8be8-16c57d19ba12</name>
+          <entityField>STATUS</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>55cdd3d2-548a-4a7f-9590-14413d0a6f34</name>
+          <entityField>ORGANISATION_ID</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>305716b3-d99b-4fea-8f8a-a71b9dbeeacd</name>
+          <entityField>STANDARD_EMAIL_COMMUNICATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>446a5dea-a93f-4b1e-9b51-b8a00990972d</name>
+          <entityField>STANDARD_PHONE_COMMUNICATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>1fedd9be-6492-4e89-ae8e-03bc212078e1</name>
+          <entityField>STANDARD_ADDRESS</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/DuplicatePersonFilter_view/DuplicatePersonFilter_view.aod b/neonView/DuplicatePersonFilter_view/DuplicatePersonFilter_view.aod
new file mode 100644
index 0000000000000000000000000000000000000000..c1f6405a3cc09e5a8eda9af6abb92dcce3fa1f06
--- /dev/null
+++ b/neonView/DuplicatePersonFilter_view/DuplicatePersonFilter_view.aod
@@ -0,0 +1,70 @@
+<?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>DuplicatePersonFilter_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <filterable v="true" />
+  <layout>
+    <groupLayout>
+      <name>layout</name>
+    </groupLayout>
+  </layout>
+  <children>
+    <tableViewTemplate>
+      <name>table</name>
+      <favoriteActionGroup1>filterActions</favoriteActionGroup1>
+      <isCreatable v="false" />
+      <isDeletable v="false" />
+      <isEditable v="false" />
+      <columns>
+        <neonTableColumn>
+          <name>c89d9927-c3f1-4e0c-b7fa-20d5e031f8b7</name>
+          <entityField>PICTURE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>c68a371e-0baa-4e6c-baee-424ca4f1d258</name>
+          <entityField>DUPLICATE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>42fb67ab-6bc9-4a02-9dad-10f54d9fe242</name>
+          <entityField>LETTERSALUTATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>59aa16e6-f599-4aff-8314-6b1a2c8cfd67</name>
+          <entityField>TITLE</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>3fdd6165-1a1b-4521-a23f-631e5f88beb1</name>
+          <entityField>FIRSTNAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>a76bc050-eccd-4d2a-9190-2d994fcea7e3</name>
+          <entityField>MIDDLENAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>381ba7a3-1591-40a2-8837-0516db984bb7</name>
+          <entityField>LASTNAME</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>6b828d7c-7b3c-490f-98a1-41520dec0773</name>
+          <entityField>STATUS</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>47c28842-59ab-4f9c-9239-3fda9c6171e0</name>
+          <entityField>ORGANISATION_ID</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>68b9211a-b4e7-4b7b-b110-9d76d7e14bb2</name>
+          <entityField>STANDARD_PHONE_COMMUNICATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>7a3fd399-0e19-4399-8df1-4f8d521b6729</name>
+          <entityField>STANDARD_EMAIL_COMMUNICATION</entityField>
+        </neonTableColumn>
+        <neonTableColumn>
+          <name>f54a6069-994c-4c77-b462-dc449e42ef49</name>
+          <entityField>STANDARD_ADDRESS</entityField>
+        </neonTableColumn>
+      </columns>
+    </tableViewTemplate>
+  </children>
+</neonView>
diff --git a/neonView/OrganisationUnrelatedDuplicates_view/OrganisationUnrelatedDuplicates_view.aod b/neonView/DuplicatePersonPreview_view/DuplicatePersonPreview_view.aod
similarity index 50%
rename from neonView/OrganisationUnrelatedDuplicates_view/OrganisationUnrelatedDuplicates_view.aod
rename to neonView/DuplicatePersonPreview_view/DuplicatePersonPreview_view.aod
index 0b23c809aafd9bedf13995b9049e1be41c8a6ea2..bd812680650a1960d3848cc068685b565b20f281 100644
--- a/neonView/OrganisationUnrelatedDuplicates_view/OrganisationUnrelatedDuplicates_view.aod
+++ b/neonView/DuplicatePersonPreview_view/DuplicatePersonPreview_view.aod
@@ -1,17 +1,10 @@
 <?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>OrganisationUnrelatedDuplicates_view</name>
+  <name>DuplicatePersonPreview_view</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
   <layout>
-    <boxLayout>
+    <noneLayout>
       <name>layout</name>
-    </boxLayout>
+    </noneLayout>
   </layout>
-  <children>
-    <neonViewReference>
-      <name>edc0822d-4388-4e3d-93d7-2e46e32f5742</name>
-      <entityField>DuplicatesUnrelatedOrganisationConsumer</entityField>
-      <view>DuplicatesUnrelatedOrganisationFilter_view</view>
-    </neonViewReference>
-  </children>
 </neonView>
diff --git a/neonView/DuplicateScannerFilter_view/DuplicateScannerFilter_view.aod b/neonView/DuplicateScannerFilter_view/DuplicateScannerFilter_view.aod
index 5a99ae0226ac05f614f190c54732bedc624b4a5c..0a9b1256cbdc2176dacc927a459bcf2e66d599fb 100644
--- a/neonView/DuplicateScannerFilter_view/DuplicateScannerFilter_view.aod
+++ b/neonView/DuplicateScannerFilter_view/DuplicateScannerFilter_view.aod
@@ -11,6 +11,7 @@
     <tableViewTemplate>
       <name>Filters</name>
       <entityField>#ENTITY</entityField>
+      <favoriteActionGroup1>FilterActions</favoriteActionGroup1>
       <isCreatable v="false" />
       <isDeletable v="false" />
       <isEditable v="true" />
@@ -23,11 +24,16 @@
           <name>8615259b-de5b-493a-9c9d-2ff934ae1b8c</name>
           <entityField>ENTITY_TO_SCAN_NAME</entityField>
         </neonTableColumn>
+        <neonTableColumn>
+          <name>5ae7793f-353c-45ed-995e-5153216a3661</name>
+          <entityField>DUPLICATECOUNT</entityField>
+        </neonTableColumn>
       </columns>
     </tableViewTemplate>
     <treeTableViewTemplate>
       <name>Treetable</name>
       <entityField>#ENTITY</entityField>
+      <favoriteActionGroup1>FilterActions</favoriteActionGroup1>
       <isCreatable v="false" />
       <isDeletable v="false" />
       <columns>
@@ -39,6 +45,10 @@
           <name>6730d89f-4190-4767-b3a0-a63231477ed4</name>
           <entityField>ENTITY_TO_SCAN_NAME</entityField>
         </neonTreeTableColumn>
+        <neonTreeTableColumn>
+          <name>8cd35bc9-2954-4dca-b67b-083d3a27c45c</name>
+          <entityField>DUPLICATECOUNT</entityField>
+        </neonTreeTableColumn>
       </columns>
     </treeTableViewTemplate>
   </children>
diff --git a/neonView/DuplicateScannerPreview_view/DuplicateScannerPreview_view.aod b/neonView/DuplicateScannerPreview_view/DuplicateScannerPreview_view.aod
index 75c33f74429cbf649d0353217f044074c7a56a4a..bbb07db7e29b4b566072c7ca947047641f527f92 100644
--- a/neonView/DuplicateScannerPreview_view/DuplicateScannerPreview_view.aod
+++ b/neonView/DuplicateScannerPreview_view/DuplicateScannerPreview_view.aod
@@ -22,10 +22,6 @@
           <name>b3ce81d4-bbf5-49ec-8a7a-38119ef6973f</name>
           <entityField>ENTITY_TO_SCAN_NAME</entityField>
         </entityFieldLink>
-        <entityFieldLink>
-          <name>ba6cde5d-7661-4662-9e92-dca40b597015</name>
-          <entityField>EXTERNAL_SERVICE_USAGE_ALLOWED</entityField>
-        </entityFieldLink>
         <entityFieldLink>
           <name>51bf489d-7536-4fc5-a187-8f2610b35b3d</name>
           <entityField>ID_FIELD_NAME</entityField>
diff --git a/neonView/DuplicateScannerResultFieldConfigEdit_view/DuplicateScannerResultFieldConfigEdit_view.aod b/neonView/DuplicateScannerResultFieldConfigEdit_view/DuplicateScannerResultFieldConfigEdit_view.aod
deleted file mode 100644
index 9798328f4161f04c56cd02f48166a9dce167306c..0000000000000000000000000000000000000000
--- a/neonView/DuplicateScannerResultFieldConfigEdit_view/DuplicateScannerResultFieldConfigEdit_view.aod
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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>DuplicateScannerResultFieldConfigEdit_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <genericMultipleViewTemplate>
-      <name>ResultFieldsConfig</name>
-      <autoNewRow v="true" />
-      <entityField>#ENTITY</entityField>
-      <title>Result fields</title>
-      <columns>
-        <neonGenericMultipleTableColumn>
-          <name>e330572c-aa47-4c52-a760-3e8765ce3dd0</name>
-          <entityField>ENTITY_FIELD_NAME</entityField>
-        </neonGenericMultipleTableColumn>
-      </columns>
-    </genericMultipleViewTemplate>
-  </children>
-</neonView>
diff --git a/neonView/DuplicatesUnrelatedOrganisationFilter_view/DuplicatesUnrelatedOrganisationFilter_view.aod b/neonView/DuplicatesUnrelatedOrganisationFilter_view/DuplicatesUnrelatedOrganisationFilter_view.aod
deleted file mode 100644
index 03a42bc169f8edf17595f673f799194149d4eb81..0000000000000000000000000000000000000000
--- a/neonView/DuplicatesUnrelatedOrganisationFilter_view/DuplicatesUnrelatedOrganisationFilter_view.aod
+++ /dev/null
@@ -1,30 +0,0 @@
-<?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>DuplicatesUnrelatedOrganisationFilter_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <tableViewTemplate>
-      <name>UnrelatedOrganisations</name>
-      <hideContentSearch v="true" />
-      <entityField>#ENTITY</entityField>
-      <isCreatable v="false" />
-      <isEditable v="false" />
-      <title>Unrelated organisation duplicates</title>
-      <columns>
-        <neonTableColumn>
-          <name>04681f8d-b941-4a66-be50-6ac08d6f52a4</name>
-          <entityField>SourceDuplicateDescription</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>b293ed18-ebf5-474e-8ec2-851a3562b4d5</name>
-          <entityField>UnrelatedDuplicateDescription</entityField>
-        </neonTableColumn>
-      </columns>
-    </tableViewTemplate>
-  </children>
-</neonView>
diff --git a/neonView/DuplicatesUnrelatedPersonFilter_view/DuplicatesUnrelatedPersonFilter_view.aod b/neonView/DuplicatesUnrelatedPersonFilter_view/DuplicatesUnrelatedPersonFilter_view.aod
deleted file mode 100644
index 173666ab5f8a8ffb5ded2760fd5da08851e2e209..0000000000000000000000000000000000000000
--- a/neonView/DuplicatesUnrelatedPersonFilter_view/DuplicatesUnrelatedPersonFilter_view.aod
+++ /dev/null
@@ -1,30 +0,0 @@
-<?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>DuplicatesUnrelatedPersonFilter_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <tableViewTemplate>
-      <name>UnrelatedPersons</name>
-      <hideContentSearch v="true" />
-      <entityField>#ENTITY</entityField>
-      <isCreatable v="false" />
-      <isEditable v="false" />
-      <title>Unrelated person duplicates</title>
-      <columns>
-        <neonTableColumn>
-          <name>734re984-6a0b-4126-ab49-452e2b54f76d</name>
-          <entityField>SourceDuplicateDescription</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>8615259b-de5b-378u-945d-2ff934ae1b8c</name>
-          <entityField>UnrelatedDuplicateDescription</entityField>
-        </neonTableColumn>
-      </columns>
-    </tableViewTemplate>
-  </children>
-</neonView>
diff --git a/neonView/OrganisationClusterMain_view/OrganisationClusterMain_view.aod b/neonView/OrganisationClusterMain_view/OrganisationClusterMain_view.aod
deleted file mode 100644
index 72d99cac595e86b488e878b16d1a700b90746e48..0000000000000000000000000000000000000000
--- a/neonView/OrganisationClusterMain_view/OrganisationClusterMain_view.aod
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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>OrganisationClusterMain_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-      <direction>HORIZONTAL</direction>
-    </boxLayout>
-  </layout>
-  <children>
-    <neonViewReference>
-      <name>b25f94bf-9316-4438-be78-b8cf596440b3</name>
-      <entityField>DuplicateOrganisationsConsumer</entityField>
-      <view>OrganisationFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>5589bb81-171d-417b-a1b2-975144109d55</name>
-      <entityField>#ENTITY</entityField>
-      <view>DuplicatesUnrelatedCluster_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
diff --git a/neonView/OrganisationDuplicatesFilter_view/OrganisationDuplicatesFilter_view.aod b/neonView/OrganisationDuplicatesFilter_view/OrganisationDuplicatesFilter_view.aod
deleted file mode 100644
index c950c689201ccb9ecaf23a58f879058711e6c866..0000000000000000000000000000000000000000
--- a/neonView/OrganisationDuplicatesFilter_view/OrganisationDuplicatesFilter_view.aod
+++ /dev/null
@@ -1,32 +0,0 @@
-<?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>OrganisationDuplicatesFilter_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <tableViewTemplate>
-      <name>OrganisationDuplicatesTable</name>
-      <hideContentSearch v="true" />
-      <entityField>#ENTITY</entityField>
-      <favoriteActionGroup1>OrganisationOpenClusterDetailActionGroup</favoriteActionGroup1>
-      <favoriteActionGroup2>DuplicateClusterActionGroup</favoriteActionGroup2>
-      <isCreatable v="false" />
-      <isDeletable v="false" />
-      <isEditable v="false" />
-      <columns>
-        <neonTableColumn>
-          <name>ebe8d904-449c-49bd-915c-5b4fee894bc2</name>
-          <entityField>CLUSTER_DESCRIPTION</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>48db4335-6bdb-4a6a-809e-f9c371733f85</name>
-          <entityField>COUNT_DUPLICATES_IN_CLUSTER</entityField>
-        </neonTableColumn>
-      </columns>
-    </tableViewTemplate>
-  </children>
-</neonView>
diff --git a/neonView/OrganisationDuplicatesTab_view/OrganisationDuplicatesTab_view.aod b/neonView/OrganisationDuplicatesTab_view/OrganisationDuplicatesTab_view.aod
deleted file mode 100644
index ed86c8059d4920b5576f13406c5d4d4f86597b71..0000000000000000000000000000000000000000
--- a/neonView/OrganisationDuplicatesTab_view/OrganisationDuplicatesTab_view.aod
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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>OrganisationDuplicatesTab_view</name>
-  <title>Organisation duplicates</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-      <direction>HORIZONTAL</direction>
-    </boxLayout>
-  </layout>
-  <children>
-    <neonViewReference>
-      <name>8b4ab951-afb3-4fac-915b-89226ab2f849</name>
-      <entityField>SelfOrganisationDuplicatesConsumer</entityField>
-      <view>OrganisationDuplicatesFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>d1e2ba4a-a5d6-4bba-a646-5918490e43a4</name>
-      <entityField>#ENTITY</entityField>
-      <view>OrganisationUnrelatedDuplicates_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
diff --git a/neonView/OrganisationEdit_view/OrganisationEdit_view.aod b/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
index cf3a70c9a59119e3e829b6fe0acdc0b53b1a0d10..0e6500095ffe50942035ec4db7acb782dde76106 100644
--- a/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
+++ b/neonView/OrganisationEdit_view/OrganisationEdit_view.aod
@@ -12,9 +12,9 @@
   </layout>
   <children>
     <neonViewReference>
-      <name>f2fa0351-15af-4d1c-b7dd-0e42d9c7889f</name>
-      <entityField>SelfDuplicatesUncached</entityField>
-      <view>OrganisationNoNoiseTable_view</view>
+      <name>933cd72c-fd3a-4b91-aad6-8e129d6233e5</name>
+      <entityField>Duplicates</entityField>
+      <view>DuplicateOrganisationEdit_view</view>
     </neonViewReference>
     <genericViewTemplate>
       <name>Edit</name>
diff --git a/neonView/OrganisationFilter_view/OrganisationFilter_view.aod b/neonView/OrganisationFilter_view/OrganisationFilter_view.aod
index d0a3e39a2851e9ba458d22537779ff15dd1e7454..75d8254a1e1995cd430b2e0a4f8b50a1120a49b0 100644
--- a/neonView/OrganisationFilter_view/OrganisationFilter_view.aod
+++ b/neonView/OrganisationFilter_view/OrganisationFilter_view.aod
@@ -53,7 +53,6 @@
       <entityField>#ENTITY</entityField>
       <favoriteActionGroup1>observeActionGroup</favoriteActionGroup1>
       <favoriteActionGroup2>filterViewActionGroup</favoriteActionGroup2>
-      <favoriteActionGroup3>DuplicateActions</favoriteActionGroup3>
       <linkedColumns>
         <element>NAME</element>
       </linkedColumns>
@@ -102,7 +101,6 @@
       <entityField>#ENTITY</entityField>
       <favoriteActionGroup1>observeActionGroup</favoriteActionGroup1>
       <favoriteActionGroup2>filterViewActionGroup</favoriteActionGroup2>
-      <favoriteActionGroup3>DuplicateActions</favoriteActionGroup3>
       <linkedColumns>
         <element>NAME</element>
       </linkedColumns>
diff --git a/neonView/OrganisationMain_view/OrganisationMain_view.aod b/neonView/OrganisationMain_view/OrganisationMain_view.aod
index 67ceac6a5cdafeb611c83c06583b634263c4b921..9457155195dafc5a55d96976ca5adb0ac88110a1 100644
--- a/neonView/OrganisationMain_view/OrganisationMain_view.aod
+++ b/neonView/OrganisationMain_view/OrganisationMain_view.aod
@@ -76,9 +76,9 @@
       <view>LogHistoryFilter_view</view>
     </neonViewReference>
     <neonViewReference>
-      <name>cbac7602-9eba-4e5d-8617-3d0b33e55ca1</name>
-      <entityField>SelfDuplicatesUncached</entityField>
-      <view>OrganisationFilter_view</view>
+      <name>a5ab96e5-927c-4db3-b7ed-f0c0aadcb89b</name>
+      <entityField>Duplicates</entityField>
+      <view>DuplicateOrganisationFilter_view</view>
     </neonViewReference>
   </children>
 </neonView>
diff --git a/neonView/PersonClusterMain_view/PersonClusterMain_view.aod b/neonView/PersonClusterMain_view/PersonClusterMain_view.aod
deleted file mode 100644
index dcbd9badb6fe40452c89f4d4f54cef06fb5a0938..0000000000000000000000000000000000000000
--- a/neonView/PersonClusterMain_view/PersonClusterMain_view.aod
+++ /dev/null
@@ -1,23 +0,0 @@
-<?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>PersonClusterMain_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-      <direction>HORIZONTAL</direction>
-    </boxLayout>
-  </layout>
-  <children>
-    <neonViewReference>
-      <name>ff307d1c-9de7-4842-a697-05e783eca14b</name>
-      <entityField>DuplicatePersonsConsumer</entityField>
-      <view>PersonFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>0df195b2-9074-4734-b6df-be3bbf47050a</name>
-      <entityField>#ENTITY</entityField>
-      <view>DuplicatesUnrelatedCluster_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
diff --git a/neonView/PersonClusterPreview_view/PersonClusterPreview_view.aod b/neonView/PersonClusterPreview_view/PersonClusterPreview_view.aod
deleted file mode 100644
index 69ab192629f5b172f18bc89eaccf2b384fdfb3bb..0000000000000000000000000000000000000000
--- a/neonView/PersonClusterPreview_view/PersonClusterPreview_view.aod
+++ /dev/null
@@ -1,22 +0,0 @@
-<?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>PersonClusterPreview_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-    </boxLayout>
-  </layout>
-  <children>
-    <neonViewReference>
-      <name>156ebee5-6b13-462f-b956-0470f27a174b</name>
-      <entityField>DuplicatePersonsConsumer</entityField>
-      <view>PersonLookup_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>d8afce27-436c-42f0-a326-98bf6539b7bd</name>
-      <entityField>DuplicatesUnrelatedPersonConsumer</entityField>
-      <view>DuplicatesUnrelatedPersonFilter_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
diff --git a/neonView/PersonDublicatesTab_view/PersonDublicatesTab_view.aod b/neonView/PersonDublicatesTab_view/PersonDublicatesTab_view.aod
deleted file mode 100644
index c11bc1396a663aa39b2f17a1b691d239ddbd79c6..0000000000000000000000000000000000000000
--- a/neonView/PersonDublicatesTab_view/PersonDublicatesTab_view.aod
+++ /dev/null
@@ -1,24 +0,0 @@
-<?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>PersonDublicatesTab_view</name>
-  <title>Person duplicates</title>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <boxLayout>
-      <name>layout</name>
-      <direction>HORIZONTAL</direction>
-    </boxLayout>
-  </layout>
-  <children>
-    <neonViewReference>
-      <name>c82a1ae2-9f8f-4149-8bac-5621136d779b</name>
-      <entityField>SelfPersonDuplicatesConsumer</entityField>
-      <view>PersonDuplicatesFilter_view</view>
-    </neonViewReference>
-    <neonViewReference>
-      <name>2aee29fb-9844-4e3a-a284-a04dadf9eadc</name>
-      <entityField>DuplicatesUnrelatedPersonConsumer</entityField>
-      <view>DuplicatesUnrelatedPersonFilter_view</view>
-    </neonViewReference>
-  </children>
-</neonView>
diff --git a/neonView/PersonDuplicatesFilter_view/PersonDuplicatesFilter_view.aod b/neonView/PersonDuplicatesFilter_view/PersonDuplicatesFilter_view.aod
deleted file mode 100644
index 0e95f05f72286d568edddded65e4cd0d21031823..0000000000000000000000000000000000000000
--- a/neonView/PersonDuplicatesFilter_view/PersonDuplicatesFilter_view.aod
+++ /dev/null
@@ -1,48 +0,0 @@
-<?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>PersonDuplicatesFilter_view</name>
-  <majorModelMode>DISTRIBUTED</majorModelMode>
-  <layout>
-    <groupLayout>
-      <name>layout</name>
-    </groupLayout>
-  </layout>
-  <children>
-    <tableViewTemplate>
-      <name>PersonDuplicatesTable</name>
-      <hideContentSearch v="true" />
-      <entityField>#ENTITY</entityField>
-      <favoriteActionGroup1>PersonOpenClusterDetailActionGroup</favoriteActionGroup1>
-      <isCreatable v="false" />
-      <isDeletable v="false" />
-      <isEditable v="false" />
-      <isSaveable v="false" />
-      <linkedFrame></linkedFrame>
-      <columns>
-        <neonTableColumn>
-          <name>7508e984-6a0b-4126-ab49-452e2b54f76d</name>
-          <entityField>CLUSTER_DESCRIPTION</entityField>
-        </neonTableColumn>
-        <neonTableColumn>
-          <name>8615259b-de5b-493a-945d-2ff934ae1b8c</name>
-          <entityField>COUNT_DUPLICATES_IN_CLUSTER</entityField>
-        </neonTableColumn>
-      </columns>
-    </tableViewTemplate>
-    <treeTableViewTemplate>
-      <name>Treetable</name>
-      <entityField>#ENTITY</entityField>
-      <favoriteActionGroup1>PersonOpenClusterDetailActionGroup</favoriteActionGroup1>
-      <columns>
-        <neonTreeTableColumn>
-          <name>060c69aa-242a-4141-acd1-b82a76d99521</name>
-          <entityField>CLUSTER_DESCRIPTION</entityField>
-        </neonTreeTableColumn>
-        <neonTreeTableColumn>
-          <name>67458881-0d45-406e-a362-852711b09bd1</name>
-          <entityField>COUNT_DUPLICATES_IN_CLUSTER</entityField>
-        </neonTreeTableColumn>
-      </columns>
-    </treeTableViewTemplate>
-  </children>
-</neonView>
diff --git a/neonView/PersonEdit_view/PersonEdit_view.aod b/neonView/PersonEdit_view/PersonEdit_view.aod
index 1cc1577de9b2c4f38ee39b97d8e14d70a9d74921..27586ee38b4febc4820c68577184586052e44464 100644
--- a/neonView/PersonEdit_view/PersonEdit_view.aod
+++ b/neonView/PersonEdit_view/PersonEdit_view.aod
@@ -12,9 +12,9 @@
   </layout>
   <children>
     <neonViewReference>
-      <name>589e5a82-e923-4b70-a983-5e104d2beb2b</name>
-      <entityField>SelfDuplicatesUncached</entityField>
-      <view>PersonDuplicateEditview_view</view>
+      <name>a6b55bfc-7b0c-4020-a78d-18ee9a1d2b26</name>
+      <entityField>Duplicates</entityField>
+      <view>DuplicatePersonEdit_view</view>
     </neonViewReference>
     <genericViewTemplate>
       <name>Edit</name>
diff --git a/neonView/PersonFilter_view/PersonFilter_view.aod b/neonView/PersonFilter_view/PersonFilter_view.aod
index c892033123ccd327c4dc49c13432e724b95843bf..2471b831c6a88a31be023611935956b63665d5e6 100644
--- a/neonView/PersonFilter_view/PersonFilter_view.aod
+++ b/neonView/PersonFilter_view/PersonFilter_view.aod
@@ -57,7 +57,6 @@
       <entityField>#ENTITY</entityField>
       <favoriteActionGroup1>observeActionGroup</favoriteActionGroup1>
       <favoriteActionGroup2>filterViewActionGroup</favoriteActionGroup2>
-      <favoriteActionGroup3>DuplicateActions</favoriteActionGroup3>
       <linkedColumns>
         <element>FIRSTNAME</element>
         <element>LASTNAME</element>
@@ -107,7 +106,6 @@
       <entityField>#ENTITY</entityField>
       <favoriteActionGroup1>observeActionGroup</favoriteActionGroup1>
       <favoriteActionGroup2>filterViewActionGroup</favoriteActionGroup2>
-      <favoriteActionGroup3>DuplicateActions</favoriteActionGroup3>
       <linkedColumns>
         <element>FIRSTNAME</element>
         <element>LASTNAME</element>
diff --git a/neonView/PersonMain_view/PersonMain_view.aod b/neonView/PersonMain_view/PersonMain_view.aod
index 75dd326492217de020311cd9fc123d1b9ab258cc..fd3103de794c833a085cb47d2dce69320e77a528 100644
--- a/neonView/PersonMain_view/PersonMain_view.aod
+++ b/neonView/PersonMain_view/PersonMain_view.aod
@@ -65,9 +65,9 @@
       <view>PersonMarketing_view</view>
     </neonViewReference>
     <neonViewReference>
-      <name>d128a678-b1c0-49d0-a74c-7860d3a85247</name>
-      <entityField>SelfDuplicatesUncached</entityField>
-      <view>PersonFilter_view</view>
+      <name>24ea8bc9-7ed0-4bed-a984-b1a9f3815c7c</name>
+      <entityField>Duplicates</entityField>
+      <view>DuplicatePersonFilter_view</view>
     </neonViewReference>
     <neonViewReference>
       <name>78a658a3-680b-4420-85a2-6e99ccff9f94</name>
diff --git a/process/RebuildDuplicatesCache_serverProcess/RebuildDuplicatesCache_serverProcess.aod b/process/DuplicateMerge_lib/DuplicateMerge_lib.aod
similarity index 65%
rename from process/RebuildDuplicatesCache_serverProcess/RebuildDuplicatesCache_serverProcess.aod
rename to process/DuplicateMerge_lib/DuplicateMerge_lib.aod
index 078550c7200171ccff2e26f2515a616016da481a..bc0eb0235229e83f6e13f3215fd29f3dcb46bc1a 100644
--- a/process/RebuildDuplicatesCache_serverProcess/RebuildDuplicatesCache_serverProcess.aod
+++ b/process/DuplicateMerge_lib/DuplicateMerge_lib.aod
@@ -1,9 +1,9 @@
 <?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>RebuildDuplicatesCache_serverProcess</name>
+  <name>DuplicateMerge_lib</name>
   <majorModelMode>DISTRIBUTED</majorModelMode>
-  <process>%aditoprj%/process/RebuildDuplicatesCache_serverProcess/process.js</process>
+  <process>%aditoprj%/process/DuplicateMerge_lib/process.js</process>
   <variants>
-    <element>EXECUTABLE</element>
+    <element>LIBRARY</element>
   </variants>
 </process>
diff --git a/process/DuplicateMerge_lib/process.js b/process/DuplicateMerge_lib/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..5b83ce3f225e20ebee0e6ca40ff7bc859dea99b3
--- /dev/null
+++ b/process/DuplicateMerge_lib/process.js
@@ -0,0 +1,368 @@
+import("Communication_lib");
+import("Sql_lib");
+import("system.db");
+import("ActivityTask_lib");
+import("KeywordRegistry_basic");
+import("system.translate");
+import("DuplicateScanner_lib");
+
+/**
+ * Methods for duplicate merging.
+ * Do not create an instance of this!
+ * 
+ * @class
+ */
+function DuplicateMergeUtils() {}
+
+/*
+ *
+ * Merges the source person into the target person. 
+ * This 
+ * - replaces the source's with the target's contactid in a predefined set of tables.
+ * - resets the standard communications of the source contact and keeps the ones of the target.
+ * - updates participants of campaigns and removes obsolet ones(which would be duplicates)
+ * - deletes the source person and contact
+ * - deletes the duplicate record, if one exists
+ * - deletes all unrelated-duplicate-relations containing the source contact id
+ *
+ *  @param {String} pSourceContactId The contact to be integrated into another
+ *  @param {String} pTargetContactId The contact in which the source gets integrated
+ *  @returns {Boolean} if the merge was sucessful
+ */
+DuplicateMergeUtils.mergePerson = function(pSourceContactId, pTargetContactId)
+{
+    var sourcePersonId = newSelect("PERSON_ID")
+        .from("CONTACT")
+        .where("CONTACT.CONTACTID", pSourceContactId)
+        .cell();
+    var targetPersonId = newSelect("PERSON_ID")
+        .from("CONTACT")
+        .where("CONTACT.CONTACTID", pTargetContactId)
+        .cell();
+        
+    DuplicateMergeUtils._deleteUniqueAttributes(pSourceContactId, pTargetContactId);
+    var isLinkedDataUpdated = DuplicateMergeUtils._migrateLinkedContactData(pSourceContactId, pTargetContactId);
+    var isParticipantsUpdated = DuplicateMergeUtils._migrateParticipantsToNewContact("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", 
+        pSourceContactId, pTargetContactId);
+    DuplicateMergeUtils._updateOtherContacts(pSourceContactId, sourcePersonId, targetPersonId);
+    
+    var deleteStatements = [];
+    if (sourcePersonId != targetPersonId)
+    {
+        deleteStatements.push(newWhere("PERSON.PERSONID", sourcePersonId).buildDeleteStatement());
+    }
+    
+    deleteStatements.push(newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement());
+    deleteStatements = deleteStatements.concat(DuplicateMergeUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId));
+    
+    //update binary 
+    var metaData = db.getBinaryMetadata("CONTACT", "DOCUMENT", pSourceContactId, true, SqlUtils.getBinariesAlias());
+    metaData.forEach(function (binaryMetaData) 
+    {
+        db.updateBinaryAssignment(binaryMetaData.id, "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias());
+    });
+    var deletedRows = db.deletes(deleteStatements)
+
+    DuplicateScannerUtils.deleteHasDuplicateEntries("Person_entity", [pSourceContactId, pTargetContactId]);
+    var dupIds = DuplicateScannerUtils.getDuplicateIdsByEntityScanner("Person_entity", pTargetContactId);
+    if(dupIds.length > 0)
+    {
+        DuplicateScannerUtils.insertHasDuplicateEntry("Person_entity", pTargetContactId, dupIds.length);
+    }
+
+    return isLinkedDataUpdated || isParticipantsUpdated || deletedRows > 0;
+}
+
+DuplicateMergeUtils.mergeOrganisation = function(pSourceContactId, pTargetContactId)
+{
+    var sourceOrganisationId = newSelect("ORGANISATION_ID")
+        .from("CONTACT")
+        .where("CONTACT.CONTACTID", pSourceContactId)
+        .cell();
+
+    var targetOrganisationId = newSelect("ORGANISATION_ID")
+        .from("CONTACT")
+        .where("CONTACT.CONTACTID", pTargetContactId)
+        .cell();
+    
+    DuplicateMergeUtils._deleteUniqueAttributes(pSourceContactId, pTargetContactId);
+    DuplicateMergeUtils._migrateLinkedContactData(pSourceContactId, pTargetContactId);
+    DuplicateMergeUtils._migrateParticipantsToNewContact("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", 
+        pSourceContactId, pTargetContactId);
+    DuplicateMergeUtils._migratePersonsToNewOrganisation(sourceOrganisationId, targetOrganisationId);
+    
+    var deleteStatements = [];
+    deleteStatements.push(newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement());
+    deleteStatements = deleteStatements.concat(DuplicateMergeUtils._buildDeleteOrganisationAndContactQuery(sourceOrganisationId, pSourceContactId));
+    deleteStatements = deleteStatements.concat(DuplicateMergeUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId));
+    
+    //update binary 
+    var metaData = db.getBinaryMetadata("CONTACT", "DOCUMENT", pSourceContactId, true, SqlUtils.getBinariesAlias());
+    metaData.forEach(function (binaryMetaData) 
+    {
+        db.updateBinaryAssignment(binaryMetaData.id, "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias());
+    });
+    var deletedRows = db.deletes(deleteStatements)
+
+    DuplicateScannerUtils.deleteHasDuplicateEntries("Organisation_entity", [pSourceContactId, pTargetContactId]);
+    var dupIds = DuplicateScannerUtils.getDuplicateIdsByEntityScanner("Organisation_entity", pTargetContactId);
+    if(dupIds.length > 0)
+    {
+        DuplicateScannerUtils.insertHasDuplicateEntry("Organisation_entity", pTargetContactId, dupIds.length);
+    }
+
+    return deletedRows >= 2;
+}
+
+DuplicateMergeUtils.createMergeSuccessActivity = function(pSourceContactId, pTargetContactId, pCurrentContactId, pContext)
+{
+    var activityDataForInsert = {
+        subject: translate.withArguments("A %0 record has been merged", [pContext]),
+        content: translate.withArguments("%0 with ID \"%1\" has been integrated into the %0 with the ID \"%2\"", [pContext, pSourceContactId, pTargetContactId]),
+        //categoryKeywordId: $KeywordRegistry.ac
+        directionKeywordId: $KeywordRegistry.activityDirection$internal(),
+        responsibleContactId: pCurrentContactId
+    };
+    var activityLinks = [[pContext, pTargetContactId]];
+
+    return ActivityUtils.insertNewActivity(activityDataForInsert, activityLinks, null, db.getCurrentAlias());
+}
+
+/*
+ * Persons get reassigned to new organisation
+ *
+ * @returns {Boolean} If records have been updated
+ */
+DuplicateMergeUtils._migratePersonsToNewOrganisation = function (pSourceOrganisationId, pTargetOrganisationId)
+{
+    var updateCount = newWhereIfSet(["CONTACT", "ORGANISATION_ID"], pSourceOrganisationId)
+                        .and("PERSON_ID is not null")
+                        .updateFields(new Map().set("ORGANISATION_ID", pTargetOrganisationId), "CONTACT");
+        
+    var deleteCount = newWhere(["CONTACT", "ORGANISATION_ID"], pSourceOrganisationId)
+                        .and("PERSON_ID is not null")
+                        .deleteData();
+    return updateCount > 0 || deleteCount > 0;
+}
+
+/*
+ * Person and organisations keep the max_count = 1 attribute of the target and the one from the source is deleted
+ *
+ * @returns {Boolean} If records have been deleted
+ */
+DuplicateMergeUtils._deleteUniqueAttributes = function (pSourceContactId, pTargetContactId)
+{
+    var targetAttrUnique = newSelect("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID")
+                                .from("AB_ATTRIBUTERELATION")
+                                .join("AB_ATTRIBUTEUSAGE on AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID = AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID")
+                                .where("AB_ATTRIBUTEUSAGE.MAX_COUNT = 1")
+                                .and("AB_ATTRIBUTERELATION.OBJECT_ROWID", pTargetContactId)
+                                .table();
+    var deleteCount = 0;
+    
+    targetAttrUnique.forEach(function(attribute){
+        deleteCount += newWhereIfSet("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", attribute)
+                        .and("AB_ATTRIBUTERELATION.OBJECT_ROWID", pSourceContactId)
+                        .deleteData();
+    });
+
+    return deleteCount > 0;
+}
+
+DuplicateMergeUtils._migrateLinkedContactData = function (pSourceContactId, pTargetContactId)
+{
+    var updateStatements = new Map();
+    var currentAlias = db.getCurrentAlias();
+    
+    var setStandardsStatements = [];
+    var [standardPhone, standardMail, standardAddressId] = newSelect([
+            "(" + CommUtil.getStandardSubSqlPhone() + ")", 
+            "(" + CommUtil.getStandardSubSqlMail() + ")",
+            "CONTACT.ADDRESS_ID"
+        ])
+        .from("CONTACT")
+        .where("CONTACT.CONTACTID", pTargetContactId)
+        .arrayRow();
+    
+    //if the targetContact already has a standard phone comm, set the comm from the sourceContact as not standard
+    if (standardPhone)
+    {
+        setStandardsStatements.push(
+            newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId)
+                .and("COMMUNICATION.MEDIUM_ID", CommUtil.getMediumIdsByCategory("PHONE"), SqlBuilder.IN())
+                .buildUpdateStatement({"ISSTANDARD" : "0"})
+        );
+    }
+    if (standardMail)
+    {
+        setStandardsStatements.push(
+            newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId)
+                .and("COMMUNICATION.MEDIUM_ID", CommUtil.getMediumIdsByCategory("EMAIL"), SqlBuilder.IN())
+                .buildUpdateStatement({"ISSTANDARD" : "0"})
+        );
+    }
+    //set the standardaddress of the sourceContact as standard of the targetContact if it doesn't have one set yet
+    if(!standardAddressId) 
+    {
+        var sourceStandard = newSelect("CONTACT.ADDRESS_ID")
+            .from("CONTACT")
+            .where("CONTACT.CONTACTID", pSourceContactId)
+            .cell();
+        setStandardsStatements.push(newWhere("CONTACT.CONTACTID", pTargetContactId).buildUpdateStatement({"ADDRESS_ID": sourceStandard}));
+    }
+    
+    updateStatements.set(currentAlias, setStandardsStatements);
+    
+    DuplicateMergeUtils._getLinkedTableInfos(pTargetContactId).forEach(function ([tableName, columnName, additionalCondition, dbAlias])
+    {
+        if (!dbAlias)
+        {
+            dbAlias = currentAlias;
+        }
+        
+        if (!updateStatements.has(dbAlias))
+        {
+            updateStatements.set(dbAlias, []);
+        }
+        var statements = updateStatements.get(dbAlias);
+        
+        var updateValues = {};
+        updateValues[columnName] = pTargetContactId;
+        
+        var updateCondition = new SqlBuilder(dbAlias).where([tableName, columnName], pSourceContactId).andIfSet(additionalCondition);
+        
+        //push must be used here to keep the reference
+        statements.push(updateCondition.buildUpdateStatement(updateValues, tableName));
+    });
+    
+    var totalChanges = 0;
+    
+    updateStatements.forEach(function (statements, alias)
+    {
+        totalChanges += db.updates(statements, alias);
+    });
+    
+    totalChanges += newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId).deleteData(); //delete leftover communications from the source contact
+    totalChanges += new AttributeRelationQuery(pSourceContactId).deleteAllAttributes(); //delete leftover attributes
+
+    return totalChanges > 0;
+}
+
+/*
+ * All records with contactId = sourceContactId get updated, which are not assigned to the same "group" as the targetContactId.
+ * This is because otherwise there would now be in total two "participants" in the same "group" as opposed to one before.
+ * Also if they already are in the same "group" those records shouldn't be updated because it would lead to the same outcome.
+ *
+ * @returns {Boolean} If records have been updated
+ */
+DuplicateMergeUtils._migrateParticipantsToNewContact = function (pTableName, pContactIdColumn, pAssignableIdColumn, pSourceContactId, pTargetContactId)
+{
+    var excludedIds = newSelect(pAssignableIdColumn)
+        .from(pTableName)
+        .where([pTableName, pContactIdColumn], pTargetContactId)
+        .arrayColumn();
+
+    var updateCount = newWhereIfSet([pTableName, pAssignableIdColumn], excludedIds, SqlBuilder.NOT_IN())
+        .and([pTableName, pContactIdColumn], pSourceContactId)
+        .updateFields(new Map().set(pContactIdColumn, pTargetContactId), pTableName);
+        
+    var deleteCount = newWhere([pTableName, pContactIdColumn], pSourceContactId)
+        .tableName(pTableName)
+        .deleteData();
+    
+    return updateCount > 0 || deleteCount > 0;
+}
+
+/*
+ * Update other contacts from the source
+ *
+ * @returns {Boolean} If records have been updated
+ */
+DuplicateMergeUtils._updateOtherContacts = function (pSourceContactId, sourcePersonId, targetPersonId)
+{
+    var otherContacts = newSelect("PERSON.PERSONID")
+                                .from("PERSON")
+                                .join("CONTACT", "CONTACT.PERSON_ID = PERSON.PERSONID")
+                                .where("PERSON.PERSONID", sourcePersonId)
+                                .and("CONTACT.CONTACTID", pSourceContactId, SqlBuilder.NOT_EQUAL())
+                                .table();
+    var updateCount = 0;
+    
+    otherContacts.forEach(function(person){                 
+        updateCount += newWhere("CONTACT.PERSON_ID", person)
+                        .updateFields({"PERSON_ID" : targetPersonId}, "CONTACT");
+    });
+
+    return updateCount > 0;
+}
+
+DuplicateMergeUtils._buildDeleteCachedUnrelatedDuplicateQuery = function(pSourceContactId)
+{
+    return [
+        newWhere("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", pSourceContactId).buildDeleteStatement(),
+        newWhere("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID", pSourceContactId).buildDeleteStatement()
+    ];
+}
+
+DuplicateMergeUtils._buildDeleteOrganisationAndContactQuery = function(pSourceOrganisationId, pSourceContactId)
+{
+    return [
+        newWhere("ORGANISATION.ORGANISATIONID", pSourceOrganisationId).buildDeleteStatement(),
+        newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement()
+    ];
+}
+
+/*
+ * Contains all Tables and their fields which may contain the contact id to be replaced for the data alias
+ *
+ * @returns {String[[]]} Array in the format [TableName, ContactIdColumnName, AdditionalCondition, alias]
+ */
+DuplicateMergeUtils._getLinkedTableInfos = function(pTargetContactId)
+{
+    //don't use communications that the target already has
+    var targetComms = newSelect("COMMUNICATION.ADDR") 
+        .from("COMMUNICATION")
+        .where("COMMUNICATION.CONTACT_ID", pTargetContactId)
+        .arrayColumn();
+        
+    var communicationDedupCondition = targetComms.length > 0
+        ? newWhere("COMMUNICATION.ADDR", targetComms, SqlBuilder.NOT_IN())
+        : "";
+    
+    return[
+        ["AB_APPOINTMENTLINK", "OBJECT_ROWID"],
+        ["AB_CTILOG", "CONTACT_ID"],
+        ["AB_OBJECTRELATION", "AB_OBJECTRELATIONID"],
+        ["AB_OBJECTRELATION", "OBJECT1_ROWID"],
+        ["AB_OBJECTRELATION", "OBJECT2_ROWID"],
+        ["AB_LOGHISTORY", "TABLENAMEID"],
+        ["ADDRESS", "CONTACT_ID"],
+        ["BULKMAILRECIPIENT", "CONTACT_ID"],
+        ["BULKMAIL", "TESTING_CONTACT_ID"],
+        ["CAMPAIGN", "EMPLOYEE_CONTACT_ID"],
+        ["CAMPAIGNSTEP", "EMPLOYEE_CONTACT_ID"],
+        ["COMMRESTRICTION", "CONTACT_ID"],
+        ["COMMRESTRICTION", "EMPLOYEE_INVOLVED"],
+        ["COMMUNICATION", "CONTACT_ID", communicationDedupCondition],
+        ["COMPETITION", "CONTACT_ID"],
+        ["CONTRACT", "CONTACT_ID"],
+        ["LETTERRECIPIENT", "CONTACT_ID"],
+        ["OBJECTMEMBER", "CONTACT_ID"],
+        ["OFFER", "CONTACT_ID"],
+        ["PRODUCT", "CONTACT_ID"],
+        ["PRODUCTPRICE", "CONTACT_ID"],
+        ["SALESORDER", "CONTACT_ID"],
+        ["SALESPROJECT", "CONTACT_ID"],
+        ["TASK", "REQUESTOR_CONTACT_ID"],
+        ["TASK", "EDITOR_CONTACT_ID"],
+        ["TASKLINK", "OBJECT_ROWID"],
+        ["ACTIVITY", "RESPONSIBLE"],
+        ["DSGVO", "CONTACT_ID"],
+        ["DSGVOINFO", "CONTACT_ID"],
+        ["TIMETRACKING", "CONTACT_ID"],
+        ["ACTIVITYLINK", "OBJECT_ROWID"],
+        ["AB_ATTRIBUTERELATION", "OBJECT_ROWID"],
+
+        ["ASYS_CALENDARLINK", "DBID", "", SqlUtils.getSystemAlias()]
+    ];
+}
diff --git a/process/DuplicateScanner_lib/process.js b/process/DuplicateScanner_lib/process.js
index e26053edc6cb753291a842212cbfcef324124799..be805bc2aecc3323fb0e536f545da25e8d2b5762 100644
--- a/process/DuplicateScanner_lib/process.js
+++ b/process/DuplicateScanner_lib/process.js
@@ -1,20 +1,12 @@
 import("system.project");
-import("ActivityTask_lib");
-import("KeywordRegistry_basic");
-import("system.translate");
-import("system.datetime");
-import("JditoFilter_lib");
-import("system.process");
 import("system.util");
 import("system.vars");
-import("system.net");
-import("system.logging");
 import("system.db");
 import("system.entities");
 import("Sql_lib");
 import("system.indexsearch");
-import("Communication_lib");
-import("Attribute_lib");
+import("IndexSearch_lib");
+import("system.process");
 
 /**
  * Methods for duplicate scanning.
@@ -24,1356 +16,250 @@ import("Attribute_lib");
  */
 function DuplicateScannerUtils() {}
 
-/*
- * Loads all prefilters for a scanner in the form of arrays in an array.
- * Single filter record: [FILTER_CONDITION, COUNT_CHARACTERS_TO_USE, MAX_RESULTS_THRESHOLD]
- *
- *  @param {String} pFilterName Name of the filter
- *  @param {String} pTargetEntity Entity which has been configured
- *  @returns {String[[]]} Array of arrays containing the configured values
- */
-DuplicateScannerUtils.loadFilters = function(pFilterName, pTargetEntity)
-{
-    let query = newSelect("FILTER_CONDITION, COUNT_CHARACTERS_TO_USE, MAX_RESULTS_THRESHOLD")
-                    .from("DUPLICATESCANNERPREFILTERCONFIG")
-                    .join("DUPLICATESCANNER", "DUPLICATESCANNER.ID = DUPLICATESCANNERPREFILTERCONFIG.DUPLICATESCANNER_ID")
-                    .where("DUPLICATESCANNER.FILTER_NAME", pFilterName)
-                    .and("DUPLICATESCANNER.ENTITY_TO_SCAN_NAME", pTargetEntity);
-
-    return query.table();
-}
-
-/*
- * Deletes the cached duplicate for the given id.
- * If there would only remain one item in the cluster after deletion, the whole cluster including the duplicate gets deleted.
- * In this case, all records marked as unrelated duplicate will be deleted aswell.
- *
- * @param {String} pDuplicateId Id of the duplicate to delete
- */
-DuplicateScannerUtils.deleteCachedDuplicate = function(pDuplicateId)
-{
-    var [countDuplicatesInClusterWithoutParameterId, clusterId] = newSelect("count(ID), CLUSTERID")
-                    .from("DUPLICATECLUSTERS")
-                    .where("DUPLICATECLUSTERS.CLUSTERID", newSelect("CLUSTERID")
-                                                            .from("DUPLICATECLUSTERS")
-                                                            .where("DUPLICATECLUSTERS.DUPLICATEID", pDuplicateId).build(),
-                                                        SqlBuilder.IN())
-                    .and("DUPLICATECLUSTERS.DUPLICATEID", pDuplicateId, SqlBuilder.NOT_EQUAL())
-                    .groupBy("CLUSTERID")
-                    .arrayRow();
-
-    //If only one duplicate would be remaining,
-    //the whole cluster has to be deleted because there are no more duplicates.
-    //Otherwise delete just the single duplicate. The parameterized duplicate has been excluded via sql
-    //therefore check for smaller/equals 1
-    if(countDuplicatesInClusterWithoutParameterId <= 1)
-    {
-        newWhere("DUPLICATECLUSTERS.CLUSTERID", clusterId).deleteData();
-        newWhere("UNRELATEDDUPLICATES.CLUSTERID", clusterId).deleteData();
-    }
-    else
-    {
-        newWhereIfSet("DUPLICATECLUSTERS.DUPLICATEID", pDuplicateId).deleteData();
-
-        //Delete all records where this duplicateId is mentioned
-        DuplicateScannerUtils.deleteAllUnrelatedDuplicateRelations(pDuplicateId);
-    }
-}
-
-/*
- * Deletes all Clusters for the given target Entity.
- * No records markes as unrelated duplicate are being deleted.
- *
- * @param {String} pTargetEntity Entity which has been configured
- * @return Count of deleted rows
- */
-DuplicateScannerUtils.deleteClustersByTargetEntity = function(pTargetEntity)
-{
-    return newWhereIfSet("DUPLICATECLUSTERS.TARGET_ENTITY", pTargetEntity).deleteData();
-}
-
-/*
- * Updates the duplicate relations markes as unrelated for the given target entity.
- * All ClusterIds get updated with the new values if the same combination of duplicateIds
- * still exists in the DUPLICATECLUSTERS table.
- *
- * Afterwards, all records which contain a nonexistend clusterId are being deleted
- *
- * @param {String} pTargetEntity Name of Entity whose duplicates should be updated
+/**
+ * Returns an sql condition which returns a list of duplicate ids.
+ * The count is checked using pCount and pOperator.
+ * This function can be used for FilterExtensions
+ * 
+ * @param {string[]} pEntities target entities
+ * @param {number} pCount value of count (will be applied to the operator) 
+ * @param {string} pOperator the operator in sql notation e.g.: # = ?
+ * @param {boolean} pSubtractIgnored if set the ignored duplicates will be subtracted
+ * 
+ * @returns {SqlBuilder} subselect selecting the duplicate ids
  */
-DuplicateScannerUtils.refreshUnrelatedDuplicateRelations = function(pTargetEntity)
+DuplicateScannerUtils.getDuplicateConditionalListSql = function(pEntities, pCount, pOperator, pSubtractIgnored)
 {
-    /*
-     * Update all records with the current valid clusterId where the same duplicateId combination exists
-     */
-    let clusterIdChanges = newSelect("dc1.CLUSTERID, ud.CLUSTERID")
-                    .from("UNRELATEDDUPLICATES", "ud")
-                    .join("DUPLICATECLUSTERS", "dc1.DUPLICATEID = ud.SOURCEDUPLICATEID", "dc1")
-                    .join("DUPLICATECLUSTERS", "dc2.DUPLICATEID = ud.UNRELATEDDUPLICATEID", "dc2")
-                    .where(["DUPLICATECLUSTERS", "TARGET_ENTITY", "dc1"], pTargetEntity)
-                    .table();
-
-    let updateStatements = clusterIdChanges.map(function ([newClusterId, oldClusterId])
-    {
-        return newWhere("UNRELATEDDUPLICATES.CLUSTERID", oldClusterId).buildUpdateStatement({
-            "CLUSTERID": newClusterId
-        }, "UNRELATEDDUPLICATES");
-    });
+    var subselect = newSelect("count(*)").from("UNRELATEDDUPLICATES")
+    .where("UNRELATEDDUPLICATES.DUPLICATETYPE = HASDUPLICATE.OBJECT_TYPE")
+    .and("UNRELATEDDUPLICATES.SOURCEDUPLICATEID = HASDUPLICATE.OBJECT_ROWID");
     
-    db.updates(updateStatements);
-
-    /*
-     * All unrelated duplicate ids that still exist in a cluster, have been updated with the new cluster id.
-     * All records with a nonexistend clusterid can now be deleted because they haven't been detected as a duplicate any more.
-     */
-    newWhere("UNRELATEDDUPLICATES.CLUSTERID", newSelect("dc1.CLUSTERID").from("DUPLICATECLUSTERS", "dc1"), SqlBuilder.NOT_IN())
-        .deleteData();
-}
-
-/*
- * Creates a relation between two duplicates which means they are unrelated.
- * They will not appear in each others duplicate tab any more.
- * To remove this relation use DuplicateScannerUtils.deleteUnrelatedDuplicateRelation
- *
- * @param {String} pSourceContactId Id of first duplicate
- * @param {String} pUnrelatedContactId Id of second duplicate
- * @param {String} pClusterId Id of the cluster in which the duplicates are aggregated
- * @returns {String} Number of Records inserted
- */
-DuplicateScannerUtils.createUnrelatedDuplicateRelation = function(pSourceContactId, pUnrelatedContactId, pClusterId)
-{
-    return new SqlBuilder().insertFields({
-        "UNRELATEDDUPLICATEID": pUnrelatedContactId,
-        "SOURCEDUPLICATEID": pSourceContactId,
-        "CLUSTERID": pClusterId
-    }, "UNRELATEDDUPLICATES", "ID");
-}
-
-/*
- * Gets the cluster id in which the given duplicate id exists
- *
- *  @param {String} pDuplicateId whose cluster id should be searched
- *  @returns {String} Cluster id
- */
-DuplicateScannerUtils.getClusterId = function(pDuplicateId)
-{
-    return newSelect("CLUSTERID")
-                .from("DUPLICATECLUSTERS")
-                .where("DUPLICATECLUSTERS.DUPLICATEID", pDuplicateId)
-                .cell();
-}
-
-/*
- * Deletes the "unrelated" relation between two duplicates
- *
- *  @param {String} pSourceDuplicateId Id of the source duplicate
- *  @param {String} pUnrelatedDuplicateId Id of the source duplicate
- *  @returns {String} Number of records deleted
- */
-DuplicateScannerUtils.deleteUnrelatedDuplicateRelation = function(pSourceDuplicateId, pUnrelatedDuplicateId)
-{
-    return newWhere("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", pSourceDuplicateId)
-                .and("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID", pUnrelatedDuplicateId)
-                .deleteData();
-}
-
-/*
- * Deletes all relations to a duplicate id wether the id is the source or the unrelated duplicate in the relation
- *
- *  @param {String} pDuplicateId Duplicate id whose "unrelated" relations are to delete
- *  @returns {String} Number of records deleted
- */
-DuplicateScannerUtils.deleteAllUnrelatedDuplicateRelations = function(pDuplicateId)
-{
-    DuplicateScannerUtils.deleteUnrelatedDuplicateRelation(pDuplicateId, pDuplicateId);
+    var countSql = pSubtractIgnored ? "(HASDUPLICATE.DUPLICATECOUNT - (" + subselect.toString() + "))" : "(HASDUPLICATE.DUPLICATECOUNT)";
+    return newSelect("HASDUPLICATE.OBJECT_ROWID").from("HASDUPLICATE")
+    .where("HASDUPLICATE.OBJECT_TYPE", pEntities, SqlBuilder.IN())
+    .and(pOperator.replace("#", countSql).replace("?", pCount));
 }
 
-/*
- * Loads all other duplicates from the cluster in which the parameterized duplicate is located
- *
- *  @param {String} pDuplicateId
- *  @returns {String[]} Array of duplicate ids
- */
-DuplicateScannerUtils.getCachedDuplicatesForDuplicateId = function(pDuplicateId)
-{
-    return newSelect("DUPLICATEID")
-                .from("DUPLICATECLUSTERS")
-                .where("DUPLICATECLUSTERS.CLUSTERID", newSelect("CLUSTERID")
-                                                            .from("DUPLICATECLUSTERS")
-                                                            .where("DUPLICATECLUSTERS.DUPLICATEID", pDuplicateId),
-                                                    SqlBuilder.IN())
-                .and("DUPLICATECLUSTERS.DUPLICATEID", pDuplicateId, SqlBuilder.NOT_EQUAL())
-                .and("DUPLICATECLUSTERS.DUPLICATEID", newSelect("UNRELATEDDUPLICATEID")
-                                                            .from("UNRELATEDDUPLICATES")
-                                                            .where("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", pDuplicateId),
-                                                    SqlBuilder.NOT_IN())
-                .and("DUPLICATECLUSTERS.DUPLICATEID", newSelect("SOURCEDUPLICATEID")
-                                                            .from("UNRELATEDDUPLICATES")
-                                                            .where("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID", pDuplicateId),
-                                                    SqlBuilder.NOT_IN())
-                .arrayColumn();
-}
-
-/*
- * Returns all duplicate ids which haven't been marked as unrelated for the given cluster id.
- *
- * @param {String} pClusterId The clusters id
- * @return {String[]} Array of duplicate ids excluding those marked as unrelated
- */
-DuplicateScannerUtils.getCachedDuplicatesForClusterId = function(pClusterId)
-{
-    return newSelect("DUPLICATEID")
-                .from("DUPLICATECLUSTERS")
-                .where("DUPLICATECLUSTERS.DUPLICATEID", newSelect("UNRELATEDDUPLICATEID").from("UNRELATEDDUPLICATES"),
-                            SqlBuilder.NOT_IN())
-                .and("DUPLICATECLUSTERS.CLUSTERID", pClusterId)
-                .arrayColumn();
-}
-
-/*
- * Recreates the cached duplicate clusters based on the configured pattern. <br />
- * The old clusters have to be deleted manually beforehand or by using "deleteClustersByTargetEntity".<br />
- * If there have already been ignored relations between duplicate records, it's advised to call "refreshUnrelatedDuplicateRelations" after the recreation of the duplicates cache.<br />
- * Please check the documentation of the params on how to get the infos required.<br />
- * <br />
- * If the usage of an external webservice has been activated, the search will be executed beforehand and the results will then be given to the pFormatValuesConsumeWebserviceCallback via parameter.<br />
- * To access the values it is advised to run thru the parameter like an array and access its value by key which is the index field name. The entity<br />
- * field names can be converted using DuplicateScannerUtils.translateEntityToIndexFields. For further infos see the example section below.<br />
- * <br />
- * Attention!<br />
- * If it is configured to use the external webservice callback the values have to be in the same format as they are in the parameter of the callback.<br />
- * <br />
- * @param {String} pFilterName Name of the filter to use
- * @param {String} pTargetEntity The target entity which has been assigned to the filters configuration
- * @param {String} pRecordsBlockSize The values which are checked get loaded in blocks.
- * @param {String} pFormatValuesConsumeWebserviceCallback Null if no external service is used otherwise a function with one parameter.
- * @return {Int} Count of duplicate clusters created
- *
- * @example
- * var filterName = "PersonDuplicates";
- * var targetEntity = "Person_entity";
- * var recordBlockSize = DuplicateScannerUtils.getBlockSize();
- *
- * let formatToJsonAndCallWsCallback = function(pPossibleDuplicatesRay)
- * {
- *      let indexResultFields = DuplicateScannerUtils.TranslateEntityToIndexFields(targetEntity, resultFields)
- *
- *      //Run thru every duplicate result an read out the resultfields
- *      for (let i = 0; i < pPossibleDuplicatesRay.length; i++)
- *      {
- *          for (let b = 0; b < resultFields.length; b++)
- *          {
- *              let entityFieldName = resultFields[b];
- *              let indexFieldName = indexResultFields[entityFieldName];
- *              //format values
- *          }
- *      }
- *      //call webservice
- *      //reformat results to same structure as before
- *      return pPossibleDuplicatesRay;
- * };
- *
- * DuplicateScannerUtils.DeleteDuplicateClustersByTargetEntity(targetEntity);
- *
- * DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, pRecordsBlockSize, formatToJsonAndCallWsCallback);
- *
- * DuplicateScannerUtils.RefreshUnrelatedDuplicateRelations(targetEntity);
+/**
+ * Ignores duplicates corrosponding to the type, the source, and the duplicate ids
+ * 
+ * @param {string} pDuplicateType the duplicate type e.g.: Organisation_entity
+ * @param {string} pSourceDuplicateId the source duplicate id
+ * @param {string[]} pUnrelatedDuplicateIds the target duplicate ids
+ * @param {boolean} pIgnore weather the duplicate should be ignored or unignored
  */
-DuplicateScannerUtils.rebuildDuplicatesCache = function(pFilterName, pTargetEntity,
-    pRecordsBlockSize, pFormatValuesConsumeWebserviceCallback)
+DuplicateScannerUtils.updateIgnored = function(pDuplicateType, pSourceDuplicateId, pUnrelatedDuplicateIds, pIgnore)
 {
-    let useExternalWebservice = _DuplicateScannerUtils._isUseExternalWebservice(pFilterName, pTargetEntity);
-    let resultFields = DuplicateScannerUtils.getResultFields(filterName, targetEntity);
-
-    let indexPattern = _DuplicateScannerUtils._loadIndexPattern(pFilterName, pTargetEntity);
-    let entityFieldConfigs = _DuplicateScannerUtils._loadEntityFieldConfigsFromPattern(indexPattern);
-    let entityIdField = _DuplicateScannerUtils._loadEntityIdField(pFilterName, pTargetEntity);
+    newWhere("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", pSourceDuplicateId)
+    .and("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID", pUnrelatedDuplicateIds, SqlBuilder.IN())
+    .deleteData();
     
-    let alreadyIdentifiedIds = [];
+    var TABLE_NAME = "UNRELATEDDUPLICATES";
+    var COLUMN_NAMES = ["ID", "DUPLICATETYPE", "SOURCEDUPLICATEID", "UNRELATEDDUPLICATEID"];
+    var COLUMN_TYPES = db.getColumnTypes(TABLE_NAME, COLUMN_NAMES);
     
-    let entityFields = _DuplicateScannerUtils._loadEntityFieldsFromFieldConfigs(entityFieldConfigs);
-
-    entityFields.push(entityIdField);
-    
-    let targetRecords = DuplicateScannerUtils.getEntityRecords(pTargetEntity, entityFields, 0, pRecordsBlockSize);
-
-    let currentRecordIndex = pRecordsBlockSize;
-    while(targetRecords.length > 0)
+    var statements = [];
+    pUnrelatedDuplicateIds.forEach(function(currId)
     {
-        
-        foundDuplicateIds = DuplicateScannerUtils.scanRecords(pTargetEntity, targetRecords,
-            entityFieldConfigs, resultFields, useExternalWebservice,
-            pFormatValuesConsumeWebserviceCallback, alreadyIdentifiedIds, indexPattern, entityIdField);
-        
-        if (foundDuplicateIds)
-            alreadyIdentifiedIds = alreadyIdentifiedIds.concat(foundDuplicateIds);
-
-        if(targetRecords.length < pRecordsBlockSize)
-        {
-            break;
-        }
-        targetRecords = DuplicateScannerUtils.getEntityRecords(pTargetEntity, entityFields,
-            currentRecordIndex, pRecordsBlockSize);
-
-        currentRecordIndex += pRecordsBlockSize;
-    }
-}
-
-DuplicateScannerUtils.scanRecords = function(pTargetEntity, pTargetRecordsData,
-    pEntityFieldConfigs, pResultFields, pUseExternalWebservice, pFormatValuesConsumeWebserviceCallback, pAlreadyIdentifiedIds, pIndexPattern, pEntityIdField)
-{
-    let foundDuplicateIds = [];
-
-    //If the contact id loading query has no results, stop.
-    //No ids should be deleted if an error has been made in this query.
-    if(pTargetRecordsData.length <= 0)
-        return foundDuplicateIds;
-
-    //First it gets checked if the current id has already been identified. If that's the case it'll continue with the next.
-    //Otherwise an object gets build in the form of ["FilterFieldName" = "FilterFieldValueFromQuery"] with which a scan for possible duplicates get's started
-    var duplicatesToInsertQueries = [];
-    for (let b = 0; b < pTargetRecordsData.length; b++)
+        var columnValues = [util.getNewUUID(), pDuplicateType, pSourceDuplicateId, currId];
+        statements.push([TABLE_NAME, COLUMN_NAMES, COLUMN_TYPES, columnValues]);
+    });
+    if(pIgnore)
     {
-        let entityFieldValuesRay = DuplicateScannerUtils.buildEntityFieldConfigs(pEntityFieldConfigs, pTargetRecordsData[b]);
-
-        //The first field in this Array must always be the configured id field. This is ensured using onValidation-logic
-        let idValue = pTargetRecordsData[b][pEntityIdField];
-
-        //If the current Id has already been identified, continue
-        if(pAlreadyIdentifiedIds.indexOf(pTargetRecordsData[b][pEntityIdField]) > -1)
-        {
-            continue;
-        }
-
-        let foundDuplicates = _DuplicateScannerUtils._scanForDuplicates(pTargetEntity,
-            entityFieldValuesRay, pResultFields, idValue, pFormatValuesConsumeWebserviceCallback, pUseExternalWebservice, pIndexPattern)
-
-        if(foundDuplicates == null || foundDuplicates.length == 0)
-        {
-            continue;
-        }
-        //Insert all found duplicate ids into an cache array because those ids don't have to be checked again lateron.
-        for (let i = 0; i < foundDuplicates.length; i++)
-        {
-            let localId = foundDuplicates[i][indexsearch.FIELD_ID];
-            foundDuplicateIds.push(localId);
-        }
-
-        pAlreadyIdentifiedIds = pAlreadyIdentifiedIds.concat(foundDuplicateIds);
-
-        //The duplicates list contains only the found duplicates to the original id, therefore it get's added manually
-        foundDuplicateIds.push(pTargetRecordsData[b][pEntityIdField]);
-
-        let insertQueriesRay = _DuplicateScannerUtils._createInsertDuplicatesClusterQuery(foundDuplicateIds, pTargetEntity)
-        duplicatesToInsertQueries = duplicatesToInsertQueries.concat(insertQueriesRay);
-        foundDuplicateIds = [];
+        db.inserts(statements);
     }
-    db.inserts(duplicatesToInsertQueries, db.getCurrentAlias(), 10 * datetime.ONE_MINUTE);
-    return foundDuplicateIds;
 }
 
-/* 
- * Searches for a cluster which contains the duplicates specified by the parameterized array. <br />
- * The contents of the cluster have to be identical, if no fitting cluster could be found an empty string is returned.
+/**
+ * Removes ignored duplicates from an array of duplicate ids
  * 
- * @param {String} pNewRecordId The id of the record which was used to scan for duplicates
- * @param {String[]} pDuplicateIds Duplicate ids used to search for a cluster containing them
- * @param {String} pTargetEntity Entity which has been configured
- * @returns {String} A clusterid if a matching cluster has been found, otherwise ""
- */
-DuplicateScannerUtils.cacheNewScanResults = function(pNewRecordId, pDuplicateIds, pTargetEntity)
-{
-    let duplicateIds = [];
-    //Run thru every duplicate result and read out the id. 
-    //Do it now to have a simple array on all usages lateron.
-    for (let i = 0; i < pDuplicateIds.length; i++)
-    {
-        let duplicateContactId = pDuplicateIds[i][indexsearch.FIELD_ID];
-        duplicateIds.push(duplicateContactId);
-    }
-    
-    let clusterId = DuplicateScannerUtils.getClusterWithIdenticalDuplicates(duplicateIds);
-    
-    //If no cluster has beend found, create a new one with all found duplicateIds, 
-    //otherwise add the id to the existing cluster
-    let idRayToInsert = [];
-    if(clusterId == undefined || clusterId == null || clusterId == "")
-    {
-        idRayToInsert = duplicateIds;
-        idRayToInsert.push(pNewRecordId);
-    }
-    else
-        idRayToInsert.push(pNewRecordId);
-    
-    insertQueriesRay = _DuplicateScannerUtils._createInsertDuplicatesClusterQuery(idRayToInsert, pTargetEntity, clusterId)
-
-    return db.inserts(insertQueriesRay);
-}
-
-/* 
- * Searches for a cluster which contains the duplicates specified by the parameterized array. <br />
- * The contents of the cluster have to be identical, if no fitting cluster could be found an empty string is returned.
+ * @param {string} pTargetEntity the target entity e.g.: Organisation_entity
+ * @param {string} pTargetUid the source duplicate id
+ * @param {string} pIdArray the array of duplicate ids
  * 
- * @param {String[]} pDuplicateIds Duplicate ids which should be in the same cluster
- * @returns {String} Id of the cluster which contains all given duplicate ids or ""
+ * @returns {string[]} the filtered duplicate ids
  */
-DuplicateScannerUtils.getClusterWithIdenticalDuplicates = function(pDuplicateIds)
+DuplicateScannerUtils.filterIgnored = function(pTargetEntity, pTargetUid, pIdArray)
 {
-    let RESULT_NO_CLUSTER_FOUND = "";
-
-    if(pDuplicateIds.length < 1)
-        return RESULT_NO_CLUSTER_FOUND;
-    
-    let clusterIdSelect = newSelect("distinct CLUSTERID")
-                                .from("DUPLICATECLUSTERS")
-                                .where();
-    
-    for (let i = 0; i < pDuplicateIds.length; i++) 
+    if(pIdArray.length == 0)
     {
-        clusterIdSelect.and("DUPLICATECLUSTERS.CLUSTERID", newSelect("CLUSTERID").from("DUPLICATECLUSTERS").where("DUPLICATECLUSTERS.DUPLICATEID", pDuplicateIds[i]),
-                                        SqlBuilder.IN());
+        return pIdArray;
     }
-
-    let foundClusterId = clusterIdSelect.cell();
-
-    if(foundClusterId == null || foundClusterId == "")
-        return RESULT_NO_CLUSTER_FOUND;
-    
-    let duplicatesInCluster = newSelect("DUPLICATEID")
-                                            .from("DUPLICATECLUSTERS")
-                                            .where("DUPLICATECLUSTERS.CLUSTERID", foundClusterId)
-                                            .arrayColumn();
-
-    /* 
-     * A cluster has been searched which contains all duplicate ids as specified via parameter.
-     * There's the possibility that this cluster contains even more duplicates than specified via the parameter.
-     * In this case, the cluster and the parameterized duplicateids are not identical 
-     * which means a new cluster has to be created.
-     */
-    if(pDuplicateIds.length != duplicatesInCluster.length)
-        return RESULT_NO_CLUSTER_FOUND;
-    else
-        return foundClusterId;
+    var ignoreTable = newSelect(["UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID"])
+        .from("UNRELATEDDUPLICATES")
+        .where("UNRELATEDDUPLICATES.DUPLICATETYPE", pTargetEntity)
+        .and("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", pTargetUid)
+        .and("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID", pIdArray, SqlBuilder.IN())
+        .arrayColumn();
+    return pIdArray.filter(function(curr) {
+        return !ignoreTable.includes(curr);
+    });
 }
 
-DuplicateScannerUtils.getEntityRecords = function(pTargetEntity, pEntityFields, pStartRow, pCountRecordsToLoad)
-{
-    let getRowsConfig = entities.createConfigForLoadingRows()
-    .entity(pTargetEntity)
-    .fields(pEntityFields)
-    .count(pCountRecordsToLoad)
-    .startrow(pStartRow);
-    return entities.getRows(getRowsConfig);
-}
-/*
- * Loads the configured resultfields as array
- *
- *  @param {String} pFilterName Name of the filter
- *  @param {String} pTargetEntity Entity which has been configured
- *  @returns {String[]} Resultfields as array
+/**
+ * Deletes duplicates corrosponding to the given type and ids
+ * 
+ * @param {string} pObjectType the duplicate type e.g.: Organisation_entity
+ * @param {string[]} pObjectRowIds the duplicate ids e.g. some organisation ids
  */
-DuplicateScannerUtils.getResultFields = function(pFilterName, pTargetEntity)
+DuplicateScannerUtils.deleteHasDuplicateEntries = function(pObjectType, pObjectRowIds)
 {
-    return newSelect("dsrfc.ENTITY_FIELD_NAME")
-                .from("DUPLICATESCANNERRESULTFIELDCONFIG dsrfc")
-                .join("DUPLICATESCANNER", "DUPLICATESCANNER.ID = dsrfc.DUPLICATESCANNER_ID")
-                .where("DUPLICATESCANNER.FILTER_NAME", pFilterName)
-                .and("DUPLICATESCANNER.ENTITY_TO_SCAN_NAME", pTargetEntity)
-                .arrayColumn();
+    newWhere("HASDUPLICATE.OBJECT_TYPE", pObjectType)
+    .and("HASDUPLICATE.OBJECT_ROWID", pObjectRowIds, SqlBuilder.IN())
+    .deleteData();
 }
 
-/*
- * Scans for duplicates based on the configured pattern and the selected id field<br />
- * All values to the used placeholders have to be present in "pValuesToCheck"<br />
- * First all placeholders in the pattern will be replaced with their respective values.
- * Then, the pattern is extended wo exclude the record on which the search is based on.
- *<br />
- * If the usage of an external webservice has been activated, the result will then be given to the pFormatValuesConsumeWebserviceCallback via parameter.<br />
- * To access the values it is advised to run thru the parameter like an array and access its value by key which is the index field name. The entity
- * field names can be converted using DuplicateScannerUtils.translateEntityToIndexFields
- * <br />
- * <br />
- * Attention!<br />
- * If it's a single scanForDuplicates call it doesn't matter what the callback returns because after the callback, no more modifications follow before
- * returning the data.<br />
- * If it's inside the RebuildCache the values have to be in the same format as the parameter
- *
- * @param {String} pFilterName Name of the filter
- * @param {String} pTargetEntity Respective target entity
- * @param {{"key", "value"}} pValuesToCheck An object with key value pairs which hold the name of the entity field as key and it's value as value. See the example "valuesToCheck"
- * @param {function} pFormatValuesConsumeWebserviceCallback Null if no external service is used otherwise a function with one parameter.
- * If the function is called is based on the configuration of the current scanner
- * @returns {[["key", "value"]]} Array of Key-Value-Pairs based on the configured resultfields, if an external webservices was used
- * the structure is defined by the parameterized function "pFormatValuesConsumeWebserviceCallback"
- *
- * @example
- * var filterName = "PersonDuplicates";
- * let targetEntity = "Person_entity";
- * let valuesToCheck = {};
- * var entityModel = project.getEntityStructure(targetEntity);
+/**
+ * Manually inserts a duplicate entry by the given type, id and count
  * 
- * //Read the values of all available entity fields and write the fieldname/value combination
- * //as key/value pairs into an object. This is used to trigger the scan for duplicates
- * let fieldValue = "";
- * let entityFields = [];
- * for (fieldname in entityModel.fields) 
- * { 
- *     field = entityModel.fields[fieldname]; 
- *     if(field.fieldType == project.ENTITYFIELDTYPE_FIELD)
- *     {
- *         fieldValue = vars.get("$field." + field.name);
- *         
- *         if(fieldValue != null && fieldValue != "")
- *         {
- *             valuesToCheck[field.name] = fieldValue;
- *         }
- *     }
- * }
- *
- * let formatToJsonAndCallWsCallback = function(pPossibleDuplicatesRay)
- * {
- *     let indexResultFields = DuplicateScannerUtils.TranslateEntityToIndexFields(targetEntity, resultFields)
- *
- *     //Run thru every duplicate result an read out the resultfields
- *     for (let i = 0; i < pPossibleDuplicatesRay.length; i++)
- *     {
- *         for (let b = 0; b < resultFields.length; b++)
- *         {
- *             let entityFieldName = resultFields[b];
- *             let indexFieldName = indexResultFields[entityFieldName];
- *             //format values
- *         }
- *     }
- *     //call webservice
- *     //reformat results to same structure as before
- *     return pPossibleDuplicatesRay;
- * };
- *
- * //The result values can be accessed as seen above in "formatToJsonAndCallWsCallback"
- * DuplicateScannerUtils.ScanForDuplicates(filterName, targetEntity, valuesToCheck,
- * formatToJsonAndCallWsCallback);
+ * @param {string} pObjectType the type e.g.: Organisation_entity
+ * @param {string} pObjectRowId the id e.g. a organisation id
+ * @param {number} pCount the count / how many duplicates are there
  */
-DuplicateScannerUtils.scanForDuplicates = function(pFilterName, pTargetEntity, pValuesToCheck, pFormatValuesConsumeWebserviceCallback)
+DuplicateScannerUtils.insertHasDuplicateEntry = function(pObjectType, pObjectRowId, pCount)
 {
-    let useExternalWebservice = _DuplicateScannerUtils._isUseExternalWebservice(pFilterName, pTargetEntity);
-    let resultFields = DuplicateScannerUtils.getResultFields(pFilterName, pTargetEntity);
-    
-    let indexPattern = _DuplicateScannerUtils._loadIndexPattern(pFilterName, pTargetEntity);
-    let entityFieldConfigs = _DuplicateScannerUtils._loadEntityFieldConfigsFromPattern(indexPattern);  
-    let entityIdField = _DuplicateScannerUtils._loadEntityIdField(pFilterName, pTargetEntity);
-    
-    let entityFieldConfigValuesRay = DuplicateScannerUtils.buildEntityFieldConfigs(entityFieldConfigs, pValuesToCheck);
-   
-   //The first field in this Array must always be the configured id field.
-    let idValue = pValuesToCheck[entityIdField];
-
-    return _DuplicateScannerUtils._scanForDuplicates(pTargetEntity,
-        entityFieldConfigValuesRay, resultFields, idValue,
-        pFormatValuesConsumeWebserviceCallback, useExternalWebservice, indexPattern)
+    var COLUMNS = [
+        "HASDUPLICATEID",
+        "OBJECT_TYPE", "OBJECT_ROWID",
+        "DUPLICATECOUNT"
+    ];
+    var COLUMN_TYPES = db.getColumnTypes("HASDUPLICATE", COLUMNS);
+    var values = [
+        util.getNewUUID(),
+        pObjectType, pObjectRowId,
+        pCount.toFixed(0)
+    ];
+    db.insertData("HASDUPLICATE", COLUMNS, COLUMN_TYPES, values);
 }
 
-/*
- * Executes a indexsearch.lookupIndexField for eacht entity field in the parameterized array
- * and returns it as Map.
- *
- *  @param {String} pEntityName ...Name of the entity
- *  @param {String[]} pEntityFields Array of the entities Fields to translate to index fields
- *  @returns Map-like object where (key = entity field) and (value = index field)
- *
- *  @example
- *  let entityResultFields = ["LASTNAME"];
- *  let entityIndexFields = DuplicateScannerUtils.translateEntityToIndexFields("Person_entity", entityResultFields);
- *
+/**
+ * Updates HasDuplicate by entity (used in onInser and onUpdate)
+ * 
+ * @param {string} pTargetEntity the target entity e.g.: Organisation_entity
  */
-DuplicateScannerUtils.translateEntityToIndexFields = function(pEntityName, pEntityFields)
+DuplicateScannerUtils.updateHasDuplicateEntry = function(pTargetEntity)
 {
-    let entityIndexFields = {};
-    for (let i = 0; i < pEntityFields.length; i++)
-    {
-        let entityFieldName = pEntityFields[i];
+    var scanner = DuplicateScannerUtils.getScannerByEntity(pTargetEntity);
+    var indexsearchFilter = IndexsearchFilterUtils.fromFilter(scanner.filter);
 
-        //todo remove if api has been fixed
-        if(entityFieldName.startsWith(pEntityName))
-            entityFieldName = entityFieldName.replace(pEntityName + ".", "");
-
-        let indexField = indexsearch.lookupIndexField(pEntityName, entityFieldName);
-        entityIndexFields[pEntityFields[i]] = indexField;
-    }
-    return entityIndexFields;
-}
+    var fields = indexsearchFilter.getFields();
+    fields.add(scanner.idField);
+    fields = Array.from(fields);
 
-/*
- *
- * Merges the source person into the target person. 
- * This 
- * - replaces the source's with the target's contactid in a predefined set of tables.
- * - resets the standard communications of the source contact and keeps the ones of the target.
- * - updates participants of campaigns and removes obsolet ones(which would be duplicates)
- * - deletes the source person and contact
- * - deletes the duplicate record, if one exists
- * - deletes all unrelated-duplicate-relations containing the source contact id
- *
- *  @param {String} pSourceContactId The contact to be integrated into another
- *  @param {String} pTargetContactId The contact in which the source gets integrated
- *  @returns {Boolean} if the merge was sucessful
- */
-DuplicateScannerUtils.mergePerson = function(pSourceContactId, pTargetContactId)
-{
-    var sourcePersonId = newSelect("PERSON_ID")
-        .from("CONTACT")
-        .where("CONTACT.CONTACTID", pSourceContactId)
-        .cell();
-    var targetPersonId = newSelect("PERSON_ID")
-        .from("CONTACT")
-        .where("CONTACT.CONTACTID", pTargetContactId)
-        .cell();
-        
-    _DuplicateScannerUtils._deleteUniqueAttributes(pSourceContactId, pTargetContactId);
-    var isLinkedDataUpdated = _DuplicateScannerUtils._migrateLinkedContactData(pSourceContactId, pTargetContactId);
-    var isParticipantsUpdated = _DuplicateScannerUtils._migrateParticipantsToNewContact("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", 
-        pSourceContactId, pTargetContactId);
-    _DuplicateScannerUtils._updateOtherContacts(pSourceContactId, sourcePersonId, targetPersonId);
-    
-    var deleteStatements = [];
-    if (sourcePersonId != targetPersonId)
-        deleteStatements.push(newWhere("PERSON.PERSONID", sourcePersonId).buildDeleteStatement());
-    
-    deleteStatements.push(newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement());
-    deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId));
-    
-    //update binary 
-    var metaData = db.getBinaryMetadata("CONTACT", "DOCUMENT", pSourceContactId, true, SqlUtils.getBinariesAlias());
-    metaData.forEach(function (binaryMetaData) 
+    var entityObj = {};
+    fields.forEach(function(field)
     {
-        db.updateBinaryAssignment(binaryMetaData.id, "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias());
+        entityObj[field] = vars.get("$field." + field);
     });
-    var deletedRows = db.deletes(deleteStatements)
-
-    DuplicateScannerUtils.deleteCachedDuplicate(pSourceContactId);
-
-    return isLinkedDataUpdated || isParticipantsUpdated || deletedRows > 0;
-}
-
-DuplicateScannerUtils.createMergeSuccessActivity = function(pSourceContactId, pTargetContactId, pCurrentContactId, pContext)
-{
-    var activityDataForInsert = {
-        subject: translate.withArguments("A %0 record has been merged", [pContext]),
-        content: translate.withArguments("%0 with ID \"%1\" has been integrated into the %0 with the ID \"%2\"", [pContext, pSourceContactId, pTargetContactId]),
-        //categoryKeywordId: $KeywordRegistry.ac
-        directionKeywordId: $KeywordRegistry.activityDirection$internal(),
-        responsibleContactId: pCurrentContactId
-    };
-    var activityLinks = [[pContext, pTargetContactId]];
-
-    return ActivityUtils.insertNewActivity(activityDataForInsert, activityLinks, null, db.getCurrentAlias());
-}
-
-DuplicateScannerUtils.mergeOrganisation = function(pSourceContactId, pTargetContactId)
-{
-    var sourceOrganisationId = newSelect("ORGANISATION_ID")
-        .from("CONTACT")
-        .where("CONTACT.CONTACTID", pSourceContactId)
-        .cell();
-
-    var targetOrganisationId = newSelect("ORGANISATION_ID")
-        .from("CONTACT")
-        .where("CONTACT.CONTACTID", pTargetContactId)
-        .cell();
+    var selfId = entityObj[scanner.idField];
     
-    _DuplicateScannerUtils._deleteUniqueAttributes(pSourceContactId, pTargetContactId);
-    _DuplicateScannerUtils._migrateLinkedContactData(pSourceContactId, pTargetContactId);
-    _DuplicateScannerUtils._migrateParticipantsToNewContact("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", 
-        pSourceContactId, pTargetContactId);
-    _DuplicateScannerUtils._migratePersonsToNewOrganisation(sourceOrganisationId, targetOrganisationId);
+    var indexPattern = indexsearchFilter.buildQuery(entityObj);
+    var ids = DuplicateScannerUtils.getDuplicateIds(pTargetEntity, indexPattern, selfId);
     
-    var deleteStatements = [];
-    deleteStatements.push(newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement());
-    deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteOrganisationAndContactQuery(sourceOrganisationId, pSourceContactId));
-    deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId));
-    
-    //update binary 
-    var metaData = db.getBinaryMetadata("CONTACT", "DOCUMENT", pSourceContactId, true, SqlUtils.getBinariesAlias());
-    metaData.forEach(function (binaryMetaData) 
+    DuplicateScannerUtils.deleteHasDuplicateEntries(pTargetEntity, [selfId]);
+    if(ids.length > 0)
     {
-        db.updateBinaryAssignment(binaryMetaData.id, "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias());
-    });
-    var deletedRows = db.deletes(deleteStatements)
-
-    DuplicateScannerUtils.deleteCachedDuplicate(pSourceContactId);
-
-    return deletedRows >= 2;
-}
-
-/*
- * Creates an array of arrays containing the entity field config paired with it's value.
- *
- * @param {[]} pDuplicateFieldsConfig An Array with the configured fields in the form of [ENTITY_FIELD, IS_ID, USE_FOR_SEARCH]. @see LoadDuplicateIndexFieldsConfiguration()
- * @param {{"key", "value"}} pTargetRecordData One record containing the values for the configured fields. It's in the format of {"key(=EntityFieldName", "Value"}
- * @return {[[]]} An array of arrays containing the entity field config an its value. ["{entityfield: FIRSTNAME}", "PETER"]]
- * @example
- * pDuplicateFieldsConfig
- * ["CONTACTID", true, false]
- * ["FIRSTNAME", false, true]
- *
- * pTargetRecordData
- * ["d786045c-8b21-4f22-b6d9-72be9f61c04d", "PETER"]
- *
- * => ["{entityfield: FIRSTNAME}", "PETER"]]
- */
-DuplicateScannerUtils.buildEntityFieldConfigs = function(pDuplicateFieldsConfig, pTargetRecordData)
-{
-    let INDEX_CONFIG_ENTITY_FIELD = 0;
-    let entityFieldConfigValuesRay = [];
-    /*
-    * Based on the parameterized filter field names and the values loaded via the query,
-    * an array which contains records in the style of ["FilterFieldName", "FilterFieldValueFromQuery"] gets created.
-    * This is mandatory to run the scan for this record.
-    */
-    for (let i = 0; i < pDuplicateFieldsConfig.length; i++)
-    {
-        let fieldConfig = JSON.parse("{" + pDuplicateFieldsConfig[i] + "}");
-        let entityField = fieldConfig.entityfield;
-        let entityFieldValue = pTargetRecordData[entityField];
-        if(entityFieldValue == null)
-            entityFieldValue = "";
-        else
-            entityFieldValue = indexsearch.escapeString(entityFieldValue).trim();
-        
-        let exclude = fieldConfig.exclude;
-        if (exclude)
-        {   
-            exclude.forEach(function (excludeValue)
-            {
-                entityFieldValue = " " + entityFieldValue + " ";
-                entityFieldValue = entityFieldValue.replace(new RegExp( " " + excludeValue + " ", "gi"), "");
-            });  
-        }
-        
-        let valuelength = fieldConfig.length; 
-        if ( valuelength )
-            entityFieldValue = entityFieldValue.substr(0, parseInt(valuelength)) + "*";
-        
-        let empty = fieldConfig.empty; 
-        if ( !empty && entityFieldValue == "")
-            entityFieldValue = "*";
-       
-        entityFieldValue = entityFieldValue.trim();
-        entityFieldConfigValuesRay.push([pDuplicateFieldsConfig[i], entityFieldValue]);
+        DuplicateScannerUtils.insertHasDuplicateEntry(pTargetEntity, selfId, ids.length);
     }
-    return entityFieldConfigValuesRay.length > 0 ? entityFieldConfigValuesRay : [["", ""]];
-}
-
-DuplicateScannerUtils.getBlockSize = function()
-{
-    return project.getPreferenceValue("custom.duplicates.dataBlockSize", "5000");
-}
-
-DuplicateScannerUtils.getEntityFieldsFromConfig = function(pFilterName, pTargetEntity)
-{
-    let indexPattern = _DuplicateScannerUtils._loadIndexPattern(pFilterName, pTargetEntity);
-    if(indexPattern == null || indexPattern == "")
-        return [];
-    let fieldConfigs = _DuplicateScannerUtils._loadEntityFieldConfigsFromPattern(indexPattern);
-    if(fieldConfigs == null || fieldConfigs.length < 1)
-        return [];
-    let entityFields = _DuplicateScannerUtils._loadEntityFieldsFromFieldConfigs(fieldConfigs);
-    let entityIdField = _DuplicateScannerUtils._loadEntityIdField(pFilterName, pTargetEntity);
-    entityFields.push(entityIdField);
-    return entityFields;
 }
 
 /**
- * Loads the configured entity fields required for the given duplicate scanner.
+ * Returns a DuplicateScanner object by the given entity name
+ * 
+ * @param {string} pTargetEntity a entity name e.g.: Organisation_entity
  * 
- *  @param {String} pFilterName the name of the scanner
- *  @param {String} pTargetEntity the target entity
- *  @return {Object} an object with two properties:
- *      <ul>
- *          <li>entityFields: array of entity fields</li>
- *          <li>entityIdField: the id field name as string</li>
- *      </ul>
+ * @returns {object} the scanner object
  */
-DuplicateScannerUtils.getEntityFieldObjectFromConfig = function (pFilterName, pTargetEntity)
+DuplicateScannerUtils.getScannerByEntity = function(pTargetEntity)
 {
-    var indexPattern = _DuplicateScannerUtils._loadIndexPattern(pFilterName, pTargetEntity);
-    if (!indexPattern)
-        return null;
-    var fieldConfigs = _DuplicateScannerUtils._loadEntityFieldConfigsFromPattern(indexPattern);
-    if (fieldConfigs == null || fieldConfigs.length === 0)
-        return null;
-    
+    var duplicateScanner = newSelect([
+        "DUPLICATESCANNER.ID_FIELD_NAME",
+        "DUPLICATESCANNER.SCAN_PATTERN"
+    ])
+    .from("DUPLICATESCANNER")
+    .where("DUPLICATESCANNER.ENTITY_TO_SCAN_NAME", pTargetEntity).arrayRow();
+    var filterObj = JSON.parse(duplicateScanner[1]).filter;
     return {
-        entityFields : _DuplicateScannerUtils._loadEntityFieldsFromFieldConfigs(fieldConfigs),
-        entityIdField : _DuplicateScannerUtils._loadEntityIdField(pFilterName, pTargetEntity)
+        idField: duplicateScanner[0],
+        filter: filterObj
     };
 }
 
-DuplicateScannerUtils.getUnrelatedRelationsForDuplicate = function(pDuplicateId)
-{
-    let unrelatedIds = [];
-    let duplicateIds = newSelect("SOURCEDUPLICATEID, UNRELATEDDUPLICATEID")
-                .from("UNRELATEDDUPLICATES")
-                .where("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", pDuplicateId)
-                .or("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID", pDuplicateId)
-                .table();
-    let sourceDuplicateId = "";
-    let unrelatedDuplicateId = "";
-    for (let i = 0; i < duplicateIds.length; i++) 
-    {
-        sourceDuplicateId = duplicateIds[i][0];
-        unrelatedDuplicateId = duplicateIds[i][1];
-        
-        if(sourceDuplicateId != null && sourceDuplicateId != "" && sourceDuplicateId != pDuplicateId)
-        {
-            unrelatedIds.push(sourceDuplicateId);
-        }
-        else if(unrelatedDuplicateId != null && unrelatedDuplicateId != "" && unrelatedDuplicateId != pDuplicateId)
-        {
-            unrelatedIds.push(unrelatedDuplicateId);
-        }
-    }
-    return unrelatedIds;
-}
-
-function _DuplicateScannerUtils() {}
-
-_DuplicateScannerUtils._loadEntityFieldsFromFieldConfigs = function(pEntityFieldConfigs)
-{
-    let fieldNames = [];
-    for (let i = 0; i < pEntityFieldConfigs.length; i++) 
-    {
-        let fieldConfig = JSON.parse("{" + pEntityFieldConfigs[i] + "}");
-        let entityField = fieldConfig.entityfield;
-        fieldNames.push(entityField);
-    }
-    return fieldNames;
-}
-
-/*
- * Gets the Pattern for the scanner
- * A pattern usually contains placeholders in the style of "{entityFieldName]"
+/**
+ * Calls the index search and returns the found duplicate ids
  * 
- * @param {String} pScannerName Name of the filter to use
- * @param {String} pTargetEntity The target entity which has been assigned to the filters configuration
- * @returns {String} Scan pattern as string
- */
-_DuplicateScannerUtils._loadIndexPattern = function(pScannerName, pTargetEntity)
-{
-    let scanPattern = _DuplicateScannerUtils._filterToScanPattern( newSelect("SCAN_PATTERN")
-                            .from("DUPLICATESCANNER")
-                            .where("DUPLICATESCANNER.FILTER_NAME", pScannerName)
-                            .and("DUPLICATESCANNER.ENTITY_TO_SCAN_NAME", pTargetEntity)
-                            .cell());
-    scanPattern = scanPattern.trim();
-    return scanPattern;
-}
-
-
-_DuplicateScannerUtils._filterToScanPattern = function(filterString) {
-    if (filterString == "")
-        return "";
-    try 
-    {
-        var filter = JSON.parse(filterString);
-    }
-    catch (err)
-    {
-        return "";
-    }
-    return _DuplicateScannerUtils._filterChildsToScanPattern(filter.filter.childs, filter.filter.operator);
-}
-
-_DuplicateScannerUtils._filterChildsToScanPattern = function(childs, operator) {
-    let group = "";
-    for (let i = 0; i < childs.length; i++) {
-        if (group != ""){
-            group = group + " " + operator+ " ";
-        }
-        if (childs[i].type == "row"){
-            group =  group + _DuplicateScannerUtils._filterChildsRowToScanPattern(childs[i].name, childs[i].operator, childs[i].value);
-        } else if (childs[i].type == "group") {
-            group = group + "("  + _DuplicateScannerUtils._filterChildsToScanPattern(childs[i].childs, childs[i].operator) + ")";
-        }
-    }
-    return group;
-}
-
-_DuplicateScannerUtils._filterChildsRowToScanPattern = function (name, operator, value) {
-    let row = "";
-    row = row + name.toLowerCase() + ':({"entityfield":"' + name + '"';
-    switch (operator){
-        case "NOT_EQUAL":
-        case "CONTAINSNOT":
-            row = row + ', "exclude":' + value;
-        case "ISNOTNULL":
-            row = row + ', "empty":' + false;
-    }
-    row = row + '})';
-    return row;
-}
-
-_DuplicateScannerUtils._loadEntityFieldConfigsFromPattern = function(indexPattern)
-{
-    return indexPattern.match(/[^{}]+(?=\})/g);
-}
-
-_DuplicateScannerUtils._replacePlaceholderForValuesInPattern = function(pIndexPattern, pEntityFieldValueRays)
-{
-    let INDEX_ENTITY_FIELD_NAME = 0;
-    let INDEX_ENTITY_FIELD_VALUE = 1;
-
-    let placeholder = "";
-    let fieldValue = "";
-    for (let i = 0; i < pEntityFieldValueRays.length; i++) 
-    {
-        placeholder = "{" + pEntityFieldValueRays[i][INDEX_ENTITY_FIELD_NAME] + "}";
-        fieldValue = pEntityFieldValueRays[i][INDEX_ENTITY_FIELD_VALUE];        
-        pIndexPattern = pIndexPattern.replace(placeholder, fieldValue);
-    }
-    return pIndexPattern;
-}
-
-_DuplicateScannerUtils._loadEntityIdField = function(pFilterName, pTargetEntity)
-{
-    return newSelect("ID_FIELD_NAME")
-                .from("DUPLICATESCANNER")
-                .where("DUPLICATESCANNER.FILTER_NAME", pFilterName)
-                .and("DUPLICATESCANNER.ENTITY_TO_SCAN_NAME", pTargetEntity)
-                .cell();
-}
-
-/*
- * @see DuplicateScannerUtils.scanForDuplicates for the documentation
- */
-_DuplicateScannerUtils._scanForDuplicates = function(pTargetEntity, pEntityFieldConfigValuesRay,
-pResultFields, pRecordIdValueToIgnore, pFormatValuesConsumeWebserviceCallback, pUseExternalWebservice, pIndexPattern)
-{
-    //No filterfields/indexpattern => No indexsearch
-    if(pEntityFieldConfigValuesRay.length < 1 || pIndexPattern == null || pIndexPattern == "")
-        return null;
-    
-    let possibleDuplicates = [];
-    let ignoreSourceRecordPattern = _DuplicateScannerUtils._getIgnoreSourceRecordPattern(pRecordIdValueToIgnore);
-
-    let indexPatternWithValues = _DuplicateScannerUtils._replacePlaceholderForValuesInPattern(pIndexPattern, pEntityFieldConfigValuesRay);
-
-    possibleDuplicates = _DuplicateScannerUtils._callIndexSearch(pTargetEntity, indexPatternWithValues, ignoreSourceRecordPattern, pResultFields, 100);
-    
-    if(possibleDuplicates == null)
-        return null;
-
-    possibleDuplicates = possibleDuplicates[indexsearch.HITS];
-    
-    if(pUseExternalWebservice && pFormatValuesConsumeWebserviceCallback != null)
-        possibleDuplicates = pFormatValuesConsumeWebserviceCallback.apply(this, [possibleDuplicates]);
-
-    return possibleDuplicates;
-}
-
-/*
- * Returns a bool which say wether or not an external service should be used
- *
- * @param {String} pFilterName Name of the filter
- * @param {String} pTargetEntity Entity which has been configured
- *  @returns {Bool} True = use, False = no use
- */
-_DuplicateScannerUtils._isUseExternalWebservice = function(pFilterName, pTargetEntity)
-{
-    let isUseWebservice = newSelect("EXTERNAL_SERVICE_USAGE_ALLOWED")
-                                .from("DUPLICATESCANNER")
-                                .where("DUPLICATESCANNER.FILTER_NAME", pFilterName)
-                                .and("DUPLICATESCANNER.ENTITY_TO_SCAN_NAME", pTargetEntity)
-                                .cell();
-    return isUseWebservice != 0;
-}
-
-/*
- * Runs the indexsearch based on the given parameters.
- * If the "pEntityFieldValueRays" is empty, no search will be executed.
+ * @param {string} pTargetEntity search for duplicate in this entity e.g.: Organisation_entity
+ * @param {string} pIndexPattern the index pattern as string
+ * @param {string=} pSelfId optionally the own id (this will be excluded)
  * 
- * @param {String} pTargetEntity Entity which has been configured
- * @param {String} pIndexPatternWithValues The pattern used to search. Has to contain the values already.
- * @param {String} pIdFilter The filter pattern used to exclude the current record from the result.
- * @param {String} pResultFields The result field config. Use "DuplicateScannerUtils.getResultFields"
- * @param {String} pResultSetRows todo
- * @returns {[["key", "value"]] || null} Array of Key-Value-Pairs based on the configured pResultFields, if no pattern exists null
+ * @returns {string[]} the duplicate ids
  */
-_DuplicateScannerUtils._callIndexSearch = function(pTargetEntity, pIndexPatternWithValues, pIdFilter, pResultFields, pResultSetRows)
+DuplicateScannerUtils.getDuplicateIds = function(pTargetEntity, pIndexPattern, pSelfId)
 {
-    //logging.log(pIndexPatternWithValues)
-    //The indexPattern can't be null because it is required to run the search.
-    if(pIndexPatternWithValues == null || pIndexPatternWithValues == "")
-        return null;
     let indexQuery = indexsearch.createIndexQuery()
-                                .setPattern(pIndexPatternWithValues)
-                                .setEntities([pTargetEntity])
-//                                .addFilter(pIdFilter);
-                                // .setDefaultOperator(indexsearch.OPERATOR_AND)
-                                //.addSearchFields("Person_entity.FIRSTNAME", "Person_entity.LASTNAME", "Person_entity.CONTACTID")
-                                //.setRows(pResultSetRows);
-    if(pIdFilter && pIdFilter.length > 0)
-        indexQuery.addFilter(pIdFilter);
-    
-    indexQuery = _DuplicateScannerUtils._setResultFields(indexQuery, pResultFields);
-    return indexsearch.searchIndex(indexQuery);
-}
-
-/*
- * Sets each field of the given array as resultfield on the given query.
- * Supports indexsearch internal fields aswell
- * (indexsearch.FIELD_ID, indexsearch.FIELD_TITLE, indexsearch.FIELD_TYPE, indexsearch.FIELD_DESCRIPTION)
- *
- * @param {IndexQuery} pIndexQuery An indexquery created with "indexsearch.createIndexQuery()"
- * @param {String[]} pResultFields The result field config. Use "DuplicateScannerUtils.getResultFields"
- * @returns {IndexQuery} IndexQuery with the resultfields set
- */
-_DuplicateScannerUtils._setResultFields = function(pIndexQuery, pResultFields)
-{
-    let resultIndexFields = [];
-    let resultFields = [];
-    for (let i = 0; i < pResultFields.length; i++)
+        .setPattern(pIndexPattern)
+        .setEntities([pTargetEntity]);
+    if(pSelfId)
     {
-        if(pResultFields[i] == indexsearch.FIELD_ID
-            || pResultFields[i] == indexsearch.FIELD_TITLE
-            || pResultFields[i] == indexsearch.FIELD_TYPE
-            || pResultFields[i] == indexsearch.FIELD_DESCRIPTION)
-            {
-            resultIndexFields.push(pResultFields[i]);
-        }
-        else
-            resultFields.push(pResultFields[i]);
+        // creates -_local_id_:"<pSelfId>"
+        var optFilter = indexsearch.buildPattern(indexsearch.createPatternConfig().minus(
+            indexsearch.createPhraseTerm(pSelfId)
+            .setIndexField(indexsearch.FIELD_ID)
+        ));
+        indexQuery = indexQuery.addFilter(optFilter);
     }
 
-    if(resultIndexFields.length > 0)
-        pIndexQuery = pIndexQuery.addResultIndexFields(resultIndexFields);
-
-    if(resultFields.length > 0)
+    var indexResult = indexsearch.searchIndex(indexQuery);
+    indexResult = indexResult[indexsearch.HITS];
+    if(indexResult === null || indexResult.length === 0)
     {
-        pIndexQuery = pIndexQuery.addResultFields(resultFields);
+        return [];
     }
-    return pIndexQuery;
-}
-
-/*
- * Creates the queries to insert new duplicates into a new cluster based on the pDuplicatesRay
- *
- * @param {String[]} pDuplicatesRay Array of duplicate ids
- * @param {String} pTargetEntity Entity which has been configured
- * @returns {String[]} Array of insert queries
- */
-_DuplicateScannerUtils._createInsertDuplicatesClusterQuery = function (pDuplicatesRay, pTargetEntity)
-{
-    return _DuplicateScannerUtils._createInsertDuplicatesClusterQuery(pDuplicatesRay, pTargetEntity, util.getNewUUID());
-}
-
-/*
- * Creates the queries to insert new duplicates into a new cluster based on the pDuplicatesRay
- *
- * @param {String[]} pDuplicatesRay Array of duplicate ids
- * @param {String} pTargetEntity Entity which has been configured
- * @param {String} pClusterId Clusters id to which the duplicates are in relation
- * @returns {String[]} Array of insert queries
- */
-_DuplicateScannerUtils._createInsertDuplicatesClusterQuery = function (pDuplicatesRay, pTargetEntity, pClusterId)
-{
-    let duplicatesToInsertQueries = [];
-    let cols = ["ID", "CLUSTERID", "DUPLICATEID", "TARGET_ENTITY"];
 
-    if (!pClusterId)
-        pClusterId = util.getNewUUID();
-            
-    for (let i = 0; i < pDuplicatesRay.length; i++)
+    var duplicateIds = [];
+    indexResult.forEach(function(curr)
     {
-        let newId = util.getNewUUID();
-        let valuesToInsert = [newId, pClusterId, pDuplicatesRay[i], pTargetEntity];
-
-        duplicatesToInsertQueries.push(["DUPLICATECLUSTERS", cols, null, valuesToInsert]);
-    }
-    return duplicatesToInsertQueries;
-}
-
-/*
- * Deletes all clusters
- *
- * @returns {String} Count of records deleted
- */
-_DuplicateScannerUtils._deleteDuplicateClusters = function ()
-{
-    return db.deleteData("DUPLICATECLUSTERS");
-}
-
-/*
- * All records with contactId = sourceContactId get updated, which are not assigned to the same "group" as the targetContactId.
- * This is because otherwise there would now be in total two "participants" in the same "group" as opposed to one before.
- * Also if they already are in the same "group" those records shouldn't be updated because it would lead to the same outcome.
- *
- * @returns {Boolean} If records have been updated
- */
-_DuplicateScannerUtils._migrateParticipantsToNewContact = function (pTableName, pContactIdColumn, pAssignableIdColumn, pSourceContactId, pTargetContactId)
-{
-    var excludedIds = newSelect(pAssignableIdColumn)
-        .from(pTableName)
-        .where([pTableName, pContactIdColumn], pTargetContactId)
-        .arrayColumn();
-
-    var updateCount = newWhereIfSet([pTableName, pAssignableIdColumn], excludedIds, SqlBuilder.NOT_IN())
-        .and([pTableName, pContactIdColumn], pSourceContactId)
-        .updateFields(new Map().set(pContactIdColumn, pTargetContactId), pTableName);
-        
-    var deleteCount = newWhere([pTableName, pContactIdColumn], pSourceContactId)
-        .tableName(pTableName)
-        .deleteData();
-    
-    return updateCount > 0 || deleteCount > 0;
-}
-
-_DuplicateScannerUtils._buildDeleteOrganisationAndContactQuery = function(pSourceOrganisationId, pSourceContactId)
-{
-    return [
-        newWhere("ORGANISATION.ORGANISATIONID", pSourceOrganisationId).buildDeleteStatement(),
-        newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement()
-    ];
-}
-
-_DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery = function(pSourceContactId)
-{
-    return [
-        newWhere("UNRELATEDDUPLICATES.SOURCEDUPLICATEID", pSourceContactId).buildDeleteStatement(),
-        newWhere("UNRELATEDDUPLICATES.UNRELATEDDUPLICATEID", pSourceContactId).buildDeleteStatement()
-    ];
-}
-
-/*
- * Creates a filter pattern which excludes results with the provided id from the search. 
- *
- * @param {String} pRecordIdValueToIgnore The id value to exclude from the result.
- * @returns {String} Filter pattern which excludes hits with the given id (index) from the result.
- */
-_DuplicateScannerUtils._getIgnoreSourceRecordPattern = function(pRecordIdValueToIgnore)
-{
-    // creates -_local_id_:"<pRecordIdValueToIgnore>"
-    if(pRecordIdValueToIgnore && pRecordIdValueToIgnore.length > 0)
-        return indexsearch.buildPattern(indexsearch.createPatternConfig().minus(
-                            indexsearch.createPhraseTerm(pRecordIdValueToIgnore)
-                            .setIndexField(indexsearch.FIELD_ID)
-                        ));
-    return null;
-}
-
-_DuplicateScannerUtils._migrateLinkedContactData = function (pSourceContactId, pTargetContactId)
-{
-    var updateStatements = new Map();
-    var currentAlias = db.getCurrentAlias();
-    
-    var setStandardsStatements = [];
-    var [standardPhone, standardMail, standardAddressId] = newSelect([
-            "(" + CommUtil.getStandardSubSqlPhone() + ")", 
-            "(" + CommUtil.getStandardSubSqlMail() + ")",
-            "CONTACT.ADDRESS_ID"
-        ])
-        .from("CONTACT")
-        .where("CONTACT.CONTACTID", pTargetContactId)
-        .arrayRow();
-    
-    //if the targetContact already has a standard phone comm, set the comm from the sourceContact as not standard
-    if (standardPhone)
-    {
-        setStandardsStatements.push(
-            newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId)
-                .and("COMMUNICATION.MEDIUM_ID", CommUtil.getMediumIdsByCategory("PHONE"), SqlBuilder.IN())
-                .buildUpdateStatement({"ISSTANDARD" : "0"})
-        );
-    }
-    if (standardMail)
-    {
-        setStandardsStatements.push(
-            newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId)
-                .and("COMMUNICATION.MEDIUM_ID", CommUtil.getMediumIdsByCategory("EMAIL"), SqlBuilder.IN())
-                .buildUpdateStatement({"ISSTANDARD" : "0"})
-        );
-    }
-    //set the standardaddress of the sourceContact as standard of the targetContact if it doesn't have one set yet
-    if(!standardAddressId) 
-    {
-        var sourceStandard = newSelect("CONTACT.ADDRESS_ID")
-            .from("CONTACT")
-            .where("CONTACT.CONTACTID", pSourceContactId)
-            .cell();
-        setStandardsStatements.push(newWhere("CONTACT.CONTACTID", pTargetContactId).buildUpdateStatement({"ADDRESS_ID": sourceStandard}));
-    }
-    
-    updateStatements.set(currentAlias, setStandardsStatements);
-    
-    _DuplicateScannerUtils._getLinkedTableInfos(pTargetContactId).forEach(function ([tableName, columnName, additionalCondition, dbAlias])
-    {
-        if (!dbAlias)
-            dbAlias = currentAlias;
-        
-        if (!updateStatements.has(dbAlias))
-            updateStatements.set(dbAlias, []);
-        var statements = updateStatements.get(dbAlias);
-        
-        var updateValues = {};
-        updateValues[columnName] = pTargetContactId;
-        
-        var updateCondition = new SqlBuilder(dbAlias).where([tableName, columnName], pSourceContactId).andIfSet(additionalCondition);
-        
-        //push must be used here to keep the reference
-        statements.push(updateCondition.buildUpdateStatement(updateValues, tableName));
+        duplicateIds.push(curr[indexsearch.FIELD_ID]);
     });
-    
-    var totalChanges = 0;
-    
-    updateStatements.forEach(function (statements, alias)
-    {
-        totalChanges += db.updates(statements, alias);
-    });
-    
-    totalChanges += newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId).deleteData(); //delete leftover communications from the source contact
-    totalChanges += new AttributeRelationQuery(pSourceContactId).deleteAllAttributes(); //delete leftover attributes
-
-    return totalChanges > 0;
-}
-
-/*
- * Contains all Tables and their fields which may contain the contact id to be replaced for the data alias
- *
- * @returns {String[[]]} Array in the format [TableName, ContactIdColumnName, AdditionalCondition, alias]
- */
-_DuplicateScannerUtils._getLinkedTableInfos = function(pTargetContactId)
-{
-    //don't use communications that the target already has
-    var targetComms = newSelect("COMMUNICATION.ADDR") 
-        .from("COMMUNICATION")
-        .where("COMMUNICATION.CONTACT_ID", pTargetContactId)
-        .arrayColumn();
-        
-    var communicationDedupCondition = targetComms.length > 0
-        ? newWhere("COMMUNICATION.ADDR", targetComms, SqlBuilder.NOT_IN())
-        : "";
-    
-    return[
-        ["AB_APPOINTMENTLINK", "OBJECT_ROWID"],
-        ["AB_CTILOG", "CONTACT_ID"],
-        ["AB_OBJECTRELATION", "AB_OBJECTRELATIONID"],
-        ["AB_OBJECTRELATION", "OBJECT1_ROWID"],
-        ["AB_OBJECTRELATION", "OBJECT2_ROWID"],
-        ["AB_LOGHISTORY", "TABLENAMEID"],
-        ["ADDRESS", "CONTACT_ID"],
-        ["BULKMAILRECIPIENT", "CONTACT_ID"],
-        ["BULKMAIL", "TESTING_CONTACT_ID"],
-        ["CAMPAIGN", "EMPLOYEE_CONTACT_ID"],
-        ["CAMPAIGNSTEP", "EMPLOYEE_CONTACT_ID"],
-        ["COMMRESTRICTION", "CONTACT_ID"],
-        ["COMMRESTRICTION", "EMPLOYEE_INVOLVED"],
-        ["COMMUNICATION", "CONTACT_ID", communicationDedupCondition],
-        ["COMPETITION", "CONTACT_ID"],
-        ["CONTRACT", "CONTACT_ID"],
-        ["LETTERRECIPIENT", "CONTACT_ID"],
-        ["OBJECTMEMBER", "CONTACT_ID"],
-        ["OFFER", "CONTACT_ID"],
-        ["PRODUCT", "CONTACT_ID"],
-        ["PRODUCTPRICE", "CONTACT_ID"],
-        ["SALESORDER", "CONTACT_ID"],
-        ["SALESPROJECT", "CONTACT_ID"],
-        ["TASK", "REQUESTOR_CONTACT_ID"],
-        ["TASK", "EDITOR_CONTACT_ID"],
-        ["TASKLINK", "OBJECT_ROWID"],
-        ["ACTIVITY", "RESPONSIBLE"],
-        ["DSGVO", "CONTACT_ID"],
-        ["DSGVOINFO", "CONTACT_ID"],
-        ["TIMETRACKING", "CONTACT_ID"],
-        ["ACTIVITYLINK", "OBJECT_ROWID"],
-        ["AB_ATTRIBUTERELATION", "OBJECT_ROWID"],
-
-        ["ASYS_CALENDARLINK", "DBID", "", SqlUtils.getSystemAlias()]
-    ];
-}
-
-
-/*
- * Returns wether or not a value should be substring'd
- *
- * @return true if pCountCharsOfValueToUse is a number, greater than 0 and smaller than the values length
- */
-_DuplicateScannerUtils._isValueLongerThanCharsToUse = function(pValueLength, pCountCharsOfValueToUse)
-{
-    return !isNaN(pCountCharsOfValueToUse)
-    && pCountCharsOfValueToUse > 0
-    && pValueLength > pCountCharsOfValueToUse;
-}
-
-/*
- * Returns wether or not the parameter isnt null and a number or not
- *
- * @param {String} pCountCharsOfValueToUse Hopefully a number
- * @returns {String} True if parameter isnt null and a number, False if it's null or no number
- */
-_DuplicateScannerUtils._isNotNullAndANumber = function(pCountCharsOfValueToUse)
-{
-    return pCountCharsOfValueToUse != null && !isNaN(pCountCharsOfValueToUse);
+    return duplicateIds;
 }
 
-/*
- * Persons get reassigned to new organisation
- *
- * @returns {Boolean} If records have been updated
+/**
+ * Does the same as getDuplicateIds but takes in a scanner (by entity) instead of an indexPattern
+ * 
+ * @param {string} pTargetEntity the entity name used to get the Scanner
+ * @param {string} pTargetUid all variables will be loaded by this id
+ * 
+ * @returns {string[]} the duplicate ids
  */
-_DuplicateScannerUtils._migratePersonsToNewOrganisation = function (pSourceOrganisationId, pTargetOrganisationId)
+DuplicateScannerUtils.getDuplicateIdsByEntityScanner = function(pTargetEntity, pTargetUid)
 {
-    var updateCount = newWhereIfSet(["CONTACT", "ORGANISATION_ID"], pSourceOrganisationId)
-                        .and("PERSON_ID is not null")
-                        .updateFields(new Map().set("ORGANISATION_ID", pTargetOrganisationId), "CONTACT");
-        
-    var deleteCount = newWhere(["CONTACT", "ORGANISATION_ID"], pSourceOrganisationId)
-                        .and("PERSON_ID is not null")
-                        .deleteData();
-    return updateCount > 0 || deleteCount > 0;
-}
+    var scanner = DuplicateScannerUtils.getScannerByEntity(pTargetEntity);
+    var indexsearchFilter = IndexsearchFilterUtils.fromFilter(scanner.filter);
 
-/*
- * Person and organisations keep the max_count = 1 attribute of the target and the one from the source is deleted
- *
- * @returns {Boolean} If records have been deleted
- */
-_DuplicateScannerUtils._deleteUniqueAttributes = function (pSourceContactId, pTargetContactId)
-{
-    var targetAttrUnique = newSelect("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID")
-                                .from("AB_ATTRIBUTERELATION")
-                                .join("AB_ATTRIBUTEUSAGE on AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID = AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID")
-                                .where("AB_ATTRIBUTEUSAGE.MAX_COUNT = 1")
-                                .and("AB_ATTRIBUTERELATION.OBJECT_ROWID", pTargetContactId)
-                                .table();
-    var deleteCount = 0;
+    var targetLoadConfig = entities.createConfigForLoadingRows()
+        .entity(pTargetEntity)
+        .uid(pTargetUid) // Array.from because getFields returns a Set
+        .fields(Array.from(indexsearchFilter.getFields()));
+    var targetRow = entities.getRow(targetLoadConfig);
     
-    targetAttrUnique.forEach(function(attribute){
-        deleteCount += newWhereIfSet("AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID", attribute)
-                        .and("AB_ATTRIBUTERELATION.OBJECT_ROWID", pSourceContactId)
-                        .deleteData();
-    });
-
-    return deleteCount > 0;
+    var indexPattern = indexsearchFilter.buildQuery(targetRow);
+    return DuplicateScannerUtils.getDuplicateIds(pTargetEntity, indexPattern, pTargetUid);
 }
 
-/*
- * Update other contacts from the source
- *
- * @returns {Boolean} If records have been updated
+/**
+ * Does the same as getDuplicateIdsByEntityScanner
+ * but the variables are directly passed in as an argument
+ * 
+ * @param {string} pTargetEntity the entity name used to get the Scanner
+ * @param {object} pEntityObj the variables (should include all variables needed to build the indexPattern)
+ * 
+ * @returns {string[]} the duplicate ids
  */
-    _DuplicateScannerUtils._updateOtherContacts = function (pSourceContactId, sourcePersonId, targetPersonId)
+DuplicateScannerUtils.getDuplicateIdsByEntityObj = function(pTargetEntity, pEntityObj)
 {
-    var otherContacts = newSelect("PERSON.PERSONID")
-                                .from("PERSON")
-                                .join("CONTACT", "CONTACT.PERSON_ID = PERSON.PERSONID")
-                                .where("PERSON.PERSONID", sourcePersonId)
-                                .and("CONTACT.CONTACTID", pSourceContactId, SqlBuilder.NOT_EQUAL())
-                                .table();
-    var updateCount = 0;
-    
-    otherContacts.forEach(function(person){                 
-        updateCount += newWhere("CONTACT.PERSON_ID", person)
-                        .updateFields({"PERSON_ID" : targetPersonId}, "CONTACT");
-    });
-
-    return updateCount > 0;
-}
\ No newline at end of file
+    var scanner = DuplicateScannerUtils.getScannerByEntity(pTargetEntity);
+    var indexsearchFilter = IndexsearchFilterUtils.fromFilter(scanner.filter);
+    var indexPattern = indexsearchFilter.buildQuery(pEntityObj);
+    return DuplicateScannerUtils.getDuplicateIds(pTargetEntity, indexPattern, pEntityObj[scanner.idField]);
+}
diff --git a/process/IndexSearch_lib/process.js b/process/IndexSearch_lib/process.js
index be35ad2cc8c0a24fabe76bd57ba2a64d9ce9b310..549aefab097b21cce5c1053bf013ec1daa322be9 100644
--- a/process/IndexSearch_lib/process.js
+++ b/process/IndexSearch_lib/process.js
@@ -1,3 +1,4 @@
+import("system.indexsearch");
 import("system.neon");
 import("system.text");
 
@@ -160,4 +161,146 @@ IndexsearchUtils.createAffectedInfoContainer = function(changedIdValue, changedT
         }
     });
     return res;
-}
\ No newline at end of file
+}
+
+
+/**
+ * Static utility class for constructing an indexsearch pattern
+ */
+function IndexsearchFilterUtils() {}
+
+/**
+ * Creates an indexsearch pattern from a filter
+ * 
+ * @param {object} pFilter the filter in json representation
+ * 
+ * @returns {IndexsearchFilterGroup|IndexsearchFilterRow} the IndexSearchFilter object
+ */
+IndexsearchFilterUtils.fromFilter = function(pFilter)
+{
+    if(pFilter["type"] == "group")
+    {
+        return IndexsearchFilterGroup.fromFilter(pFilter["childs"], pFilter["operator"]);
+    }
+    else if(pFilter["type"] == "row")
+    {
+        return IndexsearchFilterRow.fromFilter(pFilter["name"], pFilter["operator"], pFilter["value"]);
+    }
+    throw new Error("Unknown filter node type: " + pFilter["type"]);
+}
+
+
+/**
+ * The IndexsearchFilterGroup object represents the a filter group
+ * and is able to generate the corrosponding indexsearch pattern
+ * 
+ * @param {(IndexsearchFilterGroup|IndexsearchFilterRow)[]} pChilds the child filterrows/filtergroups
+ * @param {string} pOperator the operator for the group can either be 'AND' or 'OR'
+ */
+function IndexsearchFilterGroup(pChilds, pOperator)
+{
+    this.childs = pChilds;
+    this.operator = pOperator;
+}
+
+/**
+ * Returns all fiels as Set witch are required for this filter
+ * 
+ * @returns {Set<string>} The fields as Set
+ */
+IndexsearchFilterGroup.prototype.getFields = function()
+{
+    var fields = new Set();
+    for(let i = 0; i < this.childs.length; i++)
+    {
+        this.childs[i].getFields().forEach(fields.add, fields);
+    }
+    return fields;
+}
+
+/**
+ * Builds the index pattern and returns it as string
+ * 
+ * @param {Record<string, string>} pFieldValues the field name value pair
+ */
+IndexsearchFilterGroup.prototype.buildQuery = function(pFieldValues)
+{
+    return this.childs.map(function(curr) { return curr.buildQuery(pFieldValues); })
+    .filter(function(curr) { return curr != null; })
+    .join(" " + this.operator + " ");
+}
+
+/**
+ * Creates a new IndexsearchFilterGroup object
+ * 
+ * @param {(IndexsearchFilterGroup|IndexsearchFilterRow)[]} pChilds the child filterrows/filtergroups
+ * @param {string} pOperator the operator for the group can either be 'AND' or 'OR'
+ */
+IndexsearchFilterGroup.fromFilter = function(pChilds, pOperator)
+{
+    return new IndexsearchFilterGroup(
+        pChilds.map(function(curr)
+        {
+            return IndexsearchFilterUtils.fromFilter(curr);
+        }),
+        pOperator
+    );
+}
+
+
+function IndexsearchFilterRow(pName, pEmpty, pExclude)
+{
+    this.name = pName;
+    this.empty = pEmpty;
+    this.exclude = pExclude;
+}
+
+/**
+ * Returns all fiels as Set witch are required for this filter
+ * 
+ * @returns {Set<string>} The fields as Set
+ */
+IndexsearchFilterRow.prototype.getFields = function()
+{
+    return new Set([this.name]);
+}
+
+/**
+ * Builds the index pattern and returns it as string
+ * 
+ * @param {Record<string, string>} pFieldValues the field name value pair
+ */
+IndexsearchFilterRow.prototype.buildQuery = function(pFieldValues)
+{
+    var fieldValue = pFieldValues[this.name] ? pFieldValues[this.name] : "";
+    if(!this.empty && fieldValue == "")
+    {
+        return null;
+    }
+    var valueStr = fieldValue;
+    for(let i = 0; i < this.exclude.length; i++)
+    {
+        valueStr = valueStr.replace(new RegExp(this.exclude[i], "gi"), "");
+    }
+    return this.name.toLowerCase() + ':("' + indexsearch.escapeString(valueStr.trim().replace(/\s+/g, "")) + '")';
+}
+
+/**
+ * Creates a new IndexsearchFilterGroup object
+ * 
+ * @param {string} pName the row field name
+ * @param {string} pOperator the operator for the group can either be 'AND' or 'OR'
+ * @param {string} pValue the field valze
+ */
+IndexsearchFilterRow.fromFilter = function(pName, pOperator, pValue)
+{
+    if(pOperator == "NOT_EQUAL" || pOperator == "CONTAINSNOT")
+    {
+        return new IndexsearchFilterRow(pName, true, JSON.parse(pValue));
+    }
+    else if(pOperator == "ISNOTNULL")
+    {
+        return new IndexsearchFilterRow(pName, false, []);
+    }
+    throw new Error("Unknown filterrow operator: " + pOperator);
+}
diff --git a/process/Leadimport_lib/process.js b/process/Leadimport_lib/process.js
index d37c1f78ac48bda146e8791629958fe82d076044..1859595621f80e74f67d3b93cbd5959a5746cb60 100644
--- a/process/Leadimport_lib/process.js
+++ b/process/Leadimport_lib/process.js
@@ -918,19 +918,19 @@ LeadImportUtils.scanLeadDups = function(pAllContactData)
         
         if (orgObj != undefined && Object.keys(orgObj).length > 0)//checks if there is an ORGANISATIONDUPLICATE
         {
-            let scanResultsOrg = DuplicateScannerUtils.scanForDuplicates("OrganisationDuplicates", "Organisation_entity", orgObj, null);
-            if (scanResultsOrg != null && scanResultsOrg.length > 0)
+            let scanResultsOrg = DuplicateScannerUtils.getDuplicateIdsByEntityObj("Organisation_entity", orgObj);
+            if (scanResultsOrg.length > 0)
             {
-                let insertCountOrg = DuplicateScannerUtils.cacheNewScanResults(orgObj["CONTACTID"], scanResultsOrg, "Organisation_entity");
+                DuplicateScannerUtils.insertHasDuplicateEntry("Organisation_entity", orgObj["CONTACTID"], scanResultsOrg);
                 dupOrg = true;
             }
         }
         if (persObj != undefined && Object.keys(persObj).length > 0)//checks if there is an PERSONDUPLICATE
         {
-            let scanResultsPers = DuplicateScannerUtils.scanForDuplicates("PersonDuplicates", "Person_entity", persObj, null);
-            if (scanResultsPers != null && scanResultsPers.length > 0)
+            let scanResultsPers = DuplicateScannerUtils.getDuplicateIdsByEntityObj("Person_entity", persObj);
+            if (scanResultsPers.length > 0)
             {
-                let insertCountPers = DuplicateScannerUtils.cacheNewScanResults(persObj["CONTACTID"], scanResultsPers, "Person_entity");
+                DuplicateScannerUtils.insertHasDuplicateEntry("Person_entity", persObj["CONTACTID"], scanResultsPers);
                 dupPers = true;
             }
         }
diff --git a/process/RebuildAllDuplicateCaches_serverProcess/process.js b/process/RebuildAllDuplicateCaches_serverProcess/process.js
deleted file mode 100644
index b08a0abf9efa74df1e609510b0cd09d63a06d1bf..0000000000000000000000000000000000000000
--- a/process/RebuildAllDuplicateCaches_serverProcess/process.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import("system.logging");
-import("DuplicateScanner_lib");
-
-/* 
- * Serverprocess to reload duplicates
- * 
- * Step #1:
- * All Clusters for the specified targetEntity are deleted. 
- * Relations between records marked as unrelated are not deleted at this time
- * 
- * Step #2
- * The duplicates cache gets rebuilt
- * 
- * Step #3:
- * All unrelated relations between duplicate ids hold their respective cluster id.
- * If the same combination of duplicate ids exists in the duplicate cache after the rebuild,
- * it is assumed that those records remain duplicates. 
- * Therefore the saved clusterId gets refreshed with the newly created clusters id.
- * 
- * Relations between unrelated duplicates are deleted, if no cluster contains the same combination of duplicate ids 
- */
-
-// Build Person duplicate cache
-
-var filterName = "PersonDuplicates";
-var targetEntity = "Person_entity";
-var recordBlockSize = DuplicateScannerUtils.getBlockSize();
-
-logging.log(filterName + ": Delete duplicates -> ");
-DuplicateScannerUtils.deleteClustersByTargetEntity(targetEntity);
-
-logging.log(filterName + ": Recalculate duplicates -> ");
-DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, recordBlockSize, null);
-
-logging.log(filterName + ": Refresh unrelated duplicates -> ");
-DuplicateScannerUtils.refreshUnrelatedDuplicateRelations(targetEntity);
-
-logging.log(filterName + ": Done rebuilding ");
-
-
-// Build Organisation duplicate cache
-
-filterName = "OrganisationDuplicates";
-targetEntity = "Organisation_entity";
-
-logging.log(filterName + ": Delete duplicates -> ");
-DuplicateScannerUtils.deleteClustersByTargetEntity(targetEntity);
-
-logging.log(filterName + ": Recalculate duplicates -> ");
-DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, recordBlockSize, null);
-
-logging.log(filterName + ": Refresh unrelated duplicates -> ");
-DuplicateScannerUtils.refreshUnrelatedDuplicateRelations(targetEntity);
-
-logging.log(filterName + ": Done rebuilding ");
\ No newline at end of file
diff --git a/process/RebuildDuplicatesCache_serverProcess/process.js b/process/RebuildDuplicatesCache_serverProcess/process.js
deleted file mode 100644
index 1e7f532f75a8b4a36d1c06de9cc4503bf6f74c62..0000000000000000000000000000000000000000
--- a/process/RebuildDuplicatesCache_serverProcess/process.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import("system.logging");
-import("system.vars");
-import("DuplicateScanner_lib");
-
-/* 
- * Serverprocess to reload duplicates
- * 
- * Step #1:
- * All Clusters for the specified targetEntity are deleted. 
- * Relations between records marked as unrelated are not deleted at this time
- * 
- * Step #2
- * The duplicates cache gets rebuilt
- * 
- * Step #3:
- * All unrelated relations between duplicate ids hold their respective cluster id.
- * If the same combination of duplicate ids exists in the duplicate cache after the rebuild,
- * it is assumed that those records remain duplicates. 
- * Therefore the saved clusterId gets refreshed with the newly created clusters id.
- * 
- * Relations between unrelated duplicates are deleted, if no cluster contains the same combination of duplicate ids 
- */
-
-// Build Person duplicate cache
-
-var filterName = vars.get("$local.filterName");
-var targetEntity = vars.get("$local.targetEntity");
-var recordBlockSize = DuplicateScannerUtils.getBlockSize();
-
-logging.log(filterName + ": Delete duplicates -> ");
-DuplicateScannerUtils.deleteClustersByTargetEntity(targetEntity);
-
-logging.log(filterName + ": Recalculate duplicates -> ");
-DuplicateScannerUtils.rebuildDuplicatesCache(filterName, targetEntity, recordBlockSize, null);
-
-logging.log(filterName + ": Refresh unrelated duplicates -> ");
-DuplicateScannerUtils.refreshUnrelatedDuplicateRelations(targetEntity);
-
-logging.log(filterName + ": Done rebuilding ");
-
diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js
index 119068f4adadba3b78e1bc061fde6a4c7d40d473..383117664ccc7b40a93923d2a82b7694222b9d79 100644
--- a/process/Sql_lib/process.js
+++ b/process/Sql_lib/process.js
@@ -4657,4 +4657,33 @@ SqlUtils.escapeVars = function (pValue)
     if (typeof(pValue) == "string" && pValue.charAt(0) == "$")
         return "$" + pValue;
     return pValue;
-}
\ No newline at end of file
+}
+
+SqlUtils.getSqlConditionalOperator = function(pOperator)
+{
+    switch(parseInt(pOperator))
+    {
+        case 1:
+            return SqlBuilder.EQUAL();
+        case 2:
+            return SqlBuilder.NOT_EQUAL();
+        
+        case 4:
+            return SqlBuilder.LESS();
+        case 5:
+            return SqlBuilder.LESS_OR_EQUAL();
+            
+        case 3:
+            return SqlBuilder.GREATER();
+        case 6:
+            return SqlBuilder.GREATER_OR_EQUAL();
+            
+        case 11:
+            return "# is not null";
+        case 12:
+            return "# is null";
+            
+        default:
+            throw new Error("Unsupported operator " + pOperator);
+    }
+}
diff --git a/process/rebuildDuplicates_serverProcess/process.js b/process/rebuildDuplicates_serverProcess/process.js
new file mode 100644
index 0000000000000000000000000000000000000000..14369cff4552605e18c828601491e101ceced696
--- /dev/null
+++ b/process/rebuildDuplicates_serverProcess/process.js
@@ -0,0 +1,74 @@
+import("Sql_lib");
+import("system.db");
+import("system.entities");
+import("system.project");
+import("system.util");
+import("system.logging");
+import("system.notification");
+import("system.translate");
+import("system.vars");
+import("IndexSearch_lib");
+import("DuplicateScanner_lib");
+
+var pFilterName = vars.get("$local.filterName");
+var pTargetEntity = vars.get("$local.targetEntity");
+var pTargetIdField = vars.get("$local.targetIdField");
+var pFilter = JSON.parse(vars.get("$local.filter"));
+
+newWhere("HASDUPLICATE.OBJECT_TYPE", pTargetEntity).deleteData();
+var indexsearchFilter = IndexsearchFilterUtils.fromFilter(pFilter);
+
+var TABLE_NAME = "HASDUPLICATE";
+var COLUMNS = [
+    "HASDUPLICATEID",
+    "OBJECT_TYPE", "OBJECT_ROWID",
+    "DUPLICATECOUNT"
+];
+var COLUMN_TYPES = db.getColumnTypes(TABLE_NAME, COLUMNS);
+
+var batchSize = parseInt(project.getPreferenceValue("custom.duplicates.dataBlockSize", "5000"));
+var batchPos = 0;
+while(true)
+{
+    var inserts = [];
+    
+    var entityFields = indexsearchFilter.getFields();
+    entityFields.add(pTargetIdField);
+    var entityRowsConfig = entities.createConfigForLoadingRows()
+        .entity(pTargetEntity)
+        .fields(Array.from(entityFields))
+        .startrow(batchPos).count(batchSize);
+    var entityRows = entities.getRows(entityRowsConfig);
+    
+    entityRows.forEach(function(entityRow)
+    {
+        var currEntityRowId = entityRow[pTargetIdField];
+        var indexPattern = indexsearchFilter.buildQuery(entityRow);
+        var duplicates = DuplicateScannerUtils.getDuplicateIds(pTargetEntity, indexPattern, currEntityRowId);
+       
+        if(duplicates.length > 0)
+        {
+            var values = [
+                util.getNewUUID(),
+                pTargetEntity, currEntityRowId,
+                duplicates.length.toFixed(0)
+            ];
+            inserts.push([TABLE_NAME, COLUMNS, COLUMN_TYPES, values]);
+        }
+    });
+    
+    db.inserts(inserts);
+    if(entityRows.length < batchSize)
+    {
+        break;
+    }
+    batchPos += batchSize;
+}
+
+notification.addNotificationWith(notification.createConfig()
+.addUserWithId(vars.get("$sys.user"))
+.notificationType("_____SYSTEM_NOTIFICATION_MESSAGE")
+.caption(translate.text("Duplicaterow rebuild"))
+.description(translate.withArguments("The duplicate row corrosponding to %0 has been rebuild", [pFilterName])));
+
+logging.log(pFilterName + " has been rebuild");
diff --git a/process/RebuildAllDuplicateCaches_serverProcess/RebuildAllDuplicateCaches_serverProcess.aod b/process/rebuildDuplicates_serverProcess/rebuildDuplicates_serverProcess.aod
similarity index 50%
rename from process/RebuildAllDuplicateCaches_serverProcess/RebuildAllDuplicateCaches_serverProcess.aod
rename to process/rebuildDuplicates_serverProcess/rebuildDuplicates_serverProcess.aod
index 11432054cc7356358ef25e9d7b657ca5973bba2f..3a72b0bfc4f0fb92cacba8dbda2b2d68acbd3386 100644
--- a/process/RebuildAllDuplicateCaches_serverProcess/RebuildAllDuplicateCaches_serverProcess.aod
+++ b/process/rebuildDuplicates_serverProcess/rebuildDuplicates_serverProcess.aod
@@ -1,8 +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>RebuildAllDuplicateCaches_serverProcess</name>
+  <name>rebuildDuplicates_serverProcess</name>
+  <description>ATTENTION!
+This process can only be executed within the client.
+The action (Rebuild selected entries) can be found in the administration context "Duplicate Configuration".</description>
   <majorModelMode>DISTRIBUTED</majorModelMode>
-  <process>%aditoprj%/process/RebuildAllDuplicateCaches_serverProcess/process.js</process>
+  <process>%aditoprj%/process/rebuildDuplicates_serverProcess/process.js</process>
+  <alias>Data_alias</alias>
   <variants>
     <element>EXECUTABLE</element>
   </variants>