Custom redirection on Lead Convert operation in salesforce.com

Standard

When you convert a Lead, you will be taken to newly created Account’s detail screen. Thats the standard salesforce.com behaviour.

But what if, you want to show newly created Contact’s detail screen (instead of Account screen), upon Lead conversion? Unfortunately, there is no such setting available in salesforce (yet).

Many people might have achieved it, by some or the other workaround. And here is my trick.

  • Create following Apex Controller class, to use it along with the VF page.
    public class LeadConvertLandingController{
    
        Id newId = null;
        public LeadConvertLandingController(){
            newId = ApexPages.CurrentPage().getParameters().get('newid');
        }
    
        public PageReference redirect(){
            Lead convertedLead = [select ConvertedContactId from Lead where id=:newId];
            PageReference pRef = new PageReference('/' + convertedLead.ConvertedContactId);
            pRef.setRedirect(true);
            return pRef;
        }
    }
    
  • Create a VF page with following markup.
    <apex:page controller="LeadConvertLandingController" action="{!redirect}">
        please wait....
    </apex:page>
    
  • Create a Custom Button for Lead object, as follows:
    • Label = “Convert”.
    • Display type = “Detail Page Button”.
    • Behavior = “Display in existing window without sidebar or header”.
    • Content source = “URL”.
    • And copy below URL in the big text area.
      /lead/leadconvert.jsp?retURL=/{!Lead.Id}&id={!Lead.Id}&saveURL=/apex/LeadConvertLanding
      
  • Now edit the Lead layout and remove the standard Convert button and add the custom Convert button.
  • Thats it!

Hope thats helpful!

Note: This solution works only when, lead conversion is done with new Account/Contact during lead conversion process. It may not work, if existing Account/Contact is chosen, during lead conversion process/screens.

Abstract class and Interface – Technical Architect Series

Standard

While designing any solution, we often spend good amount of time preparing coding standards, guidelines, best practices, etc… The idea behind such effort is to make sure that the chosen design is implemented with ease and quality work is delivered. Having a good design can have a profound influence on success of any implementation.

A good design needs to be robust and scalable. The code should be structured and reusable. There is no place for redundant code in a good design. Hence it is very important to understand different ways by which we can write less and reusable code.

By using Abstract classes and Interfaces developers can design robust and scalable solutions.

Are TAs expected to write classes and interfaces?
Yes in some cases and no in most cases 🙂 Even if you (as a TA) are not writing code, then you are expected to

  1. Have a clear understanding of how Abstract classes and Interfaces can be leveraged for a good design?
  2. Guide the development teams to a right design approach. If needed, teach them how to work with abstract classes and interfaces.

What is an Abstract Class?

An abstract class is just like any other class, having properties and methods. However it has following characteristic which makes it different from other classes.

  1. It can have executable methods and abstract methods.
  2. It can only subclass one abstract class.
  3. It cannot be instantiated.
  4. It can only be extended by other classes (called subclasses).
  5. Its abstract methods must be overridden by its subclasses.
  6. Its non-abstract methods cannot be overridden by its subclasses.

An example abstract class

public abstract class MasterDataHandler{
    //executable method
    public MasterDataService initMasterDataService(){
        MasterDataService objMasterDataService = new MasterDataService();
        /**
	your code goes here....
	**/
        return objMasterDataService;
    }

    //abstract method, which should be overridden by extending class.
    public abstract Boolean doSynch();
}

Examples of extending classes (sub classes)

public class AccountSynchHelper extends MasterDataHandler{
    public override boolean doSynch(){
        return true;
    }
}
public class ContactSynchHelper extends MasterDataHandler{
    public override boolean doSynch(){
        return true;
    }
}

What is an Interface?

An interface is like a class in which none of the methods have been implemented—the method signatures are there, but the body of each method is empty. To use an interface, another class must implement it by providing a body for all of the methods contained in the interface.  Interface has following attributes that makes it different from abstract classes.

  1. It has no implementation code.interface
  2. All its methods are abstract by default.
  3. A class can implement any number of interfaces.
  4. An interface can extend another interface.
  5. As with classes, when an interface extends another interface, all the methods and properties of the extended interface are available to the extending interface.

Please refer below links for more information

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_defining.htm
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_interfaces.htm
Hope that’s helpful.

Sorting, Pagination in Visualforce using DataTables JQuery plug-in.

Standard

datatables in vf

What is this DataTables.net?
DataTables is a plug-in for the jQuery Javascript library. It is a highly flexible tool, based upon the foundations of progressive enhancement, which will add advanced interaction controls to any HTML table.

My Attempt
I did little bit of dotnet programming in my early days. I remember using ado.net controls for binding data to a list on an aspx page with just drag and drop. It was exciting to be able to pass SQL statements to controls directly in design time.

I always wondered if Salesforce would introduce similar VF components. For good or bad, that didn’t happen. However, Salesforce did a better thing by introducing VF components. Encouraging developers to create their our own VF components and reuse them just like you do in dotnet or java world.

Here is my attempt to create a VF component, which can take SOQL query, List of fields and Headers in design time.

I tried keep the code simple, you may tweak it as needed.

Here is the code…enjoy..!

VF Page

<apex:page docType="html-4.01-strict">
    <c:quickTableComp cContainerId="testtable"
        columnFields="Id, Name, AccountNumber"
        columnTitles="Record ID, Account Name, Account Number"
        soql="select Id, Name, AccountNumber from Account"    
    />
</apex:page>

VF Component

<apex:component controller="quickTableHandler">
    <apex:attribute name="cContainerId" type="String" required="true"  description="Id of the container which will hold & display the table" assignTo="{!cContainerId}"  />
    <apex:attribute name="soql" assignTo="{!soql}" type="String" description="SOQL query to execute and populate records." />
    <apex:attribute name="columnFields" assignTo="{!columnFields}" type="String" description="Comma-separated list of fields to display." />
    <apex:attribute name="columnTitles" assignTo="{!columnTitles}" type="String" description="Comma-separated list of column titles." />

    <link rel="stylesheet" type="text/css" href="http://cdn.datatables.net/1.10.0/css/jquery.dataTables.css"/>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="http://cdn.datatables.net/1.10.0/js/jquery.dataTables.js"></script>
    
    <script type="text/javascript">
            $(document).ready( function() {
                $('#{!cContainerId}').dataTable();
            } );
    </script>        

    <div class="full_width">
                
        <table cellpadding="0" cellspacing="0" border="0" class="display" id="{!cContainerId}" style="width:980px">
            <thead>
                <apex:outputPanel layout="none">
                    <tr>
                        <apex:repeat value="{!columnTitlesList}" var="t">
                            <th>
                                <apex:outputText value="{!t}" />
                            </th>                   
                        </apex:repeat>
                    </tr>
                </apex:outputPanel>
            </thead>
            <tbody>
                <apex:repeat value="{!records}" var="r">
                    <tr>
                        <apex:repeat value="{!columnFieldsList}" var="f">
                            <td>
                                <apex:outputField value="{!r[f]}" />
                            </td>
                        </apex:repeat>
                    </tr>
                </apex:repeat>
            </tbody>
        </table>
    </div>    

</apex:component>

Apex Class

public with sharing class quickTableHandler {

    public String columnFields { get; set; }
    public String soql { get; set; }
    public String columnTitles { get; set; }

    public List<String> columnFieldsList {
        get {
            if(columnFieldsList == null && columnFields != null) {
                columnFieldsList = columnFields.split(',');
                for(Integer x = 0; x < columnFieldsList.size(); x++) {
                    columnFieldsList[x] = columnFieldsList[x].trim();
                }
            }
            return columnFieldsList;
        }
        set;
    }
    
    public List<String> columnTitlesList {
        get {
            if(columnTitlesList == null && columnTitles != null) {
                columnTitlesList = columnTitles.split(',');
                for(Integer x = 0; x < columnTitlesList.size(); x++) {
                    columnTitlesList[x] = columnTitlesList[x].trim();
                }
            }
            return columnTitlesList;
        }
        set;
    }

    public List<sObject> records {
        get {
            if(records == null && soql != null) {
                records = Database.query(soql);
            }
            return records;
        }
        set;
    }
}

