1

In my org we have implemented Duplicate matching rules for leads. We have the Lead object being referenced in 2 custom objects (Enquiry__c & Needs_Analysis__c , simple lookup relationship).

In the below apex class, I am trying to update the reference of the lead with the surviving lead record. The "Enquiry" record's lead id gets updated, however, for the "Needs Analysis" record it does not change.

Am i doing something wrong in this piece of code? I am new to apex so not really sure how to go about debugging it.

public class LeadDuplicateTriggerHandler{

    @InvocableMethod(label='Handle Duplicate Leads' description='Todo')
    public static void handleDupLeads(List<DuplicateRecordItem> params) {
        Set<Id> groupIds = SObjectUtils.getIDFieldValues(params, DuplicateRecordItem.DuplicateRecordSetId);
        Map<Id, DuplicateRecordSet> duplicates = 
            new Map<Id, DuplicateRecordSet>([SELECT Id, (SELECT RecordId FROM DuplicateRecordItems) FROM DuplicateRecordSet WHERE Id IN :groupIds]);

        Map<Id, Lead> leads = LeadFinder.getLeadsWithAttachmentsByDuplicateRecordSetIds(groupIds);

        Enquiry__c[] enquiries = new Enquiry__c[] {};
        Lead[] duplicateLeads = new Lead[] {};
        Lead[] masterLeads = new Lead[] {};
        Case[] cases = new Case[] {};
        Needs_Analysis__c[] NA = new Needs_Analysis__c[] {};

        for (DuplicateRecordSet entry : duplicates.values()) {
            //calculate master
            Lead master = leads.get(entry.DuplicateRecordItems[0].RecordId);

            for (DuplicateRecordItem item : entry.DuplicateRecordItems) {
                Lead lead = leads.get(item.recordId);
                if (lead.CreatedDate < master.CreatedDate) {
                    master = lead;
                    if (String.isEmpty(master.Projects_Interested_in__c)) master.Projects_Interested_in__c = '';
                }
            }

            for (DuplicateRecordItem item : entry.DuplicateRecordItems) {
                if (item.RecordId != master.Id) {
                    Lead lead = leads.get(item.recordId);
                    if (String.isEmpty(master.SitecoreVisitorId__c) && String.isEmpty(lead.SitecoreVisitorId__c) ) master.SitecoreVisitorId__c = lead.SitecoreVisitorId__c; 
                    //copy Enquiries to master Lead from duplicate Lead
                    //populate Lead fields from updated enquiries
                    for (Enquiry__c e : lead.Enquiries__r) {
                        e.Lead__c = master.Id;
                        if (e.Project__r != null && String.isNotEmpty(e.Project__r.Name) && !master.Projects_Interested_in__c.contains(e.Project__r.Name)) master.Projects_Interested_in__c += ';' + e.Project__r.Name;//TODO refine logic
                    }
                    enquiries.addAll(lead.Enquiries__r);
                    duplicateLeads.add(lead);

                    for (Case sCase : lead.Cases__r) {
                        sCase.Lead__c = master.Id;
                    }

                    cases.addAll(lead.Cases__r);

                    for (Needs_Analysis__c sNA : lead.Needs_Analysis__r) {
                        sNA.Lead__c = master.Id;
                    }

                    NA.addAll(lead.Needs_Analysis__r);
                }
                else {
                    //copy values for Enquiry linked to master lead
                    for (Enquiry__c e : master.Enquiries__r) {
                        if (e.Project__r != null && String.isNotEmpty(e.Project__r.Name) && !master.Projects_Interested_in__c.contains(e.Project__r.Name)) master.Projects_Interested_in__c += ';' + e.Project__r.Name;//TODO refine logic
                    }
                }
            }
            masterLeads.add(master);

        }

        try {//TODO use Database. with opt=false; consider trigger byPass

            update enquiries;

            //Important: we delete duplicate first, after that update master in order to avoid conflicts with duplicates
            if(duplicateLeads.size() > 0){
                system.debug('CallUpdateCaseOnLeadDedupe:::');
                ManualDataFlowService.UpdateCaseOnLeadDedupe(duplicateLeads);
                ManualDataFlowService.CreateCaseOnEnquiryCreation(enquiries);
                update cases;
            }
            update NA;
            delete duplicateLeads;
            update masterLeads;

        }
        catch(Exception e) {
            ApplicationLogUtility.logError(LeadDuplicateTriggerHandler.class, 'handleDupLeads', e, e.getMessage(), null, null, null, null, null);
        }

    }

}
1

