How To: Clone a Parent Record with Child Records that Reference Each Other
October 22, 2018
How To: Create a Quick Action Lightning Component for Super Clone Pro
January 14, 2019

How To: Run Super Clone Pro from Batch Apex

Sometimes heavy processing requires running Apex logic asynchronously to avoid reaching Salesforce processing limits. Below is an example of how run Super Clone Pro’s methods to Clone a hierarchy or Copy child records in a batch Apex job.

Both batch examples accept parameters of which records should be processed. The batch query selects records to process based on the Ids that were received. The class implements stateful, so it may store error messages in a string. In the Finally method, an email containing the messages is sent to the submitter.

Clone in a Batch

This is an example of how to submit the clone job. The batch class’ constructor accepts a set of record Ids to clone. The submission code builds the set, instantiates the batch class, and passes it to the executeBatch method. The second parameter of “1” indicates that it should process 1 record per batch processing transaction.

set<Id> idSet = new set<Id>();
idSet.add('00X4100001aSAHR');
idSet.add('00X41000003D64e');

ScpBatchCloneJob cloneJob = new ScpBatchCloneJob(idSet);
ID batchprocessid = Database.executeBatch(cloneJob, 1);

 

global class ScpBatchCloneJob implements Database.Batchable<sObject>, Database.Stateful{
    set<Id> cloneIdSet;
    String errorMessages;
    
    /**
    * constructor, set parameter variables
    */
    public ScpBatchCloneJob(set<Id> paramCloneIdSet) {
        cloneIdSet = paramCloneIdSet;
    }
    
    /**
    * query to retrieve the sObjects for Id set
    */
    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator([SELECT ID FROM MyObject__c WHERE Id IN :cloneIdSet]);
    }
    
    /**
    * execute clone logic
    */
    global void execute(Database.BatchableContext BC, list<sObject> scope){
        set<Id> idSet = new set<Id>();
        
        // create map for scope of records
        for(sobject s : scope){
            idSet.add(s.Id);
        }

        // run Super Clone Pro's clone API
        if (!idSet.isEmpty()) {
            try {
                lcrm_scp.ScpApi.clone('MyConfig', idSet);
            } catch (exception e) {
                errorMessages = (String.isBlank(errorMessages) ? '' : errorMessages + '\n\n');
                errorMessages += idSet + '=>' + e.getMessage();
            }
        }
    }
    
    /**
    * finish
    */
    global void finish(Database.BatchableContext BC){
        // send error if exceptions were added to the errorMessages variable
        if (String.isNotBlank(errorMessages)) {
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
            email.setToAddresses(new String[] {userInfo.getUserEmail()});
            email.setSubject('Batch Clone Error Report');
            email.setPlainTextBody(errorMessages);
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });
        }
    }
}

Copy in a Batch

This is an example of how to submit the copy job. The batch class’ constructor accepts a map of record Ids to clone. The map contains a record id that will be copied to as the key and the record id that will be copied from as the value in the map. The submission code builds the map, instantiates the batch class, and passes it to the executeBatch method. The second parameter of “1” indicates that it should process 1 record per batch processing transaction. The copy contains a little extra processing than the clone because we need to rebuild the map for the API execution.

map<Id, Id> idMap = new map<Id, Id>();
idMap.put('00X4100001aSAHR', '00X41000003D64e');

ScpBatchCopyJob copyJob = new ScpBatchCopyJob(idMap);
ID batchprocessid = Database.executeBatch(copyJob , 1);
global class ScpBatchCopyJob implements Database.Batchable<sObject>, Database.Stateful{
    map<Id, Id> toFromMap;
    String errorMessages;
    
    /**
    * constructor, set parameter variables
    */
    public ScpBatchCopyJob(map<Id, Id> paramToFromMap) {
        toFromMap = paramToFromMap;
    }
    
    /**
    * query to retrieve the sObjects for the map's keySet
    */
    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator([SELECT ID FROM MyObject__c WHERE Id IN :toFromMap.keySet()]);
    }
    
    /**
    * execute clone logic
    */
    global void execute(Database.BatchableContext BC, list<sObject> scope){
        map<Id, Id> toIdFromIdMap = new map<Id, Id>();
        
        // create map for scope of records
        for(sobject s : scope){
            Id fromId = toFromMap.get(s.Id);
            if (null != fromId) {
                toIdFromIdMap.put(s.Id, fromId);   
            }
        }
        
        // run Super Clone Pro's copy API
        if (!toIdFromIdMap.isEmpty()) {
            try {
            	lcrm_scp.ScpApi.copy('MyConfig', ToIdFromIdMap);
            } catch (exception e) {
                errorMessages = (String.isBlank(errorMessages) ? '' : errorMessages + '\n\n');
                errorMessages += ToIdFromIdMap + '=>' + e.getMessage();
            }
        }
    }
    
    /**
    * finish
    */
    global void finish(Database.BatchableContext BC){
        if (String.isNotBlank(errorMessages)) {
            Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
            email.setToAddresses(new String[] {userInfo.getUserEmail()});
            email.setSubject('Batch Copy Error Report');
            email.setPlainTextBody(errorMessages);
            Messaging.sendEmail(new Messaging.SingleEmailMessage[] { email });
        }
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.