How to find out, if custom fields are referenced in your code? by using Apex & VF

Standard

How to find out, if custom fields are referenced in your code?

There could be many ways of doing it. Some common ones I keep hearing are:

  • Try deleting a field from salesforce ui, you will know if its referenced anywhere?
  • Do a text search across your code from eclipse ide.
  • etc…

Well, here is my attempt. I will take help of Apex and Visual Force to answer above question.

Many of us may or may not be aware that salesforce provides few important standard objects like:

  • ApexClass
  • ApexPage
  • ApexComponent
  • ApexTrigger

You might be thinking, when do we use these objects? what are the use cases? well, that’s what this blog post attempts to do. To get you start thinking in this direction.

I used little vf and couple of classes to perform a text search across code and tell you if a custom field is referenced anywhere in your code. I tried keeping the code simple, you may tweak it as needed.

So here goes the code..enjoy..!

fields used

VF Page


<apex:page controller="SmartWays" >
 <apex:form >
 <apex:SelectList value="{!selectedObject}" size="1" onchange="initFieldsScript()">
 <apex:selectOptions value="{!Objects}"></apex:selectOptions>
 <apex:actionFunction action="{!initFields}" name="initFieldsScript" rerender="pbtFields">
 </apex:actionFunction>
 </apex:SelectList>
 <apex:pageBlock >
 <apex:pageblocktable value="{!lstFieldResult}" var="field" id="pbtFields">
 <apex:column headervalue="Field Name">{!field.FieldApiName}</apex:column>
 <apex:column headervalue="Is Used">{!field.IsUsed}</apex:column>
 </apex:pageblocktable></apex:pageBlock>
 </apex:form>
 </apex:page>

Apex Class


public class SmartWays{

public String selectedObject {set; get;}
 private List<ApexClass>     lstClasses = new List<ApexClass>();
 private List<ApexComponent> lstComponent = new List<ApexComponent>();
 private List<ApexPage>         lstPage = new List<ApexPage>();
 private List<ApexTrigger>     lstTrigger = new List<ApexTrigger>();
 Map<String, Schema.SObjectType> mapObjects = Schema.getGlobalDescribe();
 public List<FieldsWrapper> lstFieldResult {get; set;}

public SmartWays(){
 lstClasses = [select Name, Body from ApexClass];
 lstPage = [select Name, Markup from ApexPage];
 lstComponent = [select Name, Markup from ApexComponent];
 lstTrigger = [select Name, Body from ApexTrigger];
 selectedObject = '';
 }

public List<SelectOption> getObjects(){
 List<String> sortThis = new List<String>();

List<Schema.SObjectType> gd = mapObjects.Values();
 Set<String> lstKeys = mapObjects.keySet();
 sortThis.addAll(lstKeys);
 sortThis.sort();

List<SelectOption> options = new List<SelectOption>();
 for(String s : sortThis){
 options.add(new SelectOption(s,s));
 }

return options;
 }

public PageReference initFields(){
 lstFieldResult = new List<FieldsWrapper>();
 if(mapObjects.containskey(selectedObject)){
 Schema.SObjectType s = mapObjects.get(selectedObject);
 Schema.DescribeSObjectResult r = s.getDescribe();

Map<String, Schema.SObjectField> fields = r.fields.getMap() ;
 Set<String> fieldnames = fields.keySet();
 List<String> fieldList = new List<String>();
 fieldList.addAll(fieldNames);
 fieldList.sort();
 String fName = '';
 for(integer i=0; i<fieldList.size(); i++){
 fName = fieldList[i];
 if(fName.endswith('__c')){ //only include the custom fields
 FieldsWrapper field = new FieldsWrapper();
 field.FieldApiName = fName;
 field.isUsed = hasReferences(fName);
 lstFieldResult.add(field);
 }
 }
 }
 return null;
 }

private boolean hasReferences(string fieldName){
 Boolean bRet = false;
 for(ApexClass cls:lstClasses){
 if(cls.body.contains(fieldName)){
 bRet = true;
 break;
 }
 }

if(!bRet){
 for(ApexPage pg:lstPage){
 if(pg.Markup.contains(fieldName)){
 bRet = true;
 break;
 }
 }
 }

if(!bRet){
 for(ApexTrigger trg:lstTrigger){
 if(trg.Body.contains(fieldName)){
 bRet = true;
 break;
 }
 }
 }

if(!bRet){
 for(ApexComponent com:lstComponent){
 if(com.Markup.contains(fieldName)){
 bRet = true;
 break;
 }
 }
 }

return bRet;
 }

public class FieldsWrapper{
 public string FieldApiName {set; get;}
 public string FieldLabel {set; get;}
 public boolean isUsed {set; get;}
 }

}

