2

I want to turn my trigger code into a batch Apex, however, i am encountering a number of problems with it. Posting both the original and the batch codes. Please can anyone suggest what changes to add to execute it. I am writing a batch code for the first time in Salesforce. It would be a great help.

Original Trigger Code: The trigger is on the Sales_Order__c custom object, and i am upserting a lookup field Order_History__c which is a link to OrderHistory (API name - Order_History__c) object. ID_Opp_Product_18__c, Sales_Order__c (referencing field in OpportunityLineItem), and Order_History__c are present as Custom Fields and Relationship in OpportunityLineItem.

trigger OrderHistory on Sales_Order__c (after insert) 
{ 
     Map<String, ID> salesOrderMap = new Map<String, ID>();
     for (Sales_Order__c so : Trigger.new) 
     { 
        String s2 = String.valueOf(so.Name); 
        String s1 = s2.mid(2,8); 
        if (s1 != null) 
        {
            salesOrderMap.put(s1, so.Id);
        }
    }

    List <OpportunityLineItem> oppLineItems = [select Sales_Order__c, OpportunityId, ID_Opp_Product_18__c from OpportunityLineItem where Sales_Order__c In :salesOrderMap.keyset()]; 
    for(OpportunityLineItem oli : oppLineItems) 
    { 
        ID salesOrderId = salesOrderMap.get(oli.Sales_Order__c);
        oli.Order_History__c = salesOrderId;
    }
    upsert oppLineItems;
}

Batch class code:

global class OrderHistoryBatch implements Database.Batchable<sObject>
{
    String query;
    String email;
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        query = 'select Sales_Order__c, OpportunityId, ID_Opp_Product_18__c from OpportunityLineItem where Sales_Order__C In:salesOrderMap.keyset()';
        return Database.getQueryLocator(query);
    }
    global void execute(Database.BatchableContext BC, List<OrderHistory> scope)
    {
        Map<String, ID> SalesOrderMap = new Map<String, Id>();
        for(sObject s3: scope)
        {
            String s2=String.valueOf(s3.Name);
            String s1=s2.mid(2,8);
            if(s1!=null)
            {
                salesOrderMap.put(s1,s3.Id);
            }
        }
        List<OpportunityLineItem> OppLineItems = new List<OpportunityLineItem>();
        for(sObject s4 : scope)
        {
             ID salesOrderId=salesOrderMap.get(s4.Sales_Order__c);
             s4.Order_History__c=salesOrderId;
        }
        upsert OppLineItems;
    }
    global void finish(Database.BatchableContext BC)
    {
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(new String[]{email});
        mail.setReplyTo('[email protected]');
        mail.setSenderDisplayName('Batch Processing Completed');
        mail.setPlainTextBody('Batch Process has completed');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
    }
}

Please help. Thanks in advance.

2 Answers 2

2
global class OrderHistoryBatch implements Database.Batchable<sObject>
{
    String query;
    String email;
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        query = 'select iD, Name from Sales_Order__c'; //need to define query
        return Database.getQueryLocator(query);
    }
    global void execute(Database.BatchableContext BC, List<sObject> scope)
    {
        List<Sales_Order__c> soorders = (List<Sales_Order__c>)scope;
         Map<String, ID> salesOrderMap = new Map<String, ID>();
        for (Sales_Order__c so : soorders) { 
             String s2 = String.valueOf(so.Name); 
             String s1 = s2.mid(2,8); 
             if (s1 != null)  {
                salesOrderMap.put(s1, so.Id);
              }
    }

List <OpportunityLineItem> oppLineItems = [select Sales_Order__c, OpportunityId,ID_Opp_Product_18__c from OpportunityLineItem where Sales_Order__c In   :salesOrderMap.keyset()]; 
  for(OpportunityLineItem oli : oppLineItems)  { 
    ID salesOrderId = salesOrderMap.get(oli.Sales_Order__c);
    oli.Order_History__c = salesOrderId;
    }
  upsert oppLineItems;
    }

global void finish(Database.BatchableContext BC)
    {
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        mail.setToAddresses(new String[]{email});
        mail.setReplyTo('[email protected]');
        mail.setSenderDisplayName('Batch Processing Completed');
        mail.setPlainTextBody('Batch Process has completed');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
    }
}
5
  • I think you can re-use more than you were thinking - you can cast the scope object back to Sales Order list type, and you can go from there. The main thing you need to do in the code above is define the scope for the initial query...your trigger was based on new Sales_Order records - but for the batch, how are you identifying them? By a flag or something? If so, you might to toggle the flag to processed so they aren't included in the batch again... Commented Jun 18, 2013 at 23:07
  • Thanks, its a great help to me. The code is getting compiled, however i dont know how to run this. Could you please suggest me how can i execute this batch class.
    – abc
    Commented Jun 20, 2013 at 11:32
  • @abc - see this question. salesforce.stackexchange.com/questions/3593/…
    – Mike Chale
    Commented Jun 20, 2013 at 14:16
  • You can use a scheduled class to wrap the batch, and then schedule that per Mike's link: Commented Jun 20, 2013 at 17:21
  • Hey, the batch class is executing, it is even updating the records. However, the batch is taking around 5 min time to finish execution for updating 25 orders. Is it not too long a time, or is it natural? Do we have to optimize our code in some way?
    – abc
    Commented Jul 16, 2013 at 17:59
2
global class scheduledOrderHistoryBatch implements Schedulable{

//Scheduled class to run OrderHistoryBatch
global void execute(SchedulableContext sc) {

OrderHistoryBatch OHBatch = new OrderHistoryBatch();
//OHBatch.query (You can pass in the query this way rather than hard code in batch;
Database.executeBatch(OHBatch);
}


}
5
  • i did exectly the same just befor your post.. was about to mention the solution here.. thank you.
    – abc
    Commented Jun 20, 2013 at 19:06
  • Hi.. i tested the above program, however, it is not updating any records. i have scheduled the scheduleOrderHistoryBatch using the ScheduleApex button present on the Classes screen. In scheduledOrderHistoryBatch class, i have not written any such statement like //OHBatch.query (You can pass in the query this way rather than hard code in batch; Is this mandatory to write? If yes, then which query should i pass since we have more than one query in OrderHistoryBatch class. This issue is of utter importance and i need to resolve it in a few hours.
    – abc
    Commented Jun 21, 2013 at 19:26
  • As of now, the batch is querying for every sales order (Select iD, Name from Sales_Order__c) - so I would assume you either need to add a WHERE clause to it in the batch, or via the OHBatch.Query String. Previously, you were passing in new records via a trigger - how are you identifying those records now? And if you just run the batch via the Dev Console, what happens? If you look in the debug log, is it executing? If so, what errors are you getting? Commented Jun 22, 2013 at 2:29
  • I was initially getting some email errors, however, i removed that section from it now, so i am not getting any errors. The batch is getting executed successfully, however, the records are not getting updated. How can i query only the new records now or how should i modify my query? I have deactivated that trigger.
    – abc
    Commented Jun 26, 2013 at 19:15
  • You need some way to identify new records - maybe a checkbox that defaults to true on create, and you can then set to FALSE once you have processed the record? Commented Jun 26, 2013 at 19:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .