0

My organization has a requirement that prevents two leads from being merged together when they each have a different value in a certain field (named UUID__c). We created an after delete trigger that we want to fire on merges that informs the user they cannot complete the merge when the two records have different values in the UUID__c field. However, instead of the trigger showing our custom error message, it states that the operation cannot be completed because a record has been deleted. In actuality, this is not the case as the trigger prevented the merge from completing and both records still exist.

Our problem revolves around posting the error message upon validation. throw new MergeException(MULIPLE_UUID_ERROR) never ends up firing. Any help or advice would be very welcome. The pertinent code that gets called in a trigger context is below.

public with sharing class LeadMergeValidator {
    public static final String MULTIPLE_UUID_ERROR = 'Cannot merge leads when more than one record has a different UUID';

    @TestVisible static LeadMergeValidator mock;

    public static LeadMergeValidator construct(){
        if( Test.isRunningTest() && mock != null ){
            return mock;
        } else{
            return new LeadMergeValidator();
        }
    }

    public void validateMergedLeads( Set<Id> mergedLeadIds ) {
        List<Lead> mergedLeads = [Select Id,
            UUID__c,
            MasterRecord.UUID__c,
            ParentAccount__c,
            MasterRecord.ParentAccount__c
        FROM Lead
        WHERE
            Id IN :mergedLeadIds
        ALL ROWS
        ];
        for( Lead l : mergedLeads ){
            if( !String.isEmpty(l.UUID__c)
                && !String.isEmpty(l.MasterRecord.UUID__c)
                && l.UUID__c != l.MasterRecord.UUID__c ){
                throw new MergeException(MULTIPLE_UUID_ERROR);
            }
        }
    }

    public class MergeException extends Exception{}
}

1 Answer 1

1

You shouldn't throw an exception like that; it's sufficient to just add an error to Trigger.old or Trigger.oldMap:

public void validateMergedLeads( Set<Id> mergedLeadIds ) {
    for(Lead record: [SELECT MasterRecord.UUID__c, UUID__c FROM Lead 
            WHERE   Id = :mergedLeadIds AND 
                    MasterRecordId <> NULL AND 
                    UUID__c <> NULL AND
                    MasterRecord.UUID__c <> NULL
            ALL ROWS]) {
        if(record.MasterRecord.UUID__c <> record.UUID__c) {
            Trigger.oldMap.get(record.Id).addError(MULTIPLE_UUID_ERROR);
        }
    }

Note that you need a reference to Trigger.old; if you're using a framework design, you might want to pass that in as a second parameter:

public void validateMergedLeads( Set<Id> mergedLeadIds, Map<Id, Lead> oldMap) {
3
  • Thank you so much! This worked. When would it be advisable to throw an exception versus adding an error? Dealing with classes versus triggers?
    – grimsvotn
    May 15, 2018 at 16:00
  • @grimsvotn Trigger contexts should never throw an exception, as it breaks the ability to use the partial update API. Anything do to with asynchronous code will probably want to prefer exceptions, because it allows errors to be emailed to developers and appear in the top-level logs. Anything to do with Visualforce should not throw an exception, as it destroys the view state in the process. Anything to do in Lightning should use AuraHandledException (but no others) to communicate errors back to the client.
    – sfdcfox
    May 15, 2018 at 16:05
  • @grimsvotn But in all cases, you should avoid ever having the guardable exceptions from happening. For example, if you get a NullPointerException, your code is poorly written and needs to be fixed. There's precious few times when you actually need to use exceptions, and you should avoid them in normal cases, as they're incredibly CPU expensive, especially if you put them in a loop and try-catch them.
    – sfdcfox
    May 15, 2018 at 16:08

You must log in to answer this question.

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