Wednesday, 8 January 2014

How to use Salesforce workflow rules

This blog provides some examples on when and how to use workflow rules.
Consider the workflow rule as the main container which defines when the workflow should be triggered and what actions should be taken based on the rule criteria.
So when will a workflow be triggered? Salesforce has 3 evaluation conditions:
  1. When a record is created, or when a record is edited and did not previously meet the rule criteria
    In short, this workflow rule will always be triggered (to check if the criteria are met) whenever the record is saved until the criteria are met.
  2. Only when a record is createdIt will only evaluate the criteria when the particular record is created
  3. Every time a record is created or editedIt will always evaluate the criteria every time the record is saved
When all rules are met, the workflow would either execute the workflow actions immediately or place the actions in a queue so that it will be executed when the Time-dependant Workflow Actions condition is met.

Note:
Time-dependant Workflow Actions is not available if the Every time a record is created or edited evaluation option is chosen.

The Workflow Actions

When a workflow rule is triggered and the criteria are met, a specific type of action will be performed or executed within Salesforce.

Some business scenarios and the suggested workflow evaluation rule

Scenario #1:-
The Sales director would like to receive notification for every newly created Closed Won Opportunity in Salesforce

ImplementationOnly when a record is created
This implementation ensures that the workflow rule is only triggered when the Opportunity is created. And if the Opportunity is Closed Won upon creation, the Sales Director would only receive the alert once instead of receiving duplicate emails.
Scenario #2:-

The Account Owner would like to receive notification whenever the Opportunity Owner is changed.
ImplementationEvery time a record is created or edited
The workflow rule will be triggered whenever the Opportunity record is saved and an email alert will be sent to the Account’s Owner whenever the Opportunity Owner is changed.
Scenario #3:-

The record owner needs an indication on when he can send out Invoice when the Opportunity is in Closed Won stage.
Suggested Evaluation CriteriaWhen a record is created, or when a record is edited and did not previously meet the rule criteria
This implementation ensures that only one task is created at the point where the Opportunity is Closed Won and it will not continuously create tasks whenever the Closed Won record is saved.
Scenario #4:-

The Sales Director wants visibility to any tasks there were not executed in Scenario #3. If the task is not executed within 3 days, the Sales Director needs an indication to follow up with the Record Owner.
ImplementationTime-dependant Workflow Action
This implementation ensures that the Sales Director has a scheduled reminder to follow up with the Opportunity Owner. The scheduled reminder will be executed when the Record Owner has yet to complete the given task within 3 days after the task is assigned.

Thursday, 2 January 2014

Concept of Salesforce Trigger

A Salesforce  trigger is  Apex code that executes when we do some DML operation in salesforce object.
In order to execution of trigger it is broadly  of two types ,After Trigger and Before Trigger.


Basic syntax of trigger:-

trigger triggerName on ObjectName (trigger_events) {
    //code_block
}
trigger TestTrigger on Case (Before Insert,After Insert,Before Update ,After Update ,Before Delete ,After Delete,After Undelete) {
 //Code Block
}

[Note:-Keep in mind that only the trigger of that particular object will invoke in which object we will do DML operation, not like  you will insert a record in child object and the trigger in parent object will invoke . It is possible to do some some data manipulation in different object but any way the trigger invoke only the object in which we will do Dml operation].

We can declare more than one trigger event in one trigger ,but each should be separated by comma.
Below are the possible event for trigger.

 >>Before Insert
>>Before Update
>> Before Delete
 >>After Insert
 >>After Update
 >>After Delete
>> After Undelete

There is a System defind class called Trigger which contains 12(twelve) implicit variable,which we can access at run time.
Below are the varibales with description.

1.isExecuting-It rutuns ture if the any code inside trigger context is executing.That means you can test whether your trigger is excuting or not by the help of this variable.

2.isBefore-It rutuns ture if the any code inside trigger context is executing before record is saved to the database.

3.isAfter-It rutuns ture if the any code inside trigger context is executing after record is saved to the database.

4.isInsert-It rutuns ture if the any code inside trigger context is executing due to an insert operation.

