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}"/>

Salesforce - Display the History related lists in visualforce


To display the Account History Related lists,
<apex:page standardController=”Accounts”>
<!—Displays Accounts History Related lists -- >
<apex:dataTable value="{!Account.histories}" var="accountHistory" width="100%">
                 <!—Displays Created Date of the Field History -- >
                <apex:column>
                                <apex:facet name="header">Date</apex:facet>
                                <apex:outputText value="{0,date,MM/dd/yyyy HH:mm }">
                                                <apex:param value="{!accountHistory.createddate}" />
                                </apex:outputText>
               </apex:column>
              <!—Displays the corresponding field -- >
              <apex:column >
                 <apex:facet name="header">Field</apex:facet>
                                 <b> <apex:outputText  value="{!IF(CONTAINS(accountHistory.field,'__c'),LEFT(accountHistory.field, LEN(accountHistory.field) -3),accountHistory.field)}"/></b>
            </apex:column>
            <!—Displays Edited By User-- >                        
            <apex:column >
                <apex:facet name="header">Edited By</apex:facet>
                <apex:outputText value="{!accountHistory.createdby.name}"/>
            </apex:column>
            <!—Displays Old value of the field -- >
            <apex:column >
                <apex:facet name="header">Old Value</apex:facet>
                <apex:outputText value="{!accountHistory.oldvalue}"/>
            </apex:column>
            <!—Displays New Value of the field -- >
            <apex:column >
                <apex:facet name="header">New Value</apex:facet>
                <apex:outputText value="{!accountHistory.newvalue}"/>
            </apex:column>
        </apex:datatable>
    </apex:pageblock>   
</apex:page>

Security Health Check App


Developed by the salesforce.com information security team, the Security Health Check application performs a quick review of your security-related settings and makes recommendations for improvement. The health check provides a numeric score and tracks your overall security posture over time.

Scan your Force.com developed code for potential security issues.


To generate Google Charts (images) in Visual force-PDF


To enable the Images you have to unblock the callout from apex code. To make a callout from apex code you have to specify the end point in the Remote Site Settings as following,

Setup -> Administration Setup -> Security Controls -> Remote Site Settings -> New Remote Site.  

