Ads

Friday 23 August 2013

Winter ’14 Release Developer Preview

Summer is fading and fall will soon be here. Question: do you know what the best part of fall is? That’s right, the winter release of Salesforce.com. The Winter ’14 release of Salesforce.com is right around the corner and that means once again I get the distinct pleasure of reviewing some of the new developer features that have been added. There are a large number of new features in the Winter ’14 release that developers will enjoy and in this post I’ll highlight a few of, what I feel, are the more pertinent points that developers will be interested in.

Visualforce:
The enhancements to Visualforce in this release are around improving the developer experience of building HTML5 apps along with some other core improvements and new tools.
• <apex:input>is a new, HTML5-friendly, general purpose input component that adapts to the data expected by a form field. It uses the HTML type attribute to allow client browsers to display type-appropriate user input widgets,
• The HTML5<datalist>element specifies a list of auto-complete options to associate with an <input type=”text” /> element.
• A Visualforce page’s view state can be viewed now in the developer console.
• We’re piloting a new feature that allows a Visualforce page’s view state to be stored on the server rather than the client thus preventing the need to send it back and forth with each request and response. This could help improve performance where low bandwidth or high latency could cause problems (think mobile). As with most features we release in pilot, you’ll need to request to have this one activated.

Sandboxes:
We’re making some interesting changes to sandboxes in this release as well. These changes significantly help with testing and life cycle management. I think developers will also like the data limits increase.
• Configuration Only sandboxes have been renamed to Developer Pro sandbox and the storage limit on them has been increased to 1GB.
• Developer Sandboxes have had their storage limit increased to 200MB.

Developer Console:
As always with each release we try to make it easier to manage the code in your applications. We’ve continued that with some of the following additions to the Developer Console.
• You can now create and edit JavaScript, XML, CSS and plain text in static resources with the Static Resource Editor. If you’ve ever managed static resources I’m sure you’ll agree with me that this is one of those hallelujah features that developers are going to use a lot.
• We’ve included a history panel that lists the last ten SOQL queries making query reuse easier. Also worth noting is the query editor now supports SOSL as well.

**UPDATE**

It was brought to my attention after I posted this that I forgot one of the cooler enhancements to the Developer Console. We now can search across the entire codebase. There’s a flow-diagram view of a transaction, which shows how workflow and triggers are timed relative to one another. This will be tremendously helpful in debugging complex or large code bases. This can also be used with declarative and programatic logic.

**

Apex Code:
As usual we’ve continued adding features to and improving on the world’s first cloud programming language. There are a ton of additions to Apex. Here are a just a few.
• There is no more code statement limit. Although we’ve removed this limit, we haven’t removed the safety mechanism it provided. Instead we’ve limited the CPU time for transactions. The limits are now 10,000ms for synchronous Apex and 60,000ms for asynchronous Apex.
• The Topic and Topic Assignment objects now support triggers.
• New Database methods improve record merging functions.

API:
I think the biggest announcement that developers have been waiting for API wise is the availability of our Analytics API. We introduced a limited pilot in summer 13 and now the Analytics REST API is generally available. The Analytics API lets you integrate Salesforce report data into your apps programmatically and has several resources that let you query metadata, and record details. Not to be outdone, the team has also added features to the REST API, SOAP API, Metadata API, Streaming API, Bulk API and the Tooling API. A big change here is the introduction of flexible limits for both the SOAP and REST API. Flexible limits allow you to excede API request limit by up to 50% within the limit timeframe.

Miscellaneous Updates:
I’ve created this last category to lump a few things together that don’t really fit anything I’ve mentioned above nor are there enough of to warrant a separate category of their own.
• Have you ever been stymied by or frustrated by the fact you couldn’t use the User object in workflow? Well be frustrated no more, there’s a new beta feature that allows the User object to be used in workflow rules.
• Advanced setup search is now beta. With it enabled you can search for Setup pages, custom profiles, permission sets, public groups, roles, and users from the sidebar in Setup.
• We introduced the custom state and country picklist beta in summer 13. They’re now generally available.







Thursday 22 August 2013

Salesforce converted currency in report?

In Salesforce, there is a field type "currency", as a standard field for example Amount in Opportunity, and we can create custom field with data type is currency.

If you enable multi-currency in your Salesforce instance, if the currency is not in the Corporate currency, you will find the corporate currency show in parenthesis after the amount.

In report, you will find (converted) field for each currency field. You can add it into report as other normal field. But, you cannot add converted field as report filter (as of now).

Solution: use original currency as filter and add currency code. Example: USD 300, SGD 500, JPY 10,000 and etc.


