Skip to content

Instantly share code, notes, and snippets.

@douglascayers
Last active September 17, 2024 23:37
Show Gist options
  • Save douglascayers/46bb1e92be9909d60fee to your computer and use it in GitHub Desktop.
Save douglascayers/46bb1e92be9909d60fee to your computer and use it in GitHub Desktop.
Approval Request Comments in Visualforce Email Template.
<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>
/**
* 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;
}
}
@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 );
}
}
<!--
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>
@mollycalypso
Copy link

Thank you so much for this!

@T0rG4L
Copy link

T0rG4L commented Jun 30, 2021

This is great Douglas. Visual Force Email template is needed for CPQ Quote lines in Approval Email templates.

@fahadmatin143
Copy link

fahadmatin143 commented May 3, 2024

Hi Doug Ayers,

I want to send multiple parameter from email template like below

Comments: <c:ApprovalRequestComments relatedToId="{!relatedTo.id}" formName= "rejectedForm"/>

I used like this but it is showing error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment