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
msimondsmsimonds 

Chatter Trigger error in production

I am in need of assistance, any help would be appreciated;


We have a trigger that updates information on Chatter feeds when a product is chaged on an Opportunity Line Item.

 

We are now receiving exception errors due to the governing limit on queries. 

 

The code:

 

trigger LineItemToOpportunityFeedUpdate on OpportunityLineItem (after update) {
    List<FeedPost> posts = new List<FeedPost>();
    Set<Id> pbeIds = new Set<Id>();
    
    for(OpportunityLineItem newOLI : Trigger.new) {
        OpportunityLineItem oldOLI = Trigger.oldMap.get (newOLI.id);
        //System.debug('New: '+newOLI.Part_Outcome__c+' Old: '+oldOLI.Part_Outcome__c);
        
        if(newOLI.Part_Outcome__c != oldOLI.Part_Outcome__c) {
            
            List<OpportunityFeed> opportunityFeedPosts = [SELECT Id, Type, FeedPost.Body
                                                            From OpportunityFeed
                                                            Where ParentID = :newOLI.OpportunityID
                                                            ORDER BY CreatedDate DESC];
                       
            pbeIds.add(newOLI.PricebookEntryId);
            Map<Id, PricebookEntry> entries = new Map<Id, PricebookEntry>([select Product2.ProductCode from PricebookEntry where id in :pbeIds]);

            pbeIds.add(newOLI.opportunityid);
            Map<Id, Opportunity> Opp = new Map<Id, Opportunity>([select Account.Name, Account.ID from Opportunity where id in :pbeIds]);
                                                                            
            //String bodyText = 'Got here....'+Opp.get(newOLI.OpportunityId).Account.Name+'';                                                               
            String bodyText = 'has updated the '+entries.get(newOLI.Pricebookentryid).Product2.ProductCode+' from '+oldOLI.Part_Outcome__c+' to '+newOLI.Part_Outcome__c+' at '+opp.get(newOLI.OpportunityId).Account.Name+'';    
            
            if(opportunityFeedPosts.size() == 0 || opportunityFeedPosts[0].FeedPost.Body != bodyText) {
                //System.debug('OpportunityFeed Posts: '+opportunityFeedPosts[0]);

               
                FeedPost opportunityPost = new Feedpost();
                opportunityPost.Type = 'LinkPost';
                opportunityPost.Title = ''+entries.get(newOLI.Pricebookentryid).Product2.ProductCode+' socket details';
                opportunityPost.Body = bodyText;
                String id = String.valueOf(newOLI.Id).substring(0,15);
                opportunityPost.LinkURL = 'https://na2.salesforce.com/'+id;
                opportunityPost.ParentID = newOLI.opportunityid;
                posts.add(opportunityPost);
                System.Debug('Got Here but did not post');
                
                /*@Version 1.3 - removed because I could not get it to display one feedpost with 2 links in the Opportunity Post Title
                FeedPost opportunityPost2 = new FeedPost ();
                opportunityPost2.Type = 'LinkPost';
                opportunityPost2.Title = 'Account Details';
                opportunityPost2.Body = bodyText;
                String id2 = String.valueOf(opp.get(newOLI.OpportunityId).Account.Id).substring(0,15);
                opportunityPost2.LinkURL = 'https://na2.salesforce.com/'+id2;
                opportunityPost2.ParentID = newOLI.opportunityid;
                posts.add(opportunityPost2);
                system.debug('got here and it should have posted twice');
                */
                }
            }
         
        //This section will trigger a feed update to the Opportunity if the Max Potential of any given socket is increased by $1,000,000           
        if(newOLI.Max_Potential__c >= oldOLI.Max_Potential__c + 1000000){
            
            List<OpportunityFeed> opportunityFeedPosts = [Select Id, Type, FeedPost.Body
                                                            From OpportunityFeed
                                                            Where ParentId = :newOLI.OpportunityID
                                                            ORDER BY CreatedDate DESC];
        
            //@1.1 Code that will traverse the Pricebookentry ID and pull back the part number. We could not directly access the part number from the opportunitylineitem.productcode field
            pbeIds.add(newOLI.PricebookEntryId);    
            Map<Id, PricebookEntry> entries = new Map<Id, PricebookEntry>([select Product2.ProductCode from PricebookEntry 
                                                                            where id in :pbeIds]);
                                                                            
            //Traverse the opportunity object to return the Account detail and get the account name                                                                
            pbeIds.add(newOLI.opportunityid);
            Map<Id, Opportunity> Opp = new Map<Id, Opportunity>([select Account.Name, Account.ID from Opportunity where id in :pbeIds]);                                                                
            
            //Round the dollar values to whole numbers
            decimal NewWholeMaxPotential = newOLI.Max_Potential__c;
            decimal maxpotentialdifference = newOLI.Max_Potential__c/1.0 - oldOLI.Max_Potential__c/1.0;                                                             
            
            String bodyText = 'has increased the Max Potential of the '+entries.get(newOLI.Pricebookentryid).Product2.ProductCode+' by $'+maxpotentialdifference+' at '+opp.get(newOLI.OpportunityId).Account.Name+'';
                                                                                                
        if(opportunityFeedPosts.size() == 0 || opportunityFeedPosts[0].FeedPost.Body != bodyText) {
                //System.debug('OpportunityFeed Posts: '+opportunityFeedPosts[0]);
                
                FeedPost opportunityPost = new FeedPost ();
                opportunityPost.Type = 'LinkPost';
                opportunityPost.Title = ''+entries.get(newOLI.Pricebookentryid).Product2.ProductCode+' socket details';
                opportunityPost.Body = bodyText;
                String id = String.valueOf(newOLI.id).substring(0,15);
                opportunityPost.LinkURL = 'https://na2.salesforce.com/'+id;
                opportunityPost.ParentID = newOLI.opportunityid;
                posts.add(opportunityPost);
                }    
            }
          
        //This section will update the Chatter feed when the PS3 checkbox is marked true
        //if(newOLI.Socket_Strategy_Required__c == true && oldOLI.Socket_Strategy_Required__C == false){
        if(newOLI.Socket_Strategy_Required__c == true && oldOLI.Socket_Strategy_Required__c == false){  
            List<OpportunityFeed> opportunityFeedPosts = [Select Id, Type, FeedPost.Body
                                                            From OpportunityFeed
                                                            Where ParentId = :newOLI.OpportunityID
                                                            ORDER BY CreatedDate DESC];
                                                      
            pbeIds.add(newOLI.PricebookEntryId);

            Map<Id, PricebookEntry> entries = new Map<Id, PricebookEntry>([select Product2.ProductCode from PricebookEntry 
                                                                            where id in :pbeIds]);
            
            
            //OppOwnerFirstName = get.FirstName;
            //OppOwnerLastName = get.LastName;
                                                                            
            String bodyText = ' has required a PS3 for the '+entries.get(newOLI.Pricebookentryid).Product2.ProductCode+'.';                                             
            //String bodyText = ''+opportunity.OwnerId+' has required a PS3 for the '+entries.get(newOLI.Pricebookentryid).Product2.ProductCode+'.';
            
        if(opportunityFeedPosts.size() == 0 || opportunityFeedPosts[0].FeedPost.Body != bodyText) {
                //System.debug('OpportunityFeed Posts: '+opportunityFeedPosts[0]);
                
                FeedPost opportunityPost = new FeedPost ();
                opportunityPost.Type = 'LinkPost';
                opportunityPost.Title = 'Click here for the PS3';
                opportunityPost.Body = bodyText;
                String id = String.valueOf(newOLI.id).substring(0,15);
                opportunityPost.LinkURL = 'https://na2.salesforce.com'+newOLI.PS3_Link__c+'';
                opportunityPost.ParentID = newOLI.opportunityid;
                posts.add(opportunityPost);
                }    
            }*/         
        }
        insert posts;
}

 

