Tuesday, May 17, 2011

Salesforce - Override Standard Approval Process Page

Sometimes requirement comes to make Rejection Reasons mandatory when Reject button is clicked. Follow the below approach to over-ride standard approval process page -
1. Create a custom visualforce page as a replica of standard approval/rejection page.
2. Create a controller to have methods for approve/reject/cancel. Approval Process api is available in apex reference book.
3. Create a home page component in which a java-script will be written to over-ride "Approve/Reject" button on Lead.
4. Add this home page component in home page layout.

Done..!!

Visualforce Page



<apex:page controller="ProcessInstanceController" tabStyle="Lead">
   <apex:form >
   <apex:sectionHeader title="Lead" subtitle="{!objLead.Name}"/>
   <apex:pageBlock title="Approve/Reject Approval Request">
       <apex:pageBlockButtons location="bottom"> 
           <apex:commandButton value="Approve" action="{!approve}"/>
           <apex:commandButton value="Reject" action="{!reject}"/>
           <apex:commandButton value="Cancel" action="{!cancel}"/>
       </apex:pageBlockButtons>   
       <apex:pageBlockSection columns="1">
           <apex:pageBlockSectionItem >
               Name <apex:outputField value="{!objLead.Name}"/>
           </apex:pageBlockSectionItem>
           <apex:pageBlockSectionItem >
               Lead Owner <apex:outputField value="{!objLead.Owner.Name}"/>
           </apex:pageBlockSectionItem>
           <apex:pageBlockSectionItem >
               Rejection Reason <font color="red">(Mandatory while Rejection)</font><apex:inputField value="{!objLead.Rejection_Reason__c}"/>
           </apex:pageBlockSectionItem>
           <apex:pageBlockSectionItem >
              Comments <font color="red">(Mandatory while Rejection)</font> <apex:inputTextArea value="{!objLead.Comments__c}" rows="5" cols="100"/>
           </apex:pageBlockSectionItem>
       </apex:pageBlockSection>
   </apex:pageBlock>
   </apex:form>
</apex:page>


Controller



public class ProcessInstanceController {
    public String processId;
    public String leadId;
    public ProcessInstance objProcessInstance;
    public Lead objLead {get; set;}
    public PageReference redirectPage;
    public ProcessInstanceController(){
        processId = ApexPages.currentPage().getParameters().get('id');
        leadId = ApexPages.currentPage().getParameters().get('leadId');
        objLead = [select Name,Owner.Name,Rejection_Reason__c,Comments__c from Lead where id =:leadId];
        redirectPage = new PageReference('/'+leadId);
    }
    
    public PageReference Approve(){
        Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();
        req.setComments(objLead.Comments__c);
        req.setAction('Approve');
        req.setWorkitemId(processId);
        Approval.ProcessResult result =  Approval.process(req);
        update objLead;
        return redirectPage ;
    }
    
    public PageReference Reject(){
        Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();
        req.setComments(objLead.Comments__c);
        req.setAction('Reject');
        req.setWorkitemId(processId);
        Approval.ProcessResult result =  Approval.process(req);
        update objLead;
        return redirectPage ;       
    }
    
     public PageReference Cancel(){
     return redirectPage ;
    }
}


Home Page Component



<div id="demoContainer"><script language="JavaScript">try{var pa=document.getElementById("demoContainer").parentNode.parentNode; pa.style.display = "none";}catch(err){alert('There was an error on this webpage='+err.description);}</script><script language="JavaScript">function CustomApproval(){try{var str=location.href;var leadId=str.substr(str.indexOf(".com/")-0 + 5,15);var divid=leadId+'_RelatedProcessHistoryList_body';var Approvalprocessdiv=document.getElementById(divid);if(Approvalprocessdiv!=null){var originalHTML=Approvalprocessdiv.innerHTML;var newHtml=originalHTML.replace('/p/process/ProcessInstanceWorkitemWizardStageManager?','/apex/ProcessInstanceWorkitemWizard?LeadId='+leadId+'&');Approvalprocessdiv.innerHTML=newHtml;}}catch(err){alert(err);}}var oldonload = window.onload; if (typeof window.onload != 'function'){window.onload = oldonload;} else { window.onload = function() {if (oldonload) {oldonload();}CustomApproval();}} </script></div>

2 comments:

  1. Hey Chitiz,

    This is really great, but we would really need this process to override the standard approvae/reject process on the object page layout.

    I set your code up for opportunity instead of lead, and we would obviously like this to sit on the opportunity page.

    Is there anyway to do this or must it sit on the hpage? We would consider designing a custom approval history/approvals related list in order to house the functionality, but it would obviously be a lot easier/more timely with a workaround on the standard object. Maybe I am missing something simple here.

    Any help would be immense -

    ReplyDelete
  2. Hey Chitiz,

    This probably worked great up until this Summer '14 release. In this release they're moving towards disabling this functionality in a couple of ways. Now you can no longer dump raw html/js into a home page component. Also, they're going to be moving to putting the components in an IFrame which means you can no longer interact with the rest of the page. Everything else will work except the way you get to the vf page that overrides the accept/reject page. Bummer!

    ReplyDelete