function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
QD93QD93 

Apex Trigger: Automatically create Opportunity Contact Roles on Newly created Opportunity on Custom object

Hi, I'm New to Apex...

I'd like to create a Trigger that fires when --> I create an Opportunity record on a custom object. The Custom object has a list of related Contact record. I would like the Trigger to automatically create  Opportunity Contact Roles, each Contact Roles with the related Contact record (related to the custom object) as the Contact Id, and the newly created Opportunity record as the Opportunity Id. 

The custom object is almost use as in an Account (custom object)--Opportunity--Contact format. 

The custom recod field is --> a__Co_Sum__c

Provided below is fairly similar Apex trigger, but it is design for the Account. Where the trigger will add all account contacts to the contact roles when creating a new opportunity. I'd love to have this code written but replacing Account with the custom record a__Co_Sum__c
trigger CreateContactRole on Opportunity (after insert, after update) {

    //get the id of all involved accounts
    Set<ID> accountIds = new Set<ID>();
    for(Opportunity opt:Trigger.New){
        accountIds.add(opt.AccountId);
    }
    
    //get all contacts for those accounts
    list<Contact> contacts = new list<Contact>();
    contacts = [select id, AccountId from Contact where AccountId in: accountIds order by createddate Limit 5000];
    
    //organize these contacts by account
    Map<Id,List<Contact>> contactsByAccount = new Map<ID,List<Contact>>();
    for(Contact c:contacts){
        if(contactsByAccount.get(c.AccountId) == null){
            contactsByAccount.put(c.AccountId,new List<Contact>());
        }
        contactsByAccount.get(c.AccountId).add(c);
    }
    
    // check to see if the Opportunity already has a contact role.  If it does, add to a set of Ids to exclude
    List<OpportunityContactRole> existingOCR = new List<OpportunityContactRole>();
    Set<Id> existingOCRIds = new Set<Id>();
    existingOCR = [select OpportunityId from OpportunityContactRole where OpportunityId in:Trigger.newMap.keySet() limit 5000];
    for(OpportunityContactRole ocr:existingOCR) if(!existingOCRIds.contains(ocr.OpportunityId)) existingOCRIds.add(ocr.OpportunityId);
    
    //create the OpportunityContactRole objects
    list<OpportunityContactRole> lstOCR = new list<OpportunityContactRole>();
    for(Opportunity opt:Trigger.New){
        if(!existingOCRIds.contains(opt.Id) && contactsByAccount.get(opt.AccountId) != null){
            Boolean firstContact = true;
            for(Contact c: contactsByAccount.get(opt.AccountId)){
                OpportunityContactRole ocr = new OpportunityContactRole(OpportunityId=opt.id, ContactId=c.id);
                if(firstContact) {
                    ocr.IsPrimary = TRUE;
                    firstContact = FALSE;
                }
                lstOCR.add(ocr);
            }
        }
    }
    insert lstOCR;
}

 
Best Answer chosen by QD93
Ashley 6Ashley 6
Hi Quan Dao 9,
I have read your question and I think the trigger should work only for the event- 'after insert' as the question stated for newly created opportunity.
I have used 'AccountSpecific__c' as the custom object name and the custom fields in the contact and opportunity are 'AccountSpecificId__c' and 'AccountSpecificOppId__c' for establishing the connection between custom object 'AccountSpecific__c' with Contact and Opportunity respectively.

So, the trigger for creating new opportunity contact roles is given below:
trigger createOpportunityContactRoles on Opportunity (after insert) {

    Set<Id> accSpecificIds = new Set<Id>();
    List<OpportunityContactRole> ocrList = new List<OpportunityContactRole>();
    Map<Id, List<Contact>> accountSpecificContacts = new Map<Id, List<Contact>>();
    
    for(Opportunity o: Trigger.New) {
        if(o.AccountSpecificOppId__c != Null) 
            accSpecificIds.add(o.AccountSpecificOppId__c);
    }
    
    for(Contact con: [select id, AccountSpecificId__c from Contact 
                    where AccountSpecificId__c in: accSpecificIds]) {
        if(!accountSpecificContacts.containsKey(con.AccountSpecificId__c)) 
            accountSpecificContacts.put(con.AccountSpecificId__c, new List<Contact>());
        accountSpecificContacts.get(con.AccountSpecificId__c).add(con);
    }
    
    for(Opportunity opp: Trigger.New) {
        if(accountSpecificContacts.containskey(opp.AccountSpecificOppId__c) 
            && accountSpecificContacts.get(opp.AccountSpecificOppId__c) != NULL) {
            Boolean isFirstContact = true;
            for(Contact c: accountSpecificContacts.get(opp.AccountSpecificOppId__c)) {
                OpportunityContactRole ocr = new OpportunityContactRole(ContactId = c.Id, 
                                                                        OpportunityId = opp.id);
                if(isFirstContact) {
                    ocr.IsPrimary = true;
                    isFirstContact = false;
                }
                ocrList.add(ocr);
            }
        }           
    }
    
    if(ocrList.size() > 0)
        insert ocrList;
}
If this is the answer of your question, please mark it as best answer.......

Regards.

All Answers

Ashley 6Ashley 6
Hi Quan Dao 9,
I have read your question and I think the trigger should work only for the event- 'after insert' as the question stated for newly created opportunity.
I have used 'AccountSpecific__c' as the custom object name and the custom fields in the contact and opportunity are 'AccountSpecificId__c' and 'AccountSpecificOppId__c' for establishing the connection between custom object 'AccountSpecific__c' with Contact and Opportunity respectively.

So, the trigger for creating new opportunity contact roles is given below:
trigger createOpportunityContactRoles on Opportunity (after insert) {

    Set<Id> accSpecificIds = new Set<Id>();
    List<OpportunityContactRole> ocrList = new List<OpportunityContactRole>();
    Map<Id, List<Contact>> accountSpecificContacts = new Map<Id, List<Contact>>();
    
    for(Opportunity o: Trigger.New) {
        if(o.AccountSpecificOppId__c != Null) 
            accSpecificIds.add(o.AccountSpecificOppId__c);
    }
    
    for(Contact con: [select id, AccountSpecificId__c from Contact 
                    where AccountSpecificId__c in: accSpecificIds]) {
        if(!accountSpecificContacts.containsKey(con.AccountSpecificId__c)) 
            accountSpecificContacts.put(con.AccountSpecificId__c, new List<Contact>());
        accountSpecificContacts.get(con.AccountSpecificId__c).add(con);
    }
    
    for(Opportunity opp: Trigger.New) {
        if(accountSpecificContacts.containskey(opp.AccountSpecificOppId__c) 
            && accountSpecificContacts.get(opp.AccountSpecificOppId__c) != NULL) {
            Boolean isFirstContact = true;
            for(Contact c: accountSpecificContacts.get(opp.AccountSpecificOppId__c)) {
                OpportunityContactRole ocr = new OpportunityContactRole(ContactId = c.Id, 
                                                                        OpportunityId = opp.id);
                if(isFirstContact) {
                    ocr.IsPrimary = true;
                    isFirstContact = false;
                }
                ocrList.add(ocr);
            }
        }           
    }
    
    if(ocrList.size() > 0)
        insert ocrList;
}
If this is the answer of your question, please mark it as best answer.......

Regards.
This was selected as the best answer
QD93QD93
Hi Ashley,

It appears I need a Code Coverage 75% for this Apex Trigger. How should I approach creating a Code Coverage for this via Apex Class? Please advise, thanks!