From 4c744160fb5b5577dbc84e9e276f2f8db6566987 Mon Sep 17 00:00:00 2001
From: "d.buechler" <d.buechler@adito.de>
Date: Tue, 13 Aug 2019 09:40:55 +0200
Subject: [PATCH] =?UTF-8?q?Die=20Typ-spezifischen=20Dubletten,=20welche=20?=
 =?UTF-8?q?an=20Person/Organisation=20angezeigt=20werden,=20werden=20nun?=
 =?UTF-8?q?=20nicht=20mehr=20=C3=BCber=20ein=20separates=20Entity=20gelade?=
 =?UTF-8?q?n,=20sondern=20direkt=20=C3=BCber=20das=20jeweilige=20Entity=20?=
 =?UTF-8?q?selbst.=20Daf=C3=BCr=20wurde=20der=20Recordcontainer=20um=20ver?=
 =?UTF-8?q?wertung=20eines=20weiteren=20Parameters=20erweitert.=20Das=20La?=
 =?UTF-8?q?den=20der=20Daten=20passiert=20=C3=BCber=20ein=20Consumer/Provi?=
 =?UTF-8?q?der=20Paar=20direkt=20im=20gleichen=20Entity.=20Die=20ActionGro?=
 =?UTF-8?q?up=20f=C3=BCr=20Dublettenaktionen=20in=20der=20Kontakteliste=20?=
 =?UTF-8?q?wird=20immer=20angezeigt,=20wenn=20der=20entsprechende=20Parame?=
 =?UTF-8?q?ter=20"onlyShowContactIds"=20gef=C3=BCllt=20ist.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../testduplicatescan/onActionProcess.js      |   3 +-
 .../Duplicates_entity/Duplicates_entity.aod   |  42 +++--
 .../onActionProcess.js                        |  14 --
 .../onActionProcess.js                        |  14 --
 .../onlyshowcontactids_param/valueProcess.js  |   6 +
 .../jditorecordcontainer/contentProcess.js    | 154 +++++++++---------
 .../onActionProcess.js                        |  14 ++
 .../onActionProcess.js                        |  14 ++
 .../duplicateactions/stateProcess.js          |  11 ++
 .../valueProcess.js                           |   3 +
 .../onlyshowcontactids_param/valueProcess.js  |  11 ++
 .../recordcontainers/db/conditionProcess.js   |  31 +++-
 .../_____LANGUAGE_EXTRA.aod                   |   3 +
 .../_____LANGUAGE_de/_____LANGUAGE_de.aod     |   4 +
 .../_____LANGUAGE_en/_____LANGUAGE_en.aod     |   3 +
 neonContext/Duplicates/Duplicates.aod         |   4 +
 .../PersonDuplicates_view.aod                 |  17 ++
 .../PersonFilter_view/PersonFilter_view.aod   |   1 +
 neonView/PersonMain_view/PersonMain_view.aod  |   6 +-
 process/DuplicateScanner_lib/process.js       |  37 +++--
 20 files changed, 244 insertions(+), 148 deletions(-)
 create mode 100644 entity/Duplicates_entity/entityfields/personconsumer/children/onlyshowcontactids_param/valueProcess.js
 create mode 100644 entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js
 create mode 100644 entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js
 create mode 100644 entity/Person_entity/entityfields/duplicateactions/stateProcess.js
 create mode 100644 entity/Person_entity/entityfields/personduplicates/children/contactidtocheckforcachedduplicates_param/valueProcess.js
 create mode 100644 entity/Person_entity/entityfields/selfduplicates/children/onlyshowcontactids_param/valueProcess.js
 create mode 100644 neonView/PersonDuplicates_view/PersonDuplicates_view.aod

diff --git a/entity/DuplicateScan_entity/entityfields/testactiongroup/children/testduplicatescan/onActionProcess.js b/entity/DuplicateScan_entity/entityfields/testactiongroup/children/testduplicatescan/onActionProcess.js
index 3b5bdf750a9..a7272d7517a 100644
--- a/entity/DuplicateScan_entity/entityfields/testactiongroup/children/testduplicatescan/onActionProcess.js
+++ b/entity/DuplicateScan_entity/entityfields/testactiongroup/children/testduplicatescan/onActionProcess.js
@@ -9,7 +9,6 @@ import("DuplicateScanner_lib");
 
 var filterName = "PersonDuplicates";
 var targetEntity = "Person_entity";
