Thursday, August 24, 2017

Custom Task VF Page

Page:

<apex:page standardController="Task" extensions="TaskControllerExtn">
<apex:form >
<apex:sectionHeader title="Log A Call" help="www.google.com"/>
<apex:pageBlock mode="edit" title="Task Edit">
<apex:pageblockButtons ><br/>
<apex:commandButton value="Save" action="{!saveAndNew}" />
<apex:commandButton value="cancel" action="{!cancel}"/><br/>
</apex:pageblockButtons><br/>
        <apex:pageBlockSection title="Task Information"  columns="1" collapsible="false">
            <apex:inputField value="{!Task.Whatid}"/>
            <apex:inputField value="{!Task.Subject}"/>  
            <apex:inputField value="{!Task.type}"/> 
            <apex:inputField value="{!Task.whoid}"/>            
            <apex:inputField value="{!Task.Meeting_Completed__c}"/>
            <apex:inputField value="{!Task.Do_you_want_to_create_Opportunity__c}"/>                
        </apex:pageBlockSection>
    </apex:pageBlock>
</apex:form>
</apex:page>


Controller:

public class TaskControllerExtn {
    ApexPages.StandardController sController;
    public TaskControllerExtn(ApexPages.StandardController controller) {
        sController = controller;
    }
    public PageReference saveAndNew() {
        sController.save(); 
        PageReference pg = new PageReference('/006/e');
        pg.setRedirect(true);
        return pg;
    }
}

How to Use Like With Lists and Sets In SOQL Queries

//Possible options we're going to query for.
Set<String> voiceMailOptions = new Set<String>{'%voicemail%', '%voicemali%', '%vm%','%message%'};
List<Task> tsks = [select Id, Call_Result__c from Task Where Call_Result__c LIKE :voiceMailOptions];
for (Task tsk : tsks) {
 doSomething(tsk);
}

Wednesday, August 23, 2017

Salesforce Custom Settings

Custom Settings are basically custom objects that are available from the applications cache, so there’s no need to do a SOQL query to get the value. Custom settings are a vast improvement over just using custom objects because there’s no SOQL Query, there’s very few limits, and they can be used pretty much anywhere. Hierarchical custom settings can be used in formula fields, validation rules. All types of custom settings can be used in apex code which allows them to be incredibly powerful.

Salesforce has a couple of different types of custom settings available: list, hierarchical, and custom metadata. I’m considering custom metadata to be a custom setting although I’ve heard some in the community say that it isn’t. In my experience, Custom MetaData is an excellent replacement for the List Custom Setting.

1.List Custom Setting

List Custom Settings were introduced several years ago. They were the first iteration of custom settings, basically they allowed companies to avoid using custom objects as a way to store meta data and introduced an application cache. As mentioned previously, they avoid the overhead of having to query and avoid counting against the SOQL limits. For the most part, I am rarely using List Custom Settings anymore and instead preferring to use the newer Custom MetaData Type. Currently, it’s not very easy to write Apex to update a custom metadata type, so in those cases I recommend using a List Custom Setting.

Accessing a list custom setting is pretty easy because of the instance methods that Salesforce has provided. For example, say we had a list of SIC/MCC codes that we had saved into a custom setting called SIC_Codes__c. In the name field, we are storing the actual code, and then we have another field called Official_Name__c, and finally another field called Short_Description__c.

If we wanted to get the different values for 1521, which is a general contractor we could do the following:

SIC_Codes__c code = SIC_Codes__c.getInstance('1521'); 

system.debug('the official name is' + code.Official_Name__c);


Even more useful, is the fact we can also get back all of the possible options as a Map. To do that, using the exact same list custom setting we could do this:

Map<string, SIC_Codes__c> codes = SIC_Codes__c.getAll(); 

//iterate through the map and show all of the official names.

for (string key: codes.ketset())

{
     SIC_Codes__c code = codes.get(key);
     system.debug('the official name is' + code.Official_Name__c)
}


