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
Abhi MalikAbhi Malik 

Please Help For Batch Class

Hi everyone
am trying to write a batch class for my project 
when i will create a pledge for donation then based on the duration our transactions are created by trigger but those transactions are not more then 12 but, if my duration is 24 months then .it will create 12 transaction by trigger after that when my list size of transactions is less then 12 every month then it will create a new transaction for that 12 th month and repeat this process for the complete duration .
code:

global class BatchClassPledgeTransaction implements Database.batchable<sObject> {
        String query;
     list<Transaction__c > transList=new list<Transaction__c >();
     // Start Method
    global Database.querylocator start(Database.BatchableContext BC){
        Query = 'Select id,name,Duration__c,Start_Date__c,End_Date__c from Pledge__c';   
        return Database.getQueryLocator(query);
    }
     // Execute Logic
    global void execute(Database.BatchableContext BC, List<Pledge__c> Scope){
       Id PledgeRecTypeCard = Schema.SObjectType.Pledge__c.getRecordTypeInfosByName().get('Card').getRecordTypeId();
       Id PledgeRecTypeGIRO = Schema.SObjectType.Pledge__c.getRecordTypeInfosByName().get('GIRO').getRecordTypeId();
       Id PledgeRecTypeOnline = Schema.SObjectType.Pledge__c.getRecordTypeInfosByName().get('Online').getRecordTypeId();
       Id PledgeRecTypeRecurringCash = Schema.SObjectType.Pledge__c.getRecordTypeInfosByName().get('Recurring Cash').getRecordTypeId();
       Id PledgeRecTypeRecurringCheque  = Schema.SObjectType.Pledge__c.getRecordTypeInfosByName().get('Recurring Cheque ').getRecordTypeId();
       Id TransactionRecTypeCard = Schema.SObjectType.Transaction__c .getRecordTypeInfosByName().get('Card').getRecordTypeId();
       Id TransactionRecTypeGIRO = Schema.SObjectType.Transaction__c .getRecordTypeInfosByName().get('GIRO').getRecordTypeId();
       Id TransactionRecTypeOnline = Schema.SObjectType.Transaction__c .getRecordTypeInfosByName().get('Online').getRecordTypeId();
       Id TransactionRecTypeRecurringCash = Schema.SObjectType.Transaction__c .getRecordTypeInfosByName().get('Recurring Cash').getRecordTypeId();
       Id TransactionRecTypeRecurringCheque  = Schema.SObjectType.Transaction__c .getRecordTypeInfosByName().get('Recurring Cheque ').getRecordTypeId();
       
       for(Pledge__c plg:Scope){
            Integer i=0;
            Integer loopiterater=0;
            Integer j=integer.valueof(plg.Duration__c)-12;
            Integer monthDiff = plg.Start_Date__c.monthsBetween(plg.End_Date__c);
            loopiterater=monthDiff;
        
       if(integer.valueof(plg.Duration__c)>12||loopiterater>12){ 
              for(i=0;i<=j;i++){
                Transaction__c tran= new Transaction__c ();
                       tran.Transaction_Date__c=plg.Start_Date__c.addMonths(i);
                       tran.Pledge__c=plg.id;
                       tran.Amount_Reconciled__c=plg.Amount__c;
                       tran.Donor__c=plg.Account__c;
                       tran.Status__c=plg.Status__c;
                      
                           if(plg.recordtypeid==PledgeRecTypeCard){
                              tran.recordtypeid=TransactionRecTypeCard;
                           } 
                            
                           if(plg.recordtypeid==PledgeRecTypeGIRO){
                              tran.recordtypeid=TransactionRecTypeGIRO;
                           } 
                           
                           if(plg.recordtypeid==PledgeRecTypeOnline){
                              tran.recordtypeid=TransactionRecTypeOnline;
                           } 
                           
                           if(plg.recordtypeid==PledgeRecTypeRecurringCash){
                              tran.recordtypeid=TransactionRecTypeRecurringCash;
                           } 
                           
                           if(plg.recordtypeid==PledgeRecTypeRecurringCheque){
                              tran.recordtypeid=TransactionRecTypeRecurringCheque;
                           } 
                       translist.add(tran);
            }
        
         }
        
       }
    }
     global void finish(Database.BatchableContext BC){
    }
}
Best Answer chosen by Abhi Malik
UC InnovationUC Innovation
The actual batch class is the following:
 