5.isUpdate-It rutuns ture if the any code inside trigger context is executing due to an update operation.

6.isDelete-It rutuns ture if the any code inside trigger context is executing due to a delete operation.

7.isUnDelete-It rutuns ture if the any code inside trigger context is executing due to undelete operation  i,e when we recovered data from recyclebin .

8.new-It returns the new version of the object record.

9.newMap-It returns a map  which contains an IDs  as a key and  the old versions of the sObject records as value.This map is only available in before update, after insert, and after
update triggers.

10.old-It returns the old version of the object record.

11.oldMap-It returns a map  which contains an IDs  as a key and  the new versions of the sObject records as value.This map is available for only update and delete trigger.

12.size- It return the size of the trigger.It will return one if you will insert one record, It will return the size of the record you are inserting ,updating or deleting or undeleting.

Examples to test the implicit variable:


trigger  TestTrigger on Case (Before Insert,After Insert,Before Update ,After Update ,Before Delete ,After Delete,After Undelete) {
    System.debug('*********testExecution*************'+Trigger.isExecuting);
    System.debug('****************size of trigger***************'+Trigger.size);
    if(Trigger.isBefore){
        if(Trigger.isInsert){
            for(Case cs:Trigger.new){
                System.debug('********beforeInsertNew************'+Trigger.new);
              
            }
        }
        if(Trigger.isUpdate){
            for(Case cs:Trigger.new){
                System.debug('********beforeUpdateNew************'+Trigger.new);
                System.debug('**********beforeUpdateOld**********'+Trigger.old);
                System.debug('********beforeMapUpdateNewMap************'+Trigger.newMap);
                System.debug('**********beforeMapUpdateOldMap**********'+Trigger.oldMap);
            }
      
        }
        if(Trigger.isDelete){
            for(Case cs:Trigger.old){
              
                System.debug('**********beforeDeleteOld**********'+Trigger.old);
                System.debug('**********beforeMapDeleteOldMap**********'+Trigger.oldMap);
            }
      
        }
  
      
    }
    if(Trigger.isAfter){
        if(Trigger.isInsert){
             for(Case cs:Trigger.new){
                System.debug('**********afterInsertNew**********'+Trigger.new);
                System.debug('**********afterInsertNewMap**********'+Trigger.newMap);
             }
         }
        if(Trigger.isUpdate){
             for(Case cs:Trigger.new){
                System.debug('**********afterUpdateNew**********'+Trigger.new);
                System.debug('*************afterUpdateOld*******'+Trigger.Old);
                System.debug('**********afterUpdateNewMap**********'+Trigger.newMap);
                System.debug('*************afterUpdateOldMap*******'+Trigger.oldMap);
            }
        }
       if(Trigger.isDelete){
            for(Case cs:Trigger.old){
                System.debug('*************afterDeleteold*******'+Trigger.Old);
                System.debug('*************afterDeleteoldMap*******'+Trigger.oldMap);
            }
       }
       if(Trigger.isUnDelete){
            for(Case cs:Trigger.new){
                System.debug('**********afterunUndeleteNew**********'+Trigger.new);
                System.debug('**********afterunUndeleteNewMap**********'+Trigger.newMap);
              
           }
       }
    }
}
[Note: Just copy this code and paste in case object or else in which object you want to test just the object name in the above example.After saving the trigger you can insert ,update ,delete and undelete records and just create debug log for different situation and observe.]

Below is the steps how to add this trigger in sales force in case object.

click Your Name  Setup  Cases  Case   Triggers  New

Just remove the existing code and paste the above code ans save the code .


After that follow the below steps to create the debug log.

click Your Name  Setup  Monitoring Debug logs  

Click on New button to set the debug log in your name .

Now you can create record for case object and try to observe the debug log and just realize all context variable.
Just Insert ,update delete and undelete one record from recycle bin.

Monday, 2 December 2013

avoid recursive trigger salesforce

