+ Start a Discussion
Micky MMicky M 

Trigger Problem

Hi all i have this trigger where i want to update some values on an opp based on values in the opps line items but im getting the "maximum trigger depth exceeded" error but i dont really know how to resolve it, can anyone see what i can do here?

 

trigger opportunitySubTotalSummaryTrigger2 on Opportunity (after insert, after update)
{
    list<id> OppIds = new list<id>();
    list<Opportunity> oppsWithLineItems = new list<Opportunity>();
    list<Opportunity> oppsToUpdate = new list<Opportunity>();
    
    for(Opportunity o : trigger.new)
    {
        if(o.HasOpportunityLineItem == true)
            OppIds.add(o.id);        
    }
    
    oppsWithLineItems = [Select o.System_Revenue_2__c, System_Margin_2__c, CS_Revenue_2__c, CS_Margin_2__c, PS_Revenue_2__c, PS_Margin_2__c, o.Name, o.Id, (Select Id, OpportunityId, SortOrder, PricebookEntryId, CurrencyIsoCode, Quantity, TotalPrice, UnitPrice, ListPrice, ServiceDate, Description, Unit_Cost_Price__c, Unit_List_Price__c, Vendor_Quote_Reference__c, Vendor_Registration__c, Total_Cost_Price__c, Total_List_Price__c, Total_Sell_Price__c, Total_Product_Margin__c, Margin_percent__c, Test_Type__c, Type__c, CS_Revenue__c, CS_Margin__c, System_Revenue__c, PS_Margin__c, PS_Revenue__c, System_Margin__c, Other_Revenue__c, Other_Margin__c From OpportunityLineItems) From Opportunity o where o.HasOpportunityLineItem = true and id in :oppIds];
    
    for(Opportunity o : oppsWithLineItems)
    {
        for(OpportunityLineItem oli : o.OpportunityLineItems)
        {
            o.System_Revenue_2__c += oli.System_Revenue__c;
        }
    }
    update(oppsWithLineItems);
}

 

Thanks All

Best Answer chosen by Admin (Salesforce Developers) 
Anoop AsokAnoop Asok

Just interchange your last two lines of your logic.

You should be setting the flag to false before firing the DML. This way when the trigger is fired again, the condition will evaluate to false.

 

Thanks,

Anoop

All Answers

SamuelDeRyckeSamuelDeRycke

you're in an infinite loop, you'll keep updating your oportunity object and keep increasing the system_reveue.

 Think of a condition to use, and only update the oportunities for which the condition is met. As a side note, are you taking into account a decrease of system_revenue_2 when a line item is deleted ?

Micky MMicky M

Hi yeah the problem is i dont know how to not be an infintite loop, basically the trigger is just creating a roll up value on the opp, but i dont know how to say that this trigger has already fired dont execute again.

SamuelDeRyckeSamuelDeRycke

You can verify if the system_revenye_2__c field on opportunity already equals the roll up of the values of all system_revenue__c fields on the  lineitems. If this is already the case, an update is not required. 

Anoop AsokAnoop Asok

Hey Micky,

All you need is to create and initialize (to either true or false) a static flag in one of your classes.

Your trigger logic should be wrapped inside the condition, which will evaluate to true only if your flag holds the same value which you initialized.

And before you fire the DML on opportunity, switch your flag.

I believe this should do the trick.

 

Thanks,

Anoop

Micky MMicky M

Thanks for the help guys, ive just tried this:

 

here's my clase with a flag

public with sharing class staticFlagsForRecursionTriggers
{
    public static boolean firstRun = true;
}

 

//Trigger Code