How to calculate date for weekday and weekend only In Salesforce?

In Salesforce, it is easy to calculate number of day between 2 date.
Just create a formula field, example: End_Date__c - Start_Date__c. DONE!!!

But, is it possible to find out only weekday and only weekend between 2 date?
Hmmm.... most of us will think about Apex Trigger.
Yes, it is correct solution, apex trigger able to calculate without issue, but, if you are not from developer, you need a developer for this.

Wait a minute.... Can we use 'just' formula to calculate weekday and weekend?

YES, it is possible with complex formula. Here we go:

To calculate Weekday
CASE(MOD( Request_Date__c - DATE(2007,1,1),7),
0 , CASE( MOD( Execution_Date__c - Request_Date__c ,7),1,2,2,3,3,4,4,5,5,5,6,5,1),
1 , CASE( MOD( Execution_Date__c - Request_Date__c ,7),1,2,2,3,3,4,4,4,5,4,6,5,1),
2 , CASE( MOD( Execution_Date__c - Request_Date__c ,7),1,2,2,3,3,3,4,3,5,4,6,5,1),
3 , CASE( MOD( Execution_Date__c - Request_Date__c ,7),1,2,2,2,3,2,4,3,5,4,6,5,1),
4 , CASE( MOD( Execution_Date__c - Request_Date__c ,7),1,1,2,1,3,2,4,3,5,4,6,5,1),
5 , CASE( MOD( Execution_Date__c - Request_Date__c ,7),1,0,2,1,3,2,4,3,5,4,6,5,0),
6 , CASE( MOD( Execution_Date__c - Request_Date__c ,7),1,1,2,2,3,3,4,4,5,5,6,5,0),
999)
+ (FLOOR(( Execution_Date__c - Request_Date__c )/7)*5)
-1

To calculate Weekend
CASE(MOD( Request_Date__c - DATE(2007,1,1),7),
0 , CASE( MOD( Execution_Date__c - Request_Date__c, 7),1,0,2,0,3,0,4,0,5,1,6,2,0),
1 , CASE( MOD( Execution_Date__c - Request_Date__c, 7),0,0,1,0,2,0,3,0,4,0,5,2,2),
2 , CASE( MOD( Execution_Date__c - Request_Date__c, 7),0,0,1,0,2,0,3,1,2),
3 , CASE( MOD( Execution_Date__c - Request_Date__c, 7),0,0,1,0,2,1,2),
4 , CASE( MOD( Execution_Date__c - Request_Date__c, 7),0,0,1,1,2),
5 , CASE( MOD( Execution_Date__c - Request_Date__c, 7),0,1,2),
6 , CASE( MOD( Execution_Date__c - Request_Date__c, 7),6,2,1),
999)
+ (FLOOR(( Execution_Date__c - Request_Date__c )/7)*2)

If you see in formula above, we have DATE(2007,1,1), this is refer to 1-Jan-2007 is Monday. So, you can use any date which is Monday, example 1-Jan-1900

How to undelete records in Salesforce?

Salesforce keep record you delete to Recycle Bin for 15 days with maximum record of 25 times the Megabytes (MBs) in your storage. For example, if your organization has 1 GB of storage then your limit is 25 times 1000 MB or 25,000 records. If your organization reaches its Recycle Bin limit, Salesforce automatically removes the oldest records if they have been in the Recycle Bin for at least two hours.

You can manually undelete records by click Recycle Bin icon in bottom left menu. Undelete account will include contact, case, opportunity tagged to that Account. But, if you have many records or you have specific record Id or you want to undelete records with some conditions, manually delete is not an option, use Apex code for it.

You not really need to be good developer to utilize Apex code. Here we go:

1. Open Developer Console
From your name in top right, look for Developer Console











2.From Developer Console
Go to Debug menu and select Open Execute Anonymous Window











3. Enter SOQL 
Example:
Account[] a = [SELECT Id FROM Account WHERE name = 'singtel' ALL ROWS];
undelete a;
Important to add ALL ROWS, otherwise deleted records will be not return on query.






4. Monitor Apex Debug Log
Go to Monitor - Logs - Debug Logs (in Salesforce menu, not Developer console)
Add user to monitor, default it will capture 20 log request for the users

5. Execute 
Click Execute button in Enter Apex Code window

6. Back to Debug Log
Select latest debug log and click View to monitor

ISBLANK() or ISNULL() in Salesforce?

To determine if an expression has a value or not, you can use ISBLANK() function in Salesforce. It will  returns TRUE if it does not and if it contains a value, this function returns FALSE. You can use this function in formula field, as well as in workflow.

