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
Muhammad MoneebMuhammad Moneeb 

Too Many SOQL Error when deleting tasks from opportunity

Hello ! i am developing this code to delete tasks from previous opportunity's the problem in this code is this gives too many soql error because i have 1000's of opportunity's to work is there a way i can do this i mean can i delete tasks from opportunity's based on lastmodified date or all at once please help 
global class SalesOrderOpportunityTasks implements Schedulable{
    
    global static String CRON_EXP = '0 0 8 * * ? *'; 

    global void execute(SchedulableContext sc)
    {
        doOpportunityUpdates();
    }
    global void doOpportunityUpdates()
    {
          List<Opportunity> opps = [Select Id,StageName,Name From Opportunity Where LastModifiedDate > = 2015-11-27T00:00:00Z and LastModifiedDate < = 2015-12-01T00:00:00Z Limit 33];
          List<Sales_Order__c> so = new List<Sales_Order__c>();
        for (Opportunity o : opps)
        {
        System.debug('Debug Opportunity :' + o.Id +'----' + o.Name);
            so = [SELECT Id,OrderNum__c,Quote__c FROM Sales_Order__c WHERE Quote__c = :o.Id];
        }
        for(Sales_Order__c s :so)
            {
                if(s.OrderNum__c != Null)
                {
                 if(s.OrderNum__c == 'QUOTE WON' || s.OrderNum__c == 'QUOTE LOST' || s.OrderNum__c.charAt(0) == 67 || s.OrderNum__c.charAt(0) == 99)
                 {
                    
                    List<Task> deleteTasks = [SELECT Id, Type, Status, WhatId FROM Task WHERE WhatId = :s.Quote__c];
                    System.debug('Deug Tasks' +deleteTasks);
                    System.debug(s.Quote__c);
                  if(!deleteTasks.isEmpty())
                  {
                    System.debug('Mon'  + deleteTasks);
                    delete deleteTasks;
                    }
                    
                 }
                }
                
            }
        
        
        
    }
    

}

 
James LoghryJames Loghry
You're looping through a list of Opportunities and querying inside the loop.  This is an easy and surefire way to hit governor limits.  You'll want to move the Quote and Task queries outside of any loops.

You can do this by utilizing maps, as in my example below.  Note, my example is very simplified and may not even compile, but should get you in the right direction.

Also, please read the following blog post which highlights how to work within Salesforce governor limits and other Apex best practices: https://developer.salesforce.com/blogs/developer-relations/2015/01/apex-best-practices-15-apex-commandments.html
 
global class SalesOrderOpportunityTasks implements Schedulable{
    
    global static String CRON_EXP = '0 0 8 * * ? *'; 

    global void execute(SchedulableContext sc)
    {
        doOpportunityUpdates();
    }

    global void doOpportunityUpdates()
    {
          Map<Id,Opportunity> oppMap = new Map<Id,Opportunity>(
                [Select 
                    Id
                 From 
                    Opportunity 
                Where 
                    LastModifiedDate > = 2015-11-27T00:00:00Z 
                    And LastModifiedDate < = 2015-12-01T00:00:00Z 
                Limit 33]
          );

        delete 
            [Select 
                Id
                ,Type
                ,Status
                ,WhatId 
             From 
                Task 
            Where 
                What.Quote__c in :oppMap.keySet 
                And (
                    What.OrderNum__c = 'Quote Lost' 
                    Or What.OrderNum__c = 'Quote Won'
                )
           ];
    }
}



 
ManojjenaManojjena
HI Muhammad,
Try with below  code ,You are getting this error as you have query inside loop .
Just check the relationship name what I have added in query may be it is diffreent in your object .
 
global class SalesOrderOpportunityTasks implements Schedulable{
    global static String CRON_EXP = '0 0 8 * * ? *'; 
	global void execute(SchedulableContext sc) {
        doOpportunityUpdates();
    }
    global void doOpportunityUpdates(){
          List<Opportunity> opps = [SELECT Id,StageName,Name,(SELECT Id,OrderNum__c,Quote__c FROM Sales_Order__c WHERE OrderNum__c != null AND (OrderNum__c == 'QUOTE WON' OR OrderNum__c == 'QUOTE LOST')) From Opportunity WHERE LastModifiedDate > = 2015-11-27T00:00:00Z and LastModifiedDate < = 2015-12-01T00:00:00Z LIMIT 33];
        Set<Id> quoteIdSet=new Set<Id>(); 
        for (Opportunity op : opps){
            for(Sales_Order__c so: op.Sales_Order__r){
				if(so.OrderNum__c.charAt(0) == 67 || so.OrderNum__c.charAt(0) == 99){
					if(so.Quote__c != null){
						quoteIdSet.add(so.Quote__c);
					}
				}
			}
        }
		if(!quoteIdSet.isEmpty()){
		   List<Task> delTaskList = [SELECT Id, Type, Status, WhatId FROM Task WHERE WhatId IN:quoteIdSet];
		   if(!delTaskListisEmpty()){
		      try{
			    Delete delTaskList;
			  }catch(DmlException de ){
			      System.debug(de);
			  }
		   }
		}
    } 
}
Also I am not sure why you have added LIMIT 33 in opportunity query .Also logic I kept same as your code .
Let me know if it helps !!
Thanks
Manoj
 
Muhammad MoneebMuhammad Moneeb
@James Loghry i didn't understand your where clause on line 31 what is "What.Quote__c" Quote__c is custom field in SalesOrder Object 
Muhammad MoneebMuhammad Moneeb
@Manoj  i didn't understand the relationship where to add it its giving error in soql query about "Didn't understand the relationship" i looked in salesorder object and the relation between opportunity and salesorder is names Sales_Orders what should i do User-added image
ManojjenaManojjena
Hi Muhammad,

Try with below code it will hep !!
 
global class SalesOrderOpportunityTasks implements Schedulable{
    global static String CRON_EXP = '0 0 8 * * ? *'; 
	global void execute(SchedulableContext sc) {
        doOpportunityUpdates();
    }
    global void doOpportunityUpdates(){
          List<Opportunity> opps = [SELECT Id,StageName,Name,(SELECT Id,OrderNum__c,Quote__c FROM Sales_Orders__r WHERE OrderNum__c != null AND (OrderNum__c == 'QUOTE WON' OR OrderNum__c == 'QUOTE LOST')) From Opportunity WHERE LastModifiedDate > = 2015-11-27T00:00:00Z and LastModifiedDate < = 2015-12-01T00:00:00Z LIMIT 33];
        Set<Id> quoteIdSet=new Set<Id>(); 
        for (Opportunity op : opps){
            for(Sales_Order__c so: op.Sales_Orders__r){
				if(so.OrderNum__c.charAt(0) == 67 || so.OrderNum__c.charAt(0) == 99){
					if(so.Quote__c != null){
						quoteIdSet.add(so.Quote__c);
					}
				}
			}
        }
		if(!quoteIdSet.isEmpty()){
		   List<Task> delTaskList = [SELECT Id, Type, Status, WhatId FROM Task WHERE WhatId IN:quoteIdSet];
		   if(!delTaskListisEmpty()){
		      try{
			    Delete delTaskList;
			  }catch(DmlException de ){
			      System.debug(de);
			  }
		   }
		}
    } 
}


Thanks
Manoj
Muhammad MoneebMuhammad Moneeb

@James Loghry @Manoj Thank You both of you i created new code by understanding both of your codes and it worked Cheers!