Approval process using apex.
Approval process using apex
An approval process is an automated process which can be used to approve/reject record updates. A record can be submitted for approval request from related list "Approval History". Once a records is submitted it goes for approval to a specified approver. This is a manual process where in every record should be individually sent for approval.How about doing this using apex? Sending the record fro approval from trigger? Salesforec provides number of method for handling approval processes in apex.
Let us submit a record for approval process from trigger in an example below.
Lets say you have a approval process named "Account Owner Approval". You can create a approval process by navigating to following:
set up --> create --> approval process
Trigger to submit a account record for approval if its annual revenue is less then 2000
trigger Call_AprovalProcess_In_Trigger on Account (before insert, before update) {
for(Account acc:trigger.new){
if(acc.AnnualRevenue < 2000){
approval.ProcessSubmitRequest aprlPrcs = new Approval.ProcessSubmitRequest();
aprlPrcs .setComments('Submitting record for approval.');
aprlPrcs.setObjectId(acc.id);
approval.ProcessResult result = Approval.process(aprlPrcs);
}
}
}
Dynamic Approval Process in
Salesforce using Apex and Trigger
This article explain the Automatic submission of
Approval process using Apex and trigger. It include Automatic submission,
approval as well as rejection of record completely using Apex and trigger.
Although this is very common approach and lots of articles are
around on this topic, still I want to delineate the topic in other way. This
topic covers complete scenarios for the approval process based on the Apex
class.
Agenda of this article:
1. Automatically submit the
record for approval on the basis of field value.
2. Automatically select the
next Approver.
3. Approve / Reject the record
on the basis of field.
Assumptions:
·
Opportunity Object is used.
·
Approval Process is already set on the Opportunity.
·
Field “Next_Approver” will decide that who is going to approve the
record.
·
There are three steps in the approval process.
·
There is no test class written and no check for mandatory fields
needed for the trigger, as I have considered positive scenarios only.
Important URLS:
API of Approval Process classes:
1. Apex process
Steps of Standard approval
process defined:
To achieve this, I am going
to create the trigger named “AutomateApprove”.
Automatically submit the
approval process using trigger – Apex:
Below method is used to automatically submit the approval
process using trigger.
public void submitForApproval(Opportunity opp)
{
// Create an
approval request for the Opportunity
Approval.ProcessSubmitRequest req1 = new
Approval.ProcessSubmitRequest();
req1.setComments('Submitting request for approval automatically using Trigger');
req1.setObjectId(opp.id);
req1.setNextApproverIds(new Id[] {opp.Next_Approver__c});
// Submit the
approval request for the Opportunity
Approval.ProcessResult result = Approval.process(req1);
}
Class
“ProcessSubmitRequest“ is used to automatically
submit the approval process. We need to set following items while submitting
the approval process using trigger:
·
Comment
·
TargetObjectId
·
NextApproverIds – if needed. Here Custom logic can be written to
dynamically set approver for approval process. In this case I am using the
custom field present on the Opportunity.
Automatically approve the approval process using trigger – Apex:
Below method is
used to automatically approve the approval process using trigger.
/*
* This method will
Approve the opportunity
*/
public void
approveRecord(Opportunity opp)
{
Approval.ProcessWorkitemRequest
req = new Approval.ProcessWorkitemRequest();
req.setComments('Approving request using Trigger');
req.setAction('Approve');
req.setNextApproverIds(new Id[] {opp.Next_Approver__c});
Id workItemId =
getWorkItemId(opp.id);
if(workItemId ==
null)
{
opp.addError('Error Occured in Trigger');
}
else
{
req.setWorkitemId(workItemId);
// Submit the
request for approval
Approval.ProcessResult result = Approval.process(req);
}
}
Class
“ProcessWorkitemRequest“ is used to automatically
approve the approval process. We need to set following items while submitting
the approval process using trigger:
·
Comment
·
TargetObjectId
·
NextApproverIds – if needed
·
WorkItemId – Custom code required to get this
Get the WorkItemId for the pending approval process of the
Object:
This is the tricky part, if the Submission and approval of the record is done in single code block then it’s very easy to get the WorkItemId of the needed process.
This is the tricky part, if the Submission and approval of the record is done in single code block then it’s very easy to get the WorkItemId of the needed process.
Here the standard code snap provided:
1 |
Approval.ProcessResult
result = Approval.process(req1); |
And from the
class we can get workitemid as :
1 |
List<Id>
newWorkItemIds = result.getNewWorkitemIds(); |
And set the id
like:
1 |
req2.setWorkitemId(newWorkItemIds.get(0)); |
Other method to get the “WorkItemId” :
The above code was not usable in our scenario as the submission and approval or rejection was done at different level. So I have created following utility method to get the WorkitemId of the supplied Object’s id. Here I have considered that only one workitem will present.
The above code was not usable in our scenario as the submission and approval or rejection was done at different level. So I have created following utility method to get the WorkitemId of the supplied Object’s id. Here I have considered that only one workitem will present.
public Id getWorkItemId(Id targetObjectId)
{
Id retVal = null;
for(ProcessInstanceWorkitem workItem
: [Select p.Id from ProcessInstanceWorkitem p
where
p.ProcessInstance.TargetObjectId =: targetObjectId])
{
retVal =
workItem.Id;
}
return retVal;
}
As you
can see, we need to query the object “ProcessInstanceWorkitem“ to get
workitemId of the object.
Automatically reject the approval process using trigger – Apex:
Following code is used to reject the approval process using code.
Following code is used to reject the approval process using code.
public void rejectRecord(Opportunity opp)
{
Approval.ProcessWorkitemRequest req = new
Approval.ProcessWorkitemRequest();
req.setComments('Rejected
request using Trigger');
req.setAction('Reject');
//req.setNextApproverIds(new Id[] {UserInfo.getUserId()});
Id workItemId =
getWorkItemId(opp.id);
if(workItemId ==
null)
{
opp.addError('Error
Occured in Trigger');
}
else
{
req.setWorkitemId(workItemId);
// Submit the
request for approval
Approval.ProcessResult result =
Approval.process(req);
}
}
Execution of Approval process using Apex and trigger:
Complete code:
trigger AutomateApprove on Opportunity(After insert, After update)
{
for (Integer i = 0; i
< Trigger.new.size(); i++)
{
try
{
if( Trigger.isInsert
|| (Trigger.new[i].Next_Step__c == 'Submit' &&
Trigger.old[i].Next_Step__c != 'Submit'))
{
submitForApproval(Trigger.new[i]);
}
else
if(Trigger.isInsert || (Trigger.new[i].Next_Step__c == 'Approve' &&
Trigger.old[i].Next_Step__c != 'Approve'))
{
approveRecord(Trigger.new[i]);
}
else
if(Trigger.isInsert || (Trigger.new[i].Next_Step__c == 'Reject' &&
Trigger.old[i].Next_Step__c != 'Reject'))
{
rejectRecord(Trigger.new[i]);
}
}catch(Exception e)
{
Trigger.new[i].addError(e.getMessage());
}
}
/**
* This method will
submit the opportunity automatically
**/
public void
submitForApproval(Opportunity opp)
{
// Create an
approval request for the Opportunity
Approval.ProcessSubmitRequest req1 = new
Approval.ProcessSubmitRequest();
req1.setComments('Submitting request for approval automatically using
Trigger');
req1.setObjectId(opp.id);
req1.setNextApproverIds(new Id[] {opp.Next_Approver__c});
// Submit the
approval request for the Opportunity
Approval.ProcessResult result = Approval.process(req1);
}
/**
* Get
ProcessInstanceWorkItemId using SOQL
**/
public Id
getWorkItemId(Id targetObjectId)
{
Id retVal = null;
for(ProcessInstanceWorkitem workItem
: [Select p.Id from ProcessInstanceWorkitem p
where
p.ProcessInstance.TargetObjectId =: targetObjectId])
{
retVal
= workItem.Id;
}
return retVal;
}
/**
* This method will
Approve the opportunity
**/
public void
approveRecord(Opportunity opp)
{
Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();
req.setComments('Approving request using Trigger');
req.setAction('Approve');
req.setNextApproverIds(new Id[] {opp.Next_Approver__c});
Id workItemId =
getWorkItemId(opp.id);
if(workItemId ==
null)
{
opp.addError('Error Occured in Trigger');
}
else
{
req.setWorkitemId(workItemId);
// Submit the
request for approval
Approval.ProcessResult result =
Approval.process(req);
}
}
/**
* This method will
Reject the opportunity
**/
public void
rejectRecord(Opportunity opp)
{
Approval.ProcessWorkitemRequest req = new
Approval.ProcessWorkitemRequest();
req.setComments('Rejected request using Trigger');
req.setAction('Reject');
Id workItemId =
getWorkItemId(opp.id);
if(workItemId ==
null)
{
opp.addError('Error Occured in Trigger');
}
else
{
req.setWorkitemId(workItemId);
// Submit the
request for approval
Approval.ProcessResult result =
Approval.process(req);
}
}
}
Note on possible errors:
1.If you have
the “manual Selection of approver” enabled for your approval process/steps then
you must specify the approver in the trigger, else you will get an error
something like:
“System.DmlException:
Process failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING,
missing required field: []”
2.If you set the
wrong WorkitemId then may get following error:
Process failed. First
exception on row 0; first error: INVALID_CROSS_REFERENCE_KEY, invalid cross
reference id: []
updated on 25-March-2015
Question :
1. Can we add multiple users (Parallel Approval process) as a aprrover automated using above code?
Ans : No. Logic in above code is that we need to select next approver option as “manual”. Currently we cannot use multiple users manually in approval process, you can vote this idea for this feature support. Only solution is to have multiple steps for each approver.
1. Can we add multiple users (Parallel Approval process) as a aprrover automated using above code?
Ans : No. Logic in above code is that we need to select next approver option as “manual”. Currently we cannot use multiple users manually in approval process, you can vote this idea for this feature support. Only solution is to have multiple steps for each approver.
No comments:
Post a Comment