1

I've written a trigger which will create a new child Entitlement record whenever an Account is created.

I need to populate the Account's Application_Entitlement_Id__c field with the Id of the newly created Entitlement.

I'm new to Apex and can't work out how to fetch the Id of the newly created Entitlement and add that to the Application Entitlement Id field of the new Account.

trigger AcctSubmitAppEntitlement on Account (after insert) {

    List<WEID__c> weids = WEID__c.getall().values();
    Set<Id> validRecordTypeIds = new Set<Id>();

        for (WEID__c weid: weids) {
        try {
            validRecordTypeIds.add(weid.WEAccId__c);
            } catch (System.StringException e) {
              System.debug(
                System.LoggingLevel.ERROR,
                'Invalid Record Type Id ' + weid.WEAccId__c
                );
            }
        }

      List<Entitlement> entitlements = new List<Entitlement>();
      for (Account newAccount: Trigger.New) {

          if(validRecordTypeIds.contains(newAccount.RecordTypeId)){

           Entitlement newEnt = new Entitlement();
           newEnt.Name = 'Submit Application';
           newEnt.AccountId = newAccount.Id;
           newEnt.StartDate = Date.Today();
           newEnt.EndDate = Date.Today().addYears(50);
           newEnt.BusinessHoursId = '01m7000000008Ke';
           newEnt.SlaProcessId = '552M000000000XA';
           entitlements.add(newEnt);
          }
          insert entitlements;
      }
}

I've also written the following, I just don't know where to go from here.

          if (entitlements.size() > 0){
              List<Entitlement> newEntitlements = [SELECT Id from Entitlement
                                                WHERE AccountId = :newAccount.Id];
              if (newEntitlements.size() > 0) {
                  newAccount.Entitlement_ID__c = newEntitlements[0].Id;
              }
          }

The Application Entitlement Id will be referenced when a new case is created from the related list in Opportunities, using a JavaScript button. This will allow me to assign an Entitlement for every case which is created using the custom button.

2

The rest of your code should look like what's below which begins following the insertion of the new entitlements.

Once you've inserted the records, the list that contained them is automatically populated with the Ids of the new records, so there's no need to query them.

          insert entitlements;
      }

      list<account>acctsUp = new list<account>();

      for(entitlement e:entitlements){

         account a = new account(Id = e.AccountId);
         a.Entitlement_ID__c = e.Id;

         acctsUp.add(a);
      }

      update acctsUp;         

} // end of trigger

Edit: Discussion on Comments

This trigger as designed creates a new child Entitlement record whenever a new Account is inserted. As designed, it only creates one Entitlement record, for each new Account. Afterward, it then populates a custom field in Account with the Id of the new Entitlement Record. The above trigger cannot create more than one Entitlement record per account.

Normally, when a custom field such as this is created to hold a link to a related record, it's done so because only one related record is anticipated in the design. Otherwise, the architect will use a related list of records to display all related records from that object on the Record Page.

That having been said, there's nothing that prevents you from manually creating additional Entitlement records after the new Account has been created. The Entitlement_ID__c field however won't be automatically updated when you do with the most recent Entitlement. That may or may not be an issue of concern for you.

If it is of concern, you can easily create an AfterInsert trigger on Entitlement by moving the functionality of the above code into a separate trigger. The issue of more than one Entitlement Record/Account can readily be handled by putting all records into a map<Id,account> using the Id of the account as the key for the map. Since only one account record per Id can be held in the map, only the last record in trigger.new that is added to the map will be updated, so there won't be any problems with duplicate accounts causing the trigger to fail.

The code would look something like this:

trigger UpdateAccountEntitlement on Entitlement (after insert) {

      map<Id,account>acctsUpMap = new map<Id,account>();

      for(entitlement e:trigger.new){

         account a = new account(Id = e.AccountId);
         a.Entitlement_ID__c = e.Id;

         acctsUpMap.put(a.Id,a);
      }

      if(!acctsUpMap.isEmpty()){

         list<account>toUp = new list<account>();
         toUp = acctsUpMap.values();
         update toUp;

      }

 } // end trigger         

