You need to sign in to do that
Don't have an account?

Apex Class Batch Execution Questions
I am new to SalesForce. I have created my first Apex Class. The goal of the class is to read through all ccrz__E_Order__c that are in 'Order Submitted' status. For each order, read the items. If all items are currently in 'Received' status, then update the status on the order to 'Order Received'. I want this to be a batch process ran daily.
Following questions being a first time creator of an Apex Class.
Thanks in advance for any advise.
Dan
/*
* @Name: Batch_OrderStatus
* @Author: Dan Norfleet
* Updates : 02/12/2018 - Dan Norfleet - Created Apex Class
*/
global class Batch_OrderStatus Implements Schedulable
{
global void execute(SchedulableContext sc)
{
execute();
}
global void execute()
{
System.debug('Batch_OrderStatus BEGIN');
// Create a list of Orders in status of 'Order Submitted'
List<ccrz__E_Order__c> orders =
[SELECT Id, Name, ccrz__orderstatus__c
FROM ccrz__E_Order__c
WHERE ccrz__orderstatus__c = 'Order Submitted'];
// WHERE ccrz__orderstatus__c = 'Order Submitted' AND Name = 'O-0000112447'];
Integer total_orders_cnt = 0;
Integer update_cnt = 0;
Integer notupdated_cnt = 0;
String status_received = 'Received';
String status_order_received = 'Order Received';
// Loop through the list of orders
for(ccrz__E_Order__c ord : orders)
{
total_orders_cnt = total_orders_cnt + 1;
String order_id = ord.Id;
// For each order, see how many items are in 'Received' status
integer ItemsReceived =
[SELECT COUNT()
FROM ccrz__E_OrderItem__c
WHERE ccrz__orderitemstatus__c = :status_received
AND ccrz__order__c = :order_id];
integer ItemsNOTReceived =
[SELECT COUNT()
FROM ccrz__E_OrderItem__c
WHERE ccrz__orderitemstatus__c != :status_received
AND ccrz__order__c = :order_id];
if (ItemsReceived > 0)
{
if (ItemsNOTReceived == 0)
{
ord.ccrz__orderstatus__c = status_order_received;
System.debug(' UPDATE Order - ID = ' + order_id + ' / Order Name = ' + ord.Name + ' / Items Received = ' + ItemsReceived + ' / ItemsNOTReceived = ' + ItemsNOTReceived);
update_cnt = update_cnt + 1;
update orders;
}
else
{
notupdated_cnt = notupdated_cnt + 1;
}
}
}
System.debug('TOTAL ORDERS IN SUBMITTED STATUS = ' + total_orders_cnt);
System.debug('TOTAL UPDATED = ' + update_cnt);
System.debug('TOTAL NOTUPDATED = ' + notupdated_cnt);
System.debug('Batch_OrderStatus END');
}
}
Following questions being a first time creator of an Apex Class.
- Is the best way to trigger this process to run by going into Apex Class and Schedule Apex? Or is there a more appropriate way to schedule?
- When testing, I have used Developers Console and executed the class. However, I run into limits. Even when I have scheduled in our test environments, i have hit limits. There are only a couple hundred orders in this status but it hits Too many SOQL queries system limit exception. Is there a way to test the entire process w/o exceeding these limits? Are they the same limits when going to production? When testing I enter specific orders (you'll see commented out line below in the code), but when i read all orders i am hitting these limits.
- Is there a system log that i can write totals too? As you can see on the code below i have written beginning / ending / total information into the debug log. But when going to production, i will comment these out - is there a traditional way to look at this kind of information in a salesforce log.
Thanks in advance for any advise.
Dan
/*
* @Name: Batch_OrderStatus
* @Author: Dan Norfleet
* Updates : 02/12/2018 - Dan Norfleet - Created Apex Class
*/
global class Batch_OrderStatus Implements Schedulable
{
global void execute(SchedulableContext sc)
{
execute();
}
global void execute()
{
System.debug('Batch_OrderStatus BEGIN');
// Create a list of Orders in status of 'Order Submitted'
List<ccrz__E_Order__c> orders =
[SELECT Id, Name, ccrz__orderstatus__c
FROM ccrz__E_Order__c
WHERE ccrz__orderstatus__c = 'Order Submitted'];
// WHERE ccrz__orderstatus__c = 'Order Submitted' AND Name = 'O-0000112447'];
Integer total_orders_cnt = 0;
Integer update_cnt = 0;
Integer notupdated_cnt = 0;
String status_received = 'Received';
String status_order_received = 'Order Received';
// Loop through the list of orders
for(ccrz__E_Order__c ord : orders)
{
total_orders_cnt = total_orders_cnt + 1;
String order_id = ord.Id;
// For each order, see how many items are in 'Received' status
integer ItemsReceived =
[SELECT COUNT()
FROM ccrz__E_OrderItem__c
WHERE ccrz__orderitemstatus__c = :status_received
AND ccrz__order__c = :order_id];
integer ItemsNOTReceived =
[SELECT COUNT()
FROM ccrz__E_OrderItem__c
WHERE ccrz__orderitemstatus__c != :status_received
AND ccrz__order__c = :order_id];
if (ItemsReceived > 0)
{
if (ItemsNOTReceived == 0)
{
ord.ccrz__orderstatus__c = status_order_received;
System.debug(' UPDATE Order - ID = ' + order_id + ' / Order Name = ' + ord.Name + ' / Items Received = ' + ItemsReceived + ' / ItemsNOTReceived = ' + ItemsNOTReceived);
update_cnt = update_cnt + 1;
update orders;
}
else
{
notupdated_cnt = notupdated_cnt + 1;
}
}
}
System.debug('TOTAL ORDERS IN SUBMITTED STATUS = ' + total_orders_cnt);
System.debug('TOTAL UPDATED = ' + update_cnt);
System.debug('TOTAL NOTUPDATED = ' + notupdated_cnt);
System.debug('Batch_OrderStatus END');
}
}
The above code you specified isn't executing in asynchronous mode. Its executing in synchronous mode as you are just trying to execute the above code in scheduled apex.
Try to write the above code in batch apex and then execute this batch apex from scheduled apex.
Please go through the following link https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_batch_interface.htm
Put this in start method of batch apex
// Create a list of Orders in status of 'Order Submitted'
List<ccrz__E_Order__c> orders =
[SELECT Id, Name, ccrz__orderstatus__c
FROM ccrz__E_Order__c
WHERE ccrz__orderstatus__c = 'Order Submitted'];
Put this code block in execute method
Integer total_orders_cnt = 0;
Integer update_cnt = 0;
Integer notupdated_cnt = 0;
String status_received = 'Received';
String status_order_received = 'Order Received';
// Loop through the list of orders
for(ccrz__E_Order__c ord : orders)
{
total_orders_cnt = total_orders_cnt + 1;
String order_id = ord.Id;
// For each order, see how many items are in 'Received' status
integer ItemsReceived =
[SELECT COUNT()
FROM ccrz__E_OrderItem__c
WHERE ccrz__orderitemstatus__c = :status_received
AND ccrz__order__c = :order_id];
integer ItemsNOTReceived =
[SELECT COUNT()
FROM ccrz__E_OrderItem__c
WHERE ccrz__orderitemstatus__c != :status_received
AND ccrz__order__c = :order_id];
if (ItemsReceived > 0)
{
if (ItemsNOTReceived == 0)
{
ord.ccrz__orderstatus__c = status_order_received;
System.debug(' UPDATE Order - ID = ' + order_id + ' / Order Name = ' + ord.Name + ' / Items Received = ' + ItemsReceived + ' / ItemsNOTReceived = ' + ItemsNOTReceived);
update_cnt = update_cnt + 1;
update orders;
}
else
{
notupdated_cnt = notupdated_cnt + 1;
}
}
}
System.debug('TOTAL ORDERS IN SUBMITTED STATUS = ' + total_orders_cnt);
System.debug('TOTAL UPDATED = ' + update_cnt);
System.debug('TOTAL NOTUPDATED = ' + notupdated_cnt);
System.debug('Batch_OrderStatus END');
}
All Answers
The above code you specified isn't executing in asynchronous mode. Its executing in synchronous mode as you are just trying to execute the above code in scheduled apex.
Try to write the above code in batch apex and then execute this batch apex from scheduled apex.
Please go through the following link https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_batch_interface.htm
Put this in start method of batch apex
// Create a list of Orders in status of 'Order Submitted'
List<ccrz__E_Order__c> orders =
[SELECT Id, Name, ccrz__orderstatus__c
FROM ccrz__E_Order__c
WHERE ccrz__orderstatus__c = 'Order Submitted'];
Put this code block in execute method
Integer total_orders_cnt = 0;
Integer update_cnt = 0;
Integer notupdated_cnt = 0;
String status_received = 'Received';
String status_order_received = 'Order Received';
// Loop through the list of orders
for(ccrz__E_Order__c ord : orders)
{
total_orders_cnt = total_orders_cnt + 1;
String order_id = ord.Id;
// For each order, see how many items are in 'Received' status
integer ItemsReceived =
[SELECT COUNT()
FROM ccrz__E_OrderItem__c
WHERE ccrz__orderitemstatus__c = :status_received
AND ccrz__order__c = :order_id];
integer ItemsNOTReceived =
[SELECT COUNT()
FROM ccrz__E_OrderItem__c
WHERE ccrz__orderitemstatus__c != :status_received
AND ccrz__order__c = :order_id];
if (ItemsReceived > 0)
{
if (ItemsNOTReceived == 0)
{
ord.ccrz__orderstatus__c = status_order_received;
System.debug(' UPDATE Order - ID = ' + order_id + ' / Order Name = ' + ord.Name + ' / Items Received = ' + ItemsReceived + ' / ItemsNOTReceived = ' + ItemsNOTReceived);
update_cnt = update_cnt + 1;
update orders;
}
else
{
notupdated_cnt = notupdated_cnt + 1;
}
}
}
System.debug('TOTAL ORDERS IN SUBMITTED STATUS = ' + total_orders_cnt);
System.debug('TOTAL UPDATED = ' + update_cnt);
System.debug('TOTAL NOTUPDATED = ' + notupdated_cnt);
System.debug('Batch_OrderStatus END');
}
Dan
Also, you are trying to run below SOQL queries in FOR loop and its not a recommended approach by Salesforce.
So try to query them out side of the FOR loop and store in Maps and make use of them appropriately.
In execute method
Initially query the map of ccrz__E_Order__c records as
Now make use of the above in Order For Loop