As of Winter ’14 release, email templates used with approval processes (e.g. email alert sent upon approval or rejection) can include {!ApprovalRequest.field_name} merge fields. For example {!ApprovalRequest.Comments} merge field returns the most recently entered comment in emails for an approval step.
However, these merge fields do not work in visualforce email templates. Thankfully, Pradeep on the Salesforce Developer Forums came up with a solution to use a visualforce component in the template backed by a controller that queries the approval step information. Ingenius!
I’ve included gist of my rendition of the apex class, visualforce component, and usage in an email template. I hope this saves you the headache and trouble I went through!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<apex:component controller="ApprovalRequestCommentsController" access="global"> | |
<apex:attribute name="relatedToId" assignTo="{!targetObjectId}" type="String" description="ID of the record whose last approval comments to retrieve"/> | |
<apex:outputText value="{!comments}"/> | |
</apex:component> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* As of Winter '14 release, email templates used with approval processes can | |
* include {!ApprovalRequest.field_name} merge fields. | |
* For example, {!ApprovalRequest.Comments} merge field returns the most recently | |
* entered comment in emails for an approval step. | |
* | |
* However, the merge fields do not work in visualforce email templates. | |
* Thankfully, Pradeep on Developer Forums came up with a solution to use | |
* a visualforce component in the template backed by controller that queries | |
* the approval step information. | |
* | |
* This class represents the controller in this workaround solution. | |
* Also see ApprovalRequestComments visualforce component. | |
* | |
* Inspired by https://developer.salesforce.com/forums/ForumsMain?id=906F00000008xjUIAQ | |
* | |
* http://docs.releasenotes.salesforce.com/en-us/winter14/release-notes/rn_186_forcecom_process_approval_comment_merge_fields.htm | |
*/ | |
public class ApprovalRequestCommentsController { | |
// ID of the record whose most recent approval process comments to retrieve | |
public ID targetObjectId { get; set; } | |
// The most recent approval process comments | |
// Could show in visualforce email template, for example | |
public String comments { | |
get { | |
if ( comments == null ) { | |
ProcessInstanceStep lastStep = getLastApprovalStep(); | |
comments = ( lastStep != null ) ? lastStep.comments : ''; | |
} | |
return comments; | |
} | |
private set; | |
} | |
public ApprovalRequestCommentsController() {} | |
// Queries the most recent approval process step for the target record | |
private ProcessInstanceStep getLastApprovalStep() { | |
List<ProcessInstanceStep> steps = new List<ProcessInstanceStep>([ | |
SELECT | |
Comments | |
FROM | |
ProcessInstanceStep | |
WHERE | |
ProcessInstance.TargetObjectId = :targetObjectId | |
ORDER BY | |
SystemModStamp DESC | |
LIMIT | |
1 | |
]); | |
return ( steps.size() > 0 ) ? steps[0] : null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@IsTest | |
private class ApprovalRequestCommentsControllerTest { | |
@IsTest | |
private static void test_get_comments() { | |
// As of 12/31/2014, Salesforce does not provide us ability | |
// to create ProcessInstance or ProcessInstanceStep records, | |
// so there is no way to test this *correctly* without actually | |
// submitting a record through an actual approve process. | |
// However, this does get 100% code coverage =/ | |
ApprovalRequestCommentsController contr = new ApprovalRequestCommentsController(); | |
System.debug( contr.comments ); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!– | |
Note, for the comments made by the final approver, you must explicitly send this email template | |
as an email alert in the Final Approval and/or Final Rejection actions. This is because the | |
email template for "Approval Assignment Email Template" field on the Approval Process is only sent | |
when the record is assigned to the next approver. For final approver/rejection step, there is no next approver, | |
hence the need for a Final Approval/Rejection email alert. | |
–> | |
<messaging:emailTemplate subject="Opportunity Approved" | |
recipientType="User" | |
relatedToType="Opportunity"> | |
<messaging:htmlEmailBody> | |
Comments: <c:ApprovalRequestComments relatedToId="{!relatedTo.id}"/> | |
</messaging:htmlEmailBody> | |
</messaging:emailTemplate> |
This looks great! How do you include more than just the most recent comment? Thank you!
LikeLiked by 1 person
Thanks Jessie! Great question, I’ll need to tweak the code to support more than the last comment. Should be straight forward to do. I’ll see if I can’t get to this soonish and give an update.
LikeLike
Hello…. I cannot get this to work correctly. It keeps saying “Error: Component c:approvalrequestcomments does not exist.” Do you know what is not configured properly?
LikeLike