As mentioned previously, the List custom setting was normally used as a list of custom objects that rarely changed. It’s also possible to get all of the custom settings as a list by taking advantage of the fact that .get() returns a map. I used this pattern very frequently for countries, and SIC codes.

List<SIC_Codes__c> codes = SIC_Codes__c.getAll().values();


2.Hierarchical Custom Setting

For the most part, I found I use the hierarchical custom setting most frequently. There’s a few different ways that it can be used. In the first example, we’ll use it in a way similar to the List Custom Setting. Here’s one way that you could use a Hierarchical custom setting for getting url for an API.

public string getUrl()

{

MyRemoteAppSettings__c settings = MyRemoteAppSettings__c.getInstance();

return settings.AccessUrl__c;
}


As you have likely noticed, the custom setting methods are called by and operate on a particular custom setting. The methods have some difference between Lists and Hierarchical Custom Settings. The Hierarchical Custom Setting actually conceals some significant differences that can be utilized. In a hierachical custom setting, it’s possible to have different values returned based on the organization, profile, and user.

Hierarchical custom settings allow values at any of three different levels:
1. Organization, the default value for everyone
2. Profile, which overrides the Organization value
3. User, which overrides both Organization and Profile values

In our above example, we didn’t provide an Id or Name or anything in the getInstance() call so the call would default to whatever the User Settings are set to. If the User Settings aren’t set, it would then default to what the Profile Settings are set to, and then finally it would default to what the Organization Settings are set to. There’s a bit of a trick to this as well, if one field isn’t set it may use the next tier’s value, and so on.

This difference allows us to use the Hierarchical custom setting pretty much everywhere and in some pretty clever ways. Hierarchical Custom Settings can even be used in a formula. I use it the exact same way that I used App.Config Application Settings in C#.NET.

In a visualforce page, we can allow a section to only be rendered for a certain profile or for the org, etc. To do this we use the $Setup object, and then reference our custom setting and then finally our field.

So for a custom setting called MyAppSettings, and a field of Show_Example_Panel__c we would do this:

<apex:outputPanel id="examplePanel" rendered="{!$Setup.MyAppSettings.Show_Example_Panel__c}">

Some content...



</apex:outputPanel>

In an apex trigger, we could use the Hierarchical Custom Setting as a Trigger kill switch for a particular user or profile.

trigger TriggerKillSwitch on Account (after update, after insert) {

if (MyRemoteAppSettings__c.getInstance().RunAccountTrigger__c == true)

{

     AccountTriggerHandler.doSomething();
}
}


To make things even more interesting, Hierachical Custom Settings also have other methods that allow us to look at only a certain tier. Let’s say, we don’t want to run for the whole organization instead.

trigger TriggerKillSwitch on Account (after update, after insert) {

if (MyRemoteAppSettings__c.getOrgDefaults().RunAccountTrigger__c == true)

{

   AccountTriggerHandler.doSomething();
}
}


Custom MetaData Types

Custom MetaData Types change a lot of things about custom settings. In my mind, the biggest advantage is that the data is deployable and can be managed by a package or by developers without having to write code or sign into the production org and manually set values. This means that the values aren’t really data, they’re metadata and it’s a fantastic improvement for developers and admins. Most Salesforce orgs have dozens or hundreds of custom objects or custom settings that handle configuration. A lot of the time these changes are manually migrated from a sandbox or developer org.

For the most part, custom metadata can do everything that a list custom setting can do. The two downsides that I am aware of are that there’s no native support to create or modify the records within the apex language. I believe this is currently on the roadmap for Salesforce to deliver at some point.

The other downside is that the Custom MetaData Type must be queried unlike the List Custom Setting. Thankfully, the SOQL queries for the custom metadata types don’t count against the number of soql queries.

Common Usages

For most situations, where you used a list custom setting you can probably use custom metadata types. The only caveat with that is they can’t Create Update or Delete done on them without using the MetaData API. For developers working on managed packages, they are a fantastic replacement for storing anything that doesn’t need to be updated by the apex. During the installation process, there’s also no need to write any code to initialize them because the values are deployed with the package.

