function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Soraya AttiaSoraya Attia 

How to automatically assign an entitlement name / process to a case

I have implemented web-to-case + entitlements / service contracts and an entitlement process.
How can I automatically create and assign an entitlement to a case? I now have to do it manually and only then does it trigger the entitlement process with the relevant processes. In my use case it concerns a case that needs to be picked up after 60 minutes when it is in the queue. I can assign an escalation rule but I would rather work with an entitlement process as you can add other milestones in the process to resolve the case according to SLA settings.
Best Answer chosen by Soraya Attia
pconpcon
You would write something like the following
 
trigger EntitlementAssign on Case (before insert) {
    Set<Id> accountIds = new Set<Id>();

    for (Case c : Trigger.new) {
        accountIds.add(c.AccountId);
    }

    accountIds.remove(null);

    if (!accountIds.isEmpty()) {
        Map<Id, Entitlement> entitlementMap = new Map<Id, Entitlement>();

        for (Entitlement e : [
            select AccountId,
                Name
            from Entitlement
            where AccountId in :accountIds
        ]) {
            entitlementMap.put(e.AccountId, e);
        }

        EntitlementProcess process = [
            select Name
            from EntitlementProcess
            where Name = 'Entitlement Process Name'
        ];

        List<Entitlement> entitlementsToInsert = new List<Entitlement>();
        for (Id id : accountIds) {
            if (entitlementMap.containsKey(id)) {
                continue;
            }

            entitlementsToInsert.add(new Entitlement(
                Name = 'Entitlement Name',
                SlaProcessId = process.Id,
                StartDate = Date.today().addDays(-1), // Start date of yesterday
                Enddate = Date.today().addDays(1), // End date of tomorrow
                AccountId = id
            ));
        }

        if (!entitlementsToInsert.isEmpty()) {
            insert entitlementsToInsert;

            for (Entitlement e : entitlementsToInsert) {
                entitlementMap.put(e.AccountId, e);
            }
        }

        for (Case c : Trigger.new) {
            if (c.AccountId == null) {
                continue;
            }

            c.EntitlementId = entitlementMap.get(c.AccountId).Id;
        }
    }
}
NOTE: This code has not been tested and may contain typographical or logical errors

You will need to update Line 25 to pull the correct EntitlementProcess and you will need to update lines 35-39 to have the data you want.  Just make sure to not remove / change line 39

All Answers

pconpcon
We currently do this in a trigger.  When the case comes in we query for the entitlements for the account and assign the "best*" one and put it on the case.  We do not auto-insert entitlements, but you could query for entitlements on the Account and insert a new one and assign it to the case if they do not exist.  I would do this in a before trigger so you don't have to update the Case object.

*This is a relative term and would be up to you to determine what "best" is.
Soraya AttiaSoraya Attia
Hi pcon, can you explain how to configure this via a trigger? I have never done this before. Thanks.
BTW I only have 1 entitlement per account (B2C environment)
pconpcon
You would write something like the following
 
trigger EntitlementAssign on Case (before insert) {
    Set<Id> accountIds = new Set<Id>();

    for (Case c : Trigger.new) {
        accountIds.add(c.AccountId);
    }

    accountIds.remove(null);

    if (!accountIds.isEmpty()) {
        Map<Id, Entitlement> entitlementMap = new Map<Id, Entitlement>();

        for (Entitlement e : [
            select AccountId,
                Name
            from Entitlement
            where AccountId in :accountIds
        ]) {
            entitlementMap.put(e.AccountId, e);
        }

        EntitlementProcess process = [
            select Name
            from EntitlementProcess
            where Name = 'Entitlement Process Name'
        ];

        List<Entitlement> entitlementsToInsert = new List<Entitlement>();
        for (Id id : accountIds) {
            if (entitlementMap.containsKey(id)) {
                continue;
            }

            entitlementsToInsert.add(new Entitlement(
                Name = 'Entitlement Name',
                SlaProcessId = process.Id,
                StartDate = Date.today().addDays(-1), // Start date of yesterday
                Enddate = Date.today().addDays(1), // End date of tomorrow
                AccountId = id
            ));
        }

        if (!entitlementsToInsert.isEmpty()) {
            insert entitlementsToInsert;

            for (Entitlement e : entitlementsToInsert) {
                entitlementMap.put(e.AccountId, e);
            }
        }

        for (Case c : Trigger.new) {
            if (c.AccountId == null) {
                continue;
            }

            c.EntitlementId = entitlementMap.get(c.AccountId).Id;
        }
    }
}
NOTE: This code has not been tested and may contain typographical or logical errors

