Sunday, April 10, 2016

Salesforce SOQL Rule Engine

Build A Dynamic SOQL based Rule Engine and Evaluate the Rules for a given record on click of Button:

Use Case:
At times we come across an use-case where we wanted to evaluate a set of conditions for a given record and perform certain actions if satisfied. Workflows/Process builders are some of the ways to handle such requirements.

  • Sometimes the expansion of use-cases/complexity/frequent changes limit our ability to respond to it in a quicker way.
  • Too many Workflows with frequently changing criteria or with large criteria set at times hits the formula size limit. It can also impact the performance, makes it harder to maintain.

One way to overcome this is using "SOQL based simplified rule engine" which is configurable and the rules can be configured on the fly. This can be evaluated on a button click per record. If it has to be used in bulk then good to be evaluated as part of batch job in order to respect the Salesforce query limit exceptions.

Steps to build and use a simple SOQL based Rule Engine:
1> Create a custom object/custom metadata type (Available in Winter-16) "Rule Criteria" with following fields:
  • Rule Name, Group Rule Name (used if more than one rules), a long-text area to store the SOQL Rule, Next Rule Name field and sequence incase of multiple rules to be evaluated if the first rule criteria did not meet.
2> On Click of a button fetch the SOQL rule and run against the selected record if returned false if no other rules in the "Next Rule Name" within the "Group of Rules" for the "Rule Group" then end the rule evaluation else evaluate the next rule in the "Rule Group". If returned true check for "Evaluate Next" Flag to evaluate if any next rule defined in the Group else abort the evaluation.

3> Replace the dynamic variables in the stored SOQL in the "Rule Criteria Object" before executing the query for the rule evaluation.


Example:

Evaluate a User record is active followed by if the profile has Salesforce License.

1) Create Rule1 with a user based query with where condition isActive=true
2) Create Rule2 with a profile based query with where condition license name like Salesforce

 Evaluate the above Rule on click of a button for the above scenario:

{!REQUIRESCRIPT("/soap/ajax/32.0/connection.js")}
{!REQUIRESCRIPT("/js/functions.js")}
{!REQUIRESCRIPT("/soap/ajax/32.0/apex.js")}

var user = sforce.connection.getUserInfo();
var result = sforce.connection.query("SELECT RuleName__c,RuleSOQL__c,NextRuleName__c,Evaluate_Rules__c,Group_Rule_Name__c,Rule_Sequence__c from RuleCriteria__c where Group_Rule_Name__c='UserProfileValidation' order by Rule_Sequence__c");
var RuleC = result.getArray("records");
var RuleResult,RuleStr;

for (var i=0; i< RuleC.length; i++) {
        RuleStr = RuleC[i].RuleSOQL__c;
    if(RuleStr.indexOf("{UserId}")>-1)
           RuleStr=RuleStr.replace("{UserId}", "'"+user.userId+"'");

    if(RuleStr.indexOf("{ProfileId}")>-1)
           RuleStr=RuleStr.replace("{ProfileId}", "'"+user.profileId+"'");

    RuleResult = sforce.connection.query(RuleStr);
        if(RuleResult.size>0 && RuleC[i].Evaluate_Rules__c=='true') {
        if(RuleC[i].NextRuleName__c.length>0)
        {
            alert("Rule: "+RuleC[i].RuleName__c+" Passed!");
            continue;
        }
        else
        {
            alert("All Rules Evaluation Passed.");
            //Perform Next steps.
            break;
        }
    }
    else if(RuleResult.size>0)
    {
        alert("All Rules Evaluation Passed.");
        //Perform Next steps.
        break;
    }
}

*** You can install the unpackaged to have the above components from the following link: ***
https://login.salesforce.com/packaging/installPackage.apexp?p0=04t61000000Sk9H

Salesforce SObjects - Dynamic Cloning using Field Sets (Re-usable)

Using Field Sets (with a given set of fields) you can dynamic clone objects.

