2

I'm working on a requirement where I need to stop contact merge if the child record associated with both of them are same.

I have written a before delete trigger on Contact, but I'm not getting MasterRecordId in before delete as it is not available at that time.

In My after delete trigger, I'm getting the MasterRecordId but by that time my child records are already associated with Master record. so I'm not able to get any child record in after delete.

How can I prevent the merge if associated child will create duplicates on merging?

Set<Id> masterRecordIdSet = new Set<Id>();
        Set<Id> allContactIdSet = new Set<Id>();
        for(Contact con : oldList){
            if(con.MasterRecordId != null){
                masterRecordIdSet.add(con.MasterRecordId);
                allContactIdSet.add(con.Id);
                allContactIdSet.add(con.MasterRecordId);
            }
        }
        
        
        Map<Id,List<Custom__c>> customMemListPerContactIdMap = new Map<Id,List<Custom__c>>();
        for(Custom__c corres : [SELECT Id, Contact__c,Dublicate__c FROM Custom__c WHERE Contact__c IN : allContactIdSet]){
            
            if(customMemListPerContactIdMap.containsKey(corres.Contact__c)){
                customMemListPerContactIdMap.get(corres.Contact__c).add(corres);
            }else{
                customMemListPerContactIdMap.put(corres.Contact__c,new List<Custom__c>{corres});
            }
        }
        
        system.debug('>>> customMemListPerContactIdMap... '+customMemListPerContactIdMap);
        
        
        for(Contact con : oldList){
            if(customMemListPerContactIdMap.containsKey(con.Id)){
                for(Custom__c corr : customMemListPerContactIdMap.get(con.Id)){
                    if(customMemListPerContactIdMap.containsKey(con.MasterRecordId)){
                        for(Custom__c Corres : customMemListPerContactIdMap.get(con.MasterRecordId)){
                            if(corr.Dublicate__c == masterCorres.Dublicate__c){
                                con.addError('Merging these contacts will create duplicate Custom records');
                            }
                        }
                    }
                }
            }
        }

1 Answer 1

3

You've outlined the problem well

  • In before delete trigger, you have access to the child records but no MasterRecordId for the merging operation
  • In after delete trigger, the child records have already merged and you have access to MasterRecordId

As such, you'll need to pass over (or persist) information between before and after delete with a static map of contacts and the child records you're interested in to perform the check when you do have access to MasterRecordId.

For this, as noted in Static and Instance Methods, Variables, and Initialization Code, you'll want to define this static variable in a trigger handler class

A static variable defined in a trigger doesn't retain its value between different trigger contexts within the same transaction, such as between before insert and after insert invocations. Instead, define the static variables in a class so that the trigger can access these class member variables and check their static values.

//define static variable to store information between before + after delete
private static Map<Id,List<Custom__c>> customMemListPerContactIdMap = new Map<Id,List<Custom__c>>();

In your before delete method, do what you're already doing:

//method in before delete trigger - store information from before trigger
for(Custom__c corres : [SELECT Id, Contact__c,Dublicate__c FROM Custom__c WHERE Contact__c IN : allContactIdSet]){
    if(customMemListPerContactIdMap != null && customMemListPerContactIdMap.containsKey(corres.Contact__c)){
        customMemListPerContactIdMap.get(corres.Contact__c).add(corres);
    } else {
        customMemListPerContactIdMap.put(corres.Contact__c,new List<Custom__c>{corres});
    }
}

In your separate method for after delete, you would then be able to leverage the information you stored in the before trigger and MasterRecordId as you already provided in the question (I did not change this code). For the addError in after delete, make sure you're leveraging Trigger.old.

//in your after delete method
for(Contact con : oldList){
    if(customMemListPerContactIdMap.containsKey(con.Id)){
        for(Custom__c corr : customMemListPerContactIdMap.get(con.Id)){
            if(customMemListPerContactIdMap.containsKey(con.MasterRecordId)){
                for(Custom__c Corres : customMemListPerContactIdMap.get(con.MasterRecordId)){
                    if(corr.Dublicate__c == masterCorres.Dublicate__c){
                        con.addError('Merging these contacts will create duplicate Custom records');
                    }
                }
            }
        }
    }
}
3
  • but throwing the error in after delete, will it work? Commented Feb 22, 2022 at 13:18
  • Yes. You will just need to make sure to use Trigger.old or Trigger.oldMap which I believe you are based on your naming convention (oldList). Commented Feb 22, 2022 at 13:24
  • Thanks, It worked Commented Feb 23, 2022 at 12:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .