Saturday, June 22, 2013

Autonumber Trigger

This is my third blog and i have a delicious content to post here. I had an requirement to complete like this the client wants an unique Id in the lead section and opportunity section in Salesforce. they might create lead and opportunity manually or either automatically using Rest API transaction. So i planned to create a unique id in lead and opportunity. For example L-38 for lead number 38, O-15 for lead number 15 . I understood what's running in your mind what will happen if the lead is converted ? Even for the converted lead the opportunity number becomes like L-38(even after conversion) so the user can differentiate which is a converted opportunity and which is a manually created opportunity. I came up with the solution of writing trigger to achieve this.

In order to achieve this we have to write two triggers one on lead and one on Opportunity. This is my first trigger on lead

The Main purpose of writing this trigger is to generate a unique number for each record.. So i gave the condition that it has to pick the maximum values among Lead and Opportunity assign a value with maximum number  and concatenate with L and O based on the records.Any way i didn't give condition for concatenation instead i created a formula field instead which will concatenate the number with L and O since the client want the field read only.
Never forget to instantiate the field value else this trigger will wont work so before creating the trigger add default value "0" for the field Lead_Record_ID__c. In order to avoid null pointer exceptions.

The trigger is very simple to understand i queried lead and opportunity and ordered by descending values so that the highest number will be stored in the first index position of the list and the "Limit 1" in the query will store only one value.
 /******  
 ***Created by:Nirmal  
 ***Created Date:22.04.2013  
 ***last modified date:23:04:2013  
 ***Description:This trigger is used to generate a unique ID on Lead  
 ******/  
 trigger AutonumberIDonlead on Lead (before insert) {  
 List leadList=[select Lead_Record_ID__c,Id from Lead where Lead_Record_ID__c !=: null order by Lead_Record_ID__c desc limit 1];  
 List OppList1=[Select Lead_Record_ID__c,Id from Opportunity where Lead_Record_ID__c !=: null order by Lead_Record_ID__c desc limit 1];  
 Decimal maxlead = leadList[0].Lead_Record_ID__c;  
 Decimal maxopp = OppList1[0].Lead_Record_ID__c;  
 for(Lead led :trigger.new){  
 led.Lead_Record_ID__c= Integer.valueOf( ( maxlead > maxopp ? maxlead: maxopp ) +1 ) ;  
 }  
 }  



The next trigger would be the trigger on opportunity similar to the above one and this trigger will work if the isconvertedlead value is false this is good for not generating the autonumber if the opportunity is converted from to a lead..
 /*********************************  
 ***Created by:Nirmal  
 ***Created Date:22.04.2013  
 ***last modified date:23:04:2013  
 ***Description:This trigger is used to generate unique id on opportunity  
 ********************************/  
 trigger Autonumberonopp on Opportunity (after insert) {  
     List<Opportunity> OppList=[SELECT Id,ParentOpportunity__r.Lead_Record_ID__c, Lead_Record_ID__c,Sys_IsConvertedLead__c FROM Opportunity Where ID=:trigger.new[0].id];  
     List <Lead> leadList=[select Lead_Record_ID__c,Id from Lead where Lead_Record_ID__c !=: null order by Lead_Record_ID__c desc limit 1];  
     List <Opportunity> OppList1=[Select Lead_Record_ID__c,Id from Opportunity where Lead_Record_ID__c !=: null order by Lead_Record_ID__c desc limit 1];  
     Decimal maxlead = leadList[0].Lead_Record_ID__c;  
     Decimal maxopp = OppList1[0].Lead_Record_ID__c;  
     for(Opportunity Opp1:OppList){  
         if(Opp1.Lead_Record_ID__c!=null && Opp1.Sys_IsConvertedLead__c==false){  
                    opp1.Lead_Record_ID__c= opp1.ParentOpportunity__c == null ?    Integer.valueOf( ( maxlead > maxopp ? maxlead: maxopp ) +1 ) : opp1.ParentOpportunity__r.Lead_Record_ID__c ;  
       }  
     }  
     update OppList;   
 }  
