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
Abby DouglasAbby Douglas 

Opportunity Trigger - Contact Roles Count - Mass Update - Counting Batch Total

I have the below trigger on the fritz.  I just processed a mass update via DataLoader and when the records updated it put the batch Contact Role count in each field and not the records Contact Roles count.  

What did I do wrong? 
trigger updatecontactrolecount on Opportunity (before insert, before update)
{

Boolean isPrimary;
Integer iCount;

Map<String, Opportunity> oppty_con = new Map<String, Opportunity>();//check if the contact role is needed and add it to the oppty_con map
for (Integer i = 0; i < Trigger.new.size(); i++) 
{
        oppty_con.put(Trigger.new[i].id,
        Trigger.new[i]);      
}
isPrimary = False; 
for (List<OpportunityContactRole> oppcntctrle :[select OpportunityId from OpportunityContactRole where (OpportunityContactRole.IsPrimary = True and OpportunityContactRole.OpportunityId in :oppty_con.keySet())])
{
 if (oppcntctrle .Size() >0)
 {
 isPrimary = True;     
 }
}
iCount = 0;
for (List<OpportunityContactRole> oppcntctrle2 : [select OpportunityId from OpportunityContactRole where (OpportunityContactRole.OpportunityId in :oppty_con.keySet())])//Query for Contact Roles
{    
 if (oppcntctrle2 .Size()>0)
 {
 iCount= oppcntctrle2 .Size();     
 }
}
for (Opportunity Oppty : system.trigger.new) //Check if  roles exist in the map or contact role isn't required 
{
Oppty.Number_of_Contacts_Roles_Assigned__c = iCount;
Oppty.Primary_Contact_Assigned__c =isPrimary; 
}
}

 
Dev_AryaDev_Arya
Hi Abby,

As you updated your data through Dataloader, the data is processed in batches. So when you execute the first batch, lets say your first 200 records, the trigger will be called once for all the 200 records. Trigger.old and Trigger.new will have the values for these 200 batch records. 
Now, in your code, in the second and third for loop, you are getting the value of isPrimary and iCount 
...
isPrimary = False; 
for (List<OpportunityContactRole> oppcntctrle :[select OpportunityId from OpportunityContactRole where (OpportunityContactRole.IsPrimary = True and OpportunityContactRole.OpportunityId in :oppty_con.keySet())])
{
 if (oppcntctrle .Size() >0)
 {
 isPrimary = True;     
 }
}
iCount = 0;
for (List<OpportunityContactRole> oppcntctrle2 : [select OpportunityId from OpportunityContactRole where (OpportunityContactRole.OpportunityId in :oppty_con.keySet())])//Query for Contact Roles
{    
 if (oppcntctrle2 .Size()>0)
 {
 iCount= oppcntctrle2 .Size();     
 }
}
...

And later in the fourth loop, where you actually iterated over all the records in the batch, you assigned the same value of iCount and isPrimary to all the records in the batch. Hence you will be seeing the same value of  Number_of_Contacts_Roles_Assigned__c  and Primary_Contact_Assigned__c for all the records in the batch.
for (Opportunity Oppty : system.trigger.new) //Check if  roles exist in the map or contact role isn't required 
{
  Oppty.Number_of_Contacts_Roles_Assigned__c = iCount;
  Oppty.Primary_Contact_Assigned__c =isPrimary; 
}
You need to get the value of Contact role count and the primary contact role ID for individual Opportunity in Trigger.old.
If you need code clarification and optimization, on how to achieve your requirement, feel free to ask. For now, I will leave it up to you if you are keen to solve it by yourself.

Happy coding. Cheers, Dev
Dev_AryaDev_Arya
And please mark the answer  green, if it solved your doubts. Thanks.
Abby DouglasAbby Douglas
@Dev_Arya Thank you for your response. Unfortunately, I inherited this code and have no idea on how to fix it.  If you would be so gracious to help me it would be greatly appreciated! I'm just an admin working my way into learning development.