diff --git a/entity/CampaignPlanning_entity/recordcontainers/jditorecordcontainer/onDelete.js b/entity/CampaignPlanning_entity/recordcontainers/jditorecordcontainer/onDelete.js
index 0bfb4a162b77ca300d0c33fb8a73e83c4095135b..8daa120a4c1da42852657cb6a7865e0a51bfbfb0 100644
--- a/entity/CampaignPlanning_entity/recordcontainers/jditorecordcontainer/onDelete.js
+++ b/entity/CampaignPlanning_entity/recordcontainers/jditorecordcontainer/onDelete.js
@@ -1,3 +1,4 @@
+import("system.neon");
 import("system.vars");
 import("Campaign_lib");
 
@@ -9,4 +10,6 @@ if(selectedElement.length > 0)
         CampaignUtils.deleteCampaignStepData(selectedElement[0].UID);
     else
         CampaignUtils.deleteCampaignData(selectedElement[0].UID);
+    //todo temporary fix for #1041096. As soon as entities.delete is available and integrated into the deletion process, this can be removed
+    neon.refreshAll();
 }
\ No newline at end of file
diff --git a/entity/CampaignStep_entity/recordcontainers/db/conditionProcess.js b/entity/CampaignStep_entity/recordcontainers/db/conditionProcess.js
index c693832d8e3fad0d122698e5320c4248edf4735f..295493d78e809e8e6e55e99285ad4716cc28a105 100644
--- a/entity/CampaignStep_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/CampaignStep_entity/recordcontainers/db/conditionProcess.js
@@ -1,7 +1,7 @@
 import("system.vars");
 import("system.result");
 
-if(vars.exists("$param.campaignId_param") && vars.get("$param.campaignId_param"))
+if(vars.get("$param.campaignId_param"))
 {
     result.string("CAMPAIGN_ID = '" + vars.getString("$param.campaignId_param") + "'");
 }
diff --git a/entity/DuplicateScanConditionConfig_entity/DuplicateScanConditionConfig_entity.aod b/entity/DuplicateScanConditionConfig_entity/DuplicateScanConditionConfig_entity.aod
index 456a0f924d264e5a23ccc34d0716ea581b270b41..07fc1f2dff683afef6d01cd6067930a8c8a47cd1 100644
--- a/entity/DuplicateScanConditionConfig_entity/DuplicateScanConditionConfig_entity.aod
+++ b/entity/DuplicateScanConditionConfig_entity/DuplicateScanConditionConfig_entity.aod
@@ -82,19 +82,21 @@
     </entityField>
     <entityField>
       <name>MAX_RESULTS_THRESHOLD</name>
+      <title>Max results threshold</title>
     </entityField>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
       <name>DBRecordContainer</name>
       <alias>Data_alias</alias>
+      <conditionProcess>%aditoprj%/entity/DuplicateScanConditionConfig_entity/recordcontainers/dbrecordcontainer/conditionProcess.js</conditionProcess>
       <onDBUpdate>%aditoprj%/entity/DuplicateScanConditionConfig_entity/recordcontainers/dbrecordcontainer/onDBUpdate.js</onDBUpdate>
       <linkInformation>
         <linkInformation>
-          <name>22217bb2-6fbf-4a7f-94f3-b200ef54c49f</name>
+          <name>072783b0-8914-4886-bfa3-74565db81474</name>
           <tableName>DUPLICATESCANCONDITIONCONFIG</tableName>
           <primaryKey>ID</primaryKey>
-          <isUIDTable v="false" />
+          <isUIDTable v="true" />
           <readonly v="false" />
         </linkInformation>
       </linkInformation>
diff --git a/entity/DuplicateScanConditionConfig_entity/recordcontainers/dbrecordcontainer/conditionProcess.js b/entity/DuplicateScanConditionConfig_entity/recordcontainers/dbrecordcontainer/conditionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..32b8c7a5734ea01291f8beec4262d7bc3488869e
--- /dev/null
+++ b/entity/DuplicateScanConditionConfig_entity/recordcontainers/dbrecordcontainer/conditionProcess.js
@@ -0,0 +1,7 @@
+import("system.vars");
+import("system.result");
+
+if(vars.get("$param.DuplicateScanId_param"))
+{
+    result.string("DUPLICATESCAN_ID = '" + vars.getString("$param.DuplicateScanId_param") + "'");
+}
\ No newline at end of file
diff --git a/entity/Duplicates_entity/Duplicates_entity.aod b/entity/Duplicates_entity/Duplicates_entity.aod
index c0a6d7fe20f6dd0caced42a0d3e84175246b5272..896c64c1cb924c5334af96b9bf671869ba77a255 100644
--- a/entity/Duplicates_entity/Duplicates_entity.aod
+++ b/entity/Duplicates_entity/Duplicates_entity.aod
@@ -6,8 +6,6 @@
   <entityFields>
     <entityProvider>
       <name>#PROVIDER</name>