Sample Code:
//Fetch the fields from the field set
Schema.SObjectType SObjectTypeObj = GlobalDescribeMap.get('User');
Schema.DescribeSObjectResult DescribeSObjectResultObj = SObjectTypeObj.getDescribe();
Schema.FieldSet fieldSetObj = DescribeSObjectResultObj.FieldSets.getMap().get('<<Pass UserFieldSetName>>');
Set<string> fieldSetFields = new Set<string>();
for(Schema.FieldSetMember f : fieldSetObj.getFields())
{
    fieldSetFields.add(f.getFieldPath());
}
//custom clone original User (clone only those fields which are defined in fieldset)
Id userId = UserInfo.getUserId();
List<SObject> sObjects = AllFieldCloner.cloneByIds(new List<Id> { userId }, 'User', fieldSetFields);

// Clone a list of objects to a particular object type
public class AllFieldCloner
{
    /**
    * Clone list of SOBject Ids with the given set of fields from a field set
    * Parameters:
    * - List<Id> sObjectsIds - the list of Ids of the objects to be cloned. Objects must exist already in the database.
    * - Schema.SobjectType objectType - the type of object to be cloned.
    * - Set<String> sObjectFields - set of object fields to be cloned.
    */
    public static List<sObject> cloneObjectsByIds(List<Id> sObjectIds, Schema.SObjectType objectType, Set<String> sObjectFields)
    {
        return cloneObjectsByIds(sObjectIds, objectType, new List<String>(sObjectFields));
    }

    /**
    * Clone list of SOBject Ids with the given list of fields from a field set
    * Parameters:
    * - List<Id> sObjectsIds - the list of Ids of the objects to be cloned. Objects must exist already in the database.
    * - Schema.SobjectType objectType - the type of object to be cloned.
    * - List<String> sObjectFields - list of object fields to be cloned.
    */
    public static List<sObject> cloneByIds(List<Id> sObjectIds, Schema.SObjectType objectType, List<String> sObjectFields)
    {
        // A list of new cloned sObjects
        List<sObject> clonedSObjects = new List<sObject>{};

        // If there are no objects sent into the method,
        // then return an empty list
        if (sObjectIds != null && !sObjectIds.isEmpty() && !sObjectFields.isEmpty())
        {
            /* Using the list of sObject IDs and the object type,
            we can construct a string based SOQL query
            to retrieve the field values of all the objects.*/

            String allSObjectFieldsQuery = 'SELECT ' + String.join(sObjectFields, ', ') +
                                          ' FROM ' + objectType.getDescribe().getName() +
                                          ' WHERE Id IN (\'' + String.join(sObjectIds, '\', \'') + '\')';

            try
            {
                // Execute the query. For every result returned,
                // use the clone method on the generic sObject
                // and add to the collection of cloned objects
                for (SObject sObjectFromDatabase : Database.query(allSObjectFieldsQuery))
                {
                    clonedSObjects.add(sObjectFromDatabase.clone(false,true));  
                }
            }
            catch (exception e)
            {
                // Write exception capture method
                System.Debug('Error During Cloning:'+e);
            }
        }    

        // return the cloned sObject collection.
        return clonedSObjects;
    }
}

Dynamic clone of objects for all fields (except a set of fields by using Exclude logic).

Sample Code:

/**
    * Clone the given SOBJectIds with all the fields which is updatable
    * Parameters:
    * - List<Id> sObjectsIds - the list of Ids of the objects to be cloned. Objects must exist already in the database.
    * - Schema.SobjectType objectType - the type of object to be cloned.
    * - Set<String> sObjectExcludeFields - clone all createable/updateable fields EXCEPT these fields.
    */
    public static List<sObject> cloneByIdsAllfields(List<Id> sObjectIds, Schema.SObjectType objectType, Set<String> sObjectExcludeFields)
    {
        // A list of fields for the sObject being cloned
        List<String> sObjectFields = new List<String>{};

        // Get all the fields from the selected object type using
        // the get describe method on the object type.
        Map<String, Schema.SObjectField> fieldMap = objectType.getDescribe().fields.getMap();
        for(String field : fieldMap.keySet())
        {
            // go inside if condition when exclusion set is either null or it does not contain give field
            if(sObjectExcludeFields == null || !sObjectExcludeFields.contains(field))
            {
                Schema.DescribeFieldResult fieldDescribe = fieldMap.get(field).getDescribe();
                if(fieldDescribe.isCreateable() && fieldDescribe.isUpdateable() && !fieldDescribe.isCalculated())
                    sObjectFields.add(field);
            }
        }

        return cloneObjectsByIds(sObjectIds, objectType, sObjectFields);
    }

Salesforce Lightning App - AutoTypeAhead using Generic Search (Re-usable)

Steps to Implement AutoComplete/AutoTypeAhead using Lightning Component and Generic Search Term (re-usable code for searching within any Object/Term):



1) Create My Domain. (SetUp->Domain Management->My Domain)

2) Create a class "AutoTypeAheadController" with Aura enabled method (Re-usable method for searching a term within any SObject)

3) Upload Static Resources:
a) bootstrap.min.css (Static Resource Name: BootStrapCss)
Link: http://developer.salesforcefoundation.org/bootstrap-sf1/
b) jquery-1.11.3.min.js (Static Resource Name: jqueryjs)
Link: https://jquery.com/download/
c) jquery-ui.css (Static Resource Name: jqueryuicss)
Link: https://jqueryui.com/download/all/
d) jquery-ui.min.js (Static Resource Name: jqueryuijs)
Link: https://jqueryui.com/download/all/

4) Create Lightning Component "AutoTypeAhead".

5) Create Lightning App "AutoTypeAheadApp".

6) If your Org doesnt have namespace then use the following URL to access the Lightning App:
https://<<Domain Name>>.lightning.force.com/c/AutoTypeAheadApp.app
If your Org has a namespace then use the following URL to access the Lightning App:
https://<<>Domain Name>.lightning.force.com/<<NameSpace>>/AutoTypeAheadApp.app



Code Details:

************************************************************************************************************
Class: AutoTypeAheadController
************************************************************************************************************
global class AutoTypeAheadController {
 
    @AuraEnabled
    global static SObject[] autoSearch(map<string,string> request){
    /*
        Purpose: this function will be called from the lightning component,
        This will provide search result (SOSL) for any single object.
        
        request contains the following string key-value pairs
        @find: the actual string, user would search for
        @sobject: api name of sobject in which search would occur
        @fields: csv of the api names of the field that search would return
        @where: where clause used in SOSL
        @limit: limit clause used in SOSL
        @return: the function would return list of sobject
    
        Example:
        map<String, String> request
        = new Map<String, String>
        {'find' => 'test', 'sobject' => 'Account', 'fields' => 'Id, Name', 'where' => 'Status=Active', 'limit' => 25};      
    */

        String find = String.escapeSingleQuotes(request.get('find'));
        String sobject_name = request.get('sobject');
        String fields = request.containsKey('fields')? request.get('fields') : 'Name';
        String where_clause = request.containsKey('where') ? ' WHERE ' + request.get('where') : '';
        String limit_clause = request.containsKey('limit') ? ' LIMIT ' + request.get('limit') : '';
        
        
        String sosl = 'FIND \'%STR%*\'IN NAME FIELDS RETURNING %SOBJECT% (Id, %FIELDS% %WHERE% %LIMIT%)';
        sosl = sosl.replace('%WHERE%', where_clause);
        sosl = sosl.replace('%LIMIT%', limit_clause);
        
        sosl = sosl.replace('%STR%', find).replace('%SOBJECT%', sobject_name).replace('%FIELDS%', fields);
        
        SObject[] search_result = new SObject[0];
       
        
        for(sobject s :search.query(sosl)[0]){
            if(String.valueOf(s.get('Name')).containsIgnoreCase(find)) {
                search_result.add(s);            }
        }
        return search_result;
    }
}

************************************************************************************************************
************************************************************************************************************

************************************************************************************************************
Lightning Component: AutoTypeAhead
************************************************************************************************************
*************
Component:
*************
<aura:component controller="AutoTypeAheadController" implements="flexipage:availableForAllPageTypes,force:appHostable">
    <aura:attribute name="sObjectType" required="true" type="String" description="Name of the sObject that will be filtered" />
    <aura:attribute name="fields" type="String[]" default="" description="List of fields to get with each record"/>
    <aura:attribute name="limit" type="String" default="10" description="Limits the number returned to this value" />
    <aura:attribute name="inputLabel" type="String" default="Find" description="Label for text input"/>
    <aura:attribute name="ready" type="Boolean" default="false" description="Used to check if resources have been loaded"/>

    <aura:registerEvent name="autotypeaheadEvt" type="c:autotypeaheadEvt"/>
  
    <ltng:require scripts="/resource/jqueryjs,/resource/jqueryuijs"
         styles="/resource/jqueryuicss,/resource/BootStrapCss"
        afterScriptsLoaded="{!c.init}"
    />
    <div>
        <label>Search for {!v.sObjectType}: </label>
        <input id="searchTerm" class="AutoTypeAhead" type="text" />
    </div>
</aura:component>

*************
*************

*************
Controller:
*************
({
  
    init: function(component, event, helper) {     
        if (typeof jQuery !== "undefined" && typeof $j === "undefined") {
            $j = jQuery.noConflict(true);;
        }      
      
           component.set("v.ready", true);
           helper.initHandlers(component);
    }
  
})

*************
*************

*************
Helper:
*************
({
    initHandlers: function(component) {
        var ready = component.get("v.ready");

        if (ready === false) {
               return;
        }
      
        var ctx = component.getElement();
      
        $j(".AutoTypeAhead", ctx).autocomplete({
            minLength: 2,
            delay: 500,
            source: function(request, response) {
                var action = component.get("c.autoSearch");
                var fieldsToGet = component.get("v.fields");
              
                action.setParams({
                    "request":{
                    "sobject": component.get("v.sObjectType"),
                    "find": request.term,
                    "fields": fieldsToGet.join(),
                    "limit": component.get("v.limit")}
                });
              
                action.setCallback(this, function(a) {
                    var suggestions = a.getReturnValue();
                    var responseRes = a.getState();
                    if (responseRes === "ERROR") {
                       var errors = a.getError();
                       if (errors) {
                           if (errors[0] && errors[0].message) {
                               console.log("Error message: " + errors[0].message);
                           }
                       } else {
                           console.log("Unknown error");
                       }
                    }
                    if(responseRes === "SUCCESS")
                    {
                        //console.log("Output:"+JSON.stringify(suggestions));
                        suggestions.forEach(function(s) {
                            s["label"] = s.Name,
                            s["value"] = s.Id
                        });
                    }
                    response(suggestions);
                });
              
                $A.run(function() {
                    $A.enqueueAction(action);
                });
            },
            select: function(event, ui) {
                event.preventDefault();
                var ctx = component.getElement();
                $j(".AutoTypeAhead", ctx).val(ui.item.label);
                  
                var selectionEvent = component.getEvent("autotypeaheadEvt");
                selectionEvent.setParams({
                    selectedOption: ui.item
                });
                selectionEvent.fire();
            }
        });
    }

})

*************
*************

*************
Event:
*************
<aura:event type="COMPONENT"> <aura:attribute name="selectedOption" type="Object"/></aura:event>
**************
**************

*************
Renderer:
*************
({
  
    afterRender : function(component, helper) {
        this.superAfterRender();
            helper.initHandlers(component);
    }
})

*************
*************

************************************************************************************************************
************************************************************************************************************


************************************************************************************************************
Lightning App: AutoTypeAheadApp
************************************************************************************************************

*************
Application:
*************
<aura:application implements="force:appHostable">
    <div class="container-fluid">
        <div class="jumbotron">
          <h1>Auto-Complete Lightning Component</h1>
        </div>
        <div class="row">  
        <div class="form-group text-center">
            <c:AutoTypeAhead sObjectType="Account"
                    autotypeaheadEvt="{!c.handleAutocomplete}"
                    fields="Name,AccountNumber"
                />
        </div>
        </div>
        <div id="result"></div>
    </div>
</aura:application>

*************
*************

*************
Controller:
*************
({
    handleAutocomplete : function(component, event, helper) {
        var so = event.getParam("selectedOption");
        document.getElementById("result").innerHTML = 'Selected:' + so.Name;
    }
})

*************
*************

************************************************************************************************************
************************************************************************************************************

Visualforce Page for AutoTypeAhead

1) Create a generic class with SOSL for "AutoTypeAhead" functionality.
2) Create a visualforce page with JQuery and Bootstrap and generic class for "AutoTypeAhead"

***************************************
Code Details:
***************************************
************************************************************************************************************
Class: AutoTypeAheadController
************************************************************************************************************
global class AutoTypeAheadController {

    @RemoteAction
    global static SObject[] autoSearch(map<string,string> request){
    /*
        Purpose: this function will be called from the lightning component,
        This will provide search result (SOSL) for any single object.
      
        request contains the following string key-value pairs
        @find: the actual string, user would search for
        @sobject: api name of sobject in which search would occur
        @fields: csv of the api names of the field that search would return
        @where: where clause used in SOSL
        @limit: limit clause used in SOSL
        @return: the function would return list of sobject
  
        Example:
        map<String, String> request
        = new Map<String, String>
        {'find' => 'test', 'sobject' => 'Account', 'fields' => 'Id, Name', 'where' => 'Status=Active', 'limit' => 25};    
    */

        String find = String.escapeSingleQuotes(request.get('find'));
        String sobject_name = request.get('sobject');
        String fields = request.containsKey('fields')? request.get('fields') : 'Name';
        String where_clause = request.containsKey('where') ? ' WHERE ' + request.get('where') : '';
        String limit_clause = request.containsKey('limit') ? ' LIMIT ' + request.get('limit') : '';
      
      
        String sosl = 'FIND \'%STR%*\'IN NAME FIELDS RETURNING %SOBJECT% (Id, %FIELDS% %WHERE% %LIMIT%)';
        sosl = sosl.replace('%WHERE%', where_clause);
        sosl = sosl.replace('%LIMIT%', limit_clause);
      
        sosl = sosl.replace('%STR%', find).replace('%SOBJECT%', sobject_name).replace('%FIELDS%', fields);
      
        SObject[] search_result = new SObject[0];
     
      
        for(sobject s :search.query(sosl)[0]){
            if(String.valueOf(s.get('Name')).containsIgnoreCase(find)) {
                search_result.add(s);            }
        }
        return search_result;
    }
}

