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
XIOXIO 

Apex Trigger - Opportunity Rollup Summary

Hello Developers!

I have been working on a trigger that needs to count the number of related "conference" Opportunities that are associated with a Product voucher. This allows tracking of Product vouchers of a particular conference. Basically I need to count the number of Opportunities (ConferenceOppty = TRUE) that are associated with the Product (Product2).

The rollup count field is in the Product object and it's called "Related_Conference_Opportunities__c." 

Any assistance will be greatly appreciated!
trigger RelatedVoucherOpportunity on Product2 (after insert, after update, after delete, after undelete) {
  
  Set<Id> oppIds = new Set<Id>();
 
  Map<Id,Opportunity> oppRecords = new Map<Id,Opportunity>();
  
  for(Product2 p2:Trigger.isDelete?Trigger.old:Trigger.new)
    oppIds.add(p2.oppIds);
 
  oppIds.remove(null);

  for(Id oppId:oppIds)
    oppRecords.put(oppId,new Opportunity(Id=oppId,ConferenceOppty__c = TRUE));
 
  for(Product2 c:[select id,Related_Conference_Opportunities__c from Product2 where id in :oppIds])
    oppRecords.get(p2.oppIds).ConferenceOppty__c += p2.Related_Conference_Opportunities__c;
  
  Database.update(oppRecords.values());
}

 
Best Answer chosen by XIO
EldonEldon
Hi Harmens,

There is a slight change in the code use the below code which is more ideal for your req including the delete condition
 
trigger LookupRollup on Opportunity (after insert,after update, after delete,after undelete) {
    
    List<id> ParentIds = new List<id>();
    if(Trigger.isInsert || Trigger.isUndelete || Trigger.isupdate){
        For(Opportunity Opp : Trigger.new){
            ParentIds.add(Opp.Discount_code_LU__c);
        }
    }
    if(Trigger.isDelete){
        For(Opportunity Opp : Trigger.old){
            ParentIds.add(Opp.Discount_code_LU__c);
        }
    }
    List<Product2> ProductsToUpdate = new List<Product2>();
    decimal sum = 0;
    if(Trigger.isInsert || Trigger.isUndelete || Trigger.isupdate || trigger.isdelete){
        For(Product2 q : [SELECT Related_Conference_Opportunities__c ,(SELECT id FROM  Child_Relationship_Name__r) FROM Product2 WHERE id =: ParentIds]){
            sum = 0;
            for(Opportunity p : q.Child_Relationship_Name__r){
                
                sum = sum + 1;
            }
            q.Related_Conference_Opportunities__c = sum;
            
        }
        ProductsToUpdate.add(q);        
    }
    try{
        update ProductsToUpdate;
    }Catch(Exception e){
        System.debug('Exception :'+e.getMessage());
    }
}

Try this and let me know if it works for the delete condition also.

Regards

All Answers

EldonEldon
Hi Harmens,

I need to know the relationship field name in the opportuntiy object for writing trigger. Also you need to write the trigger on child that is opportunity and update the parent ie product2.

Regards
XIOXIO
Hello, thank you for the response!

The relationship field name is called Discount_code_LU__c

thank you!!
EldonEldon
Hi Harmens,

Try the below trigger.
 
trigger LookupRollup on Opportunity (after insert,after update, after delete,after undelete) {
    
    List<id> ParentIds = new List<id>();
    if(Trigger.isInsert || Trigger.isUndelete || Trigger.isupdate){
        For(Opportunity Opp : Trigger.new){
            ParentIds.add(Opp.Discount_code_LU__c);
        }
    }
    if(Trigger.isDelete){
        For(Opportunity Opp : Trigger.old){
            ParentIds.add(Opp.Discount_code_LU__c);
        }
    }
    List<Product2> ProductsToUpdate = new List<Product2>();
    decimal sum = 0;
    if(Trigger.isInsert || Trigger.isUndelete || Trigger.isupdate){
        For(Product2 q : [SELECT Related_Conference_Opportunities__c ,(SELECT id FROM  Child_Relationship_Name__r)
         FROM Product2 WHERE id =: ParentIds]){
            sum = 0;
            for(Opportunity p : q.Child_Relationship_Name__r){
                if(p.ConferenceOppty__c)
                   sum = sum + 1;
            }
            q.Related_Conference_Opportunities__c = sum;
            ProductsToUpdate.add(q);
        }
        try{
            update ProductsToUpdate;
        }Catch(Exception e){
            System.debug('Exception :'+e.getMessage());
        }
    }
}
Here replace the Child_Relationship_Name__r with the corresponding child relationship name in your opportuntiy look up field(Discount_code_LU__c).



Let me know if you have any issues.

PS: If you are interested you can look into a library called LREngine (https://github.com/abhinavguptas/Salesforce-Lookup-Rollup-Summaries) which helps to find roll up using look up fields

Regards
 
XIOXIO
Thank you! I don't know which field to replace Child_Relationship_Name__r

I thought the child relationship name is Discount_code__LU__c? Which is a lookup field to the Product from the Opportunity.
EldonEldon
Its not a field. When you go into that lookup field you will find a section called child relationship name like one below,

User-added image


Here you can find it as pobs. Take whats there in your field and add __r

Regards
XIOXIO
Ok thank you. The trigger saved with no errors but I'm getting this message when I create an Opportunity:

Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger ContactRoleCountOpportunity caused an unexpected exception, contact your administrator: ContactRoleCountOpportunity: execution of AfterInsert caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: Opportunity.ConferenceOppty__c: Trigger.ContactRoleCountOpportunity: line 21, column 1


Also, ConferenceOppty__c doesn't have to be included. I want to count all related Opportunities not just the ones that are ConferenceOppty__c + TRUE
 
EldonEldon
I assume you changed the trigger name to ContactRoleCountOpportunity if not please check that trigger.
If you want to count all opps remove that if condition in the line 21.
XIOXIO
Awesome! Thank you very much! Works perfect!
EldonEldon
Hi Harmens,

There is a slight change in the code use the below code which is more ideal for your req including the delete condition
 
trigger LookupRollup on Opportunity (after insert,after update, after delete,after undelete) {
    
    List<id> ParentIds = new List<id>();
    if(Trigger.isInsert || Trigger.isUndelete || Trigger.isupdate){
        For(Opportunity Opp : Trigger.new){
            ParentIds.add(Opp.Discount_code_LU__c);
        }
    }
    if(Trigger.isDelete){
        For(Opportunity Opp : Trigger.old){
            ParentIds.add(Opp.Discount_code_LU__c);
        }
    }
    List<Product2> ProductsToUpdate = new List<Product2>();
    decimal sum = 0;
    if(Trigger.isInsert || Trigger.isUndelete || Trigger.isupdate || trigger.isdelete){
        For(Product2 q : [SELECT Related_Conference_Opportunities__c ,(SELECT id FROM  Child_Relationship_Name__r) FROM Product2 WHERE id =: ParentIds]){
            sum = 0;
            for(Opportunity p : q.Child_Relationship_Name__r){
                
                sum = sum + 1;
            }
            q.Related_Conference_Opportunities__c = sum;
            
        }
        ProductsToUpdate.add(q);        
    }
    try{
        update ProductsToUpdate;
    }Catch(Exception e){
        System.debug('Exception :'+e.getMessage());
    }
}

Try this and let me know if it works for the delete condition also.

Regards
This was selected as the best answer
XIOXIO
Yes that worked, thank you again Eldon!!