The Needs_Analysis__c object records aren't being updated because your code doesn't reference the object. You need to take the section of code below and essentially duplicate it with the appropriate references to the Needs_Analysis__c object. When you're finished, you can combine the results from the two loops and perform one DML operation on all the leads in one single call.

        for (DuplicateRecordItem item : entry.DuplicateRecordItems) {
            if (item.RecordId != master.Id) {
                Lead lead = leads.get(item.recordId);
                if (String.isEmpty(master.SitecoreVisitorId__c) && String.isEmpty(lead.SitecoreVisitorId__c) ) master.SitecoreVisitorId__c = lead.SitecoreVisitorId__c; 
                //copy Enquiries to master Lead from duplicate Lead
                //populate Lead fields from updated enquiries
                for (Enquiry__c e : lead.Enquiries__r) {
                    e.Lead__c = master.Id;
                    if (e.Project__r != null && String.isNotEmpty(e.Project__r.Name) && !master.Projects_Interested_in__c.contains(e.Project__r.Name)) master.Projects_Interested_in__c += ';' + e.Project__r.Name;//TODO refine logic
                }
                enquiries.addAll(lead.Enquiries__r);
                duplicateLeads.add(lead);

                for (Case sCase : lead.Cases__r) {
                    sCase.Lead__c = master.Id;
                }

                cases.addAll(lead.Cases__r);

                for (Needs_Analysis__c sNA : lead.Needs_Analysis__r) {
                    sNA.Lead__c = master.Id;
                }

                NA.addAll(lead.Needs_Analysis__r);
            }
            else {
                //copy values for Enquiry linked to master lead
                for (Enquiry__c e : master.Enquiries__r) {
                    if (e.Project__r != null && String.isNotEmpty(e.Project__r.Name) && !master.Projects_Interested_in__c.contains(e.Project__r.Name)) master.Projects_Interested_in__c += ';' + e.Project__r.Name;//TODO refine logic
                }
            }
        }
        masterLeads.add(master);

    }

What I hope you'll understand is that leads in the enquiry__c object are of a different recordType or at a different stage in their processing than the leads in the needs_analysis__c object. For that reason, I wouldn't expect lead records in the two objects to overlap. The objects are being used as a means of separating leads in your company's workflow processing.

Edit - in response to comments

What I think you're missing here is that from your description, both the Enquiry__c and Needs_Analysis__c objects have either lookup relationships or are are in M-D relationships with Lead. As such, there's a reference link on records from both of those objects to the source Lead records.

When you dedupe or "merge" a Lead record, you also need to dedupe or merge the corresponding record on both of the related objects; not just one of them. When you only do this on the Enquiry__c object, you're leaving orphaned records on the Needs_Analysis__c object. So, to do this correctly, you need to run the same logic on both objects. I don't know about the work that's done on the related objects, but I suspect you have no way of knowing whether they're kept in sync. There may be some records that exist in one object that aren't in the other. Regardless of whether there are or aren't, the records/links in both objects will need to be updated/deduped at the same time Leads are deduped.

  • Thanks crmprogdev for your response. Functionally how this works is when a person enquiries on the company website, an enquiry and a corresponding lead gets created in Salesforce. The call center folks then speak to the client and update their needs under the needs analysis object for the same lead. Both enquiry & need analysis are displayed as related lists under the same lead. This is the reason why the leads overlap for both the objects. In such a case shouldn't the single loop suffice for both the objects since they both refer to the same lead? – ReM83 Jul 6 '18 at 0:16
  • @ReM83 See my edited answer. – crmprogdev Jul 6 '18 at 13:49
  • I have the below piece of code for updating the reference on the Needs analysis as well which is identical to that for Enquiries, but it doesn't work. for (Needs_Analysis__c sNA : lead.Needs_Analysis__r) { sNA.Lead__c = master.Id; } NA.addAll(lead.Needs_Analysis__r); – ReM83 Jul 10 '18 at 0:13
  • @ReM83 Please use the edit button/link at the bottom left of your question to update the code so I can see how you're trying to incorporate this code. Showing it to me in a comment gives me no context to be able to help you. – crmprogdev Jul 10 '18 at 14:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.