Error:

 

Trigger.LineItemToOpportunityFeedUpdate: line 40, column 65

 

 

That line of code is:

 

Map<Id, Opportunity> Opp = new Map<Id, Opportunity>([select Account.Name, Account.ID from Opportunity where id in :pbeIds]);

 I know that the query should be outside the for loop and please understand that I am still fairly new to APEX. 

 

Where can I place these queries and still have this trigger work as designed.

 

Thanks to anyone in advance!!

 

~Mike

Best Answer chosen by Admin (Salesforce Developers) 
WYamWYam

Thanks. We figured it out - I guess I'll mark this as solved.

All Answers

msimondsmsimonds

Please, Anyone ???

 

~Mike

d3developerd3developer

Is there an error message that come along with the line number?

WYamWYam

 

Apex script unhandled trigger exception by user/organization: <user ID>/<org ID>

LineItemToOpportunityFeedUpdate: execution of AfterUpdate

caused by: System.Exception: Too many SOQL queries: 21

Trigger.LineItemToOpportunityFeedUpdate: line 40, column 65

Debug Log:

 

 

One of our users said that she got the error after she did an "edit all" that failed on the opportunity line item. She said that it wouldn't let her save but apparently it kicked off the trigger anyway... is this even possible? The trigger says, "On Update" so I figured it would not trigger until there was a save to the database. Maybe I don't understand correctly?

 

Thanks for your help in advance.

msimondsmsimonds

We could really use some help on a correction for this. We cannot figure it out

 

 

Please someone can you look at it

 

jostmanjostman

You need to look into moving out the soql query outside the for loop

WYamWYam

Thanks. We figured it out - I guess I'll mark this as solved.

This was selected as the best answer