1. Remote Site Name: A name used to refer to the Remote Site Settings.
2. Remote Site URL: A URL of remote site. For example, to enable Google charts:
3. Disable Protocol Security: Check the Checkbox (As the PDF renderer is a code on the org
     making the request and as such gets denied access if you've not expressly allowed it).
4. Description: An optional description of the Remote Site Setting.
5. Active: Check the Checkbox (By default it is checked to make the settings active).

Salesforce - Increase Year Range of Standard Salesforce Datepicker shown

1. Create a narrow home page component and copy the below html code.
2. Add the home page component to home page layout.
3. Done

Component Code

<script language="javascript">
function addoption(selectobj,txt,val){ 
var optn = document.createElement("OPTION"); 
optn.text = txt; 
optn.value = val; 
selectobj.options.add(optn); 
}

var oldwinload = window.onload;
window.onload = function() {  
if (oldwinload) {    
 oldwinload();  
}  
var obj = document.getElementById("calYearPicker"); 
if(obj!=null){  
var d = new Date();
var curYear = d.getFullYear() + 6;
for(var i=curYear;i<2030;i++) { 
 addoption(obj,i,i);  
}
 }
}

</script>

Salesforce - Get Salesforce Base URL


Tuesday, May 17, 2011

Salesforce - Override Standard Approval Process Page

Sometimes requirement comes to make Rejection Reasons mandatory when Reject button is clicked. Follow the below approach to over-ride standard approval process page -
1. Create a custom visualforce page as a replica of standard approval/rejection page.
2. Create a controller to have methods for approve/reject/cancel. Approval Process api is available in apex reference book.
3. Create a home page component in which a java-script will be written to over-ride "Approve/Reject" button on Lead.
4. Add this home page component in home page layout.

Done..!!

Visualforce Page



<apex:page controller="ProcessInstanceController" tabStyle="Lead">
   <apex:form >
   <apex:sectionHeader title="Lead" subtitle="{!objLead.Name}"/>
   <apex:pageBlock title="Approve/Reject Approval Request">
       <apex:pageBlockButtons location="bottom"> 
           <apex:commandButton value="Approve" action="{!approve}"/>
           <apex:commandButton value="Reject" action="{!reject}"/>
           <apex:commandButton value="Cancel" action="{!cancel}"/>
       </apex:pageBlockButtons>   
       <apex:pageBlockSection columns="1">
           <apex:pageBlockSectionItem >
               Name <apex:outputField value="{!objLead.Name}"/>
           </apex:pageBlockSectionItem>
           <apex:pageBlockSectionItem >
               Lead Owner <apex:outputField value="{!objLead.Owner.Name}"/>
           </apex:pageBlockSectionItem>
           <apex:pageBlockSectionItem >
               Rejection Reason <font color="red">(Mandatory while Rejection)</font><apex:inputField value="{!objLead.Rejection_Reason__c}"/>
           </apex:pageBlockSectionItem>
           <apex:pageBlockSectionItem >
              Comments <font color="red">(Mandatory while Rejection)</font> <apex:inputTextArea value="{!objLead.Comments__c}" rows="5" cols="100"/>
           </apex:pageBlockSectionItem>
       </apex:pageBlockSection>
   </apex:pageBlock>
   </apex:form>
</apex:page>


Controller



public class ProcessInstanceController {
    public String processId;
    public String leadId;
    public ProcessInstance objProcessInstance;
    public Lead objLead {get; set;}
    public PageReference redirectPage;
    public ProcessInstanceController(){
        processId = ApexPages.currentPage().getParameters().get('id');
        leadId = ApexPages.currentPage().getParameters().get('leadId');
        objLead = [select Name,Owner.Name,Rejection_Reason__c,Comments__c from Lead where id =:leadId];
        redirectPage = new PageReference('/'+leadId);
    }
    
    public PageReference Approve(){
        Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();
        req.setComments(objLead.Comments__c);
        req.setAction('Approve');
        req.setWorkitemId(processId);
        Approval.ProcessResult result =  Approval.process(req);
        update objLead;
        return redirectPage ;
    }
    
    public PageReference Reject(){
        Approval.ProcessWorkitemRequest req = new Approval.ProcessWorkitemRequest();
        req.setComments(objLead.Comments__c);
        req.setAction('Reject');
        req.setWorkitemId(processId);
        Approval.ProcessResult result =  Approval.process(req);
        update objLead;
        return redirectPage ;       
    }
    
     public PageReference Cancel(){
     return redirectPage ;
    }
}


Home Page Component



<div id="demoContainer"><script language="JavaScript">try{var pa=document.getElementById("demoContainer").parentNode.parentNode; pa.style.display = "none";}catch(err){alert('There was an error on this webpage='+err.description);}</script><script language="JavaScript">function CustomApproval(){try{var str=location.href;var leadId=str.substr(str.indexOf(".com/")-0 + 5,15);var divid=leadId+'_RelatedProcessHistoryList_body';var Approvalprocessdiv=document.getElementById(divid);if(Approvalprocessdiv!=null){var originalHTML=Approvalprocessdiv.innerHTML;var newHtml=originalHTML.replace('/p/process/ProcessInstanceWorkitemWizardStageManager?','/apex/ProcessInstanceWorkitemWizard?LeadId='+leadId+'&');Approvalprocessdiv.innerHTML=newHtml;}}catch(err){alert(err);}}var oldonload = window.onload; if (typeof window.onload != 'function'){window.onload = oldonload;} else { window.onload = function() {if (oldonload) {oldonload();}CustomApproval();}} </script></div>