Both triggers worked fine but the new problem arises from the ashes if the lead is converted what will happen to the existing auto number field. i don't need a new value while converting instead i need the same value in the opportunity section i came up with a different trigger for that.  this trigger will will written on lead i can modify the existing lead trigger to add the condition but in order to make the beginners understand i have created this as a separate trigger.
 trigger autonumberafterconv on Lead (before update) {  
   for(Lead lead:System.Trigger.new) {  
   if (lead.IsConverted) {  
       // Assign the value from the Lead "Status" field to the Contact "Type" field  
       Opportunity opp = [SELECT Id,Contact__c,Lead_Record_ID__c FROM Opportunity WHERE       Id = :lead.ConvertedOpportunityId];  
       opp.Lead_Record_ID__c = lead.Lead_Record_ID__c;  
       update opp;  
     }  
   }  
 }  
In this way we can make the id's unique in lead and opportunity and concatenated with L and O using a  formula field.

Wednesday, June 19, 2013

Sending Email on field change using a trigger


How to send Email to current and former lead owner if there is a change in the owner of the lead record?????
               The answer in simple you can do this by a trigger using messaging.single email message class. The scenario for me was like this in a lead record if there is a change in the lead owner a notification email has to be sent to the previous owner and current owner i've posted the code below for your reference.
 /*************  
 *******Created by:Nirmal Christopher  
 *******Created Date:02.05.2013  
 *******Description:Email will be sent if the owner is changed to new owner and old owner of the respective lead record  
 *************/  
 trigger SendEmailOnOwnerChange on Lead (before update,After Update) {  
   if (trigger.old[0].OwnerId != trigger.new[0].OwnerId ) {  
     Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();  
     //Select the Email Address of the old owner  
     String emailAddrnew = [select Email from User where Id = :trigger.old[0].OwnerId].Email;  
     String emailAddrold = [select Email from User where Id = :trigger.new[0].OwnerId].Email;  
     //Select the new owner and old owner from user  
     String newOwnerName = [select Name from User where Id = :trigger.new[0].OwnerId].Name;  
     String oldownerName=[select name from User where Id =:trigger.old[0].OwnerId].Name;  
     //Store the email address  
     String[] emailAddrnew1 = new String[] {emailAddrnew};  
     String[] emailAddrold1 = new string[]{emailAddrold};  
     mail.setToAddresses(emailAddrnew1 );  
     mail.setCcAddresses(emailAddrold1 );  
     mail.setSubject('Owner Changed for Lead : ' + trigger.new[0].Name);  
     mail.setPlainTextBody('Owner of lead: ' + oldownerName + ' Changed to ' + newOwnerName);  
     mail.setHtmlBody('This is to notify that the Owner of lead: https://ap1.salesforce.com/ <b>' + trigger.new[0].Id+'<b>&nbsp;&nbsp;Changed from</b>&nbsp;&nbsp;'+oldownerName + '</b>&nbsp;&nbsp; Changed to <b>' + newOwnerName + '</b>');  
     Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });  
   }  
 }  

hope this helps 

Email handler class-Salesforce