Hope that’s helpful

Get your Visitor’s IP address via sites

Standard

Have you ever ran into a situation, where you need to figure out your site’s visitor’s IP address? Well, many of us may or may not have. But the fact is, while working with sites, sooner or later you will bump into this requirement.

So, like every requirement, even this one can be dealt with, in many different ways. Like

1. Use an existing program like http://jsonip.com or http://jsonip.appspot.com/
2. Write a program (which will return visitor ip) in your choice of language (like php, asp, jsp, etc..) and put it on a web server.
3. Create a public vf page and use apex in the background, to get your visitor’s ip address.

I wouldn’t suggest option # 1 and 2 as they may or may not be available when your visitors come to your site. But if you go with option 3
then its almost certain that your visitor ip address can be traced. Because both your site and ip tracing vf page will be on sfdc servers. So, if a visitor is able to see your site that mean you can trace their ip address, for sure.

Here is the sample code:

VF page: getip


<apex:page controller="getipController" showheader="false" contenttype="application/json">{!ipAddress}</apex:page>

 

Apex class getipController


public class getipController {
 public String ipAddress {get; set;}
 public getipController(){
 ipAddress = ApexPages.currentPage().getHeaders().get('X-Salesforce-SIP');
 }
 }

 

Now that you can have code in place. Go ahead and make this page public from your force.com site.

That’s it. Your ip tracing page is now ready to be used in your site.

Using jQuery, you could make a JSON call:




$.getJSON("your page url", function(data){alert(data);});



 

Hope that’s helpful.

Dynamic SOQL with conditions

Standard

Very often, salesforce developers work on requirements where they have to generate SOQL queries on the fly/dynamically. And everyone has there own style of coding, hence they attempt this topic in their own unique ways.

Here is the code snippet I generally use when working with dynamic SOQL. Hope thats helpful 🙂

private String strSOQL = '';

private void prepareSOQL(){
 strSOQL = 'Select Name, Ticker_symbol__c, Headquarters__c, Company_Type__c, Ownership__c from CustomObject__c';
 List<string> conditions = new List<string>();

if(acct.Name!=''){
 conditions.add('Name LIKE \'%' + acct.Name + '%\' ');
 }

if(acct.Ticker_symbol__c!=''){
 conditions.add('Ticker_symbol__c LIKE \'%' + acct.Ticker_symbol__c + '%\' ');
 }

if(acct.Industry__c!=''){
 conditions.add('Industry__c = \'' + acct.Industry__c + '\' ');
 }

if(acct.Company_type__c!=''){
 conditions.add('Company_type__c = \'' + acct.Company_type__c + '\' ');
 }

if(acct.Company_status__c!=''){
 conditions.add('Company_status__c = \'' + acct.Company_status__c + '\' ');
 }

if (conditions.size() > 0) {
 strSOQL += ' WHERE ' + conditions[0];
 for (Integer i = 1; i < conditions.size(); i++)
 strSOQL += 'AND ' + conditions[i];
 }
 }