************************************************************************************************************
Visualforce Page: AutoTypeAheadPage
************************************************************************************************************
<apex:page controller="AutoTypeAheadController">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.min.css" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<script src="<<SFDC URL>>/soap/ajax/32.0/connection.js"></script>
<script src="<<SFDC URL>>/soap/ajax/32.0/apex.js"></script>
<script>
   var j$ = jQuery.noConflict();
   var autoTypeAheadApp = {
       opportunity_select: function(event, ui) {
        /*
         * method: opportunity_select
         * @arguments:
         * event - javascript event object
         * ui - Account record object
         * @returns records object for searched string
         * Description: This method sets Account field on select of Account record
         */
        j$("#Opportunity").val(ui.item.Id);
        var current_URL = window.location.href;
        //****Add Action to be done ****
       },
        opty_autocomplete_source: function(request, response){
            /*
             * method: autocomplete_source
             * @arguments:
             * request - request object for autocomplete widget
             * response - response from the Salesforce
             * @returns reponse object to autocomplete widget
             * Description: This method forms request and response object for account search in autocomplete widget
             */
            var ele = this.element;
            ele.data('records', []);
            var search_string = request.term;
            var obj = 'Opportunity';
            var whrCond = " OwnerId='"+'{!$User.Id}'+"'";
            var limitstr = '25';
          
            AutoTypeAheadController.autoSearch({
                find: search_string, sobject: obj
            }, function(result, event){
                ele.removeClass('ui-autocomplete-loading');
            if(result!=null){   
                ele.removeClass('ui-autocomplete-loading');
                response(j$.map(result, function(itm){
                    itm.label = itm.Name;
                    itm.value = itm.label;
                    itm.id = itm.Id;
                    return itm;
                }));
                };
            });
        },
        opportunity_typeahead: function(ele){
            /*
             * method: opportunity_typeahead
             * @arguments:
             * ele - DOM object for search box
             * Description: This method initiates autocomplete jquery UI widget on keypress in search input box and renders results as table.
             */
            j$(ele).addClass('ui-autocomplete-loading');
            if(ele.value == ""){
                j$(ele).removeClass('ui-autocomplete-loading');
            }
          
            j$(ele).autocomplete({
                source: autoTypeAheadApp.opty_autocomplete_source,
                minLength: 3,
                delay: 800,
                autoFocus: false,
                select: autoTypeAheadApp.opportunity_select,
                position: {my : "left top", at: "left bottom"}
            });
        },
        add_event_listeners: function(){
        /*
         * method: add_event_listeners
         * @arguments: N/A
         * Description: This method attaches event listeners to various actions in the application
         */

                j$('header').on('keypress keyup', '.search-opportunity-input', function (event) {
                    var key_code = event.keyCode ? event.keyCode : event.which;
                    if(key_code == 13) {
                        event.preventDefault();
                        return false;
                    }
                    autoTypeAheadApp.opportunity_typeahead(this);
                });
        }
    };
    j$(document).ready(function(){
        var self =  this;
        autoTypeAheadApp.add_event_listeners();
    });
</script>
<body>
<!--<div class="loader">Loading...</div>-->
<header>
<div id="navbar" class="form-group">
      <form class="navbar-form navbar-left search-opportunity-form" role="search">
          <div class="form-group">
              <input type="text" class="form-control input-sm search-opportunity-input" id="Opportunity" placeholder="Select Opportunity"/>          
          </div>
      </form>
 </div>
 </header>
 </body>
</apex:page>

Salesforce Lightning App Framework

What is Lightning Framework?
  • The Lightning Component framework is a UI framework for developing dynamic web apps for mobile and desktop devices. It’s a modern framework for building single-page applications.
  • Multi-tier component development that bridges the client and server. It uses JavaScript on the client side and Apex on the server side.

Difference between “Visualforce” and “Lightning”:
  • The Lightning Component framework is a component-based framework. As building blocks of an app, components encapsulate HTML, JavaScript, and CSS, while interacting via events. Lightning components are client-side centric, making them more dynamic and mobile friendly.
  • Visualforce components are page-centric and rely heavily on server calls. Visualforce facilitates delivering of template-driven web pages and email messages.