-      <targetContextField>targetEntity</targetContextField>
-      <targetIdField>UID</targetIdField>
     </entityProvider>
     <entityParameter>
       <name>filterName_param</name>
@@ -40,6 +38,9 @@
     </entityField>
     <entityProvider>
       <name>DuplicatesProvider</name>
+      <targetContextField>targetContext</targetContextField>
+      <targetIdField>UID</targetIdField>
+      <titlePlural>Duplicates</titlePlural>
       <dependencies>
         <entityDependency>
           <name>ea8abf2a-d8b8-4f83-a68e-664b3b23d822</name>
@@ -47,10 +48,16 @@
           <fieldName>PersonDuplicates</fieldName>
           <isConsumer v="false" />
         </entityDependency>
+        <entityDependency>
+          <name>4d787122-cc91-4afa-a85a-dd0265cb289e</name>
+          <entityName>Organisation_entity</entityName>
+          <fieldName>OrganisationDuplicates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
       </dependencies>
     </entityProvider>
     <entityField>
-      <name>targetEntity</name>
+      <name>targetContext</name>
     </entityField>
     <entityField>
       <name>UID</name>
@@ -69,6 +76,33 @@
       <expose v="true" />
       <mandatory v="true" />
     </entityParameter>
+    <entityParameter>
+      <name>targetContext_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+    </entityParameter>
+    <entityActionGroup>
+      <name>ActionGroup</name>
+      <children>
+        <entityActionField>
+          <name>IntegrateSelectedIntoCurrentAction</name>
+          <title>Integrate selected into current contact</title>
+          <onActionProcess>%aditoprj%/entity/Duplicates_entity/entityfields/actiongroup/children/integrateselectedintocurrentaction/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+        </entityActionField>
+        <entityActionField>
+          <name>IntegrateCurrentIntoSelectedAction</name>
+          <title>Integrate current into selected contact</title>
+          <onActionProcess>%aditoprj%/entity/Duplicates_entity/entityfields/actiongroup/children/integratecurrentintoselectedaction/onActionProcess.js</onActionProcess>
+          <isSelectionAction v="true" />
+        </entityActionField>
+      </children>
+    </entityActionGroup>
+    <entityParameter>
+      <name>sourceContactId_param</name>
+      <expose v="true" />
+      <mandatory v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
@@ -80,7 +114,7 @@
           <name>UID.value</name>
         </jDitoRecordFieldMapping>
         <jDitoRecordFieldMapping>
-          <name>targetEntity.value</name>
+          <name>targetContext.value</name>
         </jDitoRecordFieldMapping>
         <jDitoRecordFieldMapping>
           <name>VALUE1.value</name>