ISBLANK(expression) and replace expression with the expression you want evaluated.
sample:
IF(ISBLANK(Maint_Amount__c), 0, 1)

A field is not empty if it contains a character, blank space, or zero. For example, a field that contains a space inserted with the spacebar is not empty.

If you use this function with a numeric field, the function only returns the specified string if the field does not have a value and is not configured to treat blank fields as zeroes.

You also can use BLANKVALUE() function to determine if an expression has a value and returns a substitute expression if it does not. If the expression has a value, returns the value of the expression.
sample:
BLANKVALUE(Payment_Due_Date__c, StartDate +5)
Use the same data type for both the expression and substitute_expression.

How about ISNULL() ?
Use ISBLANK instead of ISNULL in new formulas. ISBLANK has the same functionality as ISNULL, but also supports text fields. Salesforce will continue to support ISNULL, so you do not need to change any existing formulas.

The same goes for NULLVALUE(), it is similar with BLANKVALUE(), with exception:

Avoid using NULLVALUE with text fields because they are never null even when they are blank. Instead, use the BLANKVALUE function to determine if a text field is blank.
Don’t use NULLVALUE for date/time fields.

Choose Treat blank fields as blanks for your formula when referencing a number, percent, or currency field. Choosing Treat blank fields as zeroes gives blank fields the value of zero so none of them will be null.

Wednesday 21 August 2013

How to Customize the Lead Conversion Process in Salesforce.com?

trigger lead_onConvert on Lead (after update) {

/*  Create variables to store the lead values,new and old.  This will be used below to determine if the leads are being converted,  not converted yet, or has already been converted.*/

List<Lead> newLeads = trigger.new;
Map<Id, Lead> mOldLeads = trigger.oldMap;
Lead oldLead;

/* Create sets of Ids to store the records associated with the converted leads */

Set<Id> convertedAccountIds = new Set<Id>();
Set<Id> convertedContactIds = new Set<Id>();
Set<Id> convertedOpportunityIds = new Set<Id>();

/* Loop through the leads submitted through this trigger.  Populate the appropriate sets of Ids for each lead with populated values.*/

for (Lead l : newLeads) {

if (l.convertedAccountId != null) {
convertedAccountIds.add(l.convertedAccountId);
}

if (l.convertedContactId != null) {
convertedContactIds.add(l.convertedContactId);
}

if (l.convertedOpportunityId != null) {
convertedOpportunityIds.add(l.convertedOpportunityId);
}
}

/* Extract the records associated with each set of Ids populated above.  Once the data has been extracted store it in a map so it can efficiently be referenced
 in the main loop below.*/

List<Account> accounts =[SELECT Id, Name FROM Account WHERE Id IN : convertedAccountIds];

Map<Id, Account> mAccounts = new Map<Id, Account>(accounts);

List<Contact> contacts =[SELECT Id, Name FROM Contact WHERE Id IN : convertedContactIds];

Map<Id, Contact> mContacts = new Map<Id, Contact>(contacts);

List<Opportunity> opportunities =[SELECT Id, Name FROM Opportunity WHERE Id IN : convertedOpportunityIds];

Map<Id, Opportunity> mOpportunities = new Map<Id, Opportunity>(opportunities);

/* Create lists of records to be updated in bulk at the end of this trigger.  We use a separate list to ensure we aren't updating records that are  not affected by this trigger. */

List<Account> updateAccounts = new List<Account>();
List<Contact> updateContacts = new List<Contact>();
List<Opportunity> updateOpportunities = new List<Opportunity>();

/*
* MAIN LOOP
*
* Loop through all leads submitted through this trigger.
* If this trigger was executed because of a conversion
* we will populate the related records.
*/
for (Lead newLead : newLeads) {

// Get a reference to the old values associated
// with this lead.
oldLead = mOldLeads.get(newLead.Id);

// Determine if the lead was converted or not.
// If the previous status was not converted and
// the current status is converted, then this
// trigger executed because of a conversion.
if (!oldLead.IsConverted && newLead.isConverted) {

// ** CONVERSION FOUND **

Account account = mAccounts.get(newLead.convertedAccountId);
// Make appropriate updates here.
updateAccounts.add(account);

Contact contact = mContacts.get(newLead.convertedContactId);
// Make appropriate updates here.
updateContacts.add(contact);

Opportunity opportunity = mOpportunities.get(newLead.convertedOpportunityId);
// Make appropriate updates here.
updateOpportunities.add(opportunity);

}
}

/* Update the records for any update list  populated with records.*/

if (updateAccounts.size() > 0) {
update updateAccounts;
}

if (updateContacts.size() > 0) {
update updateContacts;
}

if (updateOpportunities.size() > 0) {
update updateOpportunities;
}
}

