Wednesday, August 10, 2011

Approval Process Through Apex Trigger




Hi guys..
Follow the steps to create the approval process through apex trigger.
Step 1 : First you have to create a Approval Process And Activate It without any Criteria on any object Go to
Create - > Workflow and Approval - > Approval Process
Create a template for sending in email by replacing template field value using scripting in the trigger because we can not modify template field or can not include merge field values. Only Text Or Static Values can  send by Approval Process. If we want to send values dynamic then we have to replace the template values. Have a look on script.


Choose any object for which you want to manage the approval process.

I have create the approval process on ApprovalProcess__c object. I want when update the records then the Approval Request Should be gone to Admin User.

Have A Look :


trigger SendAnApproval on ApprovalProcess__c (after update) {
     set<Id> sid = new set<Id>();
    List<Id> lstid = new List<id>();
    for(ApprovalProcess__c obj :trigger.new){
        sid.add(obj.id);
        lstid.add(obj.ownerid);
    }

List<ApprovalProcess__c> lstObj = [select owner.email,Id,Name,Date__c,Description__c,Status__c from ApprovalProcess__c where Id in :sid];

EmailTemplate et = [ Select Body, HtmlValue, Id, Name, Subject from EmailTemplate  where Name='TestTemplateForApproval' Limit 1];
    system.debug('et :'+et);
    string htmlbody= et.HtmlValue;
    string Subject = et.Subject ;
    for(ApprovalProcess__c obj:lstObj) {
        try{
        if(obj.Status__c == 'Pending'){      
        Approval.ProcessSubmitRequest req = new Approval.ProcessSubmitRequest();
        req.setComments('Submitted for approval. Please Approve.');
        req.setObjectId(obj.Id);
        system.debug('req:'+req);     
        Approval.ProcessResult result = Approval.process(req);
        system.debug('lstid  '+lstid);
        string InstanceId = result.getInstanceId();
        system.debug('instance Id :'+InstanceId);
        string InstanceStatus = result.InstanceStatus;
        string[] NewWorkitemIds = result.getNewWorkitemIds();
      
        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();                    
        if(obj.Date__c !=null){
             htmlbody =htmlbody.replace('[Date]',string.ValueOf(obj.Date__c));
        }
        if(obj.Description__c !=null){
             htmlbody =htmlbody.replace('[Description]',obj.Description__c);
        }
        if(obj.Status__c !=null){
             htmlbody =htmlbody.replace('[Status]',obj.Status__c);
        } 
        if(obj.Status__c !=null){
             htmlbody =htmlbody.replace('[Status]',obj.Status__c);
        }
        system.debug('NewWorkitemIds[0] :'+NewWorkitemIds[0]);     
        string LinkRecordApproval ='https://ap1.salesforce.com/p/process/ProcessInstanceWorkitemWizardStageManager?id='+NewWorkitemIds[0];     
        htmlbody =htmlbody.replace('[Link]',LinkRecordApproval);
        system.debug('htmlbody :'+htmlbody);   
        string[] toAddress = new string[]{};
        toAddress.add(obj.owner.email);
        system.debug('toAddress :'+toAddress);
        mail.setToAddresses(toAddress);
        mail.setUseSignature(false);
        mail.setHtmlBody(htmlbody);
        mail.setSubject(Subject);       
        Messaging.sendEmail(new Messaging.SingleEmailMessage[]{mail}) ;   
        }           
        }Catch(DMLException ee){   
        }   
    }

}

Note : In this trigger we are replacing the Email Template Values Also because we can merge value in template when sending email via approval process.

In this case user recieved two mail:
1. Approval Process Email which we had configured.
2. We are sending manually because we need to replace the template values.


7 comments:

  1. Hi Vijay, This post was helpful thanks for sharing.

    I am facing one more limitation with this, my template has letterhead when is pass the htmlvalue the letter head is not coming in the email how to achieve that?

    ReplyDelete
  2. Hi Rekha ,

    You can convert your HTML template to custom you can get the all data in html value . Well your letter head images which you are using may not be public and external use also .
    If you are using custom template put <img scr='copied url of image <img src="https://c.cs5.content.force.com/servlet/servlet.ImageServer?id=015O00000004wOV&oid=00DO000000057uo&lastMod=1344528832000"> and append OID and lastmodified by at the end of image url .

    Thanks
    Vijay

    ReplyDelete
  3. Hi Vijay,

    Great article.
    A doubt, the approver continues with the approval feature answering email?
    Regards,

    Rogério

    ReplyDelete
  4. Hi Vijay,
    Is it possible to send a record for approval with creating any standard approval process on Object?

    Ex: When Field__c = "A", an email should be automatically sent to the approver and the requestor... without hitting "submit for approval" button..

    Any suggestions pls!!!!!!!!!!!


    Thanks,
    Priya.

    ReplyDelete
    Replies
    1. Hi Priya,
      Yes of course you can do that you through salesforce approval class Approval.ProcessSubmitRequest & Approval.ProcessResult. See below link.
      http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_approval.htm

      Delete
    2. Hi Vijay,

      So, does this require to create a standard approval process on object?


      if So, how can we achieve this without creating any standard approval process?

      Thanks,
      Priya.

      Delete
    3. Hi Priya,
      That is not possible without Standard Approval Process. You have to define first approval process then you can go through script.

      Thanks
      Vijay

      Delete