Sunday, June 15, 2014

Custom History tracking in salesforce

Some time we might need to track the history of the long text field or the rich text area field and Salesforce doesn't store the values for that, or might some time you need more than what Salesforce do in history tracking

Here is the custom solution how you can achieve the custom history tracking




Create a custom setting which will hold the sobject name and field to be tracked . Changes will be stored as a note to the parent record you may create a custom object if you want

Invocation on Account Object 

/** 
 * This is the trigger to capture the changes made in long text area 
**/
trigger AccountHistoryTrigger on Account (after update) {
   //checking the conditions. Target org may have existing trigger 
    if(TRIGGER.isAfter && TRIGGER.isUpdate){
        HistoryTrackingHandler handler = new HistoryTrackingHandler();
        handler.checkAndCreateNote(Trigger.newMap,Trigger.oldMap,'Account'); 
    }
}

Handler class

/** 
 * This class is the handler for the triggers on the sobjects those want to track values 
**/
public class HistoryTrackingHandler{
    /**
     * This method will take the new map and old map along with the Sobject name 
     * and comapre the values present in the custom setting for the Sobject 
     * If any values found then it will insert a note with al the changes 
     **/
    public void checkAndCreateNote(Map<Id,Sobject> newMapValues, Map<Id,Sobject> oldMapValues,String sobj){
        /**
         * Checking if the custom setting value exists 
         * input newMap,oldMap, Api name of the Sobject
        **/ 
       
        if(LongTextAreaFieldstoTrack__c.getInstance(sobj)<> NULL && LongTextAreaFieldstoTrack__c.getInstance(sobj).Field__c <> NULL && LongTextAreaFieldstoTrack__c.getInstance(sobj).Field__c.trim() <> '' && LongTextAreaFieldstoTrack__c.getInstance(sobj).Active__c == TRUE){
            // getting the values from the custom setting
            String selectedFields = LongTextAreaFieldstoTrack__c.getInstance(sobj).Field__c;
            List<Note> noteList = new List<Note>(); // creating a list to insert notes 
            Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe(); 
            Schema.SobjectType oType = gd.get(sobj); // getting the object type in runtime 
            // getting all the fields at runtime
            Map <String, Schema.SObjectField> fieldMap = Schema.getGlobalDescribe().get(sobj).getDescribe().fields.getMap();
            //Iterate through the loop and check for the field if the field present in the custom setting 
            //and the values are modified then create a note record for per transction for each record 
            for(Sobject currentSobj : newMapValues.values()){
                sObject newObjectInstance =  oType.newSObject(); // will hold new instance
                sObject oldObjectInstance =  oType.newSObject(); // will hold old instance
                newObjectInstance = currentSobj; // getting the new instance 
                oldObjectInstance= oldMapValues.get(currentSobj.Id); // getting the old values               
                for (String fieldName : fieldMap.keyset()) { 
                    if(selectedFields.containsIgnoreCase(fieldName)){// checking if present in the custom setting or not
                        if(newObjectInstance.get(fieldName) != oldObjectInstance.get(fieldName) && oldObjectInstance.get(fieldName) <> NULL){
                            String nodeTitle = ''+ fieldName + ' has been changed by ' + userInfo.getName() + ' at ' + System.now();
                            //value has been changed, so append in the body
                            String nodeBody = 'Old value was \n'+ oldObjectInstance.get(fieldName) ;  
                            Note newNote = new Note(IsPrivate=false,ParentId=newObjectInstance.Id,Body=nodeBody,Title=nodeTitle);
                        noteList.add(newNote);
                        }
                    }
                }
            }
            // if added in list inserting the recod
            if(noteList.size() > 0){
                try{
                  insert noteList;
                }
                catch(Exception e){ System.debug('Error while inserting Note : ' + e.getMessage()); }
            }
        }
    }
}

  

Saturday, March 15, 2014

Disable date picker on Visual Force Page

Most of the time customers do not want to use the standard Salesforce date picker for various reasons.
If the first field of your VF page is a date field then as soon your page got loaded the date picker pops up. It is very irritating for end users


1) How to disable the date picker pop up on page load


<apex:page>
<!-- This is a hidden text box on your page , focus gone to this field automatically when the page loaded 
 and it suppress the Date Picker Pop up --> 
 <input type="text" id="hiddenText" style="width:0px;height:0px;border: none;background-color: #fff;background: transparent;"/>
<apex:form>
  <!-- Date Field -->
</apex:form>
</apex:page>


2) Permanent disabling of date picker , override the date picker style 


 <apex:page>
<style>
.datePicker{
                    visibility:hidden;
          }
</style>
</apex:page>