0

I have written a trigger for before update and after insert function

trigger EstimateBudgetPerMonth on Opportunity__c(after insert, before update) {
    Date startDate = Date.newInstance(2008, 1, 1);
    Date endDate = Date.newInstance(2008, 1, 30);
    Set < Id > oppId = new Set < Id > ();
    Integer totalBudget;
    for (Opportunity__c opp: Trigger.new) {
        startDate = opp.Campaign_Start_Date1__c;
        endDate = opp.Campaign_End_Date1__c;
        totalBudget = Integer.valueOf(opp.Budget1__c);
        oppId.add(opp.Id);
    }

    InsertBudgetOpp insertRec = new InsertBudgetOpp();
    InsertBudgetOpp updateRec = new InsertBudgetOpp();



    if (Trigger.isInsert) {
        System.debug('--===Insert==--#--===Insert==--#--===Insert==--');

        List < Budget_Allocation__c > baList = insertRec.insertChild(oppId, startDate, endDate, totalBudget);

        insert baList;

    } else if (Trigger.isUpdate) {
        System.debug('--===Update==--#--===Update==--#--===Update==--');

        Map < String, Budget_Allocation__c > baNewMap = updateRec.updateChild(oppId, startDate, endDate, totalBudget);

        upsert baNewMap.values();
    }



} 

Its throwing the below error.

Error: Invalid Data. Review all error messages below to correct your data. Apex trigger EstimateBudgetPerMonth caused an unexpected exception, contact your administrator: EstimateBudgetPerMonth: execution of BeforeUpdate caused by: System.DmlException: Upsert failed. First exception on row 0 with id a0Up00000000FHJEA2; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = a06p0000000N3WU) is currently in trigger EstimateBudgetPerMonth, therefore it cannot recursively update itself: []: Trigger.EstimateBudgetPerMonth: line 38, column 1

  • It looks as if you're updating the Opportunity inside your trigger. Does this error happen after insert, before update or on both? – mkorman Dec 16 '15 at 13:00
  • I used rollup summary field(Budget Allocation (Total)) in Opportunity object.When I update child object(budget allocation) then got an Error. – SFDC shaikh Dec 16 '15 at 14:00
  • I guess that updating the budget allocation causes an update to the opportunity, which is in turn in the middle of being updated by a trigger, which may cause your error. Can you offload the updating of the budget allocation to a future method? Perhaps all you need to do is decorate InsertBudgetOpp.insertChild and InsertBudgetOpp.updateChild with @future declaration – mkorman Dec 16 '15 at 14:02
  • Can you give me hint how to do this? – SFDC shaikh Dec 16 '15 at 14:06
1

After what you mentioned in the comments, it looks like updating the budget allocation causes an update to the opportunity, which is in turn in the middle of being updated by a trigger, which may cause the exception.

Perhaps you can work around this by adding future methods. Add these 2 methods to your class:

public with sharing class InsertBudgetOpp {

    // existing code still goes here...

    @future
    public static void updateChildFuture (Set <Id> oppId, Date startDate, Date endDate, Integer totalBudget) {
        Map < String, Budget_Allocation__c > baMap = updateChild (oppId, startDate, endDate, totalBudget);
        upsert baMap.values();
    }

    @future
    public static void insertChildFuture (Set <Id> oppId, Date startDate, Date endDate, Integer tb)
    {
        List <Budget_Allocation__c> baList = insertChild(Set <Id> oppId, Date startDate, Date endDate, Integer tb);
        insert baList;
    }
}

Then modify your trigger to call these future methods:

trigger EstimateBudgetPerMonth on Opportunity__c(after insert, before update) {
    Date startDate = Date.newInstance(2008, 1, 1);
    Date endDate = Date.newInstance(2008, 1, 30);
    Set < Id > oppId = new Set < Id > ();
    Integer totalBudget;
    for (Opportunity__c opp: Trigger.new) {
        startDate = opp.Campaign_Start_Date1__c;
        endDate = opp.Campaign_End_Date1__c;
        totalBudget = Integer.valueOf(opp.Budget1__c);
        oppId.add(opp.Id);
    }

    if (Trigger.isInsert) {
        System.debug('--===Insert==--#--===Insert==--#--===Insert==--');
        InsertBudgetOpp.insertChildFuture(oppId, startDate, endDate, totalBudget);
    } else if (Trigger.isUpdate) {
        System.debug('--===Update==--#--===Update==--#--===Update==--');
        InsertBudgetOpp.updateChildFuture(oppId, startDate, endDate, totalBudget);
    }
}

What this will do is, when the trigger fires, start an asynchronous method (perhaps on a different thread) that will update the child budget allocation objects. They will complete sometime in the future (generally it takes less than a minute, but Salesforce will never guarantee a timeframe). This may or may not be adequate for your solution, but it might prevent the exception.

Also note that when you end a test (with Test.stopTest()), this will guarantee that all future methods are executed.

For more on future methods, read: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_invoking_future_methods.htm

0

there was rollup summary on Opportunity. Which results in recurssion. so I compared changed values of budget , start date, end date. Then I run the update trigger. And that worked for me.

 Integer isChanged=0;
    Integer totalBudget;
    for (Opportunity__c opp: Trigger.new) {
        startDate = opp.Campaign_Start_Date1__c;
        endDate = opp.Campaign_End_Date1__c;
        totalBudget = Integer.valueOf(opp.Budget1__c);
        oppId.add(opp.Id);
        if (Trigger.isUpdate){
       If( Trigger.oldMap.get(opp.Id).Campaign_Start_Date1__c != Trigger.newMap.get(opp.Id).Campaign_Start_Date1__c){
        isChanged=1;
       }
       If( Trigger.oldMap.get(opp.Id).Campaign_End_Date1__c != Trigger.newMap.get(opp.Id).Campaign_End_Date1__c){
        isChanged=1;
       }
       If( Trigger.oldMap.get(opp.Id).Budget1__c != Trigger.newMap.get(opp.Id).Budget1__c){
        isChanged=1;
       }
       }
    }

Then for Update Check if it is is "1"

if (Trigger.isUpdate && isChanged == 1) {
        System.debug('--===Update==--#--===Update==--#--===Update==--');

        Map < String, Budget_Allocation__c > baNewMap = updateRec.updateChild(oppId, startDate, endDate, totalBudget);

        upsert baNewMap.values();
    }
  • 1
    Shaikh your answer would be a lot more meaningful to others running into a similar issue if you can explain what really changed or include some of your updated code. – Samuel De Rycke Dec 17 '15 at 9:43
  • Hey Samuel, Now I have updated my answer. Thanks for reminding. – SFDC shaikh Dec 21 '15 at 7:13

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.