Recursion occurs when the code gets called again and again and goes into a infinite loop. It is always advisable to write a code that does not call itself. However, sometimes we are left with no choice. Recursion occurs in trigger if your trigger has a same DML statement and the same dml condition is used in trigger firing condition on the same object(on which trigger has been written)
For example, if your trigger fires on after update on contact and you update any contact record in your trigger then the same trigger will be called and will lead to a infinite loop.
To avoid this kind of recursion and call the trigger only once we can use global class static variable.
As an example let says you have following trigger on contact:
trigger recursiveTrigger on Contact (after update) {
Id recordId ;
 for(contact con : trigger.new){
     recordId = con.id; 
 }
 Contact conRec =[select id,name,email from contact where id !=: recordId limit 1];

 conRec.email = 'testemail@kmail.com';
 update conRec;
 }
}
As you can see the trigger is getting called on after update and as the trigger has a DML update statement on the same object, same trigger will be called again leading to recursion.
To avoid this, just create one global class with a static global boolean variable as below.
global Class recusrssionPreventController{
Global static boolean flag = true;
 Public recusrssionPreventController(){
 }
}
And set this boolean variable in your trigger and then set this boolean variable to false as done in the trigger below
trigger recursiveTrigger on Contact (after update) {
Id recordId ;
if(
recusrssionPreventController.flag == true){
   
recusrssionPreventController.flag = false;
 for(contact con : trigger.new){
     recordId = con.id; 
 }
 Contact conRec =[select id,name,email from contact where id !=: recordId limit 1];

 conRec.email = 'testemail@kmail.com';
 update conRec;
 }
}
This will call the trigger only once and hence avoid recursion.

salesforce best practices for developers

Coding in apex requires that you follow all the best practices, as you may hit the governers limit imposed by salesforce.
Let us discuss some of the best practices that you should follow in order to avoid production failures and exceptions
1. Avoid writing select queries within for loop.
   This is something which you should avoid in all cases as this could very easily give "101 soql error"
   You can fire only 100 queries in one instance of apex code run, if more than 100 queries get executed you get the  above exception. Hence write your logic in such a way that you do not use select query within for loop
2. Use collections to store you data in apex, use map list set appropriately.
3.Bulkify your trigger, most often developers write triggers considering only one record would fire the trigger. But, in reality your trigger could be fired by many records at a time. Make sure you write a logic in such a way that it runs considering many records would fire the trigger at a time
4. Clear collections that are no longer required in apex code.Use transient key word where ever possible. View state error can be avoided by doing this.
5. Try to use limit clause in you select query, a select query can return only 50k records.
6. sosl query can return only up to 2000 records hence before using sosl you have to be 100% sure that the returned records will be less in number.
7. No dmls within for loop.
  Avoid updating,inserting or any other dmlon records in for loops. Instead run your dmls on collections. You can issue only 150 dml statements.
8. Write your code logic with minimum statements. Try to reduce number of lines of apex code if possible.
  There's limit for number of lines too.
9. Do not write your logic in trigger, write it in a class method and call that method in trigger.
10. Use access modifiers appropriately.
11. try to re-use code that has been already developed
12. Put your code in try and catch blocks appropriately and catch the exceptions
13. Follow this: One object, one trigger.
14. Follow naming conventions throughout your org, this keeps your codes organised and easily understandable.
15. Develop generic components for functionality that are used in many vf pages.
16. For Test coverage, make sure all the triggers in your org are covered with at least 1%.
    Total coverage needs to be > 75%, classes can have 0% but trigger should have minimum of     1%

get all objects in salesforce org

In order to get all the object names in your org, use Schema.getGlobalDescribe() method. This would return a map of object names and object types. Keyset would be all the object names. Following visualforce page uses this method to display all the objects in an org.



Visualforce page
<apex:page controller="AllObjectsinOrg">
 <apex:form >
   <apex:pageBlock id="pgblck">
    <apex:outputlabel value="Object Name" for="ObjPickList"/>      
    <apex:selectList value="{!ObjectSelected}" multiselect="false" id="ObjPickList" size="1">
       <apex:selectOptions value="{!ObjList}"/>
    </apex:selectList>
 </apex:pageBlock>
 </apex:form>
</apex:page>