Why Lightning?
  • Out of box components (which is already available ready to use)
    • UIComponents:(https://developer.salesforce.com/docs/atlas.en-us.198.0.lightning.meta/lightning/ui_overview.htm)
    • UIEvents:(https://developer.salesforce.com/docs/atlas.en-us.198.0.lightning.meta/lightning/ui_events.htm)
  • Performance
  • Event-driven architecture like Javascript (better decoupling between components. write handlers that respond to interface events as they occur.)
  • Faster Development
  • Responsive design and cross browser compatibility

Steps to Enable Lightning Component Framework:


Useful links:

Productivity Tools related Salesforce/Few Generic (Debugging tools, Chrome Plugins, Third party tools)

Link to Generic Productivity Apps:
https://www.themuse.com/advice/20-productivity-apps-you-need-to-organize-your-life

Chrome Plugins (very useful for any user):
Grey Tab (to search for record details) https://chrome.google.com/webstore/detail/grey-tab/gdhilgkkfgmndikdhlenenjbacmnggmb/related
Force.com Logins: https://chrome.google.com/webstore/detail/forcecom-logins/ldjbglicecgnpkpdhpbogkednmmbebec
Salesforce.com Quick Login As: https://chrome.google.com/webstore/detail/salesforcecom-quick-login/dccccilgophpadpomgajjlkkioipoojh/related
Salesforce Navigator: https://chrome.google.com/webstore/detail/salesforce-navigator/ecjmdlggbilopfkkhggmgebbmbiklcdo?hl=en-GB&utm_source=chrome-ntp-launcher
Launch it: (toggle between salesforce1 app and salesforce): https://chrome.google.com/webstore/detail/launch-it-by-oyecode/ccbigdfmdgjfelngnjfooccehmpfgapi/related
Salesforce.com Id Clipper: (easily copy ids from URL)  https://chrome.google.com/webstore/detail/salesforcecom-id-clipper/hfiffenhnefppjhloglpebefjlbhoeai?hl=en
Salesforce.com Sandbox Favicon: (helps to distinguish between Prod/Sandbox): https://chrome.google.com/webstore/detail/salesforcecom-sandbox-fav/nkfllgjejgfgcddfccnijhndhdmjkamf?hl=en

Chatter Monitor: https://chrome.google.com/webstore/detail/chatter-monitor/hhlhfkhgmnojpdbedbmcljmcihhcckkl
Salesforce HoteKeys: https://chrome.google.com/webstore/detail/salesforce-hotkeys-beta/hkpmdgakkflkddmiffelfaokkgoamlil?hl=en-US&gl=US
Salesforce 15-18 Character conversion: https://chrome.google.com/webstore/detail/salesforcecom-id-converte/kiagkehielelkabjcakhpekplnelkaol
Momentum (home tab for Chrome with todo, etc): https://chrome.google.com/webstore/detail/momentum/laookkfknpbbblfpciffpaejjkokdgca?hl=en
Salesforce Admin Check All 1.2 This extension provides 'check all' checkboxes on admin pages. https://chrome.google.com/webstore/detail/sfdc-workbench-soql-asst/lbgnmgdddinmlgankmemlldolikbbbih

Following can be used in "UAT/Test Sandbox" which can be used for UAT:
Walkme Extention for Adobe: https://chrome.google.com/webstore/detail/walkme-extension-for-adob/adimkphjnpngdejidekdmiliengggnif
Paste the following URLs to your browser for Walkme free package installation: Sandbox installation link: https://test.salesforce.com/packaging/installPackage.apexp?p0=04ti0000000PVDg

Developer/Admin Tools:
Chrome Plugins (For Developers/Admins):
Rest Explorer (Post Man): https://chrome.google.com/webstore/detail/postman-rest-client/fdmmgilgnpjigdojojpjoooidkmcomcm
Data Explorer (Salesforce): https://chrome.google.com/webstore/detail/data-explorer-for-forceco/gbloanahneobjffpopabbapgdoahdljh
Salesforce.com Advanced Code Searcher: https://chrome.google.com/webstore/detail/salesforce-advanced-code/lnkgcmpjkkkeffambkllliefdpjdklmi
SOQL Extractor and Analyzer for Salesforce: https://chrome.google.com/webstore/detail/soql-extractor-and-analyz/deihalhihjdilndoidoclmhmgllebkfj
Formula editor: https://chrome.google.com/webstore/detail/salesforcecom-enhanced-fo/cnlnnpnjccjcmecojdhgpknalcahkhio
Test your webpage and get recommendations how it can be improved: https://chrome.google.com/webstore/detail/yslow/ninejjcohidippngpapiilnmkgllmakh
Salesforce Searchbox for configurations: https://chrome.google.com/webstore/detail/salesforce-searchbox/moaokcjghnjifeeahifofckbmhofjdbi
Record/Metadata comparator: https://chrome.google.com/webstore/detail/record-and-metadata-compa/laghgcpekjofijkmojnhfeiplbffaljp/related
Extract Custom setting data in one click:  https://chrome.google.com/webstore/detail/custom-settings-exporter/lmfmdaidklofmhheadbjcgcdeidnhbil
Profile comparator: https://chrome.google.com/webstore/detail/profile-comparator-for-sa/ijbipklcimjilmnaffocmjkfddhpaadg
Search Engine Chrome Extension for searching for help for Apex,code,Answers, Solutions, Discussion Boards, etc: https://chrome.google.com/webstore/detail/cloud-developers-search-e/fbojlhaajmiemkhdobbpbbdkjijadfjp
Debug Query Analyzer: https://chrome.google.com/webstore/detail/salesforce-debug-logs-ana/fmgpffinlgbhpeolebinkchfneekoloi
Package.xml builder: Sample Package.xml for Salesforce
Org Comparator using tooling.api for code between two orgs: https://sforgcompare.herokuapp.com
Metadata Glimpser - Code/Object Comparison App between Orgs
View Object Definition (In Production)
Excellent Chrome Extension for Salesforce Debug Log
SOQL Query Editor:  https://chrome.google.com/webstore/detail/jhgpiaofbicpedjhpllghnbfiilbmlio/publish-accepted
SFDC Magic Toolkit: (found it very useful): (You can build package XML from change set :) and then use it in work-bench/eclipse to retrieve the package and deploy using ANT) https://chrome.google.com/webstore/detail/sfdc-magic-toolkit/kilgdoafhhpkloidoajmlfienjndfbfo
Debug Apex code at ease: https://chrome.google.com/webstore/detail/apex-debugger/mpckkbblhbfngaininanfjpdfjhbncjo
SFDC API field names on Standard layout (example: useful to know API name if multiple labels with same is there) https://chrome.google.com/webstore/detail/salesforce-api-fieldnames/oghajcjpbolpfoikoccffglngkphjgbo
Salesforce Autosave & Recover Code (ARC) 1.3 Salesforce ARC autosaves/recovers code from/to edit page of Apex Classes, Triggers, Visualforce Pages and Components in Salesforce. https://chrome.google.com/webstore/detail/salesforce-autosave-recov/ikhffihfnmfolponkdamnbognhnljclg
Salesforce Search box in Configurations:
https://chrome.google.com/webstore/detail/salesforce-searchbox/moaokcjghnjifeeahifofckbmhofjdbi?hl=en

Salesforce-Apps related:
SOQL explorer: https://soql-explorer.herokuapp.com/#
For Run All test result download, code analysis etc: https://www.aside.io/login
Code Analysis, Editor (Good for reviews): https://www.aside.io/login
Developer workbench (data operations, Rest operations, ANT Deployment etc):  https://workbench.developerforce.com
ANT Deployment from Eclipse IDE: http://sforcehacks.blogspot.com/2013/02/getting-started-with-salesforce-ant.html


Admin tools:
Permission Comparator: https://perm-comparator.herokuapp.com/
Online Diff Tool (to compare two files): http://www.quickdiff.com/ 
SOQL to determine User Permissions: https://developer.salesforce.com/blogs/engineering/2012/06/using-soql-to-determine-your-users-permissions-2.html
Nice AppExchange app for searching through any Salesforce metadata within an org..Install as needed in your sandbox..
https://appexchange.salesforce.com/listingDetail?listingId=a0N30000009wgF7EAI
http://sftoolkit.co/ (For Org Compare etc)
Java Script related:
Compress Files: http://www.jscompressor.com/
Uncompress Files: http://www.jspretty.com/
FreeFormatter for Java script: https://www.freeformatter.com/regex-tester.html
Jsbin for Css/javascript testing: http://jsbin.com/