global class BatchClassPledgeTransaction implements Database.batchable<sObject> {
    final String query;
    list<Transaction__c> transList = new list<Transaction__c>();
    
	// constructor
	global BatchClassPledgeTransaction() {
		query = 'SELECT Id, ' +
					   'Name, ' +
					   'Duration__c, ' +
					   'Start_Date__c, ' +
					   'End_Date__c ' +
				'FROM Pledge__c';
	}
	
	// Start Method
    global Database.querylocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }
    
	// Execute Logic
    global void execute(Database.BatchableContext BC, List<Pledge__c> Scope){
		Map<String, Schema.RecordTypeInfo> pledgeRecordTypeInfosByNameMap = Schema.SObjectType.Pledge__c.getRecordTypeInfosByName();
		Map<String, Schema.RecordTypeInfo> transactionRecordTypeInfosByNameMap = Schema.SObjectType.Transaction__c.getRecordTypeInfosByName();
		
		Id PledgeRecTypeCard = pledgeRecordTypeInfosByNameMap.get('Card').getRecordTypeId();
        Id PledgeRecTypeGIRO = pledgeRecordTypeInfosByNameMap.get('GIRO').getRecordTypeId();
        Id PledgeRecTypeOnline = pledgeRecordTypeInfosByNameMap.get('Online').getRecordTypeId();
        Id PledgeRecTypeRecurringCash = pledgeRecordTypeInfosByNameMap.get('Recurring Cash').getRecordTypeId();
        Id PledgeRecTypeRecurringCheque = pledgeRecordTypeInfosByNameMap.get('Recurring Cheque').getRecordTypeId();
        
		Id TransactionRecTypeCard = transactionRecordTypeInfosByNameMap.get('Card').getRecordTypeId();
        Id TransactionRecTypeGIRO = transactionRecordTypeInfosByNameMap.get('GIRO').getRecordTypeId();
        Id TransactionRecTypeOnline = transactionRecordTypeInfosByNameMap.get('Online').getRecordTypeId();
        Id TransactionRecTypeRecurringCash = transactionRecordTypeInfosByNameMap.get('Recurring Cash').getRecordTypeId();
        Id TransactionRecTypeRecurringCheque = transactionRecordTypeInfosByNameMap.get('Recurring Cheque').getRecordTypeId();
		
		Set<Id> pledgeIdSet = new Map<Id,SObject>(Scope).keySet()
		
		// Query once per batch job
		// SOQL limits
		AggregateResult[] numberOfTransactionsPerPledge = [SELECT COUNT(id)
														   FROM Transaction__c
														   WHERE Pledge__c IN :pledgeIdSet
														   GROUP BY Pledge__c];
		
        for (Pledge__c plg : Scope){
			// make sure that we even need to create transactions. 
			// avoid going over
			if (numberOfTransactionsPerPledge.get(plg.Id) < integer.valueof(plg.Duration__c)) {
				Integer j = integer.valueof(plg.Duration__c) - 12;
			
				for (Integer i = 0; i <= j; i++){
					Transaction__c tran = new Transaction__c();
					
					// Transactions start where trigger left off
					tran.Transaction_Date__c = plg.Start_Date__c.addMonths(i + 12); 
					tran.Pledge__c = plg.id;
					tran.Amount_Reconciled__c = plg.Amount__c;
					tran.Donor__c = plg.Account__c;
					tran.Status__c = plg.Status__c;
						  
					if (plg.recordtypeid == PledgeRecTypeCard){
						tran.recordtypeid = TransactionRecTypeCard;
					} 
								
					if (plg.recordtypeid == PledgeRecTypeGIRO){
						tran.recordtypeid = TransactionRecTypeGIRO;
					} 
							   
					if (plg.recordtypeid == PledgeRecTypeOnline){
						tran.recordtypeid = TransactionRecTypeOnline;
					} 
							   
					if (plg.recordtypeid == PledgeRecTypeRecurringCash){
						tran.recordtypeid = TransactionRecTypeRecurringCash;
					} 
							   
					if (plg.recordtypeid == PledgeRecTypeRecurringCheque){
						tran.recordtypeid = TransactionRecTypeRecurringCheque;
					} 
					
					transList.add(tran);
				}
			}
		}
		
		// insert all at once
		// DML limits
		insert transList;
    }
    
	// finish
	global void finish(Database.BatchableContext BC){}
}
Please feel free to reply with questions if you have any further concerns.

