Skip to content
Snippets Groups Projects
Commit bef7d472 authored by Sebastian Listl's avatar Sebastian Listl :speech_balloon:
Browse files

#1065733 Duplicate contact merge refactoring

parent 30e34689
No related branches found
No related tags found
No related merge requests found
...@@ -613,14 +613,10 @@ DuplicateScannerUtils.TranslateEntityToIndexFields = function(pEntityName, pEnti ...@@ -613,14 +613,10 @@ DuplicateScannerUtils.TranslateEntityToIndexFields = function(pEntityName, pEnti
* *
* @param {String} pSourceContactId The contact to be integrated into another * @param {String} pSourceContactId The contact to be integrated into another
* @param {String} pTargetContactId The contact in which the source gets integrated * @param {String} pTargetContactId The contact in which the source gets integrated
* @returns {String} * @returns {Boolean} if the merge was sucessful
*/ */
DuplicateScannerUtils.MergePerson = function(pSourceContactId, pTargetContactId) DuplicateScannerUtils.MergePerson = function(pSourceContactId, pTargetContactId)
{ {
var updateStatementsCurrentAlias = [];
var updateStatementsSystemAlias = [];
var deleteStatements = [];
var sourcePersonId = newSelect("PERSON_ID") var sourcePersonId = newSelect("PERSON_ID")
.from("CONTACT") .from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId) .where("CONTACT.CONTACTID", pSourceContactId)
...@@ -629,41 +625,29 @@ DuplicateScannerUtils.MergePerson = function(pSourceContactId, pTargetContactId) ...@@ -629,41 +625,29 @@ DuplicateScannerUtils.MergePerson = function(pSourceContactId, pTargetContactId)
.from("CONTACT") .from("CONTACT")
.where("CONTACT.CONTACTID", pTargetContactId) .where("CONTACT.CONTACTID", pTargetContactId)
.cell(); .cell();
var tableInfosCurrentAlias = _DuplicateScannerUtils._getMergeUpdateTableInfosCurrentAlias();
var tableInfosSystemAlias = _DuplicateScannerUtils._getMergeUpdateTableInfosSystemAlias();
updateStatementsCurrentAlias.push(_DuplicateScannerUtils._buildUpdateResetStandardCommunications(pSourceContactId));
updateStatementsCurrentAlias = updateStatementsCurrentAlias.concat(_DuplicateScannerUtils._buildUpdateContactIdStatements(tableInfosCurrentAlias, pSourceContactId, pTargetContactId));
updateStatementsCurrentAlias = updateStatementsCurrentAlias.concat(_DuplicateScannerUtils._buildUpdateAttachParticipantsToNewContactQuery("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", pSourceContactId, pTargetContactId));
updateStatementsSystemAlias = updateStatementsSystemAlias.concat(_DuplicateScannerUtils._buildUpdateContactIdStatements(tableInfosSystemAlias, pSourceContactId, pTargetContactId, SqlUtils.getSystemAlias()));
deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteRemoveObsoleteParticipantsRecordsQuery("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", pSourceContactId, pTargetContactId));
var isLinkedDataUpdated = _DuplicateScannerUtils._migrateLinkedContactData(pSourceContactId, pTargetContactId);
var isParticipantsUpdated = _DuplicateScannerUtils._migrateParticipantsToNewContact("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID",
pSourceContactId, pTargetContactId);
var deleteStatements = [];
if (sourcePersonId != targetPersonId) if (sourcePersonId != targetPersonId)
deleteStatements.push(["PERSON", newWhere("PERSON.PERSONID", sourcePersonId).build()]); deleteStatements.push(newWhere("PERSON.PERSONID", sourcePersonId).buildDeleteStatement());
deleteStatements.push(["CONTACT", newWhere("CONTACT.CONTACTID", pSourceContactId).build()]); deleteStatements.push(newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement());
deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId)); deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId));
for (var i = 0; i < updateStatementsCurrentAlias.length; i++) {
if(updateStatementsCurrentAlias[i][0] == "RemoveThisItem") //see _DuplicateScannerUtils._buildUpdateContactIdStatements for further information
updateStatementsCurrentAlias.splice(i,1);
}
//update binary //update binary
var metaData = db.getBinaryMetadata("CONTACT", "DOCUMENT", pSourceContactId, true, SqlUtils.getBinariesAlias()); var metaData = db.getBinaryMetadata("CONTACT", "DOCUMENT", pSourceContactId, true, SqlUtils.getBinariesAlias());
for (let i = 0; i < metaData.length; i++) { metaData.forEach(function (binaryMetaData)
var updateBinary = db.updateBinaryAssignment(metaData[i]["id"], "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias()); {
} db.updateBinaryAssignment(binaryMetaData.id, "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias());
var affectedRowsCurrentAlias = db.updates(updateStatementsCurrentAlias); });
var affectedRowsSystemAlias = db.updates(updateStatementsSystemAlias, SqlUtils.getSystemAlias());
var deletedRows = db.deletes(deleteStatements) var deletedRows = db.deletes(deleteStatements)
DuplicateScannerUtils.DeleteCachedDuplicate(pSourceContactId); DuplicateScannerUtils.DeleteCachedDuplicate(pSourceContactId);
return (affectedRowsCurrentAlias > 0 && deletedRows > 0); return ((isLinkedDataUpdated || isParticipantsUpdated) && deletedRows > 0);
} }
DuplicateScannerUtils.CreateMergeSuccessActivity = function(pSourceContactId, pTargetContactId, pCurrentContactId, pContext) DuplicateScannerUtils.CreateMergeSuccessActivity = function(pSourceContactId, pTargetContactId, pCurrentContactId, pContext)
...@@ -687,30 +671,30 @@ DuplicateScannerUtils.MergeOrganisation = function(pSourceContactId, pTargetCont ...@@ -687,30 +671,30 @@ DuplicateScannerUtils.MergeOrganisation = function(pSourceContactId, pTargetCont
let deleteStatements = []; let deleteStatements = [];
var sourceOrganisationId = newSelect("ORGANISATION_ID") var sourceOrganisationId = newSelect("ORGANISATION_ID")
.from("CONTACT") .from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId) .where("CONTACT.CONTACTID", pSourceContactId)
.cell(); .cell();
var tableInfosCurrentAlias = _DuplicateScannerUtils._getMergeUpdateTableInfosCurrentAlias(); var isLinkedDataUpdated = _DuplicateScannerUtils._migrateLinkedContactData(pSourceContactId, pTargetContactId);
var tableInfosSystemAlias = _DuplicateScannerUtils._getMergeUpdateTableInfosSystemAlias(); var isParticipantsUpdated = _DuplicateScannerUtils._migrateParticipantsToNewContact("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID",
pSourceContactId, pTargetContactId);
updateStatementsCurrentAlias = updateStatementsCurrentAlias.concat(_DuplicateScannerUtils._buildUpdateResetStandardCommunications(pSourceContactId));
updateStatementsCurrentAlias = updateStatementsCurrentAlias.concat(_DuplicateScannerUtils._buildUpdateContactIdStatements(tableInfosCurrentAlias, pSourceContactId, pTargetContactId)); var deleteStatements = [];
updateStatementsCurrentAlias = updateStatementsCurrentAlias.concat(_DuplicateScannerUtils._buildUpdateAttachParticipantsToNewContactQuery("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", pSourceContactId, pTargetContactId)); deleteStatements.push(newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement());
updateStatementsSystemAlias = updateStatementsSystemAlias.concat(_DuplicateScannerUtils._buildUpdateContactIdStatements(tableInfosSystemAlias, pSourceContactId, pTargetContactId));
deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteRemoveObsoleteParticipantsRecordsQuery("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", pSourceContactId, pTargetContactId));
deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteOrganisationAndContactQuery(sourceOrganisationId, pSourceContactId)); deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteOrganisationAndContactQuery(sourceOrganisationId, pSourceContactId));
deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId)); deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId));
let affectedRowsCurrentAlias = db.updates(updateStatementsCurrentAlias); //update binary
let affectedRowsSystemAlias = db.updates(updateStatementsSystemAlias, SqlUtils.getSystemAlias()); var metaData = db.getBinaryMetadata("CONTACT", "DOCUMENT", pSourceContactId, true, SqlUtils.getBinariesAlias());
let deletedRows = db.deletes(deleteStatements) metaData.forEach(function (binaryMetaData)
{
db.updateBinaryAssignment(binaryMetaData.id, "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias());
});
var deletedRows = db.deletes(deleteStatements)
DuplicateScannerUtils.DeleteCachedDuplicate(pSourceContactId); DuplicateScannerUtils.DeleteCachedDuplicate(pSourceContactId);
return (affectedRowsCurrentAlias > 0 && deletedRows >= 2); return ((isLinkedDataUpdated || isParticipantsUpdated) && deletedRows >= 2);
} }
/* /*
...@@ -1092,7 +1076,7 @@ _DuplicateScannerUtils._createInsertDuplicatesClusterQuery = function (pDuplicat ...@@ -1092,7 +1076,7 @@ _DuplicateScannerUtils._createInsertDuplicatesClusterQuery = function (pDuplicat
let duplicatesToInsertQueries = []; let duplicatesToInsertQueries = [];
let cols = ["ID", "CLUSTERID", "DUPLICATEID", "TARGET_ENTITY"]; let cols = ["ID", "CLUSTERID", "DUPLICATEID", "TARGET_ENTITY"];
if(pClusterId == undefined || pClusterId == null || pClusterId == "") if (!pClusterId)
pClusterId = util.getNewUUID(); pClusterId = util.getNewUUID();
for (let i = 0; i < pDuplicatesRay.length; i++) for (let i = 0; i < pDuplicatesRay.length; i++)
...@@ -1120,36 +1104,24 @@ _DuplicateScannerUtils._deleteDuplicateClusters = function () ...@@ -1120,36 +1104,24 @@ _DuplicateScannerUtils._deleteDuplicateClusters = function ()
* This is because otherwise there would now be in total two "participants" in the same "group" as opposed to one before. * 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. * 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 * @returns {Boolean} If records have been updated
* @returns {String[]} Query to update records
*/ */
_DuplicateScannerUtils._buildUpdateAttachParticipantsToNewContactQuery = function (pTableName, pContactIdColumn, pAssignableIdColumn, pSourceContactId, pTargetContactId, updateStatements) _DuplicateScannerUtils._migrateParticipantsToNewContact = function (pTableName, pContactIdColumn, pAssignableIdColumn, pSourceContactId, pTargetContactId)
{
var selectAssignableIdsOfTargetContactQuery = newSelect(pAssignableIdColumn)
.from(pTableName)
.where([pTableName, pContactIdColumn], pTargetContactId);
var subSelectTable = newSelect(["subselect." + pAssignableIdColumn]).from(selectAssignableIdsOfTargetContactQuery,"subselect");
let updateCondition = newWhere([pTableName, pAssignableIdColumn], subSelectTable, SqlBuilder.NOT_IN())
.and([pTableName, pContactIdColumn], pSourceContactId)
return [[pTableName, [pContactIdColumn], null, [pTargetContactId], updateCondition.build()]];
}
_DuplicateScannerUtils._buildDeleteRemoveObsoleteParticipantsRecordsQuery = function (pTableName, pContactIdColumn, pAssignableIdColumn, pSourceContactId, pTargetContactId, updateStatements)
{ {
var selectAssignableIdsOfTargetContactQuery = newSelect(pAssignableIdColumn) var excludedIds = newSelect(pAssignableIdColumn)
.from(pTableName) .from(pTableName)
.where([pTableName, pContactIdColumn], pTargetContactId); .where([pTableName, pContactIdColumn], pTargetContactId);
var subSelectTable = newSelect(["subselect." + pAssignableIdColumn]).from(selectAssignableIdsOfTargetContactQuery,"subselect");
let deleteCondition = newWhere([pTableName, pAssignableIdColumn], subSelectTable, SqlBuilder.IN())
.and([pTableName, pAssignableIdColumn], pSourceContactId)
return [[pTableName, deleteCondition.build()]]; var updateCount = newWhere([pTableName, pAssignableIdColumn], excludedIds, SqlBuilder.NOT_IN())
.and([pTableName, pContactIdColumn], pSourceContactId)
.updateFields(new Map().set(pContactIdColumn, pTargetContactId), pTableName);
var deleteCount = newWhere([pTableName, pAssignableIdColumn], excludedIds, SqlBuilder.IN())
.and([pTableName, pContactIdColumn], pSourceContactId)
.tableName(pTableName)
.deleteData();
return updateCount > 0 || deleteCount > 0;
} }
_DuplicateScannerUtils._buildDeleteOrganisationAndContactQuery = function(pSourceOrganisationId, pSourceContactId) _DuplicateScannerUtils._buildDeleteOrganisationAndContactQuery = function(pSourceOrganisationId, pSourceContactId)
...@@ -1185,72 +1157,70 @@ _DuplicateScannerUtils._getIgnoreSourceRecordPattern = function(pRecordIdValueTo ...@@ -1185,72 +1157,70 @@ _DuplicateScannerUtils._getIgnoreSourceRecordPattern = function(pRecordIdValueTo
return null; return null;
} }
_DuplicateScannerUtils._buildUpdateContactIdStatements = function(pTableInfos, pSourceContactId, pTargetContactId, pAlias) _DuplicateScannerUtils._migrateLinkedContactData = function (pSourceContactId, pTargetContactId)
{ {
return pTableInfos.map(function ([tableName, columnName, additionalCondition]) var updateStatements = new Map();
var resetStandardCommunications = _DuplicateScannerUtils._buildUpdateResetStandardCommunications(pSourceContactId);
var currentAlias = db.getCurrentAlias();
updateStatements.set(currentAlias, [resetStandardCommunications]);
_DuplicateScannerUtils._getLinkedTableInfos.forEach(function ([tableName, columnName, additionalCondition, alias])
{ {
if (!alias)
alias = currentAlias;
var updateValues = {}; var updateValues = {};
updateValues[columnName] = pTargetContactId; updateValues[columnName] = pTargetContactId;
var exclude = false;
if(tableName == "COMMUNICATION") var targetStandard = newSelect("CONTACT.ADDRESS_ID")
.from("CONTACT")
.where("CONTACT.CONTACTID", pTargetContactId)
.cell();
//set the standardaddress of the sourceContact as standard of the targetContact if it doesn't have one set yet
if(!targetStandard)
{ {
var sourceComm = newSelect("COMMUNICATION.ADDR") var sourceStandard = newSelect("CONTACT.ADDRESS_ID")
.from("COMMUNICATION") .from("CONTACT")
.where("COMMUNICATION.CONTACT_ID", pSourceContactId) .where("CONTACT.CONTACTID", pSourceContactId)
.arrayColumn(); .cell();
newWhere("CONTACT.CONTACTID", pTargetContactId).updateFields({"ADDRESS_ID": sourceStandard});
var targetComm = newSelect("COMMUNICATION.ADDR")
.from("COMMUNICATION")
.where("COMMUNICATION.CONTACT_ID", pTargetContactId)
.arrayColumn();
//set exclude to true if both of the datatasets have the exact same address (we don't want one person to have the same address twice)
if(sourceComm.length > 0 && targetComm.length > 0 )
{
for (var i = 0; i < sourceComm.length; i++) {
for (var x = 0; x < targetComm.length; x++) {
if(sourceComm[i] == targetComm[x])
exclude = true;
}
}
}
var targetStandard = newSelect("CONTACT.ADDRESS_ID")
.from("CONTACT")
.where("CONTACT.CONTACTID", pTargetContactId)
.cell();
//set the standardaddress of the sourceContact as standard of the targetContact if it doesn't have one set yet
if(!targetStandard)
{
var sourceStandard = newSelect("CONTACT.ADDRESS_ID")
.from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId)
.cell();
newWhere("CONTACT.CONTACTID", pTargetContactId).updateData(true, "CONTACT", ["ADDRESS_ID"], null, [sourceStandard]);
}
} }
if(exclude) var updateCondition = newWhere([tableName, columnName], pSourceContactId).andIfSet(additionalCondition);
{
newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId).deleteData(true, "COMMUNICATION"); //delete the address of the sourceContact //don't use communications that the target already has
return ["RemoveThisItem"] if (tableName == "COMMUNICATION")
} updateCondition.and(null, newSelect("targetComm.COMMUNICATIONID")
.from("COMMUNICATION", "targetComm")
.where(["COMMUNICATION", "CONTACT_ID", "targetComm"], pTargetContactId)
.and("targetComm.ADDR = COMMUNICATION.ADDR"),
SqlBuilder.NOT_EXISTS());
var updateStatement = updateCondition.buildUpdateStatement(updateValues, tableName);
if (updateStatements.has(alias))
updateStatements.get(alias).push(updateStatement);
else else
{ updateStatements.set(alias, [updateStatement]);
return newWhere([tableName, columnName], pSourceContactId, undefined, undefined, pAlias) });
.andIfSet(additionalCondition)
.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
return totalChanges > 0;
} }
/* /*
* Contains all Tables and their fields which may contain the contact id to be replaced for the data alias * 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] * @returns {String[[]]} Array in the format [TableName, ContactIdColumnName, AdditionalCondition, alias]
*/ */
_DuplicateScannerUtils._getMergeUpdateTableInfosCurrentAlias = function() _DuplicateScannerUtils._getLinkedTableInfos = function()
{ {
return[ return[
["AB_APPOINTMENTLINK", "OBJECT_ROWID", ""], ["AB_APPOINTMENTLINK", "OBJECT_ROWID", ""],
...@@ -1284,22 +1254,12 @@ _DuplicateScannerUtils._getMergeUpdateTableInfosCurrentAlias = function() ...@@ -1284,22 +1254,12 @@ _DuplicateScannerUtils._getMergeUpdateTableInfosCurrentAlias = function()
["DSGVOINFO", "CONTACT_ID", ""], ["DSGVOINFO", "CONTACT_ID", ""],
["TIMETRACKING", "CONTACT_ID", ""], ["TIMETRACKING", "CONTACT_ID", ""],
["ACTIVITYLINK", "OBJECT_ROWID", ""], ["ACTIVITYLINK", "OBJECT_ROWID", ""],
["AB_ATTRIBUTERELATION", "OBJECT_ROWID", ""] ["AB_ATTRIBUTERELATION", "OBJECT_ROWID", ""],
["ASYS_CALENDARLINK", "DBID", "", SqlUtils.getSystemAlias()]
]; ];
} }
/*
* Contains all Tables and their fields which may contain the contact id to be replaced for the system alias
* in the past ASYS_BINARY had also been updated like this, but know we are using
* the function db.updateBinaryAssignment (see also DuplicateScannerUtils.MergePerson).
*
* @returns {String[[]]} Array in the format [TableName, ContactIdColumnName, AdditionalCondition]
*/
_DuplicateScannerUtils._getMergeUpdateTableInfosSystemAlias = function()
{
return [["ASYS_CALENDARLINK", "DBID", ""]];
}
/* /*
* Returns wether or not a value should be substring'd * Returns wether or not a value should be substring'd
* *
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment