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
Alaric WimerAlaric Wimer 

How to create Opportunity Contact Roles for all Opportunities without contact roles, with Accounts that have Contact(s)?

I have several Opportunities with no Contact Roles assigned. For the Opportunities with no Contact Roles, that are related to Accounts with Contacts, I need to create Contact Roles to match the related Account's Contacts. I am trying to accomplish this with an anonymous apex code block. 

 

Here's what I have started, can anyone help me to make this work? Thank you.

 

Map<Id, Id> oppIdToAccIdMap = new Map<Id, Id>();
Map<Id, Id> conIdToAccIdMap = new Map<Id, Id>();
Set<Id> oppAccountIdSet = new Set<Id>();
List<OpportunityContactRole> ocrsToInsert = new List<OpportunityContactRole>();

// 1. Get all Opportunities that have no contact roles
 List<Opportunity> myOpps = [
     SELECT Id, AccountId
     FROM Opportunity
     WHERE Id NOT IN (SELECT OpportunityId FROM OpportunityContactRole)
     ORDER BY Name ASC     
 ];

 for (Opportunity opp1 : myOpps) {
     oppAccountIdSet.add(opp1.AccountId);
 }

// 2. Get all Contacts that aren't contact Roles, that share the same Account as Opportunities with no Contact Roles
List<Contact> myCons = [
    SELECT Id, Name, AccountId
    FROM Contact 
    WHERE AccountId IN :oppAccountIdSet
    AND Id NOT IN (SELECT ContactId FROM OpportunityContactRole)
    ORDER BY Name ASC
];

System.debug('***** DEBUG: Contacts with same Account: ' + myCons);

if (!myOpps.isEmpty() && !myCons.isEmpty()) {
// 3. Lopp through Opportunities with no contact roles, store opp Id and account Id in a map
    for (Opportunity myOpp : myOpps) {
        if (myOpp.AccountId != null && myOpp.Id != null) {
            oppIdToAccIdMap.put(myOpp.Id, myOpp.AccountId);
        }
    }
    System.debug('***** DEBUG: Opportunity Id to Account Id: ' + oppIdToAccIdMap);

    // 4. Lopp through Contacts with no contact roles, store contact Id and Account Id in a map
    for (Contact myCon : myCons) {
        if (myCon.AccountId != null && myCon.Id != null) {
            conIdToAccIdMap.put(myCon.Id, myCon.AccountId);
        }
    }
    System.debug('***** DEBUG: Contact Id to Account Id: ' + conIdToAccIdMap);


    // Need to Create a new Opportunity Contact Role for each Opportunity, using Opportunity Id and Contact Id that share the same Account
    // If Account has more than one Contact, both contacts should be contact roles of the Account's Opportunity
    // If Account has more than one Opportunity, both Opportunities should have the Account's contact(s) as their contact roles

}
 

 

Abhishek BansalAbhishek Bansal
Hi Alaric,

I have done some modification in the code and you can find the updated code below:
//Map value should be of list type as there can be multiple opps associated with a single account.
Map<Id, List<Id>> accIdToOppIdsMap = new Map<Id, List<Id>>();
//Map value should be of list type as there can be multiple contacts associated with a single account.
Map<Id, List<Id>> accIdToContactIdsMap = new Map<Id, List<Id>>();
Set<Id> oppAccountIdSet = new Set<Id>();
List<OpportunityContactRole> ocrsToInsert = new List<OpportunityContactRole>();

// 1. Get all Opportunities that have no contact roles
List<Opportunity> myOpps = [ SELECT Id, AccountId
                            FROM Opportunity
                            WHERE Id NOT IN (SELECT OpportunityId FROM OpportunityContactRole)
                            AND AccountId != null
                            ORDER BY Name ASC];

for (Opportunity opp1 : myOpps) {
    oppAccountIdSet.add(opp1.AccountId);
}

// 2. Get all Contacts that aren't contact Roles, that share the same Account as Opportunities with no Contact Roles
List<Contact> myCons = [ SELECT Id, Name, AccountId
                        FROM Contact 
                        WHERE AccountId IN :oppAccountIdSet
                        AND Id NOT IN (SELECT ContactId FROM OpportunityContactRole)
                        AND AccountId != null
                        ORDER BY Name ASC];

System.debug('***** DEBUG: Contacts with same Account: ' + myCons);

if (!myOpps.isEmpty() && !myCons.isEmpty()) {
    // 3. Lopp through Opportunities with no contact roles, store opp Id and account Id in a map
    for (Opportunity myOpp : myOpps) {
        if(!accIdToOppIdsMap.containsKey(myOpp.AccountId)) {
            accIdToOppIdsMap.put(myOpp.AccountId, new List<Id>());
        }
        accIdToOppIdsMap.get(myOpp.AccountId).add(myOpp.Id);
    }
    System.debug('***** DEBUG: Opportunity Id to Account Id: ' + oppIdToAccIdMap);
    
    // 4. Lopp through Contacts with no contact roles, store contact Id and Account Id in a map
    for (Contact myCon : myCons) {
        if(!accIdToContactIdsMap.containsKey(myCon.AccountId)) {
            accIdToContactIdsMap.put(myCon.AccountId, new List<Id>());
        }
        accIdToContactIdsMap.get(myCon.AccountId).add(myCon.Id);
    }
    
    //Now we have both the maps ready and we can create OppContactRoles
    OpportunityContactRole newOppConRole;
    for(Id accId : accIdToOppIdsMap.keySet()) {
        for(Id oppId : accIdToOppIdsMap.get(accId)) {
            for(Id conId : accIdToContactIdsMap.get(accId)) {
                newOppConRole = new OpportunityContactRole();
                newOppConRole.OpportunityId = oppId;
                newOppConRole.ContactId = conId;
                ocrsToInsert.add(newOppConRole);
            }
        }
    }
    if(ocrsToInsert.size() > 0) {
        insert ocrsToInsert;
    }
}

Please take care of the syntax errors and let me know if you face any issues.

Thanks,
Abhishek Bansal.