-var resultFieldContactId = ["CONTACTID"];
 var resultFieldsIdFieldName = "CONTACTID";
 var queryPersonContactIds = "select CONTACTID, FIRSTNAME, LASTNAME, GENDER from CONTACT"
                             + " join PERSON on PERSONID = PERSON_ID";
@@ -18,4 +17,4 @@ var tmpFieldsInFilterRay = ["CONTACTID", "FIRSTNAME", "LASTNAME", "GENDER"];
 logging.log("in der action -> ");
 
 DuplicateScannerUtils.RebuildDuplicatesCache(filterName, targetEntity, queryPersonContactIds,
-tmpFieldsInFilterRay, resultFieldContactId, resultFieldsIdFieldName);
\ No newline at end of file
+tmpFieldsInFilterRay, resultFieldsIdFieldName);
\ No newline at end of file
diff --git a/entity/Duplicates_entity/Duplicates_entity.aod b/entity/Duplicates_entity/Duplicates_entity.aod
index 896c64c1cb9..ddd6e038548 100644
--- a/entity/Duplicates_entity/Duplicates_entity.aod
+++ b/entity/Duplicates_entity/Duplicates_entity.aod
@@ -42,18 +42,18 @@
       <targetIdField>UID</targetIdField>
       <titlePlural>Duplicates</titlePlural>
       <dependencies>
-        <entityDependency>
-          <name>ea8abf2a-d8b8-4f83-a68e-664b3b23d822</name>
-          <entityName>Person_entity</entityName>
-          <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>
+        <entityDependency>
+          <name>d27771c1-1302-46dc-b285-76c345532e80</name>
+          <entityName>Person_entity</entityName>
+          <fieldName>PersonDuplicates</fieldName>
+          <isConsumer v="false" />
+        </entityDependency>
       </dependencies>
     </entityProvider>
     <entityField>
@@ -103,6 +103,24 @@
       <expose v="true" />
       <mandatory v="true" />
     </entityParameter>
+    <entityConsumer>
+      <name>PersonConsumer</name>
+      <dependency>
+        <name>dependency</name>
+        <entityName>Person_entity</entityName>
+        <fieldName>Contacts</fieldName>
+      </dependency>
+      <children>
+        <entityParameter>
+          <name>OnlyShowContactIds_param</name>
+          <valueProcess>%aditoprj%/entity/Duplicates_entity/entityfields/personconsumer/children/onlyshowcontactids_param/valueProcess.js</valueProcess>
+        </entityParameter>
+      </children>
+    </entityConsumer>
+    <entityParameter>
+      <name>contactIdToCheckForCachedDuplicates_param</name>
+      <expose v="true" />
+    </entityParameter>
   </entityFields>
   <recordContainers>
     <jDitoRecordContainer>
@@ -113,18 +131,6 @@
         <jDitoRecordFieldMapping>
           <name>UID.value</name>
         </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>targetContext.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>VALUE1.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>VALUE2.value</name>
-        </jDitoRecordFieldMapping>
-        <jDitoRecordFieldMapping>
-          <name>VALUE3.value</name>
-        </jDitoRecordFieldMapping>
       </recordFieldMappings>
     </jDitoRecordContainer>
   </recordContainers>
