3

I am trying to automate the following functionality: When an opportunity stage becomes 'Pending Payment', insert 2 'OpportunityLineItems' using 2 predefined Products.

This is my current code. I am calling the class on an before update event on the Opportunity Sobject:

public void addProductWhenStageIsPendingPayment() {

        Set<id> ids = new Set<Id>();
        for(Opportunity o : newOpportunities.values()){
            if(o.stagename=='Pending Payment')
                ids.add(o.id);
        }


        List<Opportunity> opps = [Select id, Start_Date__c, End_Date__c,CurrencyIsoCode,PriceBook2id from Opportunity where id in: ids];// and  Start_Date__c!=null and  End_Date__c!=null];

        List<Product2> products = [Select id,name, CurrencyIsoCode from Product2];
        Id product1Id=NULL;
        id product2id=NULL;

        list<PriceBookEntry> priceBookList = [SELECT Id, Product2Id, Product2.Id, Product2.Name FROM PriceBookEntry 
                                             WHERE  PriceBook2.isStandard=true ];
        Id priceBook1Id=NULL;
        id priceBook2id=NULL;

        List<OpportunityLineItem> oppsline = new List<OpportunityLineItem>();

        for(Opportunity op : opps)  
        {
            // get the product ids
             for(Product2 p : products)
            {
                if(p.name=='Name A' & p.CurrencyIsoCode==op.CurrencyIsoCode)
                product1Id=p.id;
                if(p.name=='Name B' &   p.CurrencyIsoCode==op.CurrencyIsoCode)
                product2Id=p.id;
             }

            // get the price book ids
            for(PriceBookEntry pbe : priceBookList)
            {
                if(pbe.Product2Id== product1Id)
                    priceBook1id = pbe.id;
                if(pbe.Product2Id == product2Id)
                    priceBook2id = pbe.id;
            }



            Date startDate = op.Start_Date__c;
            Date endDate = op.End_Date__c;
            Integer monthDiff = startDate.monthsBetween(endDate);
            monthDiff++;

            for(integer i=0; i<monthDiff ; i++)
            {
                OpportunityLineItem oli1 = new OpportunityLineItem( PricebookEntryId=  priceBook1Id  , Opportunityid=op.id,UnitPrice=1000,Quantity=22,ServiceDate=endDate,  Description='Name A',Estimate_Actual__c='Estimated');
                OpportunityLineItem oli2 = new OpportunityLineItem( PricebookEntryId=  priceBook2Id , Opportunityid=op.id,UnitPrice=250,Quantity=22,ServiceDate=endDate,    Description='Name B',Estimate_Actual__c='Estimated');
                oppsline.add(oli1);
                oppsline.add(oli2);
            }

        }

        insert oppsline;

    }

This is the current error I am getting:

Error: Invalid Data. Review all error messages below to correct your data. Apex trigger MasterOpportunityTrigger caused an unexpected exception, contact your administrator: MasterOpportunityTrigger: execution of BeforeUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = 'xxxxxxxxxx') is currently in trigger MasterOpportunityTrigger, therefore it cannot recursively update itself: []: Class.ClassOpportunityHandler.addProductWhenStageIsPendingPayment: line 81, column 1

1

1 Answer 1

2

If you are adding child records in a before trigger when there is a rollup summary field, you will experience this issue. Simply move the application of this logic to an after trigger. It's one of the reasons Salesforce's documentation on Triggers states (bold emphasis mine):

There are two types of triggers:

  • Before triggers are used to update or validate record values before they’re saved to the database.
  • After triggers are used to access field values that are set by the system (such as a record's Id or LastModifiedDate field), and to affect changes in other records, such as logging into an audit table or firing asynchronous events with a queue. The records that fire the after trigger are read-only.
3
  • thanks for your answer. I did as you suggested but now Im getting a PriceEntryBook field integrity exception. I tried hardcoding the PriceBBookEntry ids as well, but I couldn't figure out what is causing this. Jul 28, 2016 at 8:19
  • @Marc Well, it sounds like you resolved this issue at play here and now you have a new question.
    – Adrian Larson
    Jul 28, 2016 at 12:30
  • ok sure I ll mark this question as closed then Jul 28, 2016 at 12:36

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.