Monday, August 21, 2017

Trigger to Sync the Quote with Opportunity

In Salesforce, quotes are a representation of prices that have been proposed to a customer for products or services.

An opportunity may have lots of quotes associated to it but only one quote may be synced to an opportunity at a time. Quote syncing links a quote a specific opportunity which allows updates to update between the Opportunity and Quote. Basically, when an Opportunity is added or removed it can be removed from the list of Opportunity Products without having to write any code. Keep in mind that this means Opportunity Products will be automatically removed and readded.

After an opportunity is synced to a quote there’s a few changes that will happen:

  • The Synced Quote is set
  • The Syncing checkbox on the Quote is set.
  • The Quote Products and Opportunity Products are merged.
  • The Opportunity Amount becomes readonly to the user regardless of whether a quote is currently syncing or not.
For the most part, if you are automatically creating quotes and emailing them it’s really trivial to sync the quote automatically.

Quotes can be synced manually, and pretty easily, but it can be automated very easily saving sales staff dozens of clicks a day if your sales process is very short.

Here’s a very simple example of how to do it in a trigger:

trigger QuoteTrigger on Quote (before update, before insert, after update, after insert) {
// for ease of example we're not going to use a trigger framework because it would make the example 100x longer.
// Logic shouldn't be in a trigger.

  if (Trigger.isInsert) {
        if (System.isAfter) {
            QuoteService qs = new QuoteService();
            qs.SyncQuotes(Trigger.new);
        }
    }
}