if(staticFlagsForRecursionTriggers.firstRun)
    {
        list<id> OppIds = new list<id>();
        list<Opportunity> oppsWithLineItems = new list<Opportunity>();
        list<Opportunity> oppsToUpdate = new list<Opportunity>();
        
        for(Opportunity o : trigger.new)
        {
            if(o.HasOpportunityLineItem == true)
                OppIds.add(o.id);        
        }
        
        oppsWithLineItems = [Select o.System_Revenue_2__c, System_Margin_2__c, CS_Revenue_2__c, CS_Margin_2__c, PS_Revenue_2__c, PS_Margin_2__c, o.Name, o.Id, (Select Id, OpportunityId, SortOrder, PricebookEntryId, CurrencyIsoCode, Quantity, TotalPrice, UnitPrice, ListPrice, ServiceDate, Description, Unit_Cost_Price__c, Unit_List_Price__c, Vendor_Quote_Reference__c, Vendor_Registration__c, Total_Cost_Price__c, Total_List_Price__c, Total_Sell_Price__c, Total_Product_Margin__c, Margin_percent__c, Test_Type__c, Type__c, CS_Revenue__c, CS_Margin__c, System_Revenue__c, PS_Margin__c, PS_Revenue__c, System_Margin__c, Other_Revenue__c, Other_Margin__c From OpportunityLineItems) From Opportunity o where o.HasOpportunityLineItem = true and id in :oppIds];
        
        for(Opportunity o : oppsWithLineItems)
        {
            for(OpportunityLineItem oli : o.OpportunityLineItems)
            {
                o.System_Revenue_2__c += oli.System_Revenue__c;
            }
            oppsToUpdate.add(o);
        }
        system.debug('oppsToUpdate' + oppsToUpdate);
        update(oppsToUpdate);
        staticFlagsForRecursionTriggers.firstRun = false;
    }

 

and here's the error (which is a bit long but it will probably give you a clue, i cant really see what im doing wrong.

 

Error: Invalid Data.
Review all error messages below to correct your data.
Apex trigger opportunitySubTotalSummaryTrigger2 caused an unexpected exception, contact your administrator: opportunitySubTotalSummaryTrigger2: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id 006M0000004SrlDIAS; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, opportunitySubTotalSummaryTrigger2: maximum trigger depth exceeded Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD] Opportunity trigger event AfterUpdate for [006M0000004SrlD]: []: Trigger.opportunitySubTotalSummaryTrigger2: line 26, column 1

Anoop AsokAnoop Asok

Just interchange your last two lines of your logic.

You should be setting the flag to false before firing the DML. This way when the trigger is fired again, the condition will evaluate to false.

 

Thanks,

Anoop

This was selected as the best answer
Micky MMicky M

oh yeah thats got it!! cheers for that! just another quick question, when does the static variable get set back to true? you know when i hit save again? what is it that resets the variable?

Anoop AsokAnoop Asok

Yes.

Hitting the save button is one of the cases which will re-initialize the flag.

Basically any fresh insert or update which invokes a new instance will reset the flag to the initial value.

 

Thanks,

Anoop

 

 

Micky MMicky M

Excellent! thanks for all your help guys!! thats ace.

Suresh RaghuramSuresh Raghuram

Hi ashok cant we declare a flag = true  with in the trigger and switch it when a condition is met ,Instead of using a class jst for the initating the flag variable do we need to use the class.

Anoop AsokAnoop Asok

Hey Suree,

Lets assume we followed the below steps in order within the trigger.

1. Declare flag = true

2. Condition -> if flag = true, execute steps 3,4 and 5.

3. All the trigger logic.

4. set flag = false

5. update records.

 

Now the step 5 will again invoke the same trigger, and when it reaches line 1, the flag will be set to true. So your step 2 will evaluate to true, and this will repeat infinitely.

 

In case you're creating a new class, then in future when need arises you can use this class itself for similiar helper functionalities. Or, if you've any light weight classes which is already in place, you can even use that for keeping this flag. Either way, it doesn't make much of a difference I believe.

 

I believe I answered your question. :-)

 

Thanks,

Anoop

Suresh RaghuramSuresh Raghuram
yes i got my answer thank you Anoop
Ashish P.Ashish P.

Can any one please help me to write a trigger:

I Have to write a trigger which can pick up the latest date from record type and update a filed. Please reply soon