+ Start a Discussion
Patrick G. BrownPatrick G. Brown 

Interesting Duplicate ID In List Scenario - Need Help

I have an interesting scenario where I need to update a many-to-many record (Campaign Members) on Leads associated with Campaigns and I need the trigger to refer to values in both the Lead and Campaign objects.

Here's my scenario:  I need to maintain a status value on the Campaign Member record (Campaign_Lead_Status__c) and when the Campaign Member is updated, push this value to the Status field on the Lead.  This trigger should only fire when the Campaign is Active.  If the Campaign isn't active, I don't want this trigger to fire.

Here is what I think is happening, but I'm not sure:  To make this trigger work, I need to make one list of Campaign Members related to Leads (for my update) and another list of Campaign Members related to Campaigns (to check for IsActive).  

When I update one Campaign Member at a time, this trigger works perfectly.  But if I do any type of bulk process such as update Campaign Members via scheduled batch, use DataLoader or use the Bulk update/import process for Leads, I get the dreaded "caused by: System.ListException: Duplicate id in list:" error message.

Below is my code.  Does anyone have a good idea to solve for this?  Do I need to try to create only one list somehow?
 
//////////////////////START - CAMPAIGN MEMBER - SYNC LEAD STATUS//////////////////////


//Create Set of Leads and make list

    if(Trigger.IsAfter){
        if(Trigger.IsUpdate){
        
        Set<Id> leadIds = new Set<Id>();
        for (CampaignMember cml: Trigger.new){
            leadIds.add(cml.LeadId);
        }
            Map<Id, Lead> LeadMap = new Map<Id, Lead>([SELECT Id, Current_Campaign__c, Status 
                                                        FROM Lead 
                                                        WHERE Id IN :LeadIDs]);
            List<Lead> leadToUpdate = new List<Lead>();
            Lead associatedLead;
            
//End Create Set of Leads and make list            
            
//Below, create a list of Campaigns to look and see if IsActive == FALSE

//Create Set of Campaigns and make list 

        Set<Id> campaignIds = new Set<Id>();
        for (CampaignMember cmc: Trigger.new){
            campaignIds.add(cmc.CampaignId);
        }
        Map<Id, Campaign> CampaignMap = new Map<Id, Campaign>([SELECT Id, Name, IsActive 
                                                                FROM Campaign 
                                                                WHERE Id IN :campaignIds]);
        List<Campaign> campaignToCheck = new List<Campaign>();
        Campaign associatedCampaign;
    
            for (CampaignMember cmc: Trigger.new){
                if(CampaignMap.containsKey(cmc.CampaignId)){
                associatedCampaign = CampaignMap.get(cmc.CampaignId);
                    if(associatedCampaign.IsActive==FALSE){
                    //do nothing    
                    }
                    else if (associatedCampaign.IsActive==TRUE){
            
//End Create Set of Campaigns and make list

//For List of CampaignMembers, check CampaignLeadStatus and update Lead Status

            for (CampaignMember cml: Trigger.new){
                if(LeadMap.containsKey(cml.LeadId)){
                    associatedLead = LeadMap.get(cml.LeadId);
                
        
                    if(cml.Campaign_Lead_Status__c=='Resting'){
                        associatedLead.Status = 'Resting';
                        leadToUpdate.add(associatedLead);
                    }
                        
                    
                    if(cml.Campaign_Lead_Status__c=='In Campaign'){
                         associatedLead.Status = 'In Campaign';
                         leadToUpdate.add(associatedLead);
                    }
                         
                         
                    if(cml.Campaign_Lead_Status__c=='Untouched'){
                         associatedLead.Status = 'In Campaign';
                         leadToUpdate.add(associatedLead);
                    }

                    
                    if(cml.Campaign_Lead_Status__c=='24H Call Back'){
                         associatedLead.Status = '24H Call Back';
                         leadToUpdate.add(associatedLead);
                    }

                    
                    if(cml.Campaign_Lead_Status__c=='Qualifying'){
                         associatedLead.Status = 'Qualifying';
                         leadToUpdate.add(associatedLead);
                    }
                    
                    
                    if(cml.Campaign_Lead_Status__c=='Disqualified'){
                         associatedLead.Status = 'Disqualified';
                         leadToUpdate.add(associatedLead);
                    }

                    
                    if(cml.Campaign_Lead_Status__c=='Pre-Contracting'){
                         associatedLead.Status = 'Pre-Contracting';
                         leadToUpdate.add(associatedLead);
                    }

                    
                    if(cml.Campaign_Lead_Status__c=='Contracting'){
                         associatedLead.Status = 'Contracting';
                         leadToUpdate.add(associatedLead);
                    }

                } 
            
            }   
            update leadToUpdate;
                    }
                }
                
            }
        }
    
    }
    
//////////////////////END - CAMPAIGN MEMBER - SYNC LEAD STATUS//////////////////////

} //end trigger

//10-15-12:44 am
//Restore Point
//When trying to bulk update campaign members of any size via data loader, receiving error 
//campaignMemberControl: execution of AfterUpdate caused by: System.ListException: Duplicate id in list: 00Q1b000001OvMIEA0
//Trigger.campaignMemberControl: line 226, column 1

 
AshishkAshishk
Hi Patrick,

Why you need another for loop inside else if, you can use eariler for loop and object "cmc" directly. Also you can use Set of leads instead of list of leads to update them, becuase there may be a case that, there are 2 campaign members from same lead, so your final lead list will have duplicate lead ids. If you use set, it will have unique set ids.

Thanks,
Ashish

 
Prady01Prady01
easiest way to remove duplicates

set<Id> uniqueIds = new set<Id>();
uniqueIds.addAll(listWithduplicateIds);
​now your set will have unique id's.

Thank you
PSM