Achieving bulk approval of records in Salesforce
In your career either as a Salesforce administrator or Salesforce developer, you will encounter a terminology called Approval Process. In which, a record will be processed according to the steps defined in the Approval Process.
Approval Process -
An approval process automates how records are approved/rejected in Salesforce. An approval process consists of steps required for record approval/rejection, including from whom to request approval and what to do at each point of the process.
Why bulk approval?
Using the approval process you can only submit one record at a time for approval which is good for a less number of records, but what if there are hundreds or thousands of records that need to be submitted to the approval process that will consume a lot of time and human effort.
To save this we need a bulk approval process that can be achieved by custom logic.
So, I am going to explain how you can achieve bulk approval from a list view using the VisualForce page and an Apex Controller.
- Create an approval process on whatever object you like and activate it. I am going to use the opportunity object with a custom picklist Approval Status to show status.
- Create a Visualforce Page and an Apex Controller with the following details -
a. Visualforce Page
<apex:page standardController="Opportunity" recordSetVar="Opportunity" extensions="BulkApprovalController" lightningStylesheets="true"><apex:slds /><html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <div class="slds-scope"> <div class="demo-only slds-hide" id="spinner" style="height:6rem"> <div class="slds-spinner_container"> <div role="status" class="slds-spinner slds-spinner_medium slds-spinner_brand"> <span class="slds-assistive-text">Loading</span> <div class="slds-spinner__dot-a"></div> <div class="slds-spinner__dot-b"></div> </div> </div> </div> </div> <apex:form > <apex:actionFunction action="{!redirectToListView}" name="redirection"> </apex:actionFunction> </apex:form></html><script type="text/javascript">let selectedOpportunitiesIdJSON = '{!selectedOpportunitiesIdJSON}';let div = document.getElementById('spinner');BulkProcess();function BulkProcess(){ if (selectedOpportunitiesIdJSON !== '') { div.classList.remove('slds-hide'); submittingRecords(); }}async function submittingRecords() { try { let promise = await submitForApproval(); if (!div.classList.contains('slds-hide')) { div.classList.add('slds-hide'); }redirectToListView();} catch (exception) { if (!div.classList.contains('slds-hide')) { div.classList.add('slds-hide'); } redirectToListView(); }}function redirectToListView() { redirection();}// submitting records using visualforce remotingfunction submitForApproval() { return new Promise(function (resolve, reject) {Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.BulkApprovalController.submitForApproval}', selectedOpportunitiesIdJSON, function (response, event) { if (response == 'success') { resolve(response); } else { reject(response); } }); });}</script></apex:page>
StandardSetController — StandardSetController objects allow you to create list controllers similar to, or as extensions of, the pre-built Visualforce list controllers provided by Salesforce.
recordSetVar — The recordSetVar attribute indicates that the page is using a listview controller and it indicates the name of record collection to perform an action or show records on the page.
a. Create an Apex Controller like below -
global with sharing class BulkApprovalController { public List<Id> selectedOpportunitiesId; public String selectedOpportunitiesIdJSON{get;set;} public BulkApprovalController(Apexpages.StandardSetController standardController){ selectedOpportunitiesId = new List<Id>(); for(Opportunity oppty: (List<Opportunity>)standardController.getSelected()){ selectedOpportunitiesId.add(oppty.Id); // you will get only Ids from controller. } if(selectedOpportunitiesId.size()>0){ selectedOpportunitiesIdJSON = JSON.serialize(selectedOpportunitiesId); }}@RemoteActionglobal static String submitForApproval(String selectedOpportunities){ try{ List<String> selectedOpptys = (List<String>)JSON.deserialize(selectedOpportunities, List<String>.class); List<Approval.ProcessSubmitRequest> approvalRequests = new List<Approval.ProcessSubmitRequest>(); //Creating an approval requests for each Opportunity using ProcessSubmitRequest Approval.ProcessSubmitRequest approvalRequest; for(Id opptyId: selectedOpptys){ approvalRequest = new Approval.ProcessSubmitRequest(); approvalRequest.setComments('Submitting request for approval'); approvalRequest.setObjectId(opptyId);// which record to approve//change approver id approvalRequest.setNextApproverIds(new Id[] {UserInfo.getUserId()}); approvalRequests.add(approvalRequest); }// Submit the approval request Approval.ProcessResult[] result = Approval.process(approvalRequests); return 'success'; }catch(Exception ex){ return 'error '+ex.getMessage(); }}public Pagereference redirectToListView(){ Schema.DescribeSObjectResult destination; PageReference pageRef; try{ destination = Opportunity.SObjectType.getDescribe(); pageRef = new PageReference('/' + destination.getKeyPrefix() ); pageRef.setRedirect(true); return pageRef; }catch(Exception ex){ return pageRef; } }}
3. Create a detail list button named — Bulk request on Opportunity and add it to the List view by navigating to Search Layout -
Select the record(s) and click on the Bulk request button.
Record(s) will be submitted for approval -
Conclusion -
❖ Submitting a large number of records for approval is a cumbersome task and Salesforce does not have standard functionality to achieve that therefore we need a workaround to achieve it.
❖ Now we have seen how we can submit records in bulk for approval using apex, what you just need is a record id.
❖ Keep in mind about comments.
In the next blog, I have explained how we can approve and reject records in bulk.
Here is the link to the blog — “Achieving bulk approval of records”.