public with sharing class QuoteService {
public void SyncQuotes(List<Quote> quotes) {
List<Opportunity> opps = new List<Opportunity>();

// Loops through the List of Quotes and gets the OpportunityId.
for (Quote q : quotes) {
       if (string.isNotEmpty(q.OpportunityId) {
            Opportunity opp = new Opportunity(Id = q.OpportunityId);
             opp.SyncedQuoteId = q.Id;
             opps.add(opp);
         }
 }
  if(!opps.isEmpty()) {
          update opps;
     }
   }
}

What’s the difference between Salesforce.com and Force.com?

Force.com is the platform that the Salesforce CRM and your customizations run on. The Force.com platform consists of a multi-tenant architecture that runs on application services, web servers and of course database servers. Salesforce is using Java, and Oracle for significant parts of the Force.com Platform.
Force.com is also a platform as a service (PaaS) that can be purchased separately and won’t include a lot of the key CRM functionality like Leads, and Opportunities. Lately, Salesforce has started to advertise an additional cloud called the “AppCloud” which includes services like Heroku which is another server that Salesforce owns.
Salesforce.com is generally used to refer to the CRM functionality only, so this would be the “sales cloud”, “service cloud”, and marketing related clouds. Salesforce is running on the Force.com Platform.
Salesforce1 is the mobile application that Salesforce has developed which is available on Android and iOS. It’s possible for developers to add functionality which can be used in the mobile phone application.

How to Convert Lead Using Apex

To convert a Lead into an Account, Contact and an Opportuninity we need to make use of the Database.convertLead method. The Database.convertLead method requires an instance of the Database.LeadConvert method which appears to be relatively simple to us.

// Create a lead and make sure it's been inserted because we need the Id.
Lead l = new Lead(FirstName = 'Brian', LastName = 'Cline', Company = 'my Company');
insert l;

Database.LeadConvert lc = new Database.LeadConvert();
lc.setLeadId(l.Id);

LeadStatus ls = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
lc.setConvertedStatus(ls.MasterLabel);

Database.LeadConvertResult lcr = Database.convertLead(lc);
boolean isSuccessful = lcr.isSuccess();

if (isSuccessful) {
//doSomethingElse
}

How To Reduce Visualforce’s View State

View State is a technique Salesforce uses to maintain the current state of the page and the data that was queried between the user requesting things from the server and sending any changes back to the server.If the view state gets too large problems can begin to occur. The view state is an encrypted field that contains the following data:
  • All of the non-transient data that is in the associated controller and any associated controller extensions
  • State related to all of the form elements and components that are used on the page.
  • Finally there’s some sort of internal state that Salesforce doesn’t provide much information about.
In Salesforce, the view state needs to be less than 135kb or you will get an exception.The error message will look something like this and be displayed to the end user: “Maximum view state size limit (135KB) exceeded. Actual view state size for this page was 227.239KB ”

Why View State Matters

As developers, we need to keep the view state low because it really effects page performance. The reason that the view state is so important is that because every time the page is re-rendered for some reason or that a request has been sent to the server that we need to send and receive the view state. As you can imagine, a large view state being constantly transmitted would add a lot of overhead.

Understanding what the Problem is

It’s easy to spend a lot of time doing unnecessary optimizations that will make future changes to the page and any associated apex more difficult. This means that the first step to reducing the view state when it is consistently being exceeded is to try and understand what the problem actually is. As the view state is encrypted, you can’t simply use the Chrome Developer Tools to see what’s being stored, instead you need to make some minor configuration changes to Salesforce.
The configuration change is to temporarily enable development mode for your user, or the user you will be testing with, and then open up the developer console. A new tab should be opened in the developer console that is called “view state inspector”.

Use the Transient Keyword

Use the Transient keyword to reduce the amount of data that needs to be persisted between the server and user. Transient variables are instance variables that aren’t able to be saved. Keep in mind that static variables are automatically transient and aren’t transmitted. There are some apex objects that are automatically transient, most of these are the objects created by System methods.

Return only the Minimum Data needed

Modify SOQL queries to only need the fields and objects that are actually being used by the visualforce page.

Refactor and Simplify the page

Minimize the number of form elements and visualforce components that are on the page. In almost every case that I have had issues with the view state being too large interally, the problem has been related to apex:repeat components and the apex components that are nested inside. Apex:outputpanels also generate a significant amount of viewstate that can be fairly easily replicated with plain html.

How to Select All Fields in SOQL

Instead of using Standard Query Language (SQL), Salesforce decided to create it’s own variation of the language for querying their databases. Salesforce Object Query Language, known as SOQL, has a basic syntax that is very similar to SQL but there’s some differences.

Most developers that are new to Salesforce immediately notice that there’s know way to select all of the fields for an object. SOQL doesn’t have a wilcard operator like SQL does. For developers that have experience in languages like C#.NET, Java or PHP it’s really weird not being able to do something like

select * from tableName

Don’t fear! There is a way to Select All Fields in SOQL and this post will cover how to, and why it’s actually not a good idea. Using Dynamic SOQL and describes its possible to get a set of all of the fields and then query them.

In the below example, I’m going to assume that you want all of the fields for the Opportunity object.

// This is the object for which we required data.
Map<String, Schema.SObjectField> fieldMap = Opportunity.sObjectType.getDescribe().fields.getMap();
// Get all of the fields on the object
Set<String> fieldNames = fieldMap.keySet();
// Build a Dynamic Query String.
List<Opportunity> opps = Database.query('select ' + string.join(fieldNames, ',') + ' from Opportunity');


There’s another approach that can be used which requires the Id to work.

Id rId = 'SomeValidSFDCId';
DescribeSObjectResult describeResult = rId.getSObjectType().getDescribe();
Map<String, Schema.SObjectField> fieldMap = describeResult.fields.getMap();
// Get all of the fields on the object
Set<String> fieldNames = fieldMap.keySet();
// Build a Dynamic Query String.
String soqlQuery = ' SELECT ' + string.join (fieldName, ',') + ' FROM ' + describeResult.getName() + ' Where Id =: rId';
// Need to return a generic list of sObject because we don't necessarily know exactly what the object is.
List<sObject> record = Database.query(soqlQuery);