Saturday, April 28, 2012

Copy related list from Lead to Account/Contact/Opportunity


There is a salesforce limitation that when a Lead is converted to Account, all the related objects records are lost. E.g. for a Lead, there is a related object named products in which a lead is interested. So for a lead, we can add multiple products in the Lead related list. But when we convert lead to Account, all the products related to Lead are gone!!

So for this, I have written a small code which explains how using a small trigger and few fields, we can retain the products by linking them to account, opportunities and contact. 

I have used a general term CustomObject__c(replace it with you real related object name).

Step 1)For each custom object related to Lead we need to introduce 3 fields.
  -Account__c
  -Contact__c
  -Opportunity__c

Step 2) Write a trigger on before update event on Lead viz. LeadBeforeUpdate
trigger LeadBeforeUpdate on Lead (before update) {
//This trigger will associate a Custom Object record with the new contact and account when Lead is converted
//The Custom Object is associated to an opportunity only if an opportunity record exist on the Lead.
   
    Set<Id> leadIds = new Set<Id>();
    Map<Id,Id> LeadIdContactId = new Map<Id,Id>();
    Map<Id,Id> LeadIdAccountId = new Map<Id,Id>();
    Map<Id,Id> LeadIdOpportunityId = new Map<Id,Id>();


    for (Integer i = 0; i < Trigger.new.size(); i++){
        if (Trigger.new[i].IsConverted == true && Trigger.old[i].isConverted == false){
             leadIds.add(Trigger.new[i].id);
             LeadIdContactId.put(Trigger.new[i].id,Trigger.new[i].ConvertedContactId);
             LeadIdAccountId.put(Trigger.new[i].id,Trigger.new[i].ConvertedAccountId);
             LeadIdOpportunityId.put(Trigger.new[i].id,Trigger.new[i].ConvertedOpportunityId);


        }
    }
   
    //Create a list of CustomObject__c to be updated
    List<CustomObject__c> CustomObjectsToUpdate = new List<CustomObject__c>();
       
           
    List<CustomObject__c> customObjectEntries = [select Contact__c, Opportunity__c, Account__c, Lead__c from CustomObject__c where lead__c in :leadIds];       
   

    for (Lead lead : [select id,ConvertedContactId,ConvertedOpportunityId,ConvertedAccountId from Lead where id in: leadIds])  {
             for (CustomObject__c CustomObject : customObjectEntries) {
                if (CustomObject.Lead__c == lead.Id) {
                    CustomObject.contact__c = LeadIdContactId.get(lead.id);
                    CustomObject.opportunity__c = LeadIdOpportunityId.get(lead.id);
                    CustomObject.account__c = LeadIdAccountId.get(lead.id);
                    CustomObjectsToUpdate.add(CustomObject);
                 }
            }
     }

     if(CustomObjectsToUpdate.size()>0)
         update CustomObjectsToUpdate;
      
} //End of trigger


Note: This trigger will work for multiple records to be copied and is bulk efficient.

Wednesday, May 18, 2011

Salesforce - Get the list of all related objects from an object and their particular records

Solution : Lets get the records of all objects which are related to Account


List<Schema.SObjectType> childList = new List<Schema.SObjectType>();
Schema.DescribeSObjectResult R = Account.SObjectType.getDescribe();
//Create a list of child objects schema
for(Schema.ChildRelationship C : R.getChildRelationships()){
if(C.getRelationshipName()!=null && C.getRelationshipName().contains('__r')){
Schema.SObjectType child = C.getChildSObject();
System.debug('field****'+C.getField());
System.debug('field describe****'+C.getField().getDescribe());
System.debug('child****'+child);
childList.add(child);
}
}


//Querying all records
for(Schema.SObjectType objectToQuery : childList){
//Create dynamic query
String soqlQuery = 'SELECT Id,Name FROM '+objectToQuery;
System.debug('soqlQuery****'+soqlQuery);

//Execute query
List<SObject> results =  Database.query(soqlQuery);
System.debug('results****'+results);
} 

Salesforce – Get the Record Type Id of any object with out querying it in Trigger or Apex Class