How We can get the list of contacts and accounts converted from leads on a particular Date?

We can get the list of contacts and accounts converted from leads on a particular Date

Actually everyone thinks it's impossible to find Solution,But after a lot of research I found a way for this:

Run a Report on Account History/ Contact History with a Specified date and Add the Filter Field/Event set to Created by Lead Covert to find the records that were created upon lead conversion, or set to Lead Converted to Contact to find the records that already exist and merged with lead conversion.




Tuesday 20 August 2013

Phone Number validation In Salesforce?

Converting 10-Lines of Apex code to a 1-line Validation Rule Formula
Code clean-up is what I'm doing these days ... lots of code clean-up. One of our Salesforce.com orgs (we have sixteen of them) currently has 72% test coverage in production. I'm not sure how the previous administrators were able to install code below the 75% threshold, but they managed. I'm tasked with getting that code cleaned up, so I can deploy a new release.

While looking for areas to improve code coverage, I stumbled upon this trigger:

trigger checkAccountPhoneNumberBiBu on Account (before insert, before update) {
   for (Account account : Trigger.new) {
      if (account.Phone==null) continue;
      Pattern p = Pattern.compile('[-() ]');
      String sPhone = p.matcher(account.Phone).replaceAll('');
      // check length without punctuation
      if (sPhone.length() != 10) account.Phone.addError(' Phone number must have 3 digit area code and 7 digit number');
      p = Pattern.compile('\\d');
      sPhone = p.matcher(sPhone).replaceAll('');
      if (sPhone.length() > 0) account.Phone.addError('Phone number must be formatted as (999)999-9999');
   }
}

This trigger looks at the value entered in the "Phone" field before an Account record is inserted or updated; if the phone field is not in the (999)999-9999 format, it errors out and notifies the user to enter the phone # in the proper format.

In addition to this Apex code, the developer also had to write a testmethod to ensure coverage of the trigger. His code was only getting 67% test coverage (which is what brought the trigger to my attention in the first place).

As I started looking at what I needed to add to the testmethod to ensure 100% coverage, I realized it would be easier to just get rid of the trigger altogether, and replace it with a Validation Rule. That 10 lines of Apex code was reduced to a 1-line formula in a validation rule:

NOT(REGEX(Phone, "\\D*?(\\d\\D*?){10}"))

Standard profiles in Salesforce?


Standard profiles cannot be deleted and permissions cannot be edited.


Thursday 1 August 2013

Using Rerender to Render — One Solution for Headaches?

It's a regular occurrence to have an <apex:outputPanel> or similar element in a Visualforce page, where you want to toggle visibility of said element according to some variable. Something that's caught both myself and fellow teammates out on a few such occasions is finding that it just won't appear again after being removed from the screen, when the page code looks analogous like the following.

<apex:outputPanel id="thePanel" rendered="{!bRenderThePanel}">
    <!-- Content -->
</apex:outputPanel>

<apex:commandButton action="{!DoSomeCalcs}" rerender="thePanel" value="FIRE!"/>

In this example, the action DoSomeCalcs is implemented such that it will toggle the value of the variable bRenderThePanel and so the result should be that the panel is alternately displayed and hidden with each click of the button. Woe is the developer, as this is not the case. Chances are you'll find yourself confused as to why it just won't reappear (or appear in the first place).

Essentially re-rendering a specified panel (or other component) that is not currently displayed will fail, and the solution is to wrap it with a component that is always present, using that as the target for the re-render. Thus our example becomes:

<apex:outputPanel id="thePanelWrapper">
    <apex:outputPanel rendered="{!bRenderThePanel}">
        <!-- Content -->
    </apex:outputPanel>
</apex:outputPanel>

<apex:commandButton action="{!DoSomeCalcs}" rerender="thePanelWrapper" value="FIRE!"/>

What does seem strange to me is that Salesforce have specifically ensured that you can access DOM elements within an <apex:outputPanel> when it's not displayed, as indicated by the documentation for the layout attribute, it seems odd that this functionality does not carry over for the element itself when it's being used as a re-render target.

The layout style for the panel. Possible values include "block" (which generates an HTML div tag), "inline" (which generates an HTML span tag), and "none" (which does not generate an HTML tag). If not specified, this value defaults to "none". However, if layout is set to "none", for each child element with the rendered attribute set to "false", the outputPanel generates a span tag, with the ID of each child, and a style attribute set to "display:none". Thus, while the content is not visible, JavaScript can still access the elements through the DOM ID.

Happy coding!