diff --git a/entity/Duplicates_entity/entityfields/actiongroup/children/integratecurrentintoselectedaction/onActionProcess.js b/entity/Duplicates_entity/entityfields/actiongroup/children/integratecurrentintoselectedaction/onActionProcess.js
index 63fddf359f2..e69de29bb2d 100644
--- a/entity/Duplicates_entity/entityfields/actiongroup/children/integratecurrentintoselectedaction/onActionProcess.js
+++ b/entity/Duplicates_entity/entityfields/actiongroup/children/integratecurrentintoselectedaction/onActionProcess.js
@@ -1,14 +0,0 @@
-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
index 6351f476b87..e69de29bb2d 100644
--- a/entity/Duplicates_entity/entityfields/actiongroup/children/integrateselectedintocurrentaction/onActionProcess.js
+++ b/entity/Duplicates_entity/entityfields/actiongroup/children/integrateselectedintocurrentaction/onActionProcess.js
@@ -1,14 +0,0 @@
-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/entityfields/personconsumer/children/onlyshowcontactids_param/valueProcess.js b/entity/Duplicates_entity/entityfields/personconsumer/children/onlyshowcontactids_param/valueProcess.js
new file mode 100644
index 00000000000..5832faed728
--- /dev/null
+++ b/entity/Duplicates_entity/entityfields/personconsumer/children/onlyshowcontactids_param/valueProcess.js
@@ -0,0 +1,6 @@
+import("system.vars");
+import("DuplicateScanner_lib");
+import("system.result");
+
+var contactIdToCheck = vars.get("$param.contactIdToCheckForCachedDuplicates_param");
+result.string(DuplicateScannerUtils.GetCachedDuplicatesForContactId(contactIdToCheck));
\ 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 8baa7234be7..6eb974e29cb 100644
--- a/entity/Duplicates_entity/recordcontainers/jditorecordcontainer/contentProcess.js
+++ b/entity/Duplicates_entity/recordcontainers/jditorecordcontainer/contentProcess.js
@@ -3,82 +3,90 @@ import("system.vars");
 import("DuplicateScanner_lib");
 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");
-var maxRecorValues = parseInt(vars.get("$field.maxReturnValueCount"), 10);
-var recordIdToIgnore = vars.get("$param.recordIdToIgnore_param");
+//var contactIdToCheck = vars.get("$param.contactIdToCheckForCachedDuplicates_param");
 
-logging.log("filterName -> " + filterName);
-logging.log("targetEntity -> " + targetEntity);
-logging.log("values -> " + values);
-logging.log("resultFields -> " + resultFields);
+//result.string(DuplicateScannerUtils.GetCachedDuplicatesForContactId(contactIdToCheck));
+result.string("asd");
 
-var duplicates = DuplicateScannerUtils.ScanForDuplicates(filterName, targetEntity, values, resultFields, resultFieldsIdFieldName, recordIdToIgnore);
-logging.log("duplicates -> " + JSON.stringify(duplicates));
 