Solution Approach – We need to use describe SObject for this.
Sample Code  -
        //To get the record Type Id for Account – Record Type Name is “Person Account”
                
                    //Get all the Record Types of Account and store it in a map.
    Map <String,Schema.RecordTypeInfo> recordTypes =        Account.sObjectType.getDescribe().getRecordTypeInfosByName();
 
     //Get the record type id of from the Map based on the Name
    Id RecTypeId = recordTypes.get('Person Account').getRecordTypeId());

Salesforce - Displaying number of characters remaining on 'Text Area Field'


Solution – We need java script to implement
Java Script:  
 function size(fvalue, size, divid) {
       var input_field = document.getElementById(fvalue);
       var msg_count = document.getElementById(divid);
       var char_reamining = '0';
       var char_entered = input_field.value.length;  
       if(char_entered == 0){
        msg_count.innerHTML = '';
        msg_count.style.background = '#F7F7F7';
       }else {
       if(char_entered <= size){    
         char_reamining = size - char_entered;
         msg_count.innerHTML = char_reamining+ ' remaining';
         msg_count.style.background = 'yellow';
        }else{
          msg_count.innerHTML = char_reamining + ' remaining';
          msg_count.style.background = 'yellow';
          input_field.value = input_field.value.substring(0,size);   
      } } }

  VF Code:  
   <div id="msg" class="ErrorMessageClass">
   </div>
    <apex:inputField value="{!Case.Problem_Description__c}" style="width:900px" onkeyup="javascript:size('{!$Component.formId:pgBlockId:pbs1:tdescription}',10000,'msg');" id="tdescription" />

We are passing the id of custom field in function size as first parameter and as second parameter we are passing size of the custom field i.e. In above case we are passing the size as 10000 so at the point of first character it displays the message 9999 characters remaining and so on...and it doesn't allow to enter more than 10000 characters, as third parameter we are passing the id of div where we need to display the message.

Salesforce - Translate field values


Solution – We can make use of toLabel(object.field) method while querying that field and assign the value. This facilitates to copy the translated value to be copied instead of the master value.

    Sample Code: To retrieve the account records depending on the translated picklist value HeadQuarterCountry = Bengalooru and copy the translated value to some other field. 

            Account acc = [SELECT Id, Name, Region__c, toLabel(HeadQuarterCountry__c) from Account WHERE toLabel(HeadQuarterCountry__c) ='Bengalooru' limit 1;];
            acc.Region__c = acc.HeadQuarterCountry__c; // the value "Bengalooru" will be copied to region instead of master value "Bangalore"          

Salesforce - To get the information about an object record which is sent for the approval


Solution – We can make use of ProcessInstance standard object which can be queried to get the end to end approval process of the record. The related child objects of the ProcessInstance can be used to get more information,
ProcessInstanceStep (child relationship name - "Steps") - Represents one step in an approval process (ProcessInstance).
ProcessInstanceWorkitem (child relationship name - "Workitems") - Represents a user's pending approval request.
ProcessInstanceHistory (child relationship name - "StepsAndWorkitems") - This read-only object shows all steps and pending approval requests associated with an approval process (ProcessInstance). You cannot query on this read only object instead you can query ProcessInstanceHistory by including it in a nested query on the parent ProcessInstance object.
Sample Code: The following code retrieves those submitted case records which needs the logged in user approval

 // Query the list of cases where in the Branch Manager is the logged in user
List<Case> userCaseList = [select Id, casenumber, company_name__c, Type,OwnerId, Status  from Case where Branch_Manager__c = :loggedUser];

// Query those submitted cases which needs the logged in user approval 
List<ProcessInstance> caseApprovals =[SELECT Id,TargetObjectId,
   (SELECT Id, ActorId, StepStatus, Comments, IsPending FROM StepsAndWorkitems where IsPending = True)
FROM ProcessInstance  where TargetObjectId in :userCaseList];

       

To display the HelpText for a field in visualforce


Solution: We can make use of “inlineHelpText” to display the helptext of a field in visualforce

Sample Code: To display the Help Text for Account Industry field,
                    <apex:outputText value=” {!$ObjectType.Account.Fields.Industry.inlineHelpText}"/>