Browse Category:

Entitlement and SLA management in Salesforce Using Entitlement Process, Milestone and Service Contracts.

Entitlement Management:  It helps you to provide precise and perfect support to customer. It provides features that let you define, enforce and track the service level as a part of customer support management. And you can track the working bandwidth of your customer support Agents.

Entitlement Process :  Entitlement processes are timelines that include all the steps (or milestones) that your support team must complete to resolve support records like cases or work orders. Each process includes the logic necessary to determine how to enforce the correct service level for your customers.

Milestone : Milestones represent required, time-dependent steps in your support process, like first response or case resolution times. Milestones are added to entitlement processes to ensure that agents resolve support records correctly and on time.

Service contracts : Service contracts in Salesforce represent a customer support agreement between you and your customers. You can use them to represent warranties, subscriptions, service level agreements (SLAs), and other types of customer support.

 Following are the steps to enable the use of Entitlement Processes and Service Contracts in Salesforce.

Enable Entitlements :

  1. Go to Setup, enter Entitlement Settings in quick fine box.
  2. Check the Enable Entitlement Management Checkbox, click on save.
  3. Customize the entitlement Page Layouts and fields according to Business Use.
  4. Go to Setup, enter Entitlement Settings in quick fine box, you can see more settings are available in Settings page.
  5. Enablement of Version :  If you want to maintain multiple versions of entitlement process, Check The Enable Entitlement Versioning Checkbox, Otherwise keep it unchecked.
  6. Set Up Entitlement and Asset Lookup Filters on Cases : You can select which of the filters should apply on Entitlement Name Field, where we can set the entitlement process which is registered to the asset only. Select the appropriate checkboxes according to your business needs, and then click on Save.
  7. Milestone Feed Items : If you want to enable milestone tracking in Feeds you need to check the Enable Milestone Feed Items checkbox, otherwise keep  it unchecked.

Set up Entitlement Template : Entitlement templates let you predefine terms of support that users can add to products.

  1. Go to Setup, enter Entitlement Template in quick find box. Click on New Template.
  2. Enter the Entitlement Template Name, to provide specific name to the entitlement template.
  3. Enter Entitlement Process Name, for which entitlement Process you want to add the template.
  4. Enter the Business hours of the case in Business Hours Field.
  5. Enter the Type of Entitlement Template, Either Web or Phone Support.

Set Up Milestone :

  1. Go to Setup, enter Milestones in the Quick Find box, then select Milestones.
  2. Click New Milestone.
  3. Enter a name and description.
  4. Select a recurrence type,
  5. No Recurrence: The milestone occurs only once on the record.
  6. Independent : The milestone occurs whenever the milestone criteria are met on the record.
  7. Sequential: The milestone occurs on repeat whenever the milestone criteria are met on the record.
  8. Click on Save.
  9. You can track the Milestone in Case Feed by adding Milestone Tracker in case Page Layout’s Feed View. It looks like below,
Case Feed showing a green circle for a milestone in progress
Milestone Feed Tracking In Salesforce Lightning
Case Feed showing a green circle for a milestone in progress
Milestone Feed Tracking in Salesforce Classic.

Set up  Entitlement Process :

  1. Go to Setup, enter Entitlement Processesin the Quick Find box, then select Entitlement Processes under Entitlement Management.
  2. Click New Entitlement Process.
  3. Select an entitlement process type, Either case or work order. If work order setup is enabled for your org then you can see work order, otherwise you can see case only.
  4. Enter a name and a description.
  5. If you want to enable the process, select Active.
  6. Optionally, if entitlement versioning is enabled, select Default Version to make this version of the entitlement process the default.
  7. Choose entry criteria for the Process by selecting one of the above option on <Record>(Case or Work Order) enters the Process field. A) Based on Record created Date. B) Based on custom date/time field on
  8. Choose the exit criteria for the Process by selecting one of the above option on <Record>(Case or Work Order) enters the Process field. A) Based on Record is Closed. B) Based on custom criteria.
  9. Optionally, choose the Business Hours you’d like to apply to the entitlement process. The business hours you set here calculate the Target Date for all the milestones on this entitlement process.
  10. Click on Save.