-//[{"FIRSTNAME":"Markus","LASTNAME":"Altinger","PERSONID":"0a611832-9476-481e-bde5-af3c3a98f1b4"},
-//{"FIRSTNAME":"Marshel","LASTNAME":"Ericson","PERSONID":"44c5d7db-b96e-4f67-a00f-c206cd3f7e1b"}]
-var returnRay = [];
-logging.log("duplicates.length -> " + duplicates.length);
-for (i = 0; i < duplicates.length; i++) 
-{
-    let newRecord = _compileSingleRecord(duplicates[i], resultFieldsIdFieldName, maxRecorValues, targetContext);
-    
-    logging.log("newRecord -> " + newRecord);
-    returnRay.push(newRecord);
-}
-result.object(returnRay);
+//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");
+//var maxRecorValues = parseInt(vars.get("$field.maxReturnValueCount"), 10);
+//var recordIdToIgnore = vars.get("$param.recordIdToIgnore_param");
+//
+//logging.log("filterName -> " + filterName);
+//logging.log("targetEntity -> " + targetEntity);
+//logging.log("values -> " + values);
+//logging.log("resultFields -> " + resultFields);
 
 
-function _compileSingleRecord(pDuplicate, pIdFieldName, maxRecordValues, pTargetContext)
-{
-    let newRecord = [];
-    let recordId = pDuplicate[pIdFieldName];
-    
-    newRecord.push(recordId);
-    newRecord.push(pTargetContext);
-    
-    let recordCount = 0;
-    
-    for(recordValue in pDuplicate)
-    {
-        logging.log("recordKey -> " + recordValue);
-        logging.log("revordValue -> " + pDuplicate[recordValue]);
 
-        recordCount++;
-
-        //The record Id has already been added, only the rest gets added
-        if(recordValue != pIdFieldName)
-            newRecord.push(pDuplicate[recordValue]);
-        
-        logging.log("recourdcount -> " + recordCount);
-        logging.log("maxRecordValues-1 -> " + (maxRecordValues-1));
-        //subtract 2 because in this for loop only the values get added
-        //The id as well as the targetContext are handled separately
-        if(recordCount == maxRecordValues-2)
-            break;
-    }
-    
-    logging.log("newRecord.length -> " + newRecord.length);
-    logging.log("maxRecordValues -> " + maxRecordValues);
-    
-    
-    
-    //If there are less elements than required, fill the record with empty strings
-    //because a recor dof a recordContainer always has to have the correct length defined by the "recordFieldMappings
-    if(newRecord.length < maxRecordValues)
-    {
-        let elementsToFill = maxRecordValues - newRecord.length;
-        for (a = 0; a < elementsToFill; a++) 
-        {
-            newRecord.push("");
-        }
-    }
-    logging.log("newRecord -> " + newRecord);
-    return newRecord;
-    
-}
\ No newline at end of file
+//var duplicates = DuplicateScannerUtils.ScanForDuplicates(filterName, targetEntity, values, resultFields, resultFieldsIdFieldName, recordIdToIgnore);
+//logging.log("duplicates -> " + JSON.stringify(duplicates));
+//
+////[{"FIRSTNAME":"Markus","LASTNAME":"Altinger","PERSONID":"0a611832-9476-481e-bde5-af3c3a98f1b4"},
+////{"FIRSTNAME":"Marshel","LASTNAME":"Ericson","PERSONID":"44c5d7db-b96e-4f67-a00f-c206cd3f7e1b"}]
+//var returnRay = [];
+//logging.log("duplicates.length -> " + duplicates.length);
+//for (i = 0; i < duplicates.length; i++) 
+//{
+//    let newRecord = _compileSingleRecord(duplicates[i], resultFieldsIdFieldName, maxRecorValues, targetContext);
+//    
+//    logging.log("newRecord -> " + newRecord);
+//    returnRay.push(newRecord);
+//}
+//result.object(returnRay);
+//
+//
+//function _compileSingleRecord(pDuplicate, pIdFieldName, maxRecordValues, pTargetContext)
+//{
+//    let newRecord = [];
+//    let recordId = pDuplicate[pIdFieldName];
+//    
+//    newRecord.push(recordId);
+//    newRecord.push(pTargetContext);
+//    
+//    let recordCount = 0;
+//    
+//    for(recordValue in pDuplicate)
+//    {
+//        logging.log("recordKey -> " + recordValue);
+//        logging.log("revordValue -> " + pDuplicate[recordValue]);
+//
+//        recordCount++;
+//
+//        //The record Id has already been added, only the rest gets added
+//        if(recordValue != pIdFieldName)
+//            newRecord.push(pDuplicate[recordValue]);
+//        
+//        logging.log("recourdcount -> " + recordCount);
+//        logging.log("maxRecordValues-1 -> " + (maxRecordValues-1));
+//        //subtract 2 because in this for loop only the values get added
+//        //The id as well as the targetContext are handled separately
+//        if(recordCount == maxRecordValues-2)
+//            break;
+//    }
+//    
+//    logging.log("newRecord.length -> " + newRecord.length);
+//    logging.log("maxRecordValues -> " + maxRecordValues);
+//    
+//    
+//    
+//    //If there are less elements than required, fill the record with empty strings
+//    //because a recor dof a recordContainer always has to have the correct length defined by the "recordFieldMappings
+//    if(newRecord.length < maxRecordValues)
+//    {
+//        let elementsToFill = maxRecordValues - newRecord.length;
+//        for (a = 0; a < elementsToFill; a++) 
+//        {
+//            newRecord.push("");
+//        }
+//    }
+//    logging.log("newRecord -> " + newRecord);
+//    return newRecord;
+//    
+//}
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js b/entity/Person_entity/entityfields/duplicateactions/children/integratecurrentintoselectedaction/onActionProcess.js
new file mode 100644
index 00000000000..63fddf359f2
--- /dev/null
+++ b/entity/Person_entity/entityfields/duplicateactions/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/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js b/entity/Person_entity/entityfields/duplicateactions/children/integrateselectedintocurrentaction/onActionProcess.js
new file mode 100644
index 00000000000..6351f476b87
--- /dev/null
+++ b/entity/Person_entity/entityfields/duplicateactions/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/Person_entity/entityfields/duplicateactions/stateProcess.js b/entity/Person_entity/entityfields/duplicateactions/stateProcess.js
new file mode 100644
index 00000000000..4b5fca22f50
--- /dev/null
+++ b/entity/Person_entity/entityfields/duplicateactions/stateProcess.js
@@ -0,0 +1,11 @@
+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 onlyShowContactIds = vars.get("$param.OnlyShowContactIds_param");
+
+if(onlyShowContactIds == null)
+    result.string(neon.COMPONENTSTATE_INVISIBLE);
\ No newline at end of file
diff --git a/entity/Person_entity/entityfields/personduplicates/children/contactidtocheckforcachedduplicates_param/valueProcess.js b/entity/Person_entity/entityfields/personduplicates/children/contactidtocheckforcachedduplicates_param/valueProcess.js
new file mode 100644
index 00000000000..821415ae694
--- /dev/null
+++ b/entity/Person_entity/entityfields/personduplicates/children/contactidtocheckforcachedduplicates_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/selfduplicates/children/onlyshowcontactids_param/valueProcess.js b/entity/Person_entity/entityfields/selfduplicates/children/onlyshowcontactids_param/valueProcess.js
new file mode 100644
index 00000000000..9bacd4c3ef2
--- /dev/null
+++ b/entity/Person_entity/entityfields/selfduplicates/children/onlyshowcontactids_param/valueProcess.js
@@ -0,0 +1,11 @@
+import("system.logging");
+import("system.vars");
+import("DuplicateScanner_lib");
+import("system.result");
+
+
+let contactIdToCheck = vars.get("$field.CONTACTID");
+logging.log("im person consumer -> " + contactIdToCheck );
+let test = JSON.stringify(DuplicateScannerUtils.GetCachedDuplicatesForContactId(contactIdToCheck))
+logging.log("test -> " + test);
+    result.string(test);
\ No newline at end of file
diff --git a/entity/Person_entity/recordcontainers/db/conditionProcess.js b/entity/Person_entity/recordcontainers/db/conditionProcess.js
index 5dd47bb6a33..dc8501cfa30 100644
--- a/entity/Person_entity/recordcontainers/db/conditionProcess.js
+++ b/entity/Person_entity/recordcontainers/db/conditionProcess.js
@@ -1,3 +1,4 @@
+import("system.logging");
 import("system.vars");
 import("system.db");
 import("system.result");
