function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Raghu_VirodhulaRaghu_Virodhula 

How to add comments in auto-approve/reject in an Approval Process

In the approval steps of an approval process, if the step criteria doesn't meet then there is an option to select approve or reject the record (through the else condition). But is there any option to add the comments of why it was auto-approved/rejected?

Thanks
Gaurav KheterpalGaurav Kheterpal
There are some ideas related to this such as this one (https://success.salesforce.com/ideaView?id=08730000000BqAjAAK) which are under consideration by Salesforce product management. You can hack around it programatically using the approach as shown here (http://salesforce.stackexchange.com/questions/12481/custom-fields-not-useable-in-approve-reject-approval-request).

Apex code
 
public with sharing class OpportunityApprovalCtrl {
/*  The "with sharing" keyword will prevent unauthorized users from succesfully saving changes to Opp. Only your Approver
    and anybody "godlike" (System Administrators, users with "Modify All Data" permission etc) will be able to approve
    (http://salesforce.stackexchange.com/questions/5377/are).

    If you'd prefer some explicit spelling out of "you don't have permissions, the buttons will be disabled for you" - shout.
*/
    public String approvalComments {get;set;}

    // Mapping between our picklist values and the actions in actual process.
    public final Map<String, String> validActions = new Map<String, String>{
        'Approved' => 'Approve',
        'Conditionally Approved' => 'Approve',
        'Rejected' => 'Reject',
        'Recalled' => 'Remove'
    };

    private ApexPages.StandardController sc;

    public OpportunityApprovalCtrl(ApexPages.StandardController sc){
        if(sc.getId() == null){
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.FATAL, 'Please pass valid Opportunity Id in the page URL'));
        } else {
            this.sc = sc;
        }
    }

    public PageReference save(){
        try {
            progressApproval();
            return sc.save();
        } catch(Exception e){   
            ApexPages.addMessages(e);
            //  This probably would need some savepoint & rollback (so we don't stay in limbo of "approval OK, Opp update failed")
            //  but let's keep the example simple (lol).
            return null;
        }
    }

    private void progressApproval(){
        Opportunity opp = (Opportunity) sc.getRecord();

        if(!validActions.containsKey(opp.Approval_Status__c)){
            throw new ApprovalException('Unexpected action: ' + opp.Approval_Status__c); // Somebody was messing with the form?
        }
        if(opp.Approval_Status__c == 'Conditionally Approved' && String.isBlank(opp.Approval_Comments__c)){
            throw new ApprovalException( 'It\'s a conditional approval so please add some comments.');
        }

        // First let's fetch the current step in the approval process.
        List<ProcessInstanceWorkItem> items = [SELECT Id 
            FROM ProcessInstanceWorkItem
            WHERE ProcessInstance.Status = 'Pending' AND ProcessInstance.TargetObjectId = :sc.getId()
            LIMIT 1];
        if(items.isEmpty()){
            throw new ApprovalException('Looks like there\'s nothing to approve? Please go back to Opportunity or refresh the page.'); // somebody else has already approved?
        }

        Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();
        req.setAction(validActions.get(opp.Approval_Status__c)); // use our mapping to figure out how to translate the action
        req.setComments(String.isBlank(approvalComments) ? opp.Approval_Status__c : approvalComments.abbreviate(4000));
        req.setWorkitemId(items[0].Id);
        Approval.ProcessResult result =  Approval.process(req);
    }

    public class ApprovalException extends Exception{}
}
VF code
<apex:page standardController="Opportunity" extensions="OpportunityApprovalCtrl" title="Custom Opportunity Approval">
    <apex:sectionHeader title="{!$ObjectType.Opportunity.Label}: {!Opportunity.Name}" />
    <apex:form >
        <apex:pageMessages id="messages"/>
        <apex:pageBlock title="Approve / Reject Approval Request">

            <apex:pageBlockSection columns="1">
                <apex:outputField value="{!Opportunity.Name}" />
                <apex:outputField value="{!Opportunity.OwnerId}" />
                <apex:outputField value="{!Opportunity.AccountId}" />
                <apex:outputField value="{!Opportunity.StageName}" />
                <apex:outputField value="{!Opportunity.Amount}" />
                <apex:inputField value="{!Opportunity.Approval_Status__c}" required="true"/>
                <!-- This is for conditional approval (to store on Opportunity). -->
                <apex:inputField value="{!Opportunity.Approval_Comments__c}"/>  

                <!-- This is for standard comments field (to store in approval history). -->
                <apex:inputTextArea label="Comments" value="{!approvalComments}" cols="100" rows="5" />
            </apex:pageBlockSection>

            <apex:pageBlockButtons location="bottom">
                <apex:commandButton value="Save" action="{!save}" rerender="messages, steps" status="status"/>
                <apex:commandButton value="Cancel" action="{!Cancel}" immediate="true"/>
                <apex:actionStatus id="status" stopText="">
                    <apex:facet name="start">Requesting... <img src="/apexpages/devmode/img/saveStatus.gif" /></apex:facet>
                </apex:actionStatus>
            </apex:pageBlockButtons>
        </apex:pageBlock>
    </apex:form>
    <apex:relatedList id="steps" subject="{!Opportunity.Id}" list="ProcessSteps" />
</apex:page>
If my answer helps resolve your query, please mark it as the 'Best Answer' & upvote it to benefit others and improve the overall quality of Discussion Forums.

Gaurav Kheterpal
Certified Force.com Developer| Salesforce Mobile Evangelist| Developer Forums Moderator| Dreamforce Speaker




 
Raghu_VirodhulaRaghu_Virodhula
Thanks Gaurav. We are currently doing it programatically whenever the record is auto-approved/rejected. But i am looking for a solution or a hack through configuration. Glad to see the existing ideas.
Jacquealine CarterJacquealine Carter
This is a great solution, can you assist with a test class please.  I'm new to this and I'm trying to figure it out and I'm really struggling.