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
*
* @param {String} pSourceContactId The contact to be integrated into another
* @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)
{
var updateStatementsCurrentAlias = [];
var updateStatementsSystemAlias = [];
var deleteStatements = [];
var sourcePersonId = newSelect("PERSON_ID")
.from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId)
......@@ -629,41 +625,29 @@ DuplicateScannerUtils.MergePerson = function(pSourceContactId, pTargetContactId)
.from("CONTACT")
.where("CONTACT.CONTACTID", pTargetContactId)
.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)
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));
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
var metaData = db.getBinaryMetadata("CONTACT", "DOCUMENT", pSourceContactId, true, SqlUtils.getBinariesAlias());
for (let i = 0; i < metaData.length; i++) {
var updateBinary = db.updateBinaryAssignment(metaData[i]["id"], "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias());
}
var affectedRowsCurrentAlias = db.updates(updateStatementsCurrentAlias);
var affectedRowsSystemAlias = db.updates(updateStatementsSystemAlias, SqlUtils.getSystemAlias());
metaData.forEach(function (binaryMetaData)
{
db.updateBinaryAssignment(binaryMetaData.id, "CONTACT", "DOCUMENT", pTargetContactId, SqlUtils.getBinariesAlias());
});
var deletedRows = db.deletes(deleteStatements)
DuplicateScannerUtils.DeleteCachedDuplicate(pSourceContactId);
return (affectedRowsCurrentAlias > 0 && deletedRows > 0);
return ((isLinkedDataUpdated || isParticipantsUpdated) && deletedRows > 0);
}
DuplicateScannerUtils.CreateMergeSuccessActivity = function(pSourceContactId, pTargetContactId, pCurrentContactId, pContext)
......@@ -687,30 +671,30 @@ DuplicateScannerUtils.MergeOrganisation = function(pSourceContactId, pTargetCont
let deleteStatements = [];
var sourceOrganisationId = newSelect("ORGANISATION_ID")
.from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId)
.cell();
var tableInfosCurrentAlias = _DuplicateScannerUtils._getMergeUpdateTableInfosCurrentAlias();
var tableInfosSystemAlias = _DuplicateScannerUtils._getMergeUpdateTableInfosSystemAlias();
updateStatementsCurrentAlias = updateStatementsCurrentAlias.concat(_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));
deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteRemoveObsoleteParticipantsRecordsQuery("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID", pSourceContactId, pTargetContactId));
.from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId)
.cell();
var isLinkedDataUpdated = _DuplicateScannerUtils._migrateLinkedContactData(pSourceContactId, pTargetContactId);
var isParticipantsUpdated = _DuplicateScannerUtils._migrateParticipantsToNewContact("CAMPAIGNPARTICIPANT", "CONTACT_ID", "CAMPAIGN_ID",
pSourceContactId, pTargetContactId);
var deleteStatements = [];
deleteStatements.push(newWhere("CONTACT.CONTACTID", pSourceContactId).buildDeleteStatement());
deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteOrganisationAndContactQuery(sourceOrganisationId, pSourceContactId));
deleteStatements = deleteStatements.concat(_DuplicateScannerUtils._buildDeleteCachedUnrelatedDuplicateQuery(pSourceContactId));
let affectedRowsCurrentAlias = db.updates(updateStatementsCurrentAlias);
let affectedRowsSystemAlias = db.updates(updateStatementsSystemAlias, SqlUtils.getSystemAlias());
let deletedRows = db.deletes(deleteStatements)
//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.DeleteCachedDuplicate(pSourceContactId);
return (affectedRowsCurrentAlias > 0 && deletedRows >= 2);
return ((isLinkedDataUpdated || isParticipantsUpdated) && deletedRows >= 2);
}
/*
......@@ -1092,7 +1076,7 @@ _DuplicateScannerUtils._createInsertDuplicatesClusterQuery = function (pDuplicat
let duplicatesToInsertQueries = [];
let cols = ["ID", "CLUSTERID", "DUPLICATEID", "TARGET_ENTITY"];
if(pClusterId == undefined || pClusterId == null || pClusterId == "")
if (!pClusterId)
pClusterId = util.getNewUUID();
for (let i = 0; i < pDuplicatesRay.length; i++)
......@@ -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.
* 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 {String[]} Query to update records
* @returns {Boolean} If records have been updated
*/
_DuplicateScannerUtils._buildUpdateAttachParticipantsToNewContactQuery = function (pTableName, pContactIdColumn, pAssignableIdColumn, pSourceContactId, pTargetContactId, updateStatements)
{
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)
_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 deleteCondition = newWhere([pTableName, pAssignableIdColumn], subSelectTable, SqlBuilder.IN())
.and([pTableName, pAssignableIdColumn], pSourceContactId)
var excludedIds = newSelect(pAssignableIdColumn)
.from(pTableName)
.where([pTableName, pContactIdColumn], pTargetContactId);
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)
......@@ -1185,72 +1157,70 @@ _DuplicateScannerUtils._getIgnoreSourceRecordPattern = function(pRecordIdValueTo
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 = {};
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")
.from("COMMUNICATION")
.where("COMMUNICATION.CONTACT_ID", pSourceContactId)
.arrayColumn();
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]);
}
var sourceStandard = newSelect("CONTACT.ADDRESS_ID")
.from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId)
.cell();
newWhere("CONTACT.CONTACTID", pTargetContactId).updateFields({"ADDRESS_ID": sourceStandard});
}
if(exclude)
{
newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId).deleteData(true, "COMMUNICATION"); //delete the address of the sourceContact
return ["RemoveThisItem"]
}
var updateCondition = newWhere([tableName, columnName], pSourceContactId).andIfSet(additionalCondition);
//don't use communications that the target already has
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
{
return newWhere([tableName, columnName], pSourceContactId, undefined, undefined, pAlias)
.andIfSet(additionalCondition)
.buildUpdateStatement(updateValues, tableName)
}
updateStatements.set(alias, [updateStatement]);
});
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
*
* @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[
["AB_APPOINTMENTLINK", "OBJECT_ROWID", ""],
......@@ -1284,22 +1254,12 @@ _DuplicateScannerUtils._getMergeUpdateTableInfosCurrentAlias = function()
["DSGVOINFO", "CONTACT_ID", ""],
["TIMETRACKING", "CONTACT_ID", ""],
["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
*
......
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