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
Community User2Community User2 

Update values to grandparent in trigger

I need to update the field values from opportunityLineItem to Contract.Need to aggregate opptyLineItem field values from all opptylineItem and then update it on Contract.we have a custom lookup to Contract from Opportunity.I am having difficulty in pulling all related opptylineitems field values of each contract in trigger.

User-added image

public class OpportunityLineItemTriggerHandler {

 public void OnAfterInsert(OpportunityLineItem[] newOpptyLine){



 public void updateContractFields(OpportunityLineItem[] newOpptyLine){

 set<Id>conIds = new set<Id>();
 list<Id>oliIds = new list<Id>();
 list<Id>pbeIds = new list<Id>();
 list<OpportunityLineItem> oliList = new list<OpportunityLineItem>();
 list<PricebookEntry> pbeList = new list<PricebookEntry>();
 list<Contract> conList = new list<Contract>();
 list<Opportunity> oppList = new list<Opportunity>();
 map<Id,Id> oliConMap = new map<Id,Id>();

 Date startDate = date.newinstance(Date.Today().Year(), 1, 1);
 Date endDate = date.newinstance(Date.Today().Year(),12, 31);

 for(OpportunityLineItem oli : newOpptyLine){



 pbeList = [Select p.Product2.Family, p.Product2.Id, p.Product2Id, p.Id, (Select Id, OpportunityId, Quantity, TotalPrice, ServiceDate From OpportunityLineItems) From PricebookEntry p where p.Product2.Family = 'Regular tags'];

 for(PricebookEntry pbe : pbeList){

map<Id,OpportunityLineItem> oliMap = new map<Id,OpportunityLineItem>([Select o.TotalPrice, o.ServiceDate, o.Quantity, o.PricebookEntry.ProductCode, o.PricebookEntry.Product2Id, o.PricebookEntryId, o.Opportunity.Contract__c,o.Opportunity.Contract__r.Current_Contract_Year_End__c, o.Opportunity.Contract__r.Current_Contract_Year_Start__c, o.Opportunity.Contract__r.Contract_Year_Tags_Purchased__c,o.OpportunityId, o.Id From OpportunityLineItem o where o.Id in:oliIds and o.PricebookEntryId in: pbeIds ]); 

 for(OpportunityLineItem oli : oliMap.values()){

  map<Id,Contract> conMap = new map<Id,Contract>([Select c.Id, c.Current_Contract_Year_Start__c, c.Current_Contract_Year_End__c, c.Contract_Year_Tags_Purchased__c,c.Fiscal_Year_Tags_Purchased__c,c.Total_Tags_Purchased__c,(Select Id From Opportunities_del__r) From Contract c where Id in :conIds]);

  for(Contract con : conMap.values()){

     for(Opportunity o:con.Opportunities_del__r){

        for(OpportunityLineItem oli :o.OpportunityLineItems){

         if(oliMap.containsKey(oli.Id)) {

           if(oli.ServiceDate > con.Current_Contract_Year_Start__c &&  oli.ServiceDate < con.Current_Contract_Year_End__c){

                 con.Contract_Year_Tags_Purchased__c = con.Contract_Year_Tags_Purchased__c + oli.Quantity;


               if(oli.ServiceDate > startDate && oli.ServiceDate < endDate){
                  con.Fiscal_Year_Tags_Purchased__c  = con.Fiscal_Year_Tags_Purchased__c  + oli.Quantity;



  update conMap.values();



James LoghryJames Loghry
In Line 45, when you query from Contracts on down to the OpportunityLineItem records, you are not including OpportunityLineItems in your Opportunity subquery.  In fact, you can't nest subqueries in SOQL like you need to to achieve your requirement.  

You'll need to either switch your query around and query from OpportunityLineItems on up, issue an additional query for OpportunityLineItems off of the Contract's Opportunities.

Below is an example of how you would do the former:

//First grab a set of all contract ids from your OLI records
Set<Id> contractIds = new Set<Id>();
for(OpportunityLineItem oli : [Select Opportunity.Contract__c From OpportunityLineItem Where Id in :Trigger.newMap.keySet()]){

//Next, query for all opportunity line items for each of the applicable contracts
Map<Id,Contract> contractMap = new Map<Id,Contract>();
for(OpportunityLineItem oli : 
        Opportunity.Contract__c in :contractIds]){
    Contract current = contractMap.get(oli.Opportunity.Contract__r.Id);
    if(current == null){
        current = Opportunity.Contract__c;
    //Perform logic to increment Current Contract Year fields here

update contractMap.values();