Monday, March 28, 2016

Developer: You can’t change the completion date on a case milestone that’s already exited an entitlement process.: Completion Date

I had a requirement where you Click on a button which would launch a VisualForce page and on updating the record the Status was supposed to be set to Closed and then Case Entitlement and MileStones to be set for such a Case.

Problem: I would get the error "You can’t change the completion date on a case milestone that’s already exited an entitlement process.: Completion Date: [CompletionDate]"

Solution

Essentially, the root of the problem is that the Case is already in Closed status by the time your process or logic to update the MileStone Completion Date comes along. When it tries to update a Case whose status is already Closed you get the above error.

Review your development and design and basically introduce a delay by setting some Boolean variables. Ensure that the Case Milestone Completion Date is being set before the case status is set to Closed.

Once the delay is introduced and the sequencing works as above the error will be resolved.

Tuesday, March 15, 2016

Developer: Tackling MIXED_DML_OPERATION, on setup object is not permitted error..

A common need in most organizations is a need to create Contact records when a User is created.

If you try to implement such a requirement synchronously then you end up with the following
error:

MIXED_DML_OPERATION, DML operation on setup object is not permitted after you have updated a non-setup object

Solution

The error occurs because User is treated as a setup object by Salesforce and Contact is not.

@ future methods are a way of implementing asynchronous operations like webservice callouts.

Following is a sample of how you would start your code:
public with sharing class CreateUsrContact { 
 @future public static void CreateUsrContact (List<String> UsrId){ 

  system.debug('UsrId' + UsrId);
....Complete code as desired....
}}

There are also limitations in terms of what types of data can and cannot be passed as parameters...for e.g Sobject cannot be passed in.

Call this code from an after update User trigger for our example will prevent the clash from happening and will solve the error.

@ future methods also come with their own set of governor limitations that you need to be familiar with when designing solutions.

No more than 50 invocations per APEX code and also no more than
200* number of licenses in a 24 hr period.


Sunday, March 13, 2016

Developer: Triggering Assignment Manager ....

Sometimes you might have a scenario to Assign Cases to a Closed queue when the status of a Case is Closed and you are using the native Case Save and Close button to capture certain details and close the case.

You will find that Salesforce Assignment Rule does not trigger from this page.

Solution

The Save and Close button on a case launches a different page layout than the Case. The page layout cannot be manipulated.

In a traditional Case form, the page Layout properties button allows you to set a checkbox called
Case Assignment Checkbox --default to true. When this option is set to true, Assignment Manager kicks in as soon as you save the Case.

However, on the Save and Close page layout, this option is not available to be set.
You have to write some trigger code as follows:

Database.DMLOptions dmo = new Database.DMLOptions();

      dmo.assignmentRuleHeader.useDefaultRule = true;
      dmo.EmailHeader.triggerUserEmail = true;
     
      List<RecordType> RT = [select Id,Name from RecordType where Name='xxx' LIMIT 1];
 
          system.debug('Size' + ' ' + RT.size() );
       for(Case cs : cases){
   
        cs.setOptions(dmo);
       }

</,,,,,update case....

The above code will work for other scenarios as well where the Assignment rule manager does not kick in. Mind you, I am not advocating code as a replacement for the Assignment Rule but simply saying that under certain scenarios Salesforce does not trigger the Assignment Manager at all and that is where the above code comes in handy.


Thursday, March 10, 2016

Developer: Avoiding Recursive Triggers

Triggers allow a developer to perform actions on an object before or after an DML operation like Insert, Update, Delete. As a best practice, it is recommended that 1 trigger per object be written.

Now, if a trigger has a before/after logic for an operation like update then care must be taken to ensure that the trigger does not execute in a loop. An After Update causing a Before Update to fire which in turn causes another After Update and so on....

How to handle Recursive triggers?

Solution

Essentially, you want the code to execute in one instance and not go on firing in a loop.

Create a seperate trigger handler class as follows:

public class RecursiveTriggerHandler{
     public static Boolean isFirstTime = true;
}

Now, in your before trigger you would have something like which essentially invokes the class and sets the static variable isFirstTime.