@@ -7,18 +8,36 @@ var cond = new SqlCondition();
 cond.andPrepareVars("CONTACT.ORGANISATION_ID", "$param.OrgId_param")
     .andPrepareVars("PERSON.CONTACT_ID", "$param.ContactId_param");
 
+var onlyShowContactIds = JSON.parse(vars.get("$param.OnlyShowContactIds_param"));
+var additionalCondition = SqlCondition.begin();
+let alternativeCondition = "1 = 1";
+
+logging.log(" onlyShowContactIds-> " + onlyShowContactIds);
+
+
 if (vars.exists("$param.ExcludedContactIds_param") && vars.get("$param.ExcludedContactIds_param"))
 {
     var excludedContacts = JSON.parse(vars.getString("$param.ExcludedContactIds_param"));
-    var excludedCond = SqlCondition.begin();
-    
+
+
     excludedContacts.forEach(function(pContactId)
     {
-        excludedCond.andPrepare("CONTACT.CONTACTID", pContactId, "#<>?");
+        additionalCondition.andPrepare("CONTACT.CONTACTID", pContactId, "#<>?");
+    });
+
+    cond.andSqlCondition(additionalCondition, "1=1");
+}
+
+if(onlyShowContactIds != null || onlyShowContactIds.length != 0)
+{
+    onlyShowContactIds.forEach(function(pContactId)
+    {
+        additionalCondition.orPrepare("CONTACT.CONTACTID", pContactId);
     });
-    
-    cond.andSqlCondition(excludedCond, "1=1");
+
+    cond.andSqlCondition(additionalCondition, "1=2");
+    alternativeCondition = "1 = 2";
 }
 
 //TODO: use a preparedCondition when available #1030812 #1034026
-result.string(db.translateCondition(cond.build("1 = 1")));
\ No newline at end of file
+result.string(db.translateCondition(cond.build(alternativeCondition)));
\ No newline at end of file
diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
index c7a61be27f9..c2aad558ee9 100644
--- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
+++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod
@@ -4974,6 +4974,9 @@
     <entry>
       <key>Duplicates</key>
     </entry>
