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
Brian FordBrian Ford 

Before Trigger Not Updating Record

I have a before update trigger on the opportunity. I would like to count the number of contact roles on each opportunity in the trigger as well as indicate on the opportunity if at least one of the contact roles is flagged as a primary contact.

My original solution used a SOQL for loop inside a for loop and was running through my governor limits:
trigger ContactRole on Opportunity (before update) {

for (Opportunity o : trigger.new) {
        Integer count = 0;
        Boolean hasPrimary = FALSE;
        for (OpportunityContactRole ocr : [SELECT Id, isPrimary 
                                           FROM OpportunityContactRole 
                                           WHERE OpportunityId =:o.Id]) {
            count++;
            if (ocr.isPrimary)
                hasPrimary = TRUE;
    	}
		
        o.Number_of_Contact_Roles__c = count;
        o.Has_Primary_Contact__c = hasPrimary; 
    }
}

So I've created this work around. The problem is that the last 2 lines that should update 2 fields on the opportunity aren't updating the opportunity. In my debug log it shows that the fields are being updated but those changes aren't being written to the database. I'm sure there's a simple solution here that I'm not seeing. Thanks for your help.
for (Opportunity o : [SELECT Id, Has_Primary_Contact__c, Number_of_Contact_Roles__c, 
    					  (SELECT Id, isPrimary FROM OpportunityContactRoles)
    					  FROM Opportunity WHERE Id IN :trigger.newMap.keyset()]) {
    	Integer count = 0;
		Boolean hasPrimary = False;
        for (OpportunityContactRole ocr : o.OpportunityContactRoles) {
        	count++;
            if (ocr.isPrimary)
                hasPrimary = TRUE;
        }
        
        o.Number_of_Contact_Roles__c = count;
        o.Has_Primary_Contact__c = hasPrimary;
		System.debug('opportunity: ' + o);
	}

 
Best Answer chosen by Brian Ford
Suneel#8Suneel#8
Your trigger is good.Only issue is that you are not modifying the records that were updated but you are requerying the records.You should do it like below
 
Map<Id,Opportunity> m=new Map<Id,Opportunity>([SELECT Id, Has_Primary_Contact__c, Number_of_Contact_Roles__c, 
                                                   (SELECT Id, isPrimary FROM OpportunityContactRoles)
                                                   FROM Opportunity WHERE Id IN :trigger.newMap.keyset()]);
    for (Opportunity o : trigger.new) {
        Boolean hasPrimary = False;
        for (OpportunityContactRole ocr : m.get(o.id).OpportunityContactRoles) {
            if (ocr.isPrimary)
                hasPrimary = TRUE;
        }
        
        o.Number_of_Contact_Roles__c = m.get(o.id).OpportunityContactRoles.size();
        o.Has_Primary_Contact__c = hasPrimary; 
        System.debug('opportunity: ' + o);
    }

 

All Answers

Suneel#8Suneel#8
Your trigger is good.Only issue is that you are not modifying the records that were updated but you are requerying the records.You should do it like below
 
Map<Id,Opportunity> m=new Map<Id,Opportunity>([SELECT Id, Has_Primary_Contact__c, Number_of_Contact_Roles__c, 
                                                   (SELECT Id, isPrimary FROM OpportunityContactRoles)
                                                   FROM Opportunity WHERE Id IN :trigger.newMap.keyset()]);
    for (Opportunity o : trigger.new) {
        Boolean hasPrimary = False;
        for (OpportunityContactRole ocr : m.get(o.id).OpportunityContactRoles) {
            if (ocr.isPrimary)
                hasPrimary = TRUE;
        }
        
        o.Number_of_Contact_Roles__c = m.get(o.id).OpportunityContactRoles.size();
        o.Has_Primary_Contact__c = hasPrimary; 
        System.debug('opportunity: ' + o);
    }

 
This was selected as the best answer
Suneel#8Suneel#8
Below is another way of achieving the same.This could be bit faster as we are not manually iterating over OpportuniyContactRoles list
 
Map<Id,Opportunity> m=new Map<Id,Opportunity>([SELECT Id, Has_Primary_Contact__c, Number_of_Contact_Roles__c, 
                                                   (SELECT Id, isPrimary FROM OpportunityContactRoles)
                                                   FROM Opportunity WHERE Id IN :trigger.newMap.keyset()]);
    Map<Id,Opportunity> m1=new Map<Id,Opportunity>([SELECT Id, Has_Primary_Contact__c, Number_of_Contact_Roles__c, 
                                                   (SELECT Id, isPrimary FROM OpportunityContactRoles where isPrimary = true)
                                                   FROM Opportunity WHERE Id IN :trigger.newMap.keyset()]);    
    for (Opportunity o : trigger.new) {	
        
        o.Number_of_Contact_Roles__c = m.get(o.id).OpportunityContactRoles.size();
        if(m1.get(o.Id).OpportunityContactRoles.size()>0)
        	o.Has_Primary_Contact__c = true; 
        else
            o.Has_Primary_Contact__c = false; 
        System.debug('opportunity: ' + o);
    }

Kindly mark this questiona as Solved if this fixed your issue