Set up Service Contracts :

  1. Go to Setup, enter Objects in Quick Find Box, select Service Contracts
  2. Customize Service Contract fields according to your Business Requirements.
  3. Customize Page Layout of Service Contract Object, add Status Icon field, so that users can easily understand whether the Service Contract is Active or Inactive.
  4. Add Service Contract related list to Account and Contact Page Layouts.

 For the ease of business users we can create reports on entitlement and on service contracts. For the effective tracking of case resolution and time management for support system.



Sending a VF Page as Attachment in Mail through Apex Class

Following code can be used for sending a vf page as an attachment with an email:

public class Gene_PDF{ 
public PageReference sendPdf(){                
     PageReference pdf = Page.mail_pdf;//mail_pdf is the name of vf page
     // goToNextPage('email');
     Blob body;                
        body = pdf.getContent();
     }catch(VisualforceException e){
            body=Blob.valueOf('Some text');
      Messaging.EmailFileAttachment attach = new Messaging.EmailFileAttachment();
      attach.Body = body;
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
      mail.setToAddresses(new String[] { email });
      mail.setSubject('PDF Email Demo');
      mail.setHtmlBody('Here is the email you requested! Check the attachment!');
      mail.setFileAttachments(new Messaging.EmailFileAttachment[] { attach }); 
      // Send the email    
      Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
      ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Email with PDF sent to '+email));
      return null;

Here 1) mail_pdf is the visualforce page that we want to use as attachment and

2) email is a pre-acquired Email-ID from user to which the email will be sent.

Using @future method in salesforce

Using @future method in salesforce and its limitations