as for the schedule class 
 
// Sample call from anonymous apex window:
//
// Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
// example last day of the month at 12am
// String cronStr = '0 0 0 ? * L'; 
// BatchClassPledgeTransactionSchedule sched = BatchClassPledgeTransactionSchedule();
// System.schedule('BatchClassPledgeTransaction ', cronStr, sched);
global class BatchClassPledgeTransactionSchedule implements Schedulable {
	global void execute(SchedulableContext sc) {
        //  Instantiate batch class 
		Id batchInstanceId = Database.executeBatch(new BatchClassPledgeTransaction());
    }
}

Reffer to the documentation (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm)if you have any questions regarding the schedule class.

Hope this helps!
 

All Answers

UC InnovationUC Innovation
Hi Abhi,

I cleaned up your code a bit before I start to work on it but I dont think I understand just what it is you want the code to do. From my understanding, you want to create transactions based on the following criteria on the duration of the pledge:

1. if the duration is 12 months then create 12 transactions via some trigger 
2. if the duration is 24 months then create the first 12 transactions monthly by the 12-th month and reevaluate the criteria.

Please clarify. This is what i can gather so far.
 
global class BatchClassPledgeTransaction implements Database.batchable<sObject> {
    final String query;
    list<Transaction__c> transList = new list<Transaction__c>();
    
	// constructor
	global BatchClassPledgeTransaction() {
		query = 'SELECT Id, ' +
					   'Name, ' +
					   'Duration__c, ' +
					   'Start_Date__c, ' +
					   'End_Date__c ' +
				'FROM Pledge__c';
	}
	
	// Start Method
    global Database.querylocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }
    
	// Execute Logic
    global void execute(Database.BatchableContext BC, List<Pledge__c> Scope){
		Map<String, Schema.RecordTypeInfo> pledgeRecordTypeInfosByNameMap = Schema.SObjectType.Pledge__c.getRecordTypeInfosByName();
		Map<String, Schema.RecordTypeInfo> transactionRecordTypeInfosByNameMap = Schema.SObjectType.Transaction__c.getRecordTypeInfosByName();
		
		Id PledgeRecTypeCard = pledgeRecordTypeInfosByNameMap.get('Card').getRecordTypeId();
        Id PledgeRecTypeGIRO = pledgeRecordTypeInfosByNameMap.get('GIRO').getRecordTypeId();
        Id PledgeRecTypeOnline = pledgeRecordTypeInfosByNameMap.get('Online').getRecordTypeId();
        Id PledgeRecTypeRecurringCash = pledgeRecordTypeInfosByNameMap.get('Recurring Cash').getRecordTypeId();
        Id PledgeRecTypeRecurringCheque = pledgeRecordTypeInfosByNameMap.get('Recurring Cheque').getRecordTypeId();
        
		Id TransactionRecTypeCard = transactionRecordTypeInfosByNameMap.get('Card').getRecordTypeId();
        Id TransactionRecTypeGIRO = transactionRecordTypeInfosByNameMap.get('GIRO').getRecordTypeId();
        Id TransactionRecTypeOnline = transactionRecordTypeInfosByNameMap.get('Online').getRecordTypeId();
        Id TransactionRecTypeRecurringCash = transactionRecordTypeInfosByNameMap.get('Recurring Cash').getRecordTypeId();
        Id TransactionRecTypeRecurringCheque = transactionRecordTypeInfosByNameMap.get('Recurring Cheque').getRecordTypeId();
       
        for (Pledge__c plg : Scope){
            Integer j = integer.valueof(plg.Duration__c) - 12;
            Integer monthDiff = plg.Start_Date__c.monthsBetween(plg.End_Date__c);
            Integer loopiterater = monthDiff;
        
			if (integer.valueof(plg.Duration__c) > 12 || loopiterater > 12){ 
				for (Integer i = 0; i <= j; i++){
					Transaction__c tran = new Transaction__c();
					tran.Transaction_Date__c = plg.Start_Date__c.addMonths(i);
					tran.Pledge__c = plg.id;
					tran.Amount_Reconciled__c = plg.Amount__c;
					tran.Donor__c = plg.Account__c;
					tran.Status__c = plg.Status__c;
						  
					if (plg.recordtypeid == PledgeRecTypeCard){
						tran.recordtypeid = TransactionRecTypeCard;
					} 
								
					if(plg.recordtypeid == PledgeRecTypeGIRO){
						tran.recordtypeid = TransactionRecTypeGIRO;
					} 
							   
					if(plg.recordtypeid == PledgeRecTypeOnline){
						tran.recordtypeid = TransactionRecTypeOnline;
					} 
							   
					if(plg.recordtypeid == PledgeRecTypeRecurringCash){
						tran.recordtypeid = TransactionRecTypeRecurringCash;
					} 
							   
					if(plg.recordtypeid == PledgeRecTypeRecurringCheque){
						tran.recordtypeid = TransactionRecTypeRecurringCheque;
					} 
					
					transList.add(tran);
				}
			}
        }
    }
    
	// finish
	global void finish(Database.BatchableContext BC){}
}

 
Abhi MalikAbhi Malik
Thanks alot for reply and helping me.
let me clear the logic , if somebody do a pledge for donation and the duration of pledge is16 months then my trigger will create only 12 transactions(like start date is 1 sep 2016 and end date is 1 dec 2017 ) then my trigger will create the records of transaction till 1-august-2017 ,trigger will not create all 16 records, on 1st sep 2016 when my 1st transaction is done then my 11 transections are left then my batch class will create a record for 1 sep 2017 same process when second transection is done on 1 oct 2016 then batch class will create a record for 1 oct 2017 till complete 16 transactions are not done. 
Abhi MalikAbhi Malik
you need to check the pleadge record duration and start date and need to create one month transaction record.
 let say duration is 24 and your trigger created transaction form 1 Sept 2016 to 1 Aug 2017.
 now when your batch class will create a new record for 1Sept 2017 on 1Aug 2016.

 