How to mock the Email to Salesforce Functionality using a inbound handler class?.....

 There might be certain cases where you have to mock the email to salesforce feature in my case the scenario was like this i wanted to integrate the sales user's Gmail Account with Salesforce so if the sales user receives the E-mail it will get auto forwarded to SFDC so that it have to create activity history logs in the related records. I can use the standard  Email to salesforce feature but the problem is Google sends the verification code to the target email address while setting up the auto forwarding feature so i wanted to fetch the verification code first where as SFDC dont have a feature to display the verification code sent via email to salesforce addres. To acheive this i have to create a inbound E-mail handler class for this. So the class which i created will automatically create tasks and activity history in all its associated records in Contact,Account and Opportunity object from the incoming email of the SFDC user's G mail address. In contacts and accounts we can associate the tasks and activity history since the Email field in contacts is related with accounts in some way. But what for opportunities?

    luckily we have something called opportunity contact roles we can query the opportunity contact role and if there is an match in the email adddress from the incoming Gmail address  with contact email address in Opportunity contact role an activity history and tasks will be created automatically.
      Similarly the activity history will be created in Accounts and  Contacts if there is an match in the email address. I've posted the code for reference below.
 /****************  
 Created by:Nirmal Christopher  
 Created Date:03.05.2013  
 Decription: from the incoming mail tasks will be created for Leads,Accounts and Opportunity  
 ****************/  
 global class GetVerificationCode implements Messaging.InboundEmailHandler {  
  global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email,Messaging.InboundEnvelope envelope) {  
  system.debug(email);  
  system.debug(envelope);  
  Messaging.InboundEmailResult result = new Messaging.InboundEmailresult();  
    String mail = email.fromAddress;  
    list<Task> opptask = new list<Task>();  
    list<Task> ltask = new list<Task>();    
    list<task>ctask=new list<task>();   
    list<OpportunityContactRole> ocr= [select OpportunityId,ContactId from OpportunityContactRole where Contact.Email=:mail ];  
    Set<Id> opportunityIdSet = new Set<Id>();  
    for(OpportunityContactRole o:ocr){  
      opportunityIdSet.add(o.OpportunityId);  
    }  
    list<Opportunity> opportunitylist=[select id from opportunity where id in: opportunityIdSet];  
     System.debug('********************************'+opportunitylist.size());  
    list<lead> leadTask =[Select id,email from lead where Email=:mail];   
    list<contact>contask=[select id,email from contact where Email=:mail];  
    System.debug('********************************'+contask.size());  
    //Inserting Opportunity Task  
   for(Opportunity o:opportunitylist)  
    {  
    Task tsk=new Task();  
    tsk.Subject = email.Subject;  
    tsk.OwnerId=UserInfo.getUserId();  
    tsk.Description = email.plainTextBody;  
    tsk.WhatId = o.id;  
    tsk.status = 'Completed';  
    tsk.Type__c='Recieved';  
    tsk.SYS_Check_Task_Creation__c=false;  
    opptask.add(tsk);  
    }  
    try{  
    insert opptask;  
    }catch(DmlException e){  
      System.debug('********opptask******'+e);  
    }   
   //Inserting Contacts Task  
   for(contact con:contask){  
    Task tsk1=new Task();  
    tsk1.Subject = email.Subject;  
    tsk1.OwnerId=UserInfo.getUserId();  
    tsk1.Description = email.plainTextBody;  
    tsk1.WhoId = con.Id;  
    tsk1.status = 'Completed';  
    tsk1.Type__c='Recieved';  
    tsk1.SYS_Check_Task_Creation__c=false;   
    ctask.add(tsk1);   
    }    
    try{  
    insert ctask;  
     System.debug('*******contask*******'+ctask);  
    }catch(DmlException e){  
      System.debug('*******contask*******'+e);  
    }  
   //Inserting Lead task  
    for(Lead lt:leadTask)  
    {  
    Task tsk2=new Task();  
    tsk2.Subject = email.Subject;  
    tsk2.OwnerId=UserInfo.getUserId();  
    tsk2.Description = email.plainTextBody;  
    tsk2.WhoId = lt.ID;  
    tsk2.status = 'Completed';  
    tsk2.Type__c='Recieved';  
    tsk2.SYS_Check_Task_Creation__c=false;  
    ltask.add(tsk2);  
    }  
    try{  
    insert ltask;  
    System.debug('**************'+ltask);  
    }catch(DmlException e){  
      System.debug('**************'+e);  
    }   
     return result ;  
  }  
 }  

By this way we can mock the standard E-mail to Salesforce feature using a Apex email handler class.

          After writing the class you have to enable email service feature in salesforce. You can access email services feature like this setup-->develop-->Email services and create a new email service . For the class choose the class which we created above click save it will generate a email service address, Use the email service address in your Gmail account's auto forwarding feature it will prompt you for a verification code  and a code will be sent to the auto forwarding address which you added you can capture the verifiction code in the debug logs. That's it....tadahhhhh your g mail account and SFDC instance is now integrated. create few filters in your Gmail account as required to forward specific emails in SFDC instance. So from the incoming email tasks will be created as activity history in Leads,contacts and Opportunities if there is a match in the incoming email address.