You will need to update Line 25 to pull the correct EntitlementProcess and you will need to update lines 35-39 to have the data you want.  Just make sure to not remove / change line 39
This was selected as the best answer
Swaroopa Akula 2Swaroopa Akula 2
Hi @pcon 
I have used your trigger but looks like it is not populating the entitlement name on case. And in the 22nd  line I dont see Entitlement process name sobject in SFDC.So I used Entitlement sobject. 
My use case is: For every account has 2 entitlements(Priority 1 , Priority 2) and every entitlement has 2 milestones. We need to autopopulate the Entitlement name(Look up field) on case based on account and priority. Please let me know how can we achieve this?
pconpcon
Swaroopa, that's my fault.  The sObject isn't called EntitlementProcess but instead is SlaProcess.  Change line 22 and 24 and it should work.

As for autopopulating it, I would suggest that you either create two Entitlements under every account (would probably be best to automate that as part of a trigger on Account create) and create a unique name for that Entitlement that makes it easy to query / find inside a trigger.  The logic would be very similar to above, but instead you'd generate a map of Account => priority => Entitlement Id and pull the entitlement id from that map.
Swaroopa Akula 2Swaroopa Akula 2
@Pcon

Thanks for your reply. 
I tried changed the 22 and 24 to SlaProcess but still not able to pull the entitlement name on case.
When I tried to soql the 
select id, Name from SlaProcess where Name = 'Entitlement Process Name'--> i dont see any record listed. But if i change the Soql to select id, Name from SlaProcess -> I have records. Dont know what to change it here. Please help me on this.


And also can you provide me the draft code for auto populating entitlement and milestpne on account. THnaks in advance!!
 
Daniel GoodmanDaniel Goodman
Hi all,
I used the code and changed the values indicated.
When I create a case it would not auto-populate the entitlement process.
I would appreciate your help.
Thanks!
Brian LaughertyBrian Laugherty
I was able to get this working in my sandbox today, sample code below noting you will need to make 2 changes.

1. You will need to update line 25 ENTITLEMENT PROCESS NAME to match the 'Entitlement Process Name' shown under Setup > PLATFORM TOOLS > Service > Entitlement Management > Entitlement Processes

2. You will need to update line 35 ENTITLEMENT NAME USED ON ACCOUNTS to the name of the entitlement you have used for the accounts. 
 
trigger EntitlementAssign on Case (before insert) {
    Set<Id> accountIds = new Set<Id>();

    for (Case c : Trigger.new) {
        accountIds.add(c.AccountId);
    }

    accountIds.remove(null);

    if (!accountIds.isEmpty()) {
        Map<Id, Entitlement> entitlementMap = new Map<Id, Entitlement>();

        for (Entitlement e : [
            select AccountId,
                Name
            from Entitlement
            where AccountId in :accountIds
        ]) {
            entitlementMap.put(e.AccountId, e);
        }

        SlaProcess process = [
            select Name
            from SlaProcess
            where Name = 'ENTITLEMENT PROCESS NAME'
        ];

        List<Entitlement> entitlementsToInsert = new List<Entitlement>();
        for (Id id : accountIds) {
            if (entitlementMap.containsKey(id)) {
                continue;
            }

            entitlementsToInsert.add(new Entitlement(
                Name = 'ENTITLEMENT NAME USED ON ACCOUNTS',
                SlaProcessId = process.Id,
                StartDate = Date.today().addDays(-1), // Start date of yesterday
                Enddate = Date.today().addDays(1), // End date of tomorrow
                AccountId = id
            ));
        }

        if (!entitlementsToInsert.isEmpty()) {
            insert entitlementsToInsert;

            for (Entitlement e : entitlementsToInsert) {
                entitlementMap.put(e.AccountId, e);
            }
        }

        for (Case c : Trigger.new) {
            if (c.AccountId == null) {
                continue;
            }

            c.EntitlementId = entitlementMap.get(c.AccountId).Id;
        }
    }
}
NOTE: This code has not been tested and may contain typographical or logical errors

My only question is how does one get these things moved into the production instance?
Giancarlo AmatiGiancarlo Amati
Hi All, 

has this been tested with Email-to-case enabled ? for cases created by users sending emails? 
Thank you,
GC