Wednesday, January 18, 2012

Forcing Opportunity Creating During the Lead Conversion Trigger

Lead Conversion is a process in Sales Cloud that helps users convert leads into related accounts and open new opportunities. This is useful in preventing rework of transferring data from lead fields to Account fields. The entire process of Copy Paste is done with a single touch of button and the data is transferred.
However, on business end, the customer has just closed the deal and now the company has earned an Account  Salesforce allows you to streamline the business processes by field mapping.

We can map custom fields on Lead object to Custom Fields on Contact, Opportunity or Account object using field mapping on Lead setup.

However, there are times when we need to extend the standard the Convert functionality for a more complex purposes for e.g.,
1. Transferring some related object from lead to Account, Opportunity or Contact.
2. Throwing an Error if the Opportunity is not created on Conversation

In this example I am going to create a trigger that throws an error if the Create Opportunity check-box is not checked.

Example: Throw an error is opportunity is not created
Code:
trigger CheckOpportunityOnLeadConvert on Lead (after update) {
 //Check if the trigger is run from UI only.
  if (Trigger.new.size() == 1) {
 
     if (Trigger.old[0].isConverted == false && Trigger.new[0].isConverted == true) {
 
      // Check if if a new opportunity was created
      if (Trigger.new[0].ConvertedOpportunityId == null) {
          //Throw an error
           Trigger.new[0].addError('Please create an opportunity');
      }         
    }
  }     
}

Output:

The error is thrown on the Conversation, preventing it from moving on. The trigger is not that complicated but is a good start to recreate.

Further Reading

Tuesday, January 10, 2012

Spring 12 Salesforce Contains a Bug... a lady bug.


Its freezing cold out here. When I say its cold, I mean its cold, the cruel hellish humid city of Mumbai is also wrapped in the basket of coldness and finally after a decade, Mumbaikars (people from mumbai) have a topic of conversation with Delhites (people from Delhi) over cold. But while the entire world is still coping with the cold of winter, the clouds have already moved on to spring.

Salesforce has come out with the Spring 12 release and it contains a bug, no not software bug but a lady bug on the leaf. Obviously on the glorious traditions, new updates to not mean patches to cover up your mistakes, it means glorious new features and new things. As with the tradition with this blog, this is a feature to discuss top ten features that I find interesting in the update.

Chatter Now
Instant messenger inside chatter is now Generally Available. This is a good move towards turning into the one tool for Enterprise 2.0 collaboration platform. This can be the next Office Communicator Killer if used efficiently.

Social Contacts and Accounts
Salesforce kicked off last Dreamforce with a bold, 'Welcome to the social enterprise' it was obvious that Social Contacts and Accounts would be generally available sometime or the other. However, one beautiful addition to this is support for Klout and YouTube is added to it. This is a good step to move beyond the main stream social network and also a indication that this will expand beyond. If nothing else, you can see the picture of your contact, instead of a name.

Cross Object Workflow on Standard Object
With this release many standard objects are included in Cross Object workflow. Did I hear a sigh of relief from developers? Yes, this feature is bound to save a lot of coding time and create some beautiful processes quickly. However, currently only few Standard to Standard objects are included with limitation. But this gives a hope that in future we can expect some more features in it.


Workflow Field Updates Can Retrigger Workflow Rules
This looks amazing and was also one of the most critical interview questions. Can one workflow rule fire another workflow? Now the answer is yes. There can be 5 workflow in all which can be triggered one after another on field update. When there is a field update on a workflow, all the workflow rules are reevaluated, which did not previously meet the criteria. This is a very good update in terms of creating domino effect and will also reduce a lot of code while writing trigger.

Cloud Flow Designer is GA
With every passing update, coding is getting reduced less and less. Not sure if I like this or no. True, this saves a lot of time and we can utilize the time in designing killer system and leave the mundane task like making screens to the Flow Designer. But still, I miss coding. Fret not, I am sure most users will rejoice, now no need to tolerate the attitude of the developer, anyone can design screens on their own. Non-profits can benefit from this feature a lot as it is easy to use.

Chatter Answers

Chatter Answers integrates Cases, Answers, Force.com Sites, Customer Portal, and Salesforce Knowledge to provide you with a Web community for customers. This is also a bold move towards the Social Enterprise. We also are provided with Visualforce components to create these custom answers.

Live Chat Agent
An improvement to service cloud. Using the Live agent we can directly add live chat facility to the the public facing site. In additiaon to this feature, we get separate 8 components in visualforce to prepare the Chat Agent.

