Sunday 25 November 2012

Approval Process via Apex Email Services

Hello,
Read my previous post on Approval Process via Chatter Feed for better Understanding, where the importance of speeding up the Approval Process and the method of Approving records via Chatter Feed.

We all know that Email Service is an automated process that uses Apex class to do some process based on the email contents.

This post demonstrates another easy and speedy way of Providing Approvals (Approving/Rejecting) by sending mails and processing the Approval Process using the Apex Email Services. Based on the mail contents and Apex class logic, certain actions can be made which is the Approval Process in this post.

Let us assume that we have a Approval Process sending email alert to the Approver asking to Approve the record whenever a record is submitted for Approval, additionally the mail contains information about the record which is submitted for Approval and the Service Email Address to Reply To.

Once the Approver received this mail, he/she can send their Approval/Rejection/Recall just by sending a reply to the Service Email Address.

The Apex Class associated with this Service Address will then analyses the mail contents like Subject,Body and based on it Approves/Rejects/Recalls the Approval Process.

Create an Apex Class to process the inbound mail as below which operates on Contract Object,

global class ContractApproval implements Messaging.InboundEmailHandler 

{
    global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email,Messaging.InboundEnvelope envelope)
    {  
        Messaging.InboundEmailResult emailresult = new Messaging.InboundEmailResult();
        system.debug(email.plainTextBody);
        if(email.subject.containsIgnoreCase('Contract Approval'))
        {
            String str = email.subject.normalizeSpace();
            String ContractNumber = str.substring(str.indexOf('-')+1,str.length());
            System.debug('ContractNumber :'+ContractNumber);            
            Contract con = [Select Id,ContractNumber From Contract WHERE ContractNumber=:ContractNumber];
            try
            {        
            List<ProcessInstance> pi = [SELECT Id FROM ProcessInstance WHERE TargetObjectId=:con.Id AND Status='Pending'];  
            if(pi.size()==0)
                return emailresult;
            List<ProcessInstanceWorkitem> piw = [SELECT Id,ActorId,ProcessInstanceId FROM ProcessInstanceWorkitem WHERE Actor.Email=:email.fromAddress and ProcessInstanceId=:pi[0].Id];            
            if(piw.size()==0)
                return emailresult;
            Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();                        
            if(email.plainTextBody.containsIgnoreCase('<approved>'))
            {
                req.setComments('Request Approved by Email Approval..!!');
                req.setAction('Approve');
            }                                    
            else if(email.plainTextBody.containsIgnoreCase('<rejected>'))
            {
                req.setComments('Request Rejected by Email Approval..!!');
                req.setAction('Reject');
            }
            else if(email.plainTextBody.containsIgnoreCase('<recalled>'))
            {
                req.setComments('Request Recalled by Email Approval..!!');
                req.setAction('Removed');        
            }
            req.setWorkitemId(piw[0].Id);                                  
            Approval.ProcessResult result = Approval.process(req);
            FeedItem a = new FeedItem(ParentId=con.Id,Type='TextPost');  
            if(result.isSuccess())                                    
            {
                a.Body='Email received from Approver and the process was '+result.getInstanceStatus();                
            }
            else if(!result.isSuccess())
            {
                a.Body='Email received from Approver but some error occured, please contact sys admin';
            }
            a.Body+=email.plainTextBody;
            Insert a;
            }
            catch(Exception e)
            {
                system.debug(e);
            }            
        }
        return emailresult;       
    } 
} 
This trigger takes the Contract Auto Number from the mail subject line and queries for the Contract record. Based on the tag in the email body <Approved> or <Rejected> or <Recalled>, the Approval Process was Approved or Rejected or Recalled.

To create email services, click Your Name | Setup | Develop | Email Services and create a New Email Address for it. Associate the Email Service with the ContractApproval Apex class which was created.


Checkout this link What is the Apex Email Service? , to know more about creating and defining a Email Service.



Screenshot of the mail received and the reply to the Service Address :




Screenshot of the Chatter in SFDC UI :