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.

enter image description here

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();

If you cannot get your code to work consider changing its structure to the form shown below.

This makes use of the SOQL relationship query ability to go up the parent hierarchy several levels at once and so avoids the need to create maps and reduces the number of queries needed overall.

Rather than incrementing the existing counts on Contract, it sums all the line items. This is often more useful in that you can all the same code from after delete triggers but may or may not suit your data volumes.

Variables are best declared only when they are needed rather than in a block at the top of the code. This means their scope - the lines of code that they might be referenced in - is minimised, that they are initialised with useful values right away and this also makes unused ones easier to spot and remove.

Set<Id> oliIds = new Set<Id>();
for (OpportunityLineItem oli : newOpptyLine){

// Find the Contracts that the changed line items affect
Map<Id, Contract__c> contracts = new Map<Id, Contract__c>();
for (OpportunityLineItem oli : [
        select Opportunity.Contract__c
        from OpportunityLineItem
        where Id in :oliIds
        and PricebookEntry.Product2.Family = 'Regular tags'
        and Opportunity.Contract__c != null
        ]) {
    // Going to add all the line items in to these starting totals
    contracts.put(oli.Opportunity.Contract__c, new Contract__c(
            Id = oli.Opportunity.Contract__c,
            Contract_Year_Tags_Purchased__c = 0,
            Fiscal_Year_Tags_Purchased__c = 0

// Query all the line items relating to the Contracts
Date startDate = date.newinstance(Date.Today().Year(), 1, 1);
Date endDate = date.newinstance(Date.Today().Year(), 12, 31);
for (OpportunityLineItem oli : [
        from OpportunityLineItem
        where Opportunity.Contract__c in :contracts.keySet()
        and PricebookEntry.Product2.Family = 'Regular tags'
        ]) {
    Controct__c referenced = oli.Opportunity.Contract__r;
    Contract__c contract = contracts.get(oli.Opportunity.Contract__c);
    if (oli.ServiceDate > referenced.Current_Contract_Year_Start__c
            &&  oli.ServiceDate < referenced.Current_Contract_Year_End__c) {
        contract.Contract_Year_Tags_Purchased__c += oli.Quantity;
    if (oli.ServiceDate > startDate && oli.ServiceDate < endDate) {
        contract.Fiscal_Year_Tags_Purchased__c += oli.Quantity;
update contracts.values();
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.