Salesforce provides different ways to run your code asynchronously like Batch apex, @future method. In this post we will see how to use @future method, its advantages, limitations and the precautions that we need to follow while using it.
We can use the @future methods in cases where methods are long running. In such cases we can prevent governers limits by making it as asynchronous transaction. @ future methods also help in preventing mixed dml errors by isolating multiple dmls.
In order to mark a method as future we have to simply mark it with the ‘@future’ keyword as shown in below snippet.
Public static void futureMethod(){
//Your Code Here

Points to remember while creating @future methods:

1. future methods must always be static methods.
2. @future methods cannot return anything and its return type should always be void.
3. The input parameters to such methods can only be primitive types, arrays of primitive type or collections of primitive types.
4. Input parameters cannot be sobjects or collection of sobjects.
@future methods can also be used to make callouts to external services. To use this we must mark callout=true specifically. If it is not specified then the default value is taken as false.
public static void myfuturecalloutmethid(){
//code to call external services

Why are sObjects not allowed as parameters in case of @future methods?

It is because the sobjects may change by the time the method is executed, in such cases the @future method may overwrite the already saved values of the sObject record.
What is the workaround for above sobject case?
We can pass the object Id as parameter and then query the record within the @future method and then work on the latest data.
Limitations of @future method:
1. You cant call a future method from another future method.
2. You can call up to 50 @future methods per transaction.
3. You can call up to 250000 future methods per 24 hours. This is in conjunction with all types of asynchronous methods like batch apex.
4. @future methods are not executed during salesforce downtime and any already running jobs during the start of downtime are halted and restarted after the downtime.
Please go through Future Methods with Higher Limits (Pilot)
Precautions that we need to follow while using future methods:
1. Make sure you dont put too much in a future method as this will increase the execution time and may lead to delaying of other requests after the organisation limit of 2000 unprocessed future jobs is hit.
2. Opt for batch apex when you are processing large no of records.
3. Test your future methods with maximum possible data as this will give you an idea of how much the job may take during real time.


Platform Cache varient 2 – Org Cache

Continuing with Platform Cache….

2. Org Cache : The second variant of Platform Cache is the Org Cache. Org Cache does the same thing of storing the data in session, but the data stored is accessible through out the org, irrespective of  user, which is not the case with Session Cache.
If user1 is storing a  value1 in org cache, it is accessible by user2 also.

We can have different partitions to store values. We use the Cache.Org and Cache.OrgPartition classes to manage values in the org cache. To manage values in any partition, use the methods in the Cache.Org class. If we are managing cache values in one partition, use the Cache.OrgPartition methods instead.

This example stores a DateTime cache value with the key orderDate. Next, the snippet checks if the orderDate key is in the cache, and if so, retrieves the value from the cache.

// Add a value to the cache//
DateTime dt = DateTime.parse(’06/16/2015 11:46 AM’);  Cache.Org.put(‘ns1.partition1.orderDate’, dt);
if (Cache.Org.contains(‘ns1.partition1.orderDate’)) {
       DateTime cachedDt = (DateTime)Cache.Org.get(‘ns1.partition1.orderDate’);


To refer to the default partition and the namespace of the invoking class, omit the namespace.partition prefix and specify the key name.

Cache.Org.put(‘orderDate’, dt);
if (Cache.Org.contains(‘orderDate’)) {
DateTime cachedDt = (DateTime)Cache.Org.get(‘orderDate’);

The local prefix refers to the namespace of the current org where the code is running. The local prefix refers to the namespace of the current org where the code is running, regardless of whether the org has a namespace defined. If the org has a namespace defined as ns1, the following two statements are equivalent.

Cache.Org.put(‘local.myPartition.orderDate’, dt);
Cache.Org.put(‘ns1.myPartition.orderDate’, dt);

This is all about the Org Cache in apex.  There is another interesting thing about Platform Cache!

We can access cached values stored in the session or org cache from a Visualforce page with global variables.We can use either the $Cache.Session or $Cache.Org global variable. Include the global variable’s fully qualified key name with the namespace and partition name.

This output text component retrieves a session cache value using the global variable’s namespace, partition, and key.

<apex:outputText value=”{!$Cache.Session.myNamespace.myPartition.key1}”/>

This example is similar but uses the $Cache.Org global variable to retrieve a value from the org cache.


Now the Platform Cache concept seems more useful! We can directly use it in Vf page!!

Salesforce is Awesome!

Bundles in Steelbrick CPQ

Steelbrick CPQ allows users to define bundles to be added to Quote. This proves very helpful as it saves time of adding every product individually.

For achieving this there are two objects in CPQ.

The first is Features. Features is basically definition of the bundle. Features can be added from related lists of Products. The product that has a feature becomes the master. So whenever the Master is added, the feature can be added.

Feature is just the name of the bundle, but actual contents of the bundle are stored in Options object.

Options can be added from related list of the Features record. Options are references to the products to be included in the bundle.

Apart from just adding the products in the Bundles, various configurations can be added like predefining the quantity and whether the Quantity can be edited while adding the products in the Quote or it has to be fixed, whether the Product is mandatory or not, whether the product has to be selected by default in the bundle etc.

Bundle proves to be one of the most useful feature of the CPQ.

Rest API Call for GET and POST

global with sharing class MyRestResource {

global static Account doGet() {
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
String accountId = req.requestURI.substring(req.requestURI.lastIndexOf(‘/’)+1);
Account result = [SELECT Id, Name, Phone, Website FROM Account WHERE Id = :accountId];
return result;

global static String doPost(String name,
String phone, String website) {
Account account = new Account();
account.Name = name; = phone; = website;
insert account;
return account.Id;


  1. GET – call following URL in workbench rest explorer””
  2. POST -“”

    JSON Format-

“name” : “Wingo Ducks”,
“phone” : “707-555-1234”,
“website” : “”



What are Salesforce ID’s composed of?

The Id Field Type is a base-62 encoded string.

Each character can be one of 62 possible values:

  • a lowercase letter (a-z) – 26 values
  • an uppercase letter (A-Z) – 26 values
  • a numeric digit (0-9) – 10 values

As there is a combination of lower and upper case letters the casing of the 15 character Id has significance. E.g. 50130000000014 c is a different ID from 50130000000014C.

Within a 15 character Id the breakdown is:

  • First 3 characters – Key Prefix As per Jon’s answer, the first 3 characters are the key prefix that identify the object type. There are a few exceptions to this where multiple objects all share the same key prefix! There are a number of fixed key prefixes that are common across all of Salesforce. Custom objects get a unique key prefix per Org. Custom objects in managed packages can have a different key prefix in each installed org.
  • The 4th Character – instance/pod identifier
  • 5th Character – instance/pod identifier – extended
  • 6th character – Reserved. Will be 0 until such time that Salesforce has a need for it.
  • Remaining 9 characters – basically a really big number. Like 62^9 big or 238,328! That’s a lot of servers!

To this you can add an optional 3 character suffix that will make the Id unique case-insensitive. This is useful when working with programs that can’t maintain the case of the ID (E.g. Excel VLookup).

Create Short URLs with Bitly

This post is related to how to integrate Salesforce and Bitly to create short urls to include in communication Messages.

Step 1. Sign-up for Bitly

To use the Bitly API you will need to register. You can sign-up using Twitter, Facebook, or create a new login with their service. I chose to create a Bitly specific login using below url.

Step 2. Create Bitly Apex Classes

I developed below class, that encapsulates the Bitly http callouts.

global class bitly
Public String mode;
Public String sUrl;

public string getbitly ()
String shorten;
XmlStreamReader reader;
HttpResponse res;

//First, build the http request
Http h = new Http();
HttpRequest req = buildWebServiceRequest(sURL);

//Second, invoke web service call
if (mode==’live’) { res = invokeWebService(h, req); }

if (mode==’live’) { reader = res.getXmlStreamReader(); }
String str = ‘Foo bar’;
reader = new XmlStreamReader(str);
return readXMLResponse(reader,’shortUrl’);

public static HttpRequest buildWebServiceRequest(String purl)
String endpoint;
HttpRequest req = new HttpRequest();
endpoint = ‘’+purl +’&history=1&login=BitlyAPPName&apiKey=R_42d58b4eda1c412b8ef30577442428e4’;
return req;

public static HttpResponse invokeWebService(Http h, HttpRequest req)
{ //Invoke Web Service
HttpResponse res = h.send(req);
return res;

public static String readXMLResponse(XmlStreamReader reader, String sxmltag)
{ string retValue;
// Read through the XML
if (reader.getEventType() == XmlTag.START_ELEMENT)
if (reader.getLocalName() == sxmltag)
if (reader.getEventType() == XmlTag.characters)
retValue = reader.getText();
return retValue;

Whenever you implement it you just need to change BitlyAPPName and apikey from endpoint.


For calling bitly class use below lines

bitly b = new bitly();

b.mode = ‘live’;

b.sUrl = ‘’;

system.debug(‘Check BitLy short url – ‘ + b.getbitly() );


You will output as “Check BitLy short url –

15 Digit Vs 18 Digit Salesforce Record ID

ID fields in the user interface contain 15-character, case-sensitive strings. Each of the 15 characters can be a numeric digit (0-9), a lowercase letter (a-z), or an uppercase letter (A-Z).Two unique IDs may only be different by a change in case.

Because there are applications like Access or Excel which do not recognize that 50130000000014c is a different ID from 50130000000014C, an 18-digit, case-safe version of the ID is returned by all API calls. The 18 character IDs have been formed by adding a suffix to each ID in the API. 18-character IDs can be safely compared for uniqueness by case-insensitive applications, and can be used in all API calls when creating, editing, or deleting data.

To convert 18-character ID to a 15-character version, truncate the last three characters. recommends that you use the 18-character ID.

  • 15 digit case-sensitive version which is referenced in the UI ( at Database level).
  • 18 digit case-insensitive version which is referenced through the API.


Editing Records of Standard Objects from Salesforce site

Salesforce Sites or Sites lets you create web sites that run natively on It allows external users to access and modify records from Salesforce without the need of authentication or license.

But it does not allow Edit access to most of the standard objects. If there is a need to allow editing records of standard objects, one cannot directly edit them using fields directly on the Visualforce page (except for Orders and Contracts).

There is a simple yet effective work around for that which works just fine.

Instead of using fields reference on the Visualforce page, create variables in the controller and use them to get the input from the Visualforce page. Once the value is in those variables, assign them to the respective fields of the standard object in the controller.

Below is the part of the code that explains how this works.

<apex:inputtext value="{!value1}" label="Field1" />
<apex:inputtext value="{!value2}" label="Field2"/>
public String value1{get;set;}
public String value2{get;set;}
public pageReference updates(){

    update case_record; 

Need more help?

Hi there, was your problem or query resolved? If not & need more assistance, please do reach out to us at, we'll be more than delighted to help. Nanostuffs has 7+ years of extensive Salesforce & iOS/Android experience.
Holler Box