[SalesForce] Apex Trigger on Opportunity Contact Role to assign primary to first contact on list

I designed a trigger to automatically Create Opportunity Contact Roles. Our organization is using an app called FastForms which creates an account, contact and opportunity. An issue we have with our org, like most other orgs, is that there isn't much of a way to populate the opportunity contact roles without a trigger. I found this trigger to address, but am running into an issue in that when a new account and opportunity are created, the first contact created is not populated. I would have to click on contact role related list to find and select the first contact on the list as a primary contact.

OCR Roles

My goal is to see that the first contact on the list is automatically assigned to the primary checkbox, is there a way to modify my trigger to have it reflect.

Hope it helps, total noob.

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

It seems that the code snippet you provieded is correct. I just copy-pasted it to my dev org and it works perfectly - the first contact is populated as primary. It's either I do your business process incorrectly or the problem isn't in that trigger. I would suggest you to test this trigger on a clean dev org and check if the first contact is not populated as primary. If so, write several debug logs to understand better code execution. If in dev org this trigger will work perfectly - you need to dig deeper into debug logs and understand what else affects Contact Roles