Tuesday, July 19, 2016

Developer: Cannot have more than 10 chunks in a single operation. Please rearrange the data to reduce chunking.

Recently while trying to solve a "Too many DML rows.." error, I ran into the following
error "Cannot have more than 10 chunks in a single operation. Please rearrange the data to reduce chunking."

This error occurs when sObject contains more then 10  object types or combinations.

Basically, to work around the "Too many DML rows" error, I had created a @future method with a single delete DML statement on an sObject which had different objects in it.

To work around this chunking error, I had to create seperate @future calls from the same method based on specific Object Type. This resolved the erorr.

Wednesday, July 13, 2016

Developer: Salesforce Order of Execution of things...

Every once in a while you run into a issue which does not make sense.

I created a simple WF rule which would not fire at all. After careful evaluation, I realized that the one of the fields that I was checking for was being set thru an Approval process. Prior to this, 3 other fields on the same object were being updated, the After Update trigger on the concerned object would fire but the workflow would not.

I did the usual checks on moving the rule to execute on "Created and Edited" and found that my conditions were good.

On checking the Approval Process, I found that the Re-Evalute WF rules on update was unchecked.
On checking this flag, everytime the field was updated thru the Workflow Process was getting evaluated and executed.


Friday, June 24, 2016

Developer: “Compiled formula is too big to execute (xxxxx characters). Maximum size is 5,000 characters,”

If you have ever hit this error “Compiled formula is too big to execute (xxxxx characters). Maximum size is 5,000 characters,” then it means that is it time to revisit the implemented formula
and refine it.

This does not in the literal sense mean that you have 5000 chars in your formula, it just means that there are either: too many nested IF's, formulas referring other formulas etc.

Following are some of the approaches that you can take to resolve this error:


  • Use CASE Instead Of Nested IFs--Implementing this has usually worked for me
  • Use Workflow Field Update--the formula field here has a larger capacity and hence might
       accomodate your formula but be careful to ensure that this update is executed only as needed
  • Use an Apex Trigger
Thanks

Friday, June 17, 2016

Administrator: No Portal available error....

I was trying to setup Partner Portal on my local and getting this error. Basically, you need to create


  • Account and Enable as Partner Account.
  • Create a Contact and associate it to the Partner Account.
  • Create a User record and associate the Contact record to the Partner User.

From Setup---Portal Settings; Identify the right profile that needs to be associated to the Portal and then associate this Profile to the User record.

You should now be able to login to Partner Portal on your local.

Monday, June 6, 2016

Developer: Scheduleable class has jobs pending or in progress...

If you run into this error while making changes to an APEX class "Scheduleable class has jobs pending or in progress..." then it means that there are scheduled jobs thru the UI or thru the System.Schedule method.

Firstly, clear the existing job by running the following code:

List<CronTrigger> listCronTrigger = [select Id, CronExpression, EndTime, NextFireTime, OwnerId,
        PreviousFireTime, StartTime, State, TimesTriggered, TimeZoneSidKey from CronTrigger
        where State = 'Waiting' or State='Running'];
       
System.debug('No of jobs: '+listCronTrigger.size());

If (listCronTrigger.size() > 0)
{
    for (Integer i = 0; i < listCronTrigger.size(); i++)
    {
        System.abortJob(listCronTrigger[i].Id);
        System.debug('Job details ::'+String.valueOf(listCronTrigger[i]));
    }
}

Now, try to save your APEX class and it should go thru successfully.

Wednesday, June 1, 2016

Developer:Error: Compile Error: Loop variable must be of type SObject

Our environment had implemented seperation of concerns and so the logic for triggers was in helper classes.

When trying to access trigger.new in helper classes; the context is not available automatically, you have to explicitly pass these attributes to your helper classes.

So, ClassName.MethodName(Trigger.New) should be used to call your class and explicitly pass the trigger collections.

Developer: System.Exception: SObject row does not allow errors

"SObject row does not allow .."  error was encountered while doing validation in a BeforeDelete trigger.

Solution