UC InnovationUC Innovation
does the trigger call this batch? if so, does this batch only create one transaction record per pledge? or does this batch create all remaining transactions after the initial 12 have been generated?
Abhi MalikAbhi Malik
This class Will create all the remaining records. Every month till all the records are created and we have to write a schedule class also for this to schedule for every month. 
UC InnovationUC Innovation
The actual batch class is the following:
 
global class BatchClassPledgeTransaction implements Database.batchable<sObject> {
    final String query;
    list<Transaction__c> transList = new list<Transaction__c>();
    
	// constructor
	global BatchClassPledgeTransaction() {
		query = 'SELECT Id, ' +
					   'Name, ' +
					   'Duration__c, ' +
					   'Start_Date__c, ' +
					   'End_Date__c ' +
				'FROM Pledge__c';
	}
	
	// Start Method
    global Database.querylocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }
    
	// Execute Logic
    global void execute(Database.BatchableContext BC, List<Pledge__c> Scope){
		Map<String, Schema.RecordTypeInfo> pledgeRecordTypeInfosByNameMap = Schema.SObjectType.Pledge__c.getRecordTypeInfosByName();
		Map<String, Schema.RecordTypeInfo> transactionRecordTypeInfosByNameMap = Schema.SObjectType.Transaction__c.getRecordTypeInfosByName();
		
		Id PledgeRecTypeCard = pledgeRecordTypeInfosByNameMap.get('Card').getRecordTypeId();
        Id PledgeRecTypeGIRO = pledgeRecordTypeInfosByNameMap.get('GIRO').getRecordTypeId();
        Id PledgeRecTypeOnline = pledgeRecordTypeInfosByNameMap.get('Online').getRecordTypeId();
        Id PledgeRecTypeRecurringCash = pledgeRecordTypeInfosByNameMap.get('Recurring Cash').getRecordTypeId();
        Id PledgeRecTypeRecurringCheque = pledgeRecordTypeInfosByNameMap.get('Recurring Cheque').getRecordTypeId();
        
		Id TransactionRecTypeCard = transactionRecordTypeInfosByNameMap.get('Card').getRecordTypeId();
        Id TransactionRecTypeGIRO = transactionRecordTypeInfosByNameMap.get('GIRO').getRecordTypeId();
        Id TransactionRecTypeOnline = transactionRecordTypeInfosByNameMap.get('Online').getRecordTypeId();
        Id TransactionRecTypeRecurringCash = transactionRecordTypeInfosByNameMap.get('Recurring Cash').getRecordTypeId();
        Id TransactionRecTypeRecurringCheque = transactionRecordTypeInfosByNameMap.get('Recurring Cheque').getRecordTypeId();
		
		Set<Id> pledgeIdSet = new Map<Id,SObject>(Scope).keySet()
		
		// Query once per batch job
		// SOQL limits
		AggregateResult[] numberOfTransactionsPerPledge = [SELECT COUNT(id)
														   FROM Transaction__c
														   WHERE Pledge__c IN :pledgeIdSet
														   GROUP BY Pledge__c];
		
        for (Pledge__c plg : Scope){
			// make sure that we even need to create transactions. 
			// avoid going over
			if (numberOfTransactionsPerPledge.get(plg.Id) < integer.valueof(plg.Duration__c)) {
				Integer j = integer.valueof(plg.Duration__c) - 12;
			
				for (Integer i = 0; i <= j; i++){
					Transaction__c tran = new Transaction__c();
					
					// Transactions start where trigger left off
					tran.Transaction_Date__c = plg.Start_Date__c.addMonths(i + 12); 
					tran.Pledge__c = plg.id;
					tran.Amount_Reconciled__c = plg.Amount__c;
					tran.Donor__c = plg.Account__c;
					tran.Status__c = plg.Status__c;
						  
					if (plg.recordtypeid == PledgeRecTypeCard){
						tran.recordtypeid = TransactionRecTypeCard;
					} 
								
					if (plg.recordtypeid == PledgeRecTypeGIRO){
						tran.recordtypeid = TransactionRecTypeGIRO;
					} 
							   
					if (plg.recordtypeid == PledgeRecTypeOnline){
						tran.recordtypeid = TransactionRecTypeOnline;
					} 
							   
					if (plg.recordtypeid == PledgeRecTypeRecurringCash){
						tran.recordtypeid = TransactionRecTypeRecurringCash;
					} 
							   
					if (plg.recordtypeid == PledgeRecTypeRecurringCheque){
						tran.recordtypeid = TransactionRecTypeRecurringCheque;
					} 
					
					transList.add(tran);
				}
			}
		}
		
		// insert all at once
		// DML limits
		insert transList;
    }
    
	// finish
	global void finish(Database.BatchableContext BC){}
}
Please feel free to reply with questions if you have any further concerns.

as for the schedule class 
 
// Sample call from anonymous apex window:
//
// Seconds Minutes Hours Day_of_month Month Day_of_week optional_year
// example last day of the month at 12am
// String cronStr = '0 0 0 ? * L'; 
// BatchClassPledgeTransactionSchedule sched = BatchClassPledgeTransactionSchedule();
// System.schedule('BatchClassPledgeTransaction ', cronStr, sched);
global class BatchClassPledgeTransactionSchedule implements Schedulable {
	global void execute(SchedulableContext sc) {
        //  Instantiate batch class 
		Id batchInstanceId = Database.executeBatch(new BatchClassPledgeTransaction());
    }
}

Reffer to the documentation (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_scheduler.htm)if you have any questions regarding the schedule class.

Hope this helps!
 
This was selected as the best answer
UC InnovationUC Innovation
Please mark declare as the solution if this aanswered your question.