I'm new to Apex/SalesForce and I'm trying to figure out how to create a scheduled job to create many opportunities based on Account information. It needs to create opportunities for all contacts with a certain anniversary date once a month. I was looking at this article: http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_batch_interface.htm#apex_batch_scheduleBatch_section and thinking that a batch scheduler is the answer, but i'm unsure about how to approach my problem... Thanks!
-
Its too broad! what do u intent to achieve? why opportunities?– Amit BangadJan 2, 2015 at 17:44
-
For renewals. Sales/Marketing wants to make our renewal process easier so they want an opportunity created for the accounts with an anniversary date two months after the process creates them– EmmaJan 2, 2015 at 17:58
1 Answer
Here's a really simple batch template you can use:
public class MyBatch implements Database.Batchable<SObject>, Database.Stateful, Schedulable
{
public static final String BATCH_JOB_TITLE = 'My Batch Job';
String errors = '';
public Database.QueryLocator start(Database.BatchableContext bc)
{
return Database.getQueryLocator( 'SELECT Id FROM Contact WHERE Anniversary_Date__c = TODAY' );
}
public void execute(Database.BatchableContext bc, List<SObject> scope)
{
if( scope.isEmpty() ) return;
List<Contact> contacts = (List<Contact>) scope;
List<Opportunity> opptiesToCreate = new List<Opportunity>();
for( Contact aContact : contacts )
{
opptiesToCreate.add( buildOpportunityForContact( aContact ) )
}
try
{
insert opptiesToCreate;
}
catch( Exception ex )
{
this.errors += ex.getMessage();
}
}
private Opportunity buildOpportunityForContact( Contact aContact )
{
Opportunity opptyFoContact = new Opportunity();
//YOUR LOGIC FOR BUILDING THE OPPTY
return opptyFoContact;
}
public void finish(Database.BatchableContext bc)
{
if( this.errors != '' )
{
AsyncApexJob job = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email
FROM AsyncApexJob
WHERE Id = :bc.getJobId()];
Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
mail.setToAddresses(new String[] {job.CreatedBy.Email});
mail.setSaveAsActivity( false );
mail.setSubject(BATCH_JOB_TITLE + job.Status);
String emailBody = BATCH_JOB_TITLE + ' processed ' + job.TotalJobItems + ' batches with '+ job.NumberOfErrors + ' failures.';
emailBody += '\n\n\nThe following errors occured:\n'+ errors;
mail.setPlainTextBody(emailBody);
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
}
}
public void execute(SchedulableContext sc)
{
MyBatch theBatch = new MyBatch();
Database.executeBatch( theBatch );
}
}
To summarize what's going on in here:
public Database.QueryLocator start(Database.BatchableContext bc): This method queries for the Contacts that fit the criteria you want, so you'll probably have to modify the SOQL query
public void execute(Database.BatchableContext bc, List scope): The code in here is performed on each batch of contacts queried by the start method. In this case, I'm looping through all of the contacts and building an Opportunity for each one. You'll have to define the logic for building the actual opportunities
public void finish(Database.BatchableContext bc): This code basically just runs if any errors were caught during execute. If there are errors, whoever scheduled the batch job will get an email with a list of the errors.
public void execute(SchedulableContext sc): This code allows the class to be scheduled. All it does it schedule the job.
-
I was able to get 46% test coverage by testing my logic for the opportunity, but even after looking at some of salesforce's information I can't vigure out how to test the start(Database.BatchableContext bc) method, nor the execute(Database.BatchableContext bc, List scope)... any thoughts are appreciated– EmmaJan 12, 2015 at 18:34
-
Use Database.executeBatch( new MyBatch() ); and that should run the entire batch and get you the test coverage you need.– SeanJan 13, 2015 at 21:00