Very often; error in triggers are handled the traditional way that object.adderror('ErrorMessage').
trigger ClosedOpportunityPreventDeletion on Opportunity (before delete) {
if (system.Trigger.isDelete){
Opportunity[] Opps = [select id, (select id, Opportunity__c from PCFS__r) from Opportunity where id in :Trigger.oldMap.keySet()];

for (Opportunity o : Opps){
if(o.PCFS__r.size()>0){
o.adderror('You cannot delete this Opportunity as it has one or more Customer Forms associated with it');
}
}
}
However, when using adderror in a before delete it is important to maintain Context, the error can only be applied to those records that are in context.

Use the OldMap to get the actual record and apply the adderror message against that record. That should solve the problem. See sample below.


  Opportunity actualRecord = Trigger.oldMap.get(o.Id);
actualRecord.adderror('You cannot delete this O


Thursday, May 26, 2016

Developer: Loader/Trigger Errors....Too many batch retries in the presence of Apex triggers and partial failures.”

Too many batch retries in the presence of Apex triggers and partial failures. Usually you get this while loading data thru data loader. However, instead of the standard sensible error messages you get something like "Too many...."

If you ever run into this error; turn on the logs, identify the trigger and straight go to your trigger and review the code.

Most likely there is a bulk DML operation happening in the trigger which has AllorNone option set to True.

Review the following Salesforce document which explains in details the process:
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_dml_bulk_exceptions.htm

Review the data is being loaded and try to load with smaller sets and see if the problem is locatable.
Fix the problem and then load in bulk.

Developer: Too many SOQL queries....

When you hit this error; standard best practice will ask you to review the following:

1. Since Apex runs on a Multitenant structure, Apex runtime engine strictly enforces limits to ensure code doesn't monopolize shared resources. Learn about the Governors Limit.
2. Avoid SOQL queries that are inside FOR loop.
3. Check out the Salesforce Developer Blog where you can find Best Practices for Triggers.
4. Review best practices for Trigger and Bulk requests on our Force.com Apex Code Developer's Guide.
5. Be sure you're following the key coding principals for Apex Code in our Developer's Guide.


Sometimes the answer is not that obvious that you review a piece of code and you find the solution.

Here's my list of steps:

Review your WF/Process Builder rules; many times Admins write basic updates on the same entity causing continous firing of Before/After triggers. Try to move them to code.

Review the WF rules and move them to formulas; check for ISCHANGED so that the rules are not fired perpetually.

If this too doesn't solve your issues; turn the debug logs on. Look for SQL_EXECUTE_BEGIN.  Salesforce does a good job providing the query num that is being fired. Try to observe the pattern; atleast one query or process is being fired repeatedly. Work on that process or query; typically making it @future has helped solve the issue. However, if you are in an environment where the code is not being written by you or jumps from class to class that keeping track can become challenging and confusing use the log route to zero in on your problem.

Tuesday, May 17, 2016

Developer: DML operations not allowed on user...

Trying to build a VF page to load Accounts, Contacts and User.

While I could use the Upsert operation on Account and Contacts, User object would not allow me to use User.

"DML operation not allowed on User" was the error throw while trying to save the class.

Solutions

I worked around this by adding an operation flag to a file and creating 2 list one for insert
and one for update.

I then would check the value in the flag and then based on whether it is Insert or Update
add the record to the appropriate list and then do a bulk operation.

Developer: Salesforce Chunking error.....what is it

Error: System.TypeException: Cannot have more than 10 chunks in a single operation. Please rearrange the data to reduce chunking.

If you have received this error then most likely you are operating with a hybrid List of Sobjects
meaning you have something like

List<Sobject> S = new List<Sobject>()

and then in this list S you are adding object records from different entities like
Accoint Lead and other Custom entities.

Sometimes incorporating a simple list.sort() method works but if this does not work then you might have to break down your list into different Lists specific to each object and then perform the operation.

Referring to this post will help understand the situation better:
http://bartoszborowiec.wordpress.com/2014/06/15/execution-failed-system-typeexception-cannot-have-more-than-10-chunks-in-a-single-operation-please-rearrange-the-data-to-reduce-chunking/

but if the sort method does not work then use seperate lists and proceed.

Thursday, May 12, 2016

Developer: TestClass Run Failures: Unable to run testclass for Class ID...

I received this error recently while running test classes "Unable to run testclass for Class ID....".
The test class ran for a while before spewing out this error. There were 10-12 test methods in the test class but none of them showed as success.

Solutions

Go to Setup-->Develop-->Apex Test Class Execution.

Click on the Select Options button.

Uncheck Disable Parallel Testing and the Store Aggregate code coverage and run your tests again.

If you find that your tests run successfully you can try and check them back and re-run your tests.

It's just one of the things which worked me; nothing with a definitive logic here.


Monday, May 2, 2016

Developer: Trigger Design Patterns

Some standards to follow while writing Triggers:

a) Write only 1 trigger per object to handle all scenarios
b) Trigger should not hold any logic--bulk of the logic should be done outside of the core trigger code
     in a seperate class
c) If your trigger has an after update then make sure that you are covering for recursive trigger traps
by using a boolean variable at the start of the execution