Apex Rest Api
Aah, finally, Apex REST automatically provides the REST request and response in your the REST methods via a static RestContext object. We can expose the Apex classes directly via Rest API.

Dynamic Visualforce Components are finally GA
This is my personal favorite update, dynamic components are very necessary for so many things. Wait till I dump those JavaScript and rework on the visualforce component using dynamic components. Similarly we also have dynamic bindings which can bind a variable to the controller.

Tab Bar Organizer
That annoying horizontal scroll which was not irritating for so many Salesforce edition finally is resigning. Now the overflowing tabs are neatly folded on the screen, also indicating that many developers are lazy organizing tabs in apps. This is a funny update but trust me in all the above, this is the most important update.

That ends my top ten list of Spring 12 update. Some parts in Spring 12 are very beautiful and I will try to cover as many as I can in upcoming blog. What is your favorite spring 12 feature?

Friday, January 6, 2012

The Basics of writing a Apex Trigger

One of the most important and common asked question on Forums and everywhere is how do I write a trigger. Coding in Apex Trigger is like going to a dentist for a root canal, you keep dreading the moment until you realize it is actually not going to hurt you. If you plan to write an Apex Trigger this quick guide will help you doing so.

The first and foremost rule in writing a trigger is to remember the oldest suggestion given to the most comprehensive Hitchhikers Guide to Galaxy, 'Don't Panic.' Writing a trigger is not a rocket science, in-fact we should thank the team at Salesforce and ForceDotCom for making everything so simple, that anyone can do it.

Enough of talk, lets code.

So you want to write a trigger. Let us have a glimpse of what we are going to build. The problem statement is as follows

Problem: When the User is entering the Opportunity, check for the Opportunity Amount. If the Opportunity Amount is greater than 50,000. Mark the Parent Account as 'Featured'.
Solution: We will be modifying the parent Account Type field to 'Featured' and select value from Opportunity Amount.
Trigger:

trigger SampleTrigger on Opportunity (after insert) {
Opportunity TheOpportunity = trigger.new[0];
if(TheOpportunity.amount>50000){
Account theAccount= [Select Type, Amount, name from Account where id:=theOpportunity.Accountid];
theAccount.type='Featured';
update theAccount;
}
}

Explanation:
Let us look at the trigger one by one.


Step 1:

trigger SampleTrigger on Opportunity (after insert) {

Trigger Keyword suggest this is a trigger, the SampleTrigger is the name of the trigger. The trigger is written on the Opportunity Object. The Event that the code runs is written inside the bracket.
The following operations are possible in a trigger.

insert
update
delete
merge
upsert
undelete

There are two types of Triggers:
Before triggers are used to update or validate record values before they are saved to the database. A before insert trigger can change the value in the field. We won't get before undelete trigger.

After triggers can be used for a much more complex purposes, like updating a value of some other object when this is updated. Or it can also be used to trigger some other event (like workflow and approval process). The events that run behind the scenes are as follows:

So choose the object, choose the event and finally choose the type of trigger.
When we write a trigger, the Force.com server automatically sends us the value that was operated on in a variable called Trigger, this is called Context Variable.

Suppose I am updating the Opportunity named 'Opportunity1' on the opportunity edit page. In the before update opportunity trigger, Force.com will send all the values that were existing before the record was updated in the list called Trigger.Old and the new values that the user added in the list called Trigger.New.
 If there is a bulk updation using data loader, all the values will be in the above two list. It is logical to understand that we won't get Old values in a Insert event and we won't get new values in the Delete event (Cos they don't exist)

If the record is updated from the web browser, Salesforce application we will find always find the value in Trigger.new[0], if the record is updated using a data loader, we need to loop through Trigger.new one record at a time as shown in the figure below.


Now lets look at the line number 2 in the trigger above.
Step 2:
Opportunity TheOpportunity = trigger.new[0];

We just brought the first record updated from the Trigger.Old[0] to TheOpportunity variable (We can directly operate on Trigger.old[0] however code looks messy, developer is an endangered species, spare the messiness)

The next loop is straight forward.

The rest is easy:

if(TheOpportunity.amount>50000){
Account theAccount= [Select Type, Amount, name from Account where id:=theOpportunity.Accountid];
theAccount.type='Featured';
update theAccount;
}

We select the Amount field and check if it is greater than 50,000. If it is, we can fetch the parent Account on the Opportunity using the AccountId field. This post is not about the queries, but if you need help on understanding queries there is a beautiful article written on the Force.com blog.

Thats it then, remember the first rule in writing a trigger, 'Don't panic' rest all is easy.

Toodles.