Controller
public class AllObjectsinOrg {
 Public string ObjectSelected{get;set;}
 Public Map<String, Schema.SObjectTypeAllObjmap;
 Public AllObjectsinOrg(){
    AllObjmap = New Map<String, Schema.SObjectType>();
    AllObjmap = Schema.getGlobalDescribe();
    System.debug('******All object Names :'+ AllObjmap.keyset());
}
Public List<selectoption> getObjList(){
    List<selectoption> objList = new List<selectoption>();
    for(string s:AllObjmap.keyset()){
        objList.add(new selectoption(s,s));
    }
  return objList;   
 }
}

Salesforce Tools

Some good tools for developers

Salesforce Force.com Explore: 

This is the very first tool which comes in my mind for salesforce.com developers. Its a tool where you can explore salesforce Meta Data ( standard / custom objects, field and others.). I think as of now its best tool to write and execute SOQL queries. You can view your query history and export data to your m/c too.

Write / execute and test your SOQL queries in this tool before adding it to your apex code:

Download salesforce Force.com Explore : 

Installation Guide :

http://wiki.developerforce.com/page/ForceExplorer

Make sure you have Adobe AIR installed
Then download the latest release of Force.com Explorer 



Force.com IDE: 

The Force.com IDE is a full-featured, Eclipse-based coding environment, with capabilities like code completion, version control, collaborative development, and project sharing. 

Using this plugin, development, maintain code become very easy. Also you can deploy code&metadata ( like email templates, reports, objects etc) from your Sandbox to production easily. ( note: deployment activities varies from one Org/individual to other. There are different ways to deploy to production e.g. ANT, Eclipse Force.com plugin or salesforce application deployment interface ).

http://wiki.developerforce.com/page/Force.com_IDE_Installation

Workbench :   

Workbench is a powerful, web-based suite of tools designed for administrators and developers to interact with Salesforce.com.  


https://workbench.developerforce.com/login.php


http://wiki.developerforce.com/page/Workbench


Force.com Data Loader:

Using this tool you can export and import data out of salesforce.com instance. This tool is very much used by SFDC admins and developers for data import and export tasks.

you can download the Data Loader from the SFDC Setup menu, under Administration Setup - Data Management. 
find more details on :
http://wiki.developerforce.com/page/Data_Loader

APEX Class with/without sharing keyword

With or Without Sharing Keywords with APEX class  :

Generally Apex code executes in System contexts, means Access to  all objects,fields and records etc.
(beyond current users permissions, field level security or sharing settings).

(Where do I find "Sharing Settings"? its under "Setup" => "Administration Setup" => "Security Controls" => "Sharing Settings") Know More about "Salesforce Sharing Settings"

Note: ( Exception ) Anonymous code blocks always execute with current user permissions :)

So take care while developing code that user doesn't see/process data which he is not suppose to.
E.g. declaring apex class method as webservice ( take a look , kind of data you process or return inside webservice apex method ).
Give suitable access for class ( to suitable profiles) , once accessed by webservice call, then APEX executes in system context.

:) But this is also possible to execute Apex Class with current user's "Sharing settings". using "With Sharing" keyword. ( consider salesforce sharing setting while executing Apex code )

Note: "With sharing" keyword doesn't enforce the user's permissions and field-level security.

E.g.

public with sharing class MyNewClassWithSharing {
// Code here
}

Use the without sharing keywords means sharing rules for the current user are not enforced. For example:

public without sharing class MyNewClassWithOutSharing {
// Code here
}


Points to be noted:
A)  If with or without sharing are not mentioned with class then default is "Without sharing".

B)  If the class is defined with NO "sharing type" and called with in other class then it will execute with calling class's sharing setting accordingly.
    Else executes with with its own settings.
   
B)  The sharing setting applies to all code contained with in the class, including initialization code, constructors, and methods.

C)  Classes inherit this setting from a parent class when one class extends or implements another.

D)  Inner classes do not inherit the sharing setting from their container class.

E)  Class declared as with sharing can call code that operates as without sharing

F)  All SOQL or SOSL queries that use PriceBook2 ignore the with sharing keyword

G)  Using with sharing keyword :
i) SOQL and SOSL queries, may return fewer rows
ii) DML operation may fail due to insufficient privileges for current user.