[SalesForce] How to avoid creation of duplicate Opportunity Contact Role for every newly created Opportunity

I have written a after insert trigger on Opportunity to create a Opportunity Contact Role.

Here is the part of code

 if( trigger.isAfter && trigger.isinsert){
Set<Id> accIds = new Set<Id>();
List<OpportunityContactRole> contactRolesToInsert = new List<OpportunityContactRole>();
List<OpportunityContactRole> contactRolesToUpdate = new List<OpportunityContactRole>();
for(Opportunity o: Trigger.New)
{
    accIds.add(o.AccountId);
}

List<Account> accList = [Select Id, (Select Id, From_A2Z__c from Contacts Order By LastActivityDate desc) 
                         from Account where Id in: accIds ];
Map<Id,Id> mapOfAccIdNConId = new Map<Id,Id>();


for(Account a: accList)
{ 
    Id conId=null;
    if(a.contacts.size()>0)
    {
        //Get contact of recent LastActivityDate
        conId = a.contacts.get(0).Id;
        //Get contact where From A2Z TRUE and overwrite above contact id if found
        for(Contact c: a.contacts)
        {
            if(c.From_A2Z__c==true)
            {
                conId=c.Id;
                break;
            }
        }
    }
    mapOfAccIdNConId.put(a.Id,conId);
}

for(Opportunity o:trigger.new)
{
    if(mapOfAccIdNConId.containsKey(o.AccountId) && mapOfAccIdNConId.get(o.AccountId)!=null)
    {
        Id conId=mapOfAccIdNConId.get(o.AccountId);            
        //Insert Contact Role
        OpportunityContactRole OppContactRole = new OpportunityContactRole();
        OppContactRole.ContactId=conId;
        OppContactRole.Role='Decision Maker';
        OppContactRole.OpportunityId=o.id;
        contactRolesToInsert.add(OppContactRole);
    }
}

if(contactRolesToInsert.size()>0)
    insert contactRolesToInsert; }

Whenever a new Opportunity is created by converting a lead or from Contact detail page, two Opportunity Contact Roles are inserted for the same Opportunity. One Contact Role has "Role" set to null and other one with "Role" I have assigned in trigger.

What approach I should follow to handle these scenarios which causes duplicate Oportunity Contact Roles?

Best Answer

I think it may be happening because of this section of code which initializes the conId to null and also has a break inside the if statement in the middle of the for loop. The conId will be null if not set to null anyway. I suggest you remove both the break; and leave the initialization as simply Id conId;. You may need to add a null check before adding values to your map at the end of the 1st major loop.

for(Account a: accList)
{ 
    Id conId=null;  <<== Remove the initalizion to null.
    if(a.contacts.size()>0)
    {
        //Get contact of recent LastActivityDate
        conId = a.contacts.get(0).Id;
        //Get contact where From A2Z TRUE and overwrite above contact id if found
        for(Contact c: a.contacts)
        {
            if(c.From_A2Z__c==true)
            {
                conId=c.Id;
                break;  <<== remove this break
            }
        }
    }
    // regardless, may need to add if(conId != null){
    mapOfAccIdNConId.put(a.Id,conId);
    // }
}

With that having been said, you may have other workflow in your org that's creating the OCR for you automatically and your trigger may not be needed at all. Since you've also not included the remainder of your code that might tell us what else could be contributing to your issues, there's nothing more I can tell you.