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
Lynn the AFTD SysAdminLynn the AFTD SysAdmin 

Attempting to schedule a batch Apex on Opportunities without results

I have written the following piece of batch apex code to be run nightly (using a scheduable class call). I have tested all the stage and date conditions seperately, but I cannot seem to get the class to work. I get no error messages on compilation or run time, but nothing ever happens (the calls for follow-up or email alert aren't invoked). I am drawing a blank an have stared at the code for too long, any help would be appreciated!

Cheers! 

global class UpdateOppstoDormant implements Database.Batchable<sObject>{

    global Database.QueryLocator start(Database.BatchableContext BC){

        String query = 'SELECT Id, StageName, CloseDate, NextActivityDate__c, LastActivityDate FROM Opportunity WHERE StageName !=\''+String.escapeSingleQuotes('Received')+'\'';
        return Database.getQueryLocator(query);
        
    } //end query
    
    global void execute(Database.BatchableContext BC, List<Opportunity> scope){

        List<ID> DormantProspectIDs = New List<ID>();
        List<ID> DormantRenewalIDs  = New List<ID>();
       
        for(sObject s : scope){
            
            Opportunity o = (Opportunity)s;
            
            //check if opportunities are prospects
            if(o.Stagename == 'Prospect ID' || o.Stagename == 'Prospect Engaged'){
                
                // check activity dates to establish Prospect dormancy
                if((o.LastActivityDate == NULL || o.LastActivityDate.daysBetween(date.today()) > 30) &&
                    (date.today().daysBetween(o.CloseDate) < 180) &&
                           (o.NextActivityDate__c == NULL || o.NextActivityDate__c < date.today()) ){

                    DormantProspectIDs.add(o.ID);
                      
                } //end activity date check
            } //end dormant prospects
            
            //check if opportunities are renewals
            if(o.StageName == 'Renewal Potential' || o.StageName == 'Renewal Likely'){
               
                // check activity dates to establish Renewal dormancy
                if((o.LastActivityDate == NULL || o.LastActivityDate.daysBetween(date.today()) > 90) &&
                (o.NextActivityDate__c == NULL || date.today().daysBetween(o.NextActivityDate__c) > 90) ){
                    
                    DormantRenewalIDs.add(o.ID);
                    
                } //end activity date check
                
            } //end dormant Renewals

        }
        
        //for Dormant Prospects
        List<Opportunity> DormantProspects = [SELECT id, OwnerID FROM Opportunity WHERE id in :DormantProspectIDs];
        
          InactiveOpp.NewFollowUpTask(DormantProspects);
          InactiveOpp.OwnerEmailAllert(DormantProspects);
      
        //for Dormant Renewals
        List<Opportunity> DormantRenewals = [SELECT id, OwnerID FROM Opportunity WHERE id in :DormantRenewalIDs];
        
          InactiveOpp.RenewalFolloUpTask(DormantRenewals);
          InactiveOpp.PotentialRenewalDomantAllert(DormantRenewals);
        
    } //end execute
    
    global void finish(Database.BatchableContext BC){
        
    } //end finish

} //end class
 
Andy BoettcherAndy Boettcher
First thing I'd do is throw in some System.Debug(var); statements around your code to see what all is being set.  If you are never seeing any of the "Serial Batch" logs appear, first place I'd look is your start() method.

Try this:  
Set<String> setStageNames = new Set<String();
setStageNames.add('Received');

String query = 'SELECT Id, StageName, CloseDate, NextActivityDate__c, LastActivityDate FROM Opportunity WHERE StageName IN :setStageNames';

return Database.getQueryLocator(query);
Lynn the AFTD SysAdminLynn the AFTD SysAdmin
Andy,

I made the code imrpovements you suggested, however, still nothing ever happens as described above.

Just for the sake of testing I went through the steps in the online Apex workbook (https://developer.salesforce.com/docs/atlas.en-us.apex_workbook.meta/apex_workbook/apex_scheduled_intro.htm), but also get the same results. The code in it's various parts tests fine, but when tested as a scheudable test run it passes without any of the action.

Here my test code:
 
global class MySchedulableClass implements Schedulable {

   global void execute(SchedulableContext ctx) {

      CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime

                FROM CronTrigger WHERE Id = :ctx.getTriggerId()];
      System.debug(ct.CronExpression);

      System.debug(ct.TimesTriggered);

      Task t = new Task(Whatid = '006n00000034F8y', Subject = 'MySchedulableClass', OwnerID = '00530000006O5Co', 
                              Status = 'Not Started', ActivityDate = Date.Today() + 2 , Priority = 'Normal');

      insert t;
   } // end execute
} // end schedulable
 
@isTest
private class TestSchedulableClass {

   // CRON expression: midnight on March 15.
   // Because this is a test, job executes
   // immediately after Test.stopTest().
   public static String CRON_EXP = '0 0 0 15 3 ? 2022';

   static testmethod void test() {
      Test.startTest();

      // Schedule the test job
      String jobId = System.schedule('ScheduleApexClassTest',
                        CRON_EXP, 
                        new MySchedulableClass());
         
      // Get the information from the CronTrigger API object
      CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, 
         NextFireTime
         FROM CronTrigger WHERE id = :jobId];

      // Verify the expressions are the same
      System.assertEquals(CRON_EXP, 
         ct.CronExpression);

      // Verify the job has not run
      System.assertEquals(0, ct.TimesTriggered);

      // Verify the next time the job will run
      System.assertEquals('2022-03-15 00:00:00', 
         String.valueOf(ct.NextFireTime));
      // Verify the scheduled job hasn't run yet.
      task[] myt = [SELECT Id FROM task
                             WHERE Subject = 'MySchedulableClass'];
      System.assertEquals(myt.size(), 0);
      Test.stopTest();

      // Now that the scheduled job has executed after Test.stopTest(),
      //   fetch the new task that got added.
      myt = [SELECT Id FROM task
                             WHERE Subject = 'MySchedulableClass'];
      System.assertEquals(myt.size(), 1);

   }
}

Any ideas why I am still failing?