diff --git a/entity/Duplicates_entity/entityfields/actiongroup/children/integratecurrentintoselectedaction/onActionProcess.js b/entity/Duplicates_entity/entityfields/actiongroup/children/integratecurrentintoselectedaction/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..63fddf359f2eb4b0a04887c8a9d30b55fe88d179
--- /dev/null
+++ b/entity/Duplicates_entity/entityfields/actiongroup/children/integratecurrentintoselectedaction/onActionProcess.js
@@ -0,0 +1,14 @@
+import("system.vars");
+import("system.neon");
+import("DuplicateScanner_lib");
+
+let sourceContactId = vars.get("$param.sourceContactId_param");
+let targetContactId = vars.get("$sys.selection");
+
+//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.MergePerson(sourceContactId, targetContactId);
+
+if(mergeSuccess)
+{
+    neon.openContext("Person", "PersonMain_view", [targetContactId], neon.OPERATINGSTATE_VIEW, null)
+}
\ No newline at end of file
diff --git a/entity/Duplicates_entity/entityfields/actiongroup/children/integrateselectedintocurrentaction/onActionProcess.js b/entity/Duplicates_entity/entityfields/actiongroup/children/integrateselectedintocurrentaction/onActionProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..6351f476b874b054df0d237856615bdb8ecc2f1b
--- /dev/null
+++ b/entity/Duplicates_entity/entityfields/actiongroup/children/integrateselectedintocurrentaction/onActionProcess.js
@@ -0,0 +1,14 @@
+import("system.vars");
+import("system.neon");
+import("DuplicateScanner_lib");
+
+let targetContactId = vars.get("$param.sourceContactId_param");
+let sourceContactId = vars.get("$sys.selection");
+
+//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.MergePerson(sourceContactId, targetContactId);
+
+if(mergeSuccess)
+{
+    neon.refreshAll();
+}
\ No newline at end of file
diff --git a/entity/Duplicates_entity/recordcontainers/jditorecordcontainer/contentProcess.js b/entity/Duplicates_entity/recordcontainers/jditorecordcontainer/contentProcess.js
index f11e641ac15873f08289b4ea3cac23dc397ee48c..8baa7234be79b6c98716ac049fa1355747a24d95 100644
--- a/entity/Duplicates_entity/recordcontainers/jditorecordcontainer/contentProcess.js
+++ b/entity/Duplicates_entity/recordcontainers/jditorecordcontainer/contentProcess.js
@@ -5,6 +5,7 @@ import("system.logging");
 
 var filterName = vars.get("$param.filterName_param");
 var targetEntity = vars.get("$param.targetEntity_param");
+var targetContext = vars.get("$param.targetContext_param");
 var values = JSON.parse(vars.get("$param.valuesToScan_param"));
 var resultFields = JSON.parse(vars.get("$param.resultFields_param"));
 var resultFieldsIdFieldName = vars.get("$param.resultFieldsIdFieldName_param");