+    <entry>
+      <key>Ignore Duplicate</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 bb07b870b84..26fe06dafb0 100644
--- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
+++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod
@@ -6264,6 +6264,10 @@
     <entry>
       <key>Duplicates</key>
     </entry>
+    <entry>
+      <key>Ignore Duplicate</key>
+      <value>Dublette ignorieren</value>
+    </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 b880baca435..5a622924ea1 100644
--- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
+++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod
@@ -5023,6 +5023,9 @@
     <entry>
       <key>Duplicates</key>
     </entry>
+    <entry>
+      <key>Ignore Duplicate</key>
+    </entry>
   </keyValueMap>
   <font name="Dialog" style="0" size="11" />
 </language>
diff --git a/neonContext/Duplicates/Duplicates.aod b/neonContext/Duplicates/Duplicates.aod
index e640ba2fe31..b283f75380a 100644
--- a/neonContext/Duplicates/Duplicates.aod
+++ b/neonContext/Duplicates/Duplicates.aod
@@ -8,5 +8,9 @@
       <name>fe767c88-a869-4fe6-b61d-8727faad7a12</name>
       <view>DuplicatesFilter_view</view>
     </neonViewReference>
+    <neonViewReference>
+      <name>42958ab5-8d85-4cfd-ab81-1201348576c9</name>
+      <view>PersonDuplicates_view</view>
+    </neonViewReference>
   </references>
 </neonContext>
diff --git a/neonView/PersonDuplicates_view/PersonDuplicates_view.aod b/neonView/PersonDuplicates_view/PersonDuplicates_view.aod
new file mode 100644
index 00000000000..21e196fd4f4
--- /dev/null
+++ b/neonView/PersonDuplicates_view/PersonDuplicates_view.aod
@@ -0,0 +1,17 @@
+<?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.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
+  <name>PersonDuplicates_view</name>
+  <majorModelMode>DISTRIBUTED</majorModelMode>
+  <layout>
+    <boxLayout>
+      <name>layout</name>
+    </boxLayout>
+  </layout>
+  <children>
+    <neonViewReference>
+      <name>113cab06-ca9a-41a5-8de7-7ba759596497</name>
+      <entityField>PersonConsumer</entityField>
+      <view>PersonFilter_view</view>
+    </neonViewReference>
+  </children>
+</neonView>
diff --git a/neonView/PersonFilter_view/PersonFilter_view.aod b/neonView/PersonFilter_view/PersonFilter_view.aod
index 4389832df3e..532c8b6e3c0 100644
--- a/neonView/PersonFilter_view/PersonFilter_view.aod
+++ b/neonView/PersonFilter_view/PersonFilter_view.aod
@@ -33,6 +33,7 @@
     <tableViewTemplate>
       <name>Persons</name>
       <favoriteActionGroup1>campaignActionGroup</favoriteActionGroup1>
+      <favoriteActionGroup2>DuplicateActions</favoriteActionGroup2>
       <hideActions v="false" />
       <iconField>PICTURE</iconField>
       <titleField>NAME_fieldGroup</titleField>
diff --git a/neonView/PersonMain_view/PersonMain_view.aod b/neonView/PersonMain_view/PersonMain_view.aod
index 648df5ad4de..af425312bfa 100644
--- a/neonView/PersonMain_view/PersonMain_view.aod
+++ b/neonView/PersonMain_view/PersonMain_view.aod
@@ -65,9 +65,9 @@
       <view>DSGVOFilter_view</view>
     </neonViewReference>
     <neonViewReference>
-      <name>17b890d6-c734-4607-92dc-af87c90c1156</name>
-      <entityField>PersonDuplicates</entityField>
-      <view>DuplicatesFilter_view</view>
+      <name>d128a678-b1c0-49d0-a74c-7860d3a85247</name>
+      <entityField>SelfDuplicates</entityField>
+      <view>PersonFilter_view</view>
     </neonViewReference>
   </children>
 </neonView>
