Add Opportunity Contact role from account contacts

apextrigger

I have a requirement to creates an opportunity contact role record whenever an opportunity is created. The records should be created from the account's related contacts. I have written the following code but only one Opportunity contact role is created whereas I need to copy all the contacts from the account.

trigger OpportunityTrigger on Opportunity (after insert, after update) {
        
        SWITCH ON Trigger.operationType{
            WHEN AFTER_INSERT{
                OpportunityTotalAmountHandler.CalculateTotalOpportunityAmount(Trigger.new);
                AddContactRoleHandler.AddOpportunityContactRole(Trigger.new);
            }
            WHEN AFTER_UPDATE{
                OpportunityTotalAmountHandler.CalculateTotalOpportunityAmount(Trigger.new);
            }
        }
    }
    public class AddContactRoleHandler {
        public static void AddOpportunityContactRole(List<Opportunity> newOpportunities){
            Set<Id> accountIds = new Set<Id>();
            for(Opportunity oppObj : newOpportunities){
                accountIds.add(oppObj.AccountId);
            }
            
            Map<Id, List<Contact>> mapOfContacts = new Map<Id, List<Contact>>();
            
            for(Contact conObj : [SELECT Id, AccountId, Name 
                                    FROM Contact 
                                  WHERE AccountId IN :accountIds]){
                      mapOfContacts.put(conObj.AccountId, new List<Contact>());
                      mapOfContacts.get(conObj.AccountId).add(conObj);             
            }
            
            List<OpportunityContactRole> listOfOCR= new List<OpportunityContactRole>();
            
            for(Opportunity opp : newOpportunities){
                if(mapOfContacts.containsKey(opp.AccountId) && mapOfContacts.get(opp.AccountId)!= Null)
                    for(Contact con : mapOfContacts.get(opp.AccountId)){
                        OpportunityContactRole ocr = new OpportunityContactRole();
                        ocr.ContactId = con.Id;
                        ocr.OpportunityId = opp.Id;
                        ocr.Role = 'Business User';
                        listOfOCR.add(ocr);
                        System.debug('List of OCR: ' + listOfOCR);
                    }
             }
            if(!listOfOCR.isEmpty())
            insert listOfOCR;
        }
    }

Best Answer

You are overwriting the List contained in each element of mapOfContacts every time through the loop:

            for(Contact conObj : [SELECT Id, AccountId, Name 
                                    FROM Contact 
                                  WHERE AccountId IN :accountIds]){
                      // This overwrites what is already there!
                      mapOfContacts.put(conObj.AccountId, new List<Contact>());
                      mapOfContacts.get(conObj.AccountId).add(conObj);             
            }

Instead, add the empty List only if the key is not already present:

            for(Contact conObj : [SELECT Id, AccountId, Name 
                                    FROM Contact 
                                  WHERE AccountId IN :accountIds]){
                      if (!mapOfContacts.containsKey(conObj.AccountId) {
                          mapOfContacts.put(conObj.AccountId, new List<Contact>());
                      }
                      mapOfContacts.get(conObj.AccountId).add(conObj);             
            }