@@ -25,7 +26,7 @@ var returnRay = [];
 logging.log("duplicates.length -> " + duplicates.length);
 for (i = 0; i < duplicates.length; i++) 
 {
-    let newRecord = _compileSingleRecord(duplicates[i], resultFieldsIdFieldName, maxRecorValues, targetEntity);
+    let newRecord = _compileSingleRecord(duplicates[i], resultFieldsIdFieldName, maxRecorValues, targetContext);
     
     logging.log("newRecord -> " + newRecord);
     returnRay.push(newRecord);
@@ -33,13 +34,13 @@ for (i = 0; i < duplicates.length; i++)
 result.object(returnRay);
 
 
-function _compileSingleRecord(pDuplicate, pIdFieldName, maxRecordValues, pTargetEntity)
+function _compileSingleRecord(pDuplicate, pIdFieldName, maxRecordValues, pTargetContext)
 {
     let newRecord = [];
     let recordId = pDuplicate[pIdFieldName];
     
     newRecord.push(recordId);
-    newRecord.push(pTargetEntity);
+    newRecord.push(pTargetContext);
     
     let recordCount = 0;
     
diff --git a/entity/Organisation_entity/Organisation_entity.aod b/entity/Organisation_entity/Organisation_entity.aod
index a2a3e3a443b5da3cb138567b08ca4c5f940c79c9..b502eae91e03951bbdba32ce115cfbbd799f40e0 100644
--- a/entity/Organisation_entity/Organisation_entity.aod
+++ b/entity/Organisation_entity/Organisation_entity.aod
@@ -852,6 +852,44 @@
       <onActionProcess>%aditoprj%/entity/Organisation_entity/entityfields/newletter/onActionProcess.js</onActionProcess>
       <iconId>VAADIN:ENVELOPE</iconId>
     </entityActionField>
+    <entityConsumer>
+      <name>OrganisationDuplicates</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Duplicates_entity</entityName>
+        <fieldName>DuplicatesProvider</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>filterName_param</name>
+          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/organisationduplicates/children/filtername_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>recordIdToIgnore_param</name>
+          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/organisationduplicates/children/recordidtoignore_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>resultFields_param</name>
+          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/organisationduplicates/children/resultfields_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>resultFieldsIdFieldName_param</name>
+          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/organisationduplicates/children/resultfieldsidfieldname_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>targetEntity_param</name>
+          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/organisationduplicates/children/targetentity_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>valuesToScan_param</name>
+          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/organisationduplicates/children/valuestoscan_param/valueProcess.js</valueProcess>
+        </entityParameter>
+        <entityParameter>
+          <name>targetContext_param</name>
+          <valueProcess>%aditoprj%/entity/Organisation_entity/entityfields/organisationduplicates/children/targetcontext_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
   </entityFields>
   <recordContainers>
     <dbRecordContainer>
diff --git a/entity/Organisation_entity/entityfields/organisationduplicates/children/filtername_param/valueProcess.js b/entity/Organisation_entity/entityfields/organisationduplicates/children/filtername_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..517d55822d0c5276183daef2f41fc8dcfd0b3e58
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/organisationduplicates/children/filtername_param/valueProcess.js
@@ -0,0 +1,2 @@
+import("system.result");
+result.string("OrganisationDuplicates");
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/organisationduplicates/children/recordidtoignore_param/valueProcess.js b/entity/Organisation_entity/entityfields/organisationduplicates/children/recordidtoignore_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..68a0694645c086c652eb10ed12720998b4146cad
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/organisationduplicates/children/recordidtoignore_param/valueProcess.js
@@ -0,0 +1,3 @@
+import("system.vars");
+import("system.result");
+result.string(vars.get("$field.ORGANISATIONID"));
diff --git a/entity/Organisation_entity/entityfields/organisationduplicates/children/resultfields_param/valueProcess.js b/entity/Organisation_entity/entityfields/organisationduplicates/children/resultfields_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..daed36607e029adb9fd456d551c6e81c506d9480
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/organisationduplicates/children/resultfields_param/valueProcess.js
@@ -0,0 +1,3 @@
+import("system.result");
+
+result.string(JSON.stringify(["NAME", "STANDARD_PHONE_COMMUNICATION", "STANDARD_EMAIL_COMMUNICATION", "ORGANISATIONID"]));
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/organisationduplicates/children/resultfieldsidfieldname_param/valueProcess.js b/entity/Organisation_entity/entityfields/organisationduplicates/children/resultfieldsidfieldname_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..d3bd35e20196092d94e713892060a728a2a618fa
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/organisationduplicates/children/resultfieldsidfieldname_param/valueProcess.js
@@ -0,0 +1,2 @@
+import("system.result");
+result.string("ORGANISATIONID");
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/organisationduplicates/children/targetcontext_param/valueProcess.js b/entity/Organisation_entity/entityfields/organisationduplicates/children/targetcontext_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..6be9b7dc0bec4faae14d54827ce1dc99499fbaa0
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/organisationduplicates/children/targetcontext_param/valueProcess.js
@@ -0,0 +1,2 @@
+import("system.result");
+result.string("Organisation");
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/organisationduplicates/children/targetentity_param/valueProcess.js b/entity/Organisation_entity/entityfields/organisationduplicates/children/targetentity_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..e781fb72fd248164b8b63a98008094744aee7460
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/organisationduplicates/children/targetentity_param/valueProcess.js
@@ -0,0 +1,2 @@
+import("system.result");
+result.string("Organisation_entity");
\ No newline at end of file
diff --git a/entity/Organisation_entity/entityfields/organisationduplicates/children/valuestoscan_param/valueProcess.js b/entity/Organisation_entity/entityfields/organisationduplicates/children/valuestoscan_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..afaaa47d8ac7882a6771d63393f8adf0cd04a854
--- /dev/null
+++ b/entity/Organisation_entity/entityfields/organisationduplicates/children/valuestoscan_param/valueProcess.js
@@ -0,0 +1,12 @@
+import("system.logging");
+import("system.result");
+import("system.vars");
+
+var picture = vars.get("$field.PICTURE");
+var name = vars.get("$field.NAME");
+let status = vars.get("$field.STATUS");
+let recordId = vars.get("$field.ORGANISATIONID");
+
+logging.log("picture -> " + picture);
+
+result.object({PICTURE: picture, NAME: name, STATUS: status, ORGANISATIONID: recordId});
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/personduplicates/children/recordidtoignore_param/valueProcess.js b/entity/Person_entity/entityfields/personduplicates/children/recordidtoignore_param/valueProcess.js
index 0e4d59044e0e7deeb430491c96d6ef3b3c0e9c04..821415ae694dd9c3d98a7703f4c59b81a37f524b 100644
--- a/entity/Person_entity/entityfields/personduplicates/children/recordidtoignore_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/personduplicates/children/recordidtoignore_param/valueProcess.js
@@ -1,3 +1,3 @@
 import("system.vars");
 import("system.result");
-result.string(vars.get("$field.PERSONID"));
\ No newline at end of file
+result.string(vars.get("$field.CONTACTID"));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/personduplicates/children/resultfields_param/valueProcess.js b/entity/Person_entity/entityfields/personduplicates/children/resultfields_param/valueProcess.js
index 18a872ec6ccf09bd82d7f9aa02522a88729516c4..4b05025f1c3027e68cca59e6ca7d1c971d1f9ee2 100644
--- a/entity/Person_entity/entityfields/personduplicates/children/resultfields_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/personduplicates/children/resultfields_param/valueProcess.js
@@ -1,2 +1,2 @@
 import("system.result");
-result.string(JSON.stringify(["FIRSTNAME", "LASTNAME", "PERSONID"]));
\ No newline at end of file
+result.string(JSON.stringify(["FIRSTNAME", "LASTNAME", "CONTACTID"]));
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/personduplicates/children/resultfieldsidfieldname_param/valueProcess.js b/entity/Person_entity/entityfields/personduplicates/children/resultfieldsidfieldname_param/valueProcess.js
index 3e1b8e0b2afa639de608f618d662ea3ab658e53b..364d24387465fffab727ed9de8a8be10524e2db5 100644
--- a/entity/Person_entity/entityfields/personduplicates/children/resultfieldsidfieldname_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/personduplicates/children/resultfieldsidfieldname_param/valueProcess.js
@@ -1,2 +1,2 @@
 import("system.result");
-result.string("PERSONID");
\ No newline at end of file
+result.string("CONTACTID");
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/personduplicates/children/sourcecontactid_param/valueProcess.js b/entity/Person_entity/entityfields/personduplicates/children/sourcecontactid_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..821415ae694dd9c3d98a7703f4c59b81a37f524b
--- /dev/null
+++ b/entity/Person_entity/entityfields/personduplicates/children/sourcecontactid_param/valueProcess.js
@@ -0,0 +1,3 @@
+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/personduplicates/children/targetcontext_param/valueProcess.js b/entity/Person_entity/entityfields/personduplicates/children/targetcontext_param/valueProcess.js
new file mode 100644
index 0000000000000000000000000000000000000000..8fccd9a7e20bf5ab2fb1982a956d9e3c475ec5ff
--- /dev/null
+++ b/entity/Person_entity/entityfields/personduplicates/children/targetcontext_param/valueProcess.js
@@ -0,0 +1,2 @@
+import("system.result");
+result.string("Person");
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/personduplicates/children/valuestoscan_param/valueProcess.js b/entity/Person_entity/entityfields/personduplicates/children/valuestoscan_param/valueProcess.js
index 1e01a572a98104737bba1f2dae71fb293de8230c..8e2ffcbd3918fe9aa384c329025074d480dca3ce 100644
--- a/entity/Person_entity/entityfields/personduplicates/children/valuestoscan_param/valueProcess.js
+++ b/entity/Person_entity/entityfields/personduplicates/children/valuestoscan_param/valueProcess.js
@@ -2,18 +2,15 @@ import("system.logging");
 import("system.result");
 import("system.vars");
 
-//    var adresses = vars.get("$field.PersAddresses");
-//    var organisation = vars.get("$field.ORGANISATION_NAME");
-//    var organisationAdress = vars.get("$field.OrgAddresses");
-//
-//    logging.log("adresses -> " + adresses);
-//    logging.log("firstname -> " + firstname);
-//    logging.log("organisation -> " + organisation);
-//    logging.log("organisationAdress -> " + organisationAdress);
-
+/*
+ * All values to the configured filters have to be defined here.
+ * The same field as defined in resultFieldsIdFieldName and the respective id have to be included in the values list.
+ * It has to be the correct id of the target entity, which is also used to open the preview.
+ */
 var firstname = vars.get("$field.FIRSTNAME");
 var lastname = vars.get("$field.LASTNAME");
 let gender = vars.get("$field.GENDER");
-let recordId = vars.get("$field.PERSONID");
-    
-result.object({FIRSTNAME: firstname, LASTNAME: lastname, GENDER: gender, PERSONID: recordId});
\ No newline at end of file
+let recordId = vars.get("$field.CONTACTID");
+
+
+result.object({FIRSTNAME: firstname, LASTNAME: lastname, GENDER: gender, CONTACTID: recordId});
\ No newline at end of file
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index 076e0574da76ac6f7d6e6507290b3ab6d2eeac07..c7a61be27f95986b142015c0036bbeb9c7c64a21 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -4971,6 +4971,9 @@
     <entry>
       <key>The combination of filter name and target entity is already in use</key>
     </entry>
+    <entry>
+      <key>Duplicates</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
   <sqlModels>
diff --git a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
index 6e773b6b1b876b37e8075be92394dd08d47aec89..bb07b870b84227ef3b232c1ba15d3af1293dbe21 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -6261,6 +6261,9 @@
       <key>The combination of filter name and target entity is already in use</key>
       <value>Die Kombination von Filtername und Zielentity existiert bereits</value>
     </entry>
+    <entry>
+      <key>Duplicates</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
index dc8935925a5953e1bcba7a4bc7905a09ef5fc9cc..b880baca435a35ce787ebff949c3d007427a8c4e 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -5020,6 +5020,9 @@
     <entry>
       <key>The combination of filter name and target entity is already in use</key>
     </entry>
+    <entry>
+      <key>Duplicates</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonView/DuplicatesFilter_view/DuplicatesFilter_view.aod b/neonView/DuplicatesFilter_view/DuplicatesFilter_view.aod
index 995dc98ce19936dcb11559c190654eef5549ca6e..c0bb9039a11fc7901825602bbdade21c33cddda7 100644
--- a/neonView/DuplicatesFilter_view/DuplicatesFilter_view.aod
+++ b/neonView/DuplicatesFilter_view/DuplicatesFilter_view.aod
@@ -11,9 +11,13 @@
   <children>
     <tableViewTemplate>
       <name>DuplicatesTable</name>
+      <favoriteActionGroup2>ActionGroup</favoriteActionGroup2>
       <entityField>#ENTITY</entityField>
       <isCreatable v="false" />
       <isEditable v="false" />
+      <isDeletable v="false" />
+      <showHeader v="true" />
+      <linkedFrame></linkedFrame>
       <columns>
         <neonTableColumn>
           <name>6d6aef18-53c9-4a43-8929-c421ea2d1889</name>
diff --git a/neonView/OrganisationMain_view/OrganisationMain_view.aod b/neonView/OrganisationMain_view/OrganisationMain_view.aod
index 02cd976b495963ecbced53bf9bca6b0da3e04b07..fad806a3449fa26c917b8907cb59484996199556 100644
--- a/neonView/OrganisationMain_view/OrganisationMain_view.aod
+++ b/neonView/OrganisationMain_view/OrganisationMain_view.aod
@@ -60,5 +60,10 @@
       <entityField>LogHistoryConsumer</entityField>
       <view>LogHistoryFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>100e9c93-0d63-4dd5-94b3-b88fe24f1954</name>
+      <entityField>OrganisationDuplicates</entityField>
+      <view>DuplicatesFilter_view</view>
+    </neonViewReference>
   </children>
 </neonView>
diff --git a/process/DuplicateScanner_lib/process.js b/process/DuplicateScanner_lib/process.js
index 0a2af60fd9cf8c4b0c0c40d6fc14538cfd315343..b0f7f6736cd69e3d99fc5e486d4287c6eefde2cb 100644
--- a/process/DuplicateScanner_lib/process.js
+++ b/process/DuplicateScanner_lib/process.js
@@ -34,6 +34,30 @@ DuplicateScannerUtils.ScanForDuplicates = function(pFilterName, pTargetEntity,
     return possibleDuplicates;
 }
 
+DuplicateScannerUtils.MergePerson = function(pSourceContactId, pTargetContactId)
+{
+    let updateStatements = [];
+    let deleteStatements = [];
+    
+    var sourcePersonId = db.cell("select PERSON_ID from CONTACT where CONTACTID = '" + pSourceContactId + "'");
+    var tableInfos = _DuplicateScannerUtils._getMergeUpdateTableInfos();
+    
+    updateStatements.push(_DuplicateScannerUtils._buildUpdateContactIdStatements(tableInfos, pSourceContactId, pTargetContactId));
+    updateStatements.push(_DuplicateScannerUtils._buildUpdateAttachParticipantsToNewContactQuery("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", pSourceContactId, pTargetContactId));
+    
+    deleteStatements.push(_DuplicateScannerUtils._buildDeleteRemoveObsoleteParticipantsRecordsQuery("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", pSourceContactId, pTargetContactId));
+    deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeletePersonAndContactQuery(sourcePersonId, pSourceContactId));
+
+    logging.log("updateStatements -> " + JSON.stringify(updateStatements));
+    logging.log("deleteStatements -> " + JSON.stringify(deleteStatements));
+    //let affectedRows = db.updates(updateStatements);
+    //let deletedRows = db.deletes(deleteStatements)
+    
+    return true;//(affectedRows > 0 && deletedRows >= 2);
+}
+
+
+
 
 function _DuplicateScannerUtils() {}
 
@@ -41,6 +65,57 @@ var INDEX_FILTER_CONDITION = 0;
 var INDEX_COUNT_CHARS_TO_USE = 1;
 var INDEX_MAX_RESULTS_THRESHOLD = 2;
 
+var INDEX_TABLE_NAME = 0;
+var INDEX_COLUMN_NAME = 1;
+var INDEX_CONDITION = 2;
+
+
+/*
+ * 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.
+ * 
+ * Mandatory: All records ignored for the time being have to be deleted aswell! See #_DuplicateScannerUtils._buildRemoveObsoleteParticipantsRecordsDeleteQuery
+ * 
+ */
+_DuplicateScannerUtils._buildUpdateAttachParticipantsToNewContactQuery = function (pTableName, pContactIdColumn, pAssignableIdColumn, pSourceContactId, pTargetContactId, updateStatements)
+{
+    var selectAssignableIdsOfTargetContactQuery = "select " + pAssignableIdColumn 
+                                                    + " from " + pTableName 
+                                                    + " where " + pContactIdColumn + " = '" + pTargetContactId + "'";
+
+//+ " ( select tab." + pAssignableIdColumn + " from (" + selectAssignableIdsOfTargetContactQuery + ")tab ) "
+//+ " (select tab." + pAssignableIdColumn + " from (" + selectAssignableIdsOfTargetContactQuery + ")tab ) "
+
+
+    let updateCondition = pAssignableIdColumn
+                            + " not in"
+                            + " (" + selectAssignableIdsOfTargetContactQuery + ")"
+                            + " and " + pContactIdColumn + " = '" + pSourceContactId + "'";
+    
+    return [pTableName, [pContactIdColumn], null, [pTargetContactId], updateCondition];
+}
+
+_DuplicateScannerUtils._buildDeleteRemoveObsoleteParticipantsRecordsQuery = function (pTableName, pContactIdColumn, pAssignableIdColumn, pSourceContactId, pTargetContactId, updateStatements)
+{
+    var selectAssignableIdsOfTargetContactQuery = "select " + pAssignableIdColumn 
+                                                    + " from " + pTableName 
+                                                    + " where " + pContactIdColumn + " = '" + pTargetContactId + "'";
+
+    let deleteCondition = pAssignableIdColumn + " in"
+                            + " (" + selectAssignableIdsOfTargetContactQuery + ")"
+                            + " and " + pAssignableIdColumn + " = '" + pSourceContactId + "'";
+    return [pTableName, deleteCondition];
+}
+
+_DuplicateScannerUtils._buildDeletePersonAndContactQuery = function(pSourcePersonId, pSourceContactId)
+{
+    let recordsToDelete = []
+    recordsToDelete.push(["PERSON", "PERSONID = '" + pSourcePersonId + "'"]);
+    recordsToDelete.push(["CONTACT", "CONTACTID = '" + pSourceContactId + "'"]);
+    return recordsToDelete;
+}
+
 _DuplicateScannerUtils._getIgnoreRecordFilter = function(pRecordIdFieldToIgnore, pRecordIdValueToIgnore, pTargetEntity)
 {
     let ignoreFilterJson = JSON.stringify({"entity":pTargetEntity,"filter":{"type":"group","operator":"AND","childs":[{"type":"row","name":pRecordIdFieldToIgnore,"operator":"NOT_EQUAL","value":pRecordIdValueToIgnore,"key":"","contenttype":"TEXT"}]}});
@@ -48,6 +123,70 @@ _DuplicateScannerUtils._getIgnoreRecordFilter = function(pRecordIdFieldToIgnore,
     return [ignoreFilterJson, null, null];
 }
 
+_DuplicateScannerUtils._buildUpdateContactIdStatements = function(pTableInfos, pSourceContactId, pTargetContactId)
+{
+    let statements = [];
+    
+    for (let i = 0; i < pTableInfos.length; i++) 
+    {
+        let tableInfo = pTableInfos[i];
+        let updateStatement = _DuplicateScannerUtils._buildStatement(tableInfo, pSourceContactId, pTargetContactId);
+        statements.push(updateStatement);
+    }
+    return statements;
+}
+
+_DuplicateScannerUtils._buildStatement = function(pTableinfos, pSourceContactId, pTargetContactId)
+{
+    let tableName = pTableinfos[INDEX_TABLE_NAME];
+    let columnName = pTableinfos[INDEX_COLUMN_NAME];
+    let additionalCondition = pTableinfos[INDEX_CONDITION];
+    
+    let condition = columnName + " = '" + pSourceContactId + "'";
+    
+    if(additionalCondition != "")
+        condition += " and ( " + additionalCondition + ") ";
+    
+    return [tableName, [columnName], null, [pTargetContactId], condition];
+}
+
+_DuplicateScannerUtils._getMergeUpdateTableInfos = function(pSourceContactId, pTargetContactId)
+{
+    let campaignParticipantCondition = "CAMPAIGN_ID"
+    
+    var tableInfos = new Array();
+    tableInfos.push(["AB_APPOINTMENTLINK", "OBJECT_ROWID", ""]);
+    tableInfos.push(["AB_CTILOG", "CONTACT_ID", ""]);
+    //tableInfos.push(["AB_OBJECTRELATION", "??", "" +  nochmal?
+    tableInfos.push(["HISTORY", "RESPONSIBLE", ""]);
+    tableInfos.push(["ADDRESS", "CONTACT_ID", ""]);
+    tableInfos.push(["BULKMAILRECIPIENT", "CONTACT_ID", ""]);
+    tableInfos.push(["CAMPAIGN", "EMPLOYEE_CONTACT_ID", ""]);
+    tableInfos.push(["CAMPAIGNSTEP", "EMPLOYEE_CONTACT_ID", ""]);
+    tableInfos.push(["COMMRESTRICTION", "CONTACT_ID", ""]);
+    tableInfos.push(["COMMUNICATION", "CONTACT_ID", ""]);
+    tableInfos.push(["COMPETITION", "CONTACT_ID", ""]);
+    tableInfos.push(["CONTRACT", "CONTACT_ID", ""]);
+    tableInfos.push(["LETTERRECIPIENT", "CONTACT_ID", ""]);
+    tableInfos.push(["MEMBER", "CONTACT_ID", ""]);
+    tableInfos.push(["OFFER", "CONTACT_ID", ""]);
+    tableInfos.push(["PRODUCT", "CONTACT_ID", ""]);
+    tableInfos.push(["PRODUCTPRICE", "CONTACT_ID", ""]);
+    tableInfos.push(["SALESORDER", "CONTACT_ID", ""]);
+    tableInfos.push(["SALESPROJECT", "CONTACT_ID", ""]);
+    tableInfos.push(["TASK", "REQUESTOR_CONTACT_ID", ""]);
+    tableInfos.push(["TASK", "EDITOR_CONTACT_ID", ""]);
+    tableInfos.push(["TASKLINK", "OBJECT-ROWID", ""]);
+    tableInfos.push(["ACTIVITY", "RESPONSIBLE", ""]);
+    tableInfos.push(["AB_ATTRIBUTERELATION", "OBJECT_ROWID", ""]);
+    
+    //tableInfos.push(["CAMPAIGNPARTICIPANT", "CONTACT_ID", ""]);
+    
+    return tableInfos;
+}
+
+
+
 /*
  * The pre filter is used to narrow the records to be searched by the duplicate scan service
  * It loads the target entity and uses filters achieve this.
@@ -176,7 +315,7 @@ _DuplicateScannerUtils._insertValuesInFilterTemplate = function(pJsonRootNode, p
             
             if(fieldValue == null)
             {
-                logging.log("Duplicate Scan: Requested value for field " + fieldName + " not present in the provided valueslist");
+                logging.show("Duplicate Scan: Requested value for field " + fieldName + " not present in the provided valueslist");
                 continue;
             }