diff --git a/process/DuplicateScanner_lib/process.js b/process/DuplicateScanner_lib/process.js
index a8068b310c1..4af56b3a054 100644
--- a/process/DuplicateScanner_lib/process.js
+++ b/process/DuplicateScanner_lib/process.js
@@ -22,15 +22,7 @@ DuplicateScannerUtils.ScanForDuplicates = function(pFilterName, pTargetEntity, p
 
     let possibleDuplicates = _DuplicateScannerUtils._applyPreFilter(pTargetEntity, configuredFilters, pTargetEntityResultFields, pFilterValues);
     
-    if(possibleDuplicates.length <= 0)
-    {
-        return [];
-    }
-//    if(_DuplicateScannerUtils._isExternalScanServiceAvailable() 
-//      && _DuplicateScannerUtils._useExternalScanServiceAllowed(pFilterName, pTargetEntity))
-//    {
-//        _DuplicateScannerUtils._callExternalScanService();
-//    }
+
     
     return possibleDuplicates;
 }
@@ -64,9 +56,18 @@ DuplicateScannerUtils.RemoveFromDuplicatesCache = function(pContactId)
     
 }
 
+DuplicateScannerUtils.GetCachedDuplicatesForContactId = function(pDuplicateId)
+{
+    let querySelectDuplicateContactIds = "select DUPLICATEID from DUPLICATECLUSTERS"
+                                        + " where CLUSTERID = (select CLUSTERID from DUPLICATECLUSTERS"
+                                        + " where DUPLICATEID = '"+ pDuplicateId +"')"
+                                        + " and DUPLICATEID != '"+ pDuplicateId +"'";
+    return db.array(db.COLUMN, querySelectDuplicateContactIds);
+}
+
 //Später mal eigentsändiger Serverprozess ohne externe Konfiguration
 DuplicateScannerUtils.RebuildDuplicatesCache = function(pFilterName, pTargetEntity, 
-pQueryTargetRecords, pFilterValues, pTargetEntityResultFields, pRecordIdFieldToIgnore)
+pQueryTargetRecords, pFilterFields, pRecordIdFieldToIgnore)
 {
     logging.log("in RebuildDuplicatesCache -> ");
     let alreadyIdentifiedIds = [];
@@ -78,10 +79,10 @@ pQueryTargetRecords, pFilterValues, pTargetEntityResultFields, pRecordIdFieldToI
     if(contactIdsToScan.length <= 0)
         return;
     
-    //fie felder für die prüfung muss zusammengebaut werden aus den feldern des filters 
-    //und den dazugehörigen werten des aus der db geladenen datensatzes
+
+    //todo woanders löschen
+    //_DuplicateScannerUtils._deleteDuplicateClusters();
     
-    _DuplicateScannerUtils._deleteDuplicateClusters();
     var duplicatesToInsertQueries = [];
     for (b = 0; b < contactIdsToScan.length; b++) 
     {
@@ -95,20 +96,20 @@ pQueryTargetRecords, pFilterValues, pTargetEntityResultFields, pRecordIdFieldToI
         
         let filterValuesObject = {};
         
-        for (a = 0; a < pFilterValues.length; a++) 
+        for (a = 0; a < pFilterFields.length; a++) 
         {
-            logging.log("pFilterValues[a] -> " + pFilterValues[a]);
+            logging.log("pFilterValues[a] -> " + pFilterFields[a]);
             logging.log("contactIdsToScan[i][a] -> " + contactIdsToScan[b][a]);
             
-            filterValuesObject[pFilterValues[a]] = contactIdsToScan[b][a];
+            filterValuesObject[pFilterFields[a]] = contactIdsToScan[b][a];
             
-            logging.log("filterValuesObject[pFilterValues[a]] -> " + filterValuesObject[pFilterValues[a]]);
+            logging.log("filterValuesObject[pFilterValues[a]] -> " + filterValuesObject[pFilterFields[a]]);
         }
         
         logging.log("filterValuesObject -> " + JSON.stringify(filterValuesObject));
         
         let foundDuplicates = DuplicateScannerUtils.ScanForDuplicates(pFilterName, pTargetEntity,
-                                filterValuesObject, pTargetEntityResultFields, pRecordIdFieldToIgnore, contactIdsToScan[b][0])
+                                filterValuesObject, [pRecordIdFieldToIgnore], pRecordIdFieldToIgnore, contactIdsToScan[b][0])
         
         logging.log("foundDuplicates -> " + JSON.stringify(foundDuplicates));
         if(foundDuplicates.length == 0)
-- 
GitLab