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

1065734 Duplicate contact merge

parent bef7d472
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,7 @@ import("system.vars");
import("DuplicateScanner_lib");
var contactId = vars.get("$field.CONTACTID");
DuplicateScannerUtils.DeleteCachedDuplicate(contactId);
DuplicateScannerUtils.deleteCachedDuplicate(contactId);
new AttributeRelationQuery(contactId, null, ContextUtils.getCurrentContextId())
.deleteAllAttributes();
......
......@@ -7,14 +7,14 @@ let sourceContactId = vars.get("$param.DuplicateCurrentContactId_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.MergeOrganisation(sourceContactId, targetContactId);
let mergeSuccess = DuplicateScannerUtils.mergeOrganisation(sourceContactId, targetContactId);
if(mergeSuccess)
{
let currentContactId = EmployeeUtils.getCurrentContactId();
if(currentContactId == null)
currentContactId = "";
DuplicateScannerUtils.CreateMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Organisation");
DuplicateScannerUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Organisation");
neon.openContext("Organisation", "OrganisationMain_view", [targetContactId], neon.OPERATINGSTATE_VIEW, null)
}
\ No newline at end of file
......@@ -8,13 +8,13 @@ let targetContactId = vars.get("$param.DuplicateCurrentContactId_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.MergeOrganisation(sourceContactId, targetContactId);
let mergeSuccess = DuplicateScannerUtils.mergeOrganisation(sourceContactId, targetContactId);
if(mergeSuccess)
{
let currentContactId = EmployeeUtils.getCurrentContactId();
if(currentContactId == null)
currentContactId = "";
DuplicateScannerUtils.CreateMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Organisation");
DuplicateScannerUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Organisation");
neon.refreshAll();
}
\ No newline at end of file
......@@ -7,7 +7,7 @@ import("Attribute_lib");
// TODO: enable when duplicate-module is finalized
let contactId = vars.get("$field.CONTACTID");
DuplicateScannerUtils.DeleteCachedDuplicate(contactId);
DuplicateScannerUtils.deleteCachedDuplicate(contactId);
new AttributeRelationQuery(contactId, null, ContextUtils.getCurrentContextId())
.deleteAllAttributes();
......
......@@ -8,7 +8,7 @@ var sourceContactId = vars.get("$param.DuplicateCurrentContactId_param");
var targetContactId = vars.get("$sys.selection")[0];
//todo the actual merge ought to happen in a separate view where the contact infos can be merged manually by the user.
var mergeSuccess = DuplicateScannerUtils.MergePerson(sourceContactId, targetContactId);
var mergeSuccess = DuplicateScannerUtils.mergePerson(sourceContactId, targetContactId);
if(mergeSuccess)
{
......@@ -21,7 +21,7 @@ if(mergeSuccess)
var currentContactId = EmployeeUtils.getCurrentContactId();
if(currentContactId == null)
currentContactId = "";
DuplicateScannerUtils.CreateMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Person");
DuplicateScannerUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Person");
neon.openContext("Person", "PersonMain_view", [targetContactId], neon.OPERATINGSTATE_VIEW, null)
}
\ No newline at end of file
......@@ -12,7 +12,7 @@ var sourceContactIdArray = vars.get("$sys.selection");
var sourceContactId = sourceContactIdArray[0];
//todo the actual merge ought to happen in a separate view where the contact infos can be merged manually by the user.
var mergeSuccess = DuplicateScannerUtils.MergePerson(sourceContactId, targetContactId);
var mergeSuccess = DuplicateScannerUtils.mergePerson(sourceContactId, targetContactId);
if(mergeSuccess)
{
......@@ -25,7 +25,7 @@ if(mergeSuccess)
var currentContactId = EmployeeUtils.getCurrentContactId();
if(currentContactId == null)
currentContactId = "";
DuplicateScannerUtils.CreateMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Person");
DuplicateScannerUtils.createMergeSuccessActivity(sourceContactId, targetContactId, currentContactId, "Person");
// openContext due to the fact, that openContext will lead to an error 'due'cause it's trying to load the already opened preview
// of the duplicateContact which just got deleted = nullpointException
neon.openContext("Person", null, [targetContactId], neon.OPERATINGSTATE_VIEW, null, null);
......
......@@ -6,7 +6,7 @@ import("system.vars");
import("DuplicateScanner_lib");
var contactId = vars.get("$field.CONTACTID");
DuplicateScannerUtils.DeleteCachedDuplicate(contactId);
DuplicateScannerUtils.deleteCachedDuplicate(contactId);
new AttributeRelationQuery(contactId, null, ContextUtils.getCurrentContextId())
.deleteAllAttributes();
......
......@@ -13,6 +13,8 @@ import("system.db");
import("system.entities");
import("Sql_lib");
import("system.indexsearch");
import("Communication_lib");
import("Attribute_lib");
/**
* Methods for duplicate scanning.
......@@ -48,7 +50,7 @@ DuplicateScannerUtils.loadFilters = function(pFilterName, pTargetEntity)
*
* @param {String} pDuplicateId Id of the duplicate to delete
*/
DuplicateScannerUtils.DeleteCachedDuplicate = function(pDuplicateId)
DuplicateScannerUtils.deleteCachedDuplicate = function(pDuplicateId)
{
var [countDuplicatesInClusterWithoutParameterId, clusterId] = newSelect("count(ID), CLUSTERID")
.from("DUPLICATECLUSTERS")
......@@ -615,7 +617,7 @@ DuplicateScannerUtils.TranslateEntityToIndexFields = function(pEntityName, pEnti
* @param {String} pTargetContactId The contact in which the source gets integrated
* @returns {Boolean} if the merge was sucessful
*/
DuplicateScannerUtils.MergePerson = function(pSourceContactId, pTargetContactId)
DuplicateScannerUtils.mergePerson = function(pSourceContactId, pTargetContactId)
{
var sourcePersonId = newSelect("PERSON_ID")
.from("CONTACT")
......@@ -645,12 +647,12 @@ DuplicateScannerUtils.MergePerson = function(pSourceContactId, pTargetContactId)
});
var deletedRows = db.deletes(deleteStatements)
DuplicateScannerUtils.DeleteCachedDuplicate(pSourceContactId);
DuplicateScannerUtils.deleteCachedDuplicate(pSourceContactId);
return ((isLinkedDataUpdated || isParticipantsUpdated) && deletedRows > 0);
}
DuplicateScannerUtils.CreateMergeSuccessActivity = function(pSourceContactId, pTargetContactId, pCurrentContactId, pContext)
DuplicateScannerUtils.createMergeSuccessActivity = function(pSourceContactId, pTargetContactId, pCurrentContactId, pContext)
{
var activityDataForInsert = {
subject: translate.withArguments("A %0 record has been merged", [pContext]),
......@@ -664,12 +666,8 @@ DuplicateScannerUtils.CreateMergeSuccessActivity = function(pSourceContactId, pT
return ActivityUtils.insertNewActivity(activityDataForInsert, activityLinks, null, db.getCurrentAlias());
}
DuplicateScannerUtils.MergeOrganisation = function(pSourceContactId, pTargetContactId)
DuplicateScannerUtils.mergeOrganisation = function(pSourceContactId, pTargetContactId)
{
let updateStatementsCurrentAlias = [];
let updateStatementsSystemAlias = [];
let deleteStatements = [];
var sourceOrganisationId = newSelect("ORGANISATION_ID")
.from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId)
......@@ -692,7 +690,7 @@ DuplicateScannerUtils.MergeOrganisation = function(pSourceContactId, pTargetCont
});
var deletedRows = db.deletes(deleteStatements)
DuplicateScannerUtils.DeleteCachedDuplicate(pSourceContactId);
DuplicateScannerUtils.deleteCachedDuplicate(pSourceContactId);
return ((isLinkedDataUpdated || isParticipantsUpdated) && deletedRows >= 2);
}
......@@ -842,11 +840,6 @@ _DuplicateScannerUtils._loadEntityFieldsFromFieldConfigs = function(pEntityField
return fieldNames;
}
_DuplicateScannerUtils._buildUpdateResetStandardCommunications = function(pSourceContactId)
{
return newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId).buildUpdateStatement({"ISSTANDARD" : "0"});
}
/*
* Gets the Pattern for the scanner
* A pattern usually contains placeholders in the style of "{entityFieldName]"
......@@ -1160,47 +1153,63 @@ _DuplicateScannerUtils._getIgnoreSourceRecordPattern = function(pRecordIdValueTo
_DuplicateScannerUtils._migrateLinkedContactData = function (pSourceContactId, pTargetContactId)
{
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])
var setStandardsStatements = [];
var [standardPhone, standardMail, standardAddressId] = newSelect([
"(" + CommUtil.getStandardSubSqlPhone() + ")",
"(" +CommUtil.getStandardSubSqlMail() + ")",
"CONTACT.ADDRESS_ID"
])
.from("CONTACT")
.where("CONTACT.CONTACTID", pTargetContactId)
.arrayRow();
//if the targetContact already has a standard phone comm, set the comm from the sourceContact as not standard
if (standardPhone)
{
setStandardsStatements.push(
newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId)
.and("COMMUNICATION.MEDIUM_ID", CommUtil.getMediumIdsByCategory("PHONE"), SqlBuilder.IN())
.buildUpdateStatement({"ISSTANDARD" : "0"})
);
}
if (standardMail)
{
setStandardsStatements.push(
newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId)
.and("COMMUNICATION.MEDIUM_ID", CommUtil.getMediumIdsByCategory("EMAIL"), SqlBuilder.IN())
.buildUpdateStatement({"ISSTANDARD" : "0"})
);
}
//set the standardaddress of the sourceContact as standard of the targetContact if it doesn't have one set yet
if(!standardAddressId)
{
var sourceStandard = newSelect("CONTACT.ADDRESS_ID")
.from("CONTACT")
.where("CONTACT.CONTACTID", pSourceContactId)
.cell();
setStandardsStatements.push(newWhere("CONTACT.CONTACTID", pTargetContactId).buildUpdateStatement({"ADDRESS_ID": sourceStandard}));
}
updateStatements.set(currentAlias, setStandardsStatements);
_DuplicateScannerUtils._getLinkedTableInfos(pTargetContactId).forEach(function ([tableName, columnName, additionalCondition, dbAlias])
{
if (!alias)
alias = currentAlias;
if (!dbAlias)
dbAlias = currentAlias;
if (!updateStatements.has(dbAlias))
updateStatements.set(dbAlias, []);
var statements = updateStatements.get(dbAlias);
var updateValues = {};
updateValues[columnName] = pTargetContactId;
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).updateFields({"ADDRESS_ID": sourceStandard});
}
var updateCondition = newWhere([tableName, columnName], pSourceContactId).andIfSet(additionalCondition);
var updateCondition = new SqlBuilder(dbAlias).where([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
updateStatements.set(alias, [updateStatement]);
//push must be used here to keep the reference
statements.push(updateCondition.buildUpdateStatement(updateValues, tableName));
});
var totalChanges = 0;
......@@ -1211,6 +1220,7 @@ _DuplicateScannerUtils._migrateLinkedContactData = function (pSourceContactId, p
});
totalChanges += newWhere("COMMUNICATION.CONTACT_ID", pSourceContactId).deleteData(); //delete leftover communications from the source contact
totalChanges += new AttributeRelationQuery(pSourceContactId).deleteAllAttributes(); //delete leftover attributes
return totalChanges > 0;
}
......@@ -1220,44 +1230,63 @@ _DuplicateScannerUtils._migrateLinkedContactData = function (pSourceContactId, p
*
* @returns {String[[]]} Array in the format [TableName, ContactIdColumnName, AdditionalCondition, alias]
*/
_DuplicateScannerUtils._getLinkedTableInfos = function()
_DuplicateScannerUtils._getLinkedTableInfos = function(pTargetContactId)
{
//don't use communications that the target already has
var communicationDedupCondition = newWhere(null, newSelect("targetComm.COMMUNICATIONID")
.from("COMMUNICATION", "targetComm")
.where(["COMMUNICATION", "CONTACT_ID", "targetComm"], pTargetContactId)
.and("targetComm.ADDR = COMMUNICATION.ADDR"),
SqlBuilder.NOT_EXISTS());
//don't use attributes that the contact already has
var targetAttributeSubselect = newSelect("targetAttr.AB_ATTRIBUTERELATIONID")
.from("AB_ATTRIBUTERELATION", "targetAttr")
.where(["AB_ATTRIBUTERELATION", "OBJECT_ROWID", "targetAttr"], pTargetContactId)
.and("targetAttr.AB_ATTRIBUTE_ID = AB_ATTRIBUTERELATION.AB_ATTRIBUTE_ID");
AttributeTypeUtil.getAllDatabaseFields().forEach(function (dbColumn)
{
targetAttributeSubselect.and(newWhere("targetAttr." + dbColumn + " = AB_ATTRIBUTERELATION." + dbColumn)
.or("targetAttr." + dbColumn + " is null"));
});
return[
["AB_APPOINTMENTLINK", "OBJECT_ROWID", ""],
["AB_CTILOG", "CONTACT_ID", ""],
["AB_OBJECTRELATION", "AB_OBJECTRELATIONID", ""],
["AB_OBJECTRELATION", "OBJECT1_ROWID", ""],
["AB_OBJECTRELATION", "OBJECT2_ROWID", ""],
["AB_LOGHISTORY", "TABLENAMEID", ""],
["ADDRESS", "CONTACT_ID", ""],
["BULKMAILRECIPIENT", "CONTACT_ID", ""],
["BULKMAIL", "TESTING_CONTACT_ID", ""],
["CAMPAIGN", "EMPLOYEE_CONTACT_ID", ""],
["CAMPAIGNSTEP", "EMPLOYEE_CONTACT_ID", ""],
["COMMRESTRICTION", "CONTACT_ID", ""],
["COMMRESTRICTION", "EMPLOYEE_INVOLVED", ""],
["COMMUNICATION", "CONTACT_ID", ""],
["COMPETITION", "CONTACT_ID", ""],
["CONTRACT", "CONTACT_ID", ""],
["LETTERRECIPIENT", "CONTACT_ID", ""],
["OBJECTMEMBER", "CONTACT_ID", ""],
["OFFER", "CONTACT_ID", ""],
["PRODUCT", "CONTACT_ID", ""],
["PRODUCTPRICE", "CONTACT_ID", ""],
["SALESORDER", "CONTACT_ID", ""],
["SALESPROJECT", "CONTACT_ID", ""],
["TASK", "REQUESTOR_CONTACT_ID", ""],
["TASK", "EDITOR_CONTACT_ID", ""],
["TASKLINK", "OBJECT_ROWID", ""],
["ACTIVITY", "RESPONSIBLE", ""],
["DSGVO", "CONTACT_ID", ""],
["DSGVOINFO", "CONTACT_ID", ""],
["TIMETRACKING", "CONTACT_ID", ""],
["ACTIVITYLINK", "OBJECT_ROWID", ""],
["AB_ATTRIBUTERELATION", "OBJECT_ROWID", ""],
["ASYS_CALENDARLINK", "DBID", "", SqlUtils.getSystemAlias()]
];
["AB_APPOINTMENTLINK", "OBJECT_ROWID"],
["AB_CTILOG", "CONTACT_ID"],
["AB_OBJECTRELATION", "AB_OBJECTRELATIONID"],
["AB_OBJECTRELATION", "OBJECT1_ROWID"],
["AB_OBJECTRELATION", "OBJECT2_ROWID"],
["AB_LOGHISTORY", "TABLENAMEID"],
["ADDRESS", "CONTACT_ID"],
["BULKMAILRECIPIENT", "CONTACT_ID"],
["BULKMAIL", "TESTING_CONTACT_ID"],
["CAMPAIGN", "EMPLOYEE_CONTACT_ID"],
["CAMPAIGNSTEP", "EMPLOYEE_CONTACT_ID"],
["COMMRESTRICTION", "CONTACT_ID"],
["COMMRESTRICTION", "EMPLOYEE_INVOLVED"],
["COMMUNICATION", "CONTACT_ID", communicationDedupCondition],
["COMPETITION", "CONTACT_ID"],
["CONTRACT", "CONTACT_ID"],
["LETTERRECIPIENT", "CONTACT_ID"],
["OBJECTMEMBER", "CONTACT_ID"],
["OFFER", "CONTACT_ID"],
["PRODUCT", "CONTACT_ID"],
["PRODUCTPRICE", "CONTACT_ID"],
["SALESORDER", "CONTACT_ID"],
["SALESPROJECT", "CONTACT_ID"],
["TASK", "REQUESTOR_CONTACT_ID"],
["TASK", "EDITOR_CONTACT_ID"],
["TASKLINK", "OBJECT_ROWID"],
["ACTIVITY", "RESPONSIBLE"],
["DSGVO", "CONTACT_ID"],
["DSGVOINFO", "CONTACT_ID"],
["TIMETRACKING", "CONTACT_ID"],
["ACTIVITYLINK", "OBJECT_ROWID"],
["AB_ATTRIBUTERELATION", "OBJECT_ROWID", newWhere(null, targetAttributeSubselect, SqlBuilder.NOT_EXISTS())],
["ASYS_CALENDARLINK", "DBID", "", SqlUtils.getSystemAlias()]
];
}
/*
......
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