Write your trigger with the most basic of codes:

trigger OpportunityTrigger on Opportunity (after insert, after update) {
  if(Trigger.isAfter && Trigger.isInsert) {
    OpportunityTriggerHandler.handleAfterInsert(Trigger.new);
  } else if(Trigger.isAfter && Trigger.isUpdate) {
    OpportunityTriggerHandler.handleAfterInsert(Trigger.new, Trigger.old);
  }
}

Do all the handling in 

public class OpportunityTriggerHandler {
  public static void handleAfterInsert(List opps) {
    // handler logic
  }
}

Over time as your logic increases it will be a lot readable and maintainable.

Admin: Dataloading: Uploading Attachments to Salesforce

Occassionally there may be a need to upload PDF files from other systems and also have them attach to the respective transaction records in Salesforce.

Solution

Dataloader can be used to load attachments and have them associated to their corresponding transaction as well.


To upload attachments:
  1. Confirm that the CSV file you intend to use for attachment importing contains the following required columns (each column represents a Salesforce.com field):
    • ParentId - the Salesforce.com ID of the parent record.
    • Name - the name of the attachment file, such as myattachment.jpg.
    • Body - the absolute path to the attachment on your local drive.
      Ensure that the values in the Body column contain the full file name of the attachments as they exist on your computer. For example, if an attachment named myattachment.jpg is located on your computer at C:\Export, Body must specify C:\Export\myattachment.jpg. Your CSV file might look like this:
      ParentId,Name,Body
      50030000000VDowAAG,attachment1.jpg,C:\Export\attachment1.gif
      701300000000iNHAAY,attachment2.doc,C:\Export\files\attachment2.doc
    The CSV file can also include other optional Attachment fields, such as Description.

Wednesday, April 13, 2016

Developer: Number fields and decimals observations....

If a field is created in Salesforce with Type as Number and Decimal places as 2, you will find that while the UI displays the number as 250.00 when you query the record using WorkBench you will be surprised to see the amount displayed as 250.0.

Now if the amount were to be entered as 250.01 thru the UI then on querying the field thru Workbench you will see the amount as 250.01.

In my case; I was doing a fixed length integration with an external system with a custom REST API created by me; surprisingly the output files did not have any issues and there was nothing for me to
do.

I thought this is just something good to know and depending on your situation you might have to take appropriate action.

Developer: How to validate and test Outbound Messages when integrating between systems?

If you are using the Workflow Outbound Message feature to integrate data with other systems then there is a need to validate data going from Salesforce. Basically, you need a staging area where you can route these XML messages and validate the data being sent.

Solution

Enter the url https://requestb.in/ in your browser and click on 'Create a request bin'.
A new bin URL will be created which you can use to route messages to before you test with the destination system.

Take this newly generated URL and use this as the destination endpoint URL for your XML message.

Execute a transaction that will cause the outbound XML message to be sent.
Load the request bin URL in your browser and you should see your message there.

Salesforce will keep sending these messages to the request bin as it does not receive an ACK message from the bin. Simply, navigate to the Monitor--Outbound Messages and delete the message so that salesforce stops posting messages over and over again to the RequestBin.

Admin: About Salesforce Deletes and Truncates....

Salesforce Standard objects do not provide the option to truncate tables. So, if you are loading lots of data in a standard object say Case or Accounts and needs rounds of iteration to load and delete records then you end up using the mass delete from the UI or the delete by ID's option of the data loader.

What if you custom objects in which you have tons of data being loaded and validated? Is there a easy way to manage data?


Solution

Well, Salesforce has a customizeable setting for custom objects called Enable Custom Object Truncate.

Truncating is a fast and easy way of deleting data.

Click on Your Name-->Setup-->Customize-->User Interface
Select Enable Custom Object Truncate.

Once you check this setting, locate the desired custom object and you should see a button called Truncate next to the Delete button.

Hit the Truncate button to delete transaction records related to the object; the meta-data is left untouched. The Delete button serves a different purpose and will outright delete your object so be wary of hitting that button by mistake.

Wednesday, April 6, 2016

Developer: Calculating DueDate excluding weekends

Very often while working with Cases and Entitlements you run into situation where you need to calculate the DueDate excluding weekends and in some cases Holidays are loaded in the system and your DueDate is to factor in Holidays as well.

For the purpose of this post, I am just considering that the requirement is to calculate DueDate excluding weekends.

Solutions

Identify the field which will act as the Start date from which to calculate the Due date.
Identify the field which will store the NumofDays that are to be be added to Start Date

Add a formula field to your object as follows:

CASE( 
MOD(DATEVALUE(SlaStartDate) - DATE(1900, 1, 7), 7), 
0, (DATEVALUE(SlaStartDate )) + SLANumOfDays__c + FLOOR((SLANumOfDays__c-1)/5)*2, 
1, (DATEVALUE(SlaStartDate )) + SLANumOfDays__c + FLOOR((SLANumOfDays__c)/5)*2, 
2, (DATEVALUE(SlaStartDate )) + SLANumOfDays__c + FLOOR((SLANumOfDays__c+1)/5)*2, 
3, (DATEVALUE(SlaStartDate )) + SLANumOfDays__c + FLOOR((SLANumOfDays__c+2)/5)*2, 
4, (DATEVALUE(SlaStartDate )) + SLANumOfDays__c + FLOOR((SLANumOfDays__c+3)/5)*2, 
5, (DATEVALUE(SlaStartDate )) + SLANumOfDays__c + CEILING((SLANumOfDays__c)/5)*2, 
6, (DATEVALUE(SlaStartDate )) - IF(SLANumOfDays__c>0,1,0) + SLANumOfDays__c + CEILING((SLANumOfDays__c)/5)*2, 
null)

Display the field on the UI, it will display the DueDate excluding weekends but does not factor in Holidays.

To factor in Holidays definitely require coding and will be addressed in another post.

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.


Monday, February 29, 2016

Admin: Salesforce Audit Trail...

Have you ever had to work with people who did not document their changes or claimed to work only in Production environment etc?

Yes, while hard to believe, I have worked with such people. While I am very meticulous in documenting my changes, when it comes time to migrate you run into this problem of not knowing what your colleague has done.

Solution

Enter Setup Audit Trail. 

This option is available under:

  • Setup-Security Controls--View Setup Audit Trail


This allows you to see what other developers are doing. You can also download 6 months worth of history in a CSV file and review.

While not a perfect solution, this is much better than not knowing what to migrate
or trying to migrate to testing envs and then failing ChangeSets during Validates or Deploy.


Develop: Considerations and Debugging options when implementing API based integrations.....

Salesforce allows you to integrate using a variety of options. One such way is thru API's: native as well as Custom API's can be leveraged for integrating two systems.

Considerations

For a 1000 license organization, you have a limit of making 1000 x 1000 calls in a 24 hrs period.
This should be one of your design considerations before selecting this method of integration amongst other things.

Note: you can always purchase additional API's.

Now, you implement an API based integration and things start to fail in UAT or Production.

Debugging 
There are some options to debug:

a) Go to Company Profile and note the API Usage last 24 hrs: Salesforce itself uses API's internally which counts against this limit.

b) To find details of which User is consuming these API's head to Reports; Salesforce provides a canned report called API Usage last 7 days in the Admin reports folder. This will give you a certain amount of granularity over option a).

If option b) does not help you then you can request a report from Salesforce on API usage which tells you exactly which transaction ID caused repeated calls to be initiated from external systems.

Happy Debugging !!!

UI: Finding Company Licenses, API Requests per 24 hrs and Used Data space information...

To find License related information, go to Set Up--> Company Information--Company Profile.

You should see a section for User Licenses which lists general set up details with respect to your Org
and License related details.

Used and Remaining Licenses

If you are working on integrating Users from external systems then you might need to know from time to time how many licenses have been consumed and how many are pending.

As you create new users thru UI or Integration, you will see the Used Licenses count go up.

Users cannot be deleted in Salesforce, they can only be Inactivated. So, to get your licenses back you need to Inactivate them and you should see the count for Remaining Licenses go up.

API Requests

You should also see a field for API Requests (Last 24 hrs) which tells the number of API calls made for last 24 hrs. This is one place you can track the usage in situations where you are implementing an API based integration or having issues in Production. 

Typically, you get 1000 API calls per license. So, if you are small org with say 300 licenses then you are allowed 300* 1000 = 300,000 API calls per day.

Used Data Space

This is another attribute you can review from time to time to see how you are doing on the data usage front.

Sunday, February 28, 2016

UI: Launching Standard Forms with predefined values

From time to time, you come across requirements which require you to launch a SF form with values pre-populated say from formulas.

Solution

Every Object has a code in Salesforce and every field has an ID.
Using the combination of 2 along with the instance URL will help you launch
the page.

Create a custom button under the desired object.
Place it on the desired page; set it to execute Javascript.

Place a URL as follow and we will deconstruct what it means:

https://xxx.salesforce.com/a0m/e?CF00NZ0000001kUmV={!Case.Related_Account__c}&00NZ0000001gnrk={!Case.Account_Cost_Center__c}&CF00NZ0000001gnsT={!Case.CaseNumber}&retURL=/{!Case.Id}


https://xxx.salesforce.com  -- is the instance URL

a0m - stands for the object code for your object. One way to find it click on the screen tab for your object and note the URL; it will look something like this https://xxx.salesforce.com/a0m/o and that is what gives you the object ID or code

00NZ0000001gnrk  - stands for the field id, one way to find it is go to your object definition under setup and then click on the field hyperlink. From the URL, please locate the field ID

{!Case.Account_Cost_Center__c} - value that you need to populate the field with

For picklist fields; put the literal 'CF' before the field ID; see example above CF00NZ0000001kUmV={!Case.Related_Account__c}

Another way of pre-populating fields would be of course to write some kind of a pre-insert trigger but occassionally you can get away with this kind of a hack depending on your situation.

DataLoader: Loading Data Values using TXT files in Salesforce

Occassionally you might run into a situation where DataLoader will not work for you to load data in Salesforce. DataLoader typically works with only CSV files.

XL has a limitation of showing data in CSV after I think 15-16 chars, so if you want to load CreditCards or Gift cards which have 16 digits from a CSV file then you end seeing exponential numbers in XL i,e, something like 6.05E+9.

Solution

You can use the power of APEX to load data in TXT file format.

You need 2 things:
a) a Visual Force form to be able to select file from your desktop
b) a Controller Class to load data

//Start of Visual Force
<apex:page controller="XXX">
<body>
<center>
    <b><font size="15"><h1>Gift Card Master Data Load Form</h1></font></b><br/>
    <font size="2">1. Download the Vendor file and format in the appropriate txt file format.</font><br/>
    <font size="2">2. Click on the 'Choose File' button file below and select the file.</font><br/>
    <font size="2">3. Click on the 'Load Cards Data' to load data.</font><br/>
   
<p/>

<apex:form >

<apex:tabPanel >
<apex:tab >
<apex:inputfile value="{!fileBody}"/>
<apex:commandButton value="Load Cards Data" action="{!readContent}"/>
</apex:tab></apex:tabPanel>


</apex:form>
</center>
</body>
</apex:page>

                   
//End of Visual Force

Next, is the class to load the file:

//Start of Controller Class
public with sharing class XXX{
    public string nameFile{get;set;}
    public Blob contentFile{get;set;}
    public blob fileBody { get; set; }

    String[] filelines = new String[]{};
    List<ObjName> ObjVar1;
   
public void readContent() {
      nameFile=fileBody.toString();
        filelines = nameFile.split('\n');
        GCtoupload = new List<ObjName>();

    for(Integer i=0;i<filelines.size();i++)
    {
   
      String[] inputvalues = new String[]{};
            inputvalues = filelines[i].split(',');
           
            ObjName Var= new ObjName();
            Var.Fld1= inputvalues[0];
            Var.Fld2= inputvalues[1];      
        
        ObjVar1.add(Var);
       
    }

   try{
   insert ObjVar1;
   
   } catch (Exception e)
        {
            ApexPages.Message errormsg = new ApexPages.Message(ApexPages.severity.ERROR,'An error has occured. Please check the file and try again later.');
            ApexPages.addMessage(errormsg);
        }   
}
        
}
//End of Controller Class

Here is the file format I used:

D000493500555389448,10.23,
D006493500555389455,11.23,
D006493500553798426,10


Saturday, February 27, 2016

DataLoader: Understanding External ID

Recently, I had to integrate data using file based approach  with an external legacy system. The frequency of this integration was supposed to be daily. Circumstances, did not allow for the legacy system to store Salesforce ID in their system and send it in their extracts.

So, how do you know at your end whether to insert or update when using DataLoader?

Solution

In comes External ID, it allows you to mark a field as unique in Salesforce; prevent duplicate records from getting created and allows the DataLoader to decide whether to insert or update a record.

Launch DataLoader and select the Upsert Operation to be executed, select your object and for the field to be used for matching point to the External ID field.

Salesforce will use the External ID field as a key and decide whether to update or insert.
You can have multiple External ID fields for an object. You can also use it against lookup fields to populate ID from your lookup object. It is case insensitive unless you select the Case sensitive option when defining the field.

DataLoader: Inserting NULLS using DataLoader

If you need to insert null values using DataLoader, then merely having null values in your excel sheet for the desired column will not work.

Launch your DataLoader; go to Settings and mark the checkbox

"Insert Null Values"

Launch the desired operation and validate your results against your column.