trigger xxxx on Account (before insert,after insert, after update) {

 If (Trigger.isBefore){
 if (Trigger.isInsert){
If(RecursiveTriggerHandler.isFirstTime){


.....add your code......

Next in the after code insert the following which ensures that for the first execution flow the variable is set to false when it reaches the after operation and so does not cause the trigger logic to keep executing recursively.

f (Trigger.isAfter){
    If (Trigger.isupdate || Trigger.isinsert ){
      if(RecursiveTriggerHandler.isFirstTime){
        RecursiveTriggerHandler.isFirstTime = false;



Wednesday, March 9, 2016

Developer: Launching Standard Salesforce Email Window without pre-populating

If you have the Email related list on your Case page layout then typically it has a standard Send Email button. This button when clicked launches the Salesforce standard Email Window but also pre-populates fields like

  • To
  • BCC
  • Related To
Recently, this became a show stopper on our project.

Solution

Create a custom button on your page layout and define it to execute Javascript.

When you click on the standard Send Email button it launches the URL as follows:
https://xx.salesforce.com/_ui/core/email/author/EmailAuthor?p3_lkid=500J000000E12vx&retURL=%2F500J000000E12vx

We are going to borrow the URL that the standard button launches of course with some modifications to it. Notice the p3_lkid=500J000000E12 that is what pre-populates the value on the Email form.

Enter the Javscript for your custom button as follows:

window.open("https://xxx.salesforce.com/_ui/core/email/author/EmailAuthor?&retURL=/{!Case.Id}"

Some Cons of the above approach that I have noticed so far:

  • While the Standard Email button launches within its framework the above button launches the Email window as a seperate tab. 
  • It also does not automatically does not save the Email against the case.

I am sure the Email window can be opened as Pop-Up or a Modal Dialog using javascript.


Tuesday, March 8, 2016

Developer:Integration: Testing REST API using workbench.

So, you built a REST API integration, wrote a test class to validate your code and everything seems to be fine with the test results and code coverage.

How do you test your code and actually see it generate the desired output?

Solution

Workbench.developerforce.com is a tool that can be used to test your API's.
Log in to the desired environment.

Click on Utilities---REST explorer.

Select the method for which you have built your API. For our purpose I am going to assume it is a GET method that was written.

So, select the HTTP method as GET and in the URL:

after entering /services/apexrest/

enter the name of the RESTResource (url mapping) as defined in the global class.

Let's call it CheckReq. Your URL should now look as follows:

/services/apexrest/CheckReq

Say within the global API you have a class called CheckReqProcessing then your URL should finally look like:

/services/apexrest/CheckReq/CheckReqProcessing; hit execute.

Get Method does not require an input so you should see the results of your API.
Your class code would be looking something like:

@RestResource(urlMapping='/CheckReq/*')

global with sharing class CheckReqProcessing {

@HttpGet
<<<Define Actions>>>>

}

Test Class Code:

Your test class code would need to have the following amongst all the all the things that it needs to be successfull:

RestRequest req = new RestRequest();

        RestResponse res = new RestResponse();
        req.requestURI = '/services/apexrest/CheckReq';
        req.httpMethod = 'GET';
        RestContext.request = req;
        RestContext.response = res;
        
        List<ObjjectName> CR = CheckReqProcessing.getUnsentCR();

Developer:Integation:Creating OAuth Connection for REST API Integrations.

For native or custom Salesforce API integrations you will need to set up OAuth Connections.

To set up OAuth connection, click on Setup--Create--Apps. Scroll down to the Connected Apps section and click New.

Enter Connected App Name, API Name and Contact Email.

Check the Enable OAuth Settings and enter the callback URL.

Select the OAuth scopes say "Access and Manager your data (API)" as an example.

Click Save.

Scroll up to Setup--Manage App--Connected Apps.

You should see your created App connection there click on the App Name and drill down.

In the OAuth section, locate the IP Relaxation section and ensure that it is marked as Relax IP restrictions.

Share the details of the ConsumerSecret and the Consumer key with your developer.

With the OAuth set up you should be able to integrate external applications with Salesforce.


Admin: Using Custom Settings

Sometimes installing UnManaged Packages has given me problems while migrating Apex code even though the code is totally unrelated to the entity for which you have installed the package.

The workaround for this is to Inactivate the validation rules and then proceed with migrating your APEX code. If you have 18-20 validations like I do Inactivating these one by one can be a pain.

Solution
There's another workaround to this problem called Custom Settings.This data can then be used by formula fields, validation rules, flows, Apex, and the SOAP API.

Custom Settings allow you to create global objects and define global variables and have them access anywhere.

To create Custom Setting, click on Set Up---Develop---Custom Settings.

Click on New and give your setting a Name and Description. Mark the setting Type as Hierarchy and Visibility as Public.

Essentially you have created a global object which can be leveraged in validation rules etc and the object obviously needs some fields to hold values.

To create fields, in the Custom fields section, click New and select the DataType that you want to define.

To define values for this field at a global level, click on the Manage button--New and enter the desired value.

If you want to have different values by User or Profiles then click New and enter the desired value against the desired User or Profile.

Now, you are ready to use the global value say in your ValidationRule.
Create or Edit a Validation Rule on say the Case object and click Insert field, you should something like $Setup.V<ObjName>.<FieldName>.

Set up the rule as follows:
  $Setup.ValProceed__c.ProceedFlg__c == TRUE && LEN (Description) < 10


which means that if the global variable == TRUE and < than 10 chars is entered in the Case Description then have an error displayed to the user.

As you migrate your validation rule to different environments, set the global variable to false and try to migrate your APEX code, this will prevent the Validations Rule from firing. Once the migration is done simply set the global variable to TRUE.

That way, with 18-20 validation rules per object you do not have to worry activating and inactivating them one by one.


Thursday, March 3, 2016

Developer: About Case Thread ID

Salesforce has a Email to Case functionality which allows customers internal or external to send a request to an email address and have a transaction created for e.g. a Case created and have support teams service the Case.

In such cases you will see Incoming emails logged against the Case in the Emails related list.

Similarly if an email is initiated from a Case thru the Emails related list and sent, then the Email is associated to the Case.

Now, what if you want to send email thru Code and have it logged against your Transaction.

Solution

Enter the Case Thread ID.
This is something that Salesforce uses to associate emails to a Case if an email is sent to a Email to Case address. In the absence of Case Thread ID in the Body or in the Subject line a New Case is created else the email is associated to the existing Transaction.

This internally used field can be leveraged to do associations of our own.
Create a Formula field as follows in your entity:

"ref:_" & LEFT($Organization.Id,5) & SUBSTITUTE(RIGHT($Organization.Id,11),"0","") & "._" & LEFT(Id,5) & SUBSTITUTE(Left(RIGHT(Id,10),5),"0","") & RIGHT(Id,5) & ":ref"


Now, when sending emails thru Code, you need to append the formula field to either the Subject line or to the body of the email and also CC to the Email to Case email address.

This creates a closed loop so that you are aware of the Emails being sent out what was sent out and can always be visited any time by users for reference.