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('abc@gmail.com');
        mail.setSenderDisplayName('Batch Processing Completed');
        mail.setPlainTextBody('Batch Process has completed');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
    }
}

Please help. Thanks in advance.

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('abc@gmail.com');
        mail.setSenderDisplayName('Batch Processing Completed');
        mail.setPlainTextBody('Batch Process has completed');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] {mail});
    }
}
  • 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... – BritishBoyinDC Jun 18 '13 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 Jun 20 '13 at 11:32
  • @abc - see this question. salesforce.stackexchange.com/questions/3593/… – Mike Chale Jun 20 '13 at 14:16
  • You can use a scheduled class to wrap the batch, and then schedule that per Mike's link: – BritishBoyinDC Jun 20 '13 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 Jul 16 '13 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);
}


}
  • i did exectly the same just befor your post.. was about to mention the solution here.. thank you. – abc Jun 20 '13 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 Jun 21 '13 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? – BritishBoyinDC Jun 22 '13 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 Jun 26 '13 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? – BritishBoyinDC Jun 26 '13 at 19:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.