If you don't anticipate a many to one relationship, keeping this in a single trigger will serve your purposes. As you're still "learning to walk" with Apex coding, you may not always know what your needs are (or will be) until you gain more experience. Sometimes we're given assignments by managers or clients that are specific and "limited in scope" because an enterprise level solution either isn't required or in the budget. There can also be advantages to having related code of this type in one place.

  • Thanks for this, that works perfectly. I'd be interested to hear your thoughts on @Jitendra_Zaa's question, regarding more than one Entitlement being created. Also, there's an extra semi-colon after e.AccountId in your code, which I can't edit out because an edit needs to be more than 6 characters. – Alex S May 10 '15 at 8:56
  • 1
    See my edited answer above which addresses your questions. Have corrected the extra semi-colon too. Thanks for the catch. Easily happens when you write and post code on the fly. :) – crmprogdev May 10 '15 at 16:58
  • No worries, it happens! As you say, I'm only anticipating one related record & I don't need the Entitlement_Id__c field to be updated if an additional Entitlement is created. It's actually more likely that I'll need to create two Entitlements per account at some point (one for this internal process & another for general CS SLAs) but I'm guessing that it'll be relatively straightforward to create the second Entitlement & then select the Id for the Entitlement Id field, based on the Entitlement name..or you may see a follow up question at some point! – Alex S May 10 '15 at 17:50
0

I see, You are using after insert trigger and you want to update same Account. Solution from crmprogdev should work.

OR,
You can use Queueable interface here to delegate Entitlement creation and updating parent account field. Here is sample code, please note that i have not tested this code :

trigger AcctSubmitAppEntitlement on Account (after insert) {

    List<WEID__c> weids = WEID__c.getall().values();
    Set<Id> validRecordTypeIds = new Set<Id>();

        for (WEID__c weid: weids) {
        try {
            validRecordTypeIds.add(weid.WEAccId__c);
            } catch (System.StringException e) {
              System.debug(
                System.LoggingLevel.ERROR,
                'Invalid Record Type Id ' + weid.WEAccId__c
                );
            }
        }

        Set<Id> accIds = new Set<Id>();
        for (Account newAccount: Trigger.New) {
            accIds.add(newAccount.Id);    
        }

        createEntitlements asyncJob = new createEntitlements();
        asyncJob.setAccIds = accIds;
        asyncJob.setValidRecordTypeIds = validRecordTypeIds ;
        System.enqueueJob(asyncJob);      
}

New class delegated for entitlement logic :

public class createEntitlements implements Queueable 
{
    public Set<Id> setAccIds {get;set;}
    public Set<Id> setValidRecordTypeIds {get;set;}

    public void execute(QueueableContext context) {
        if(setAccIds != null && !setAccIds.isEMpty())
        {   
            Map<Id,Account> mpAccount = new Map<Id,Account> ([Select ID,RecordTypeId FROM Account Where Id IN :setAccIds ]) ;

            List<Entitlement> entitlements = new List<Entitlement>();
              for (Account newAccount: lstAccount) {
                  if(validRecordTypeIds.contains(newAccount.RecordTypeId)){

                   Entitlement newEnt = new Entitlement();
                   newEnt.Name = 'Submit Application';
                   newEnt.AccountId = newAccount.Id;
                   newEnt.StartDate = Date.Today();
                   newEnt.EndDate = Date.Today().addYears(50);
                   newEnt.BusinessHoursId = '01m7000000008Ke';
                   newEnt.SlaProcessId = '552M000000000XA';
                   entitlements.add(newEnt);
                  }
                  insert entitlements;
              }

             if(!entitlements.isEmpty())
             {
                    List<Account> lstTobeUpdated = new List<Account>();
                    for(Entitlement e : entitlements)
                    {
                         Account acc = mpAccount.get(e.AccountId) ;
                         if(acc != null)
                         {
                               acc.Application_Entitlement_Id__c = e.Id ;
                               lstTobeUpdated.add(acc);
                         }
                    }
                    if(!lstTobeUpdated.isEmpty())
                    {
                           update lstTobeUpdated;
                    }                        
             }

        }       
    }
} 

Also, you have one design issue , what if one account has more than one entitlements ?

  • Apologies for the slow reply, I posted the question just before midnight my time..since the user would have to manually create an Entitlement for the Account, after the Accounts been created I don't see that being an issue but I could be missing something? Also, I won't be doing mass uploads of Accounts, certainly not regularly so I don't think I'll need to go as far as using Queueable Apex and even if I was. I don't understand the solution well enough to test it and make sure that it works.. – Alex S May 10 '15 at 8:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.