Pages

Friday, February 7, 2014

Salesforce: Formula for Owner

In Summer '13 release, Salesforce open Owner lookup field and made it available for cross-object formula. Owner field is special compare to other fields, because if the object is available for Queue (e.g. Case, Lead, and custom object), it can be linked to User object or to Group object (owner is a Queue).

You can access things like the record owner email address or owner manager name through formula field or workflow rule.

For example, if you need to get owner email address and it is not for queue, your formula would be Owner:User.Email, this formula field will return blank, if the object is available for Queue and record owned by a Queue.

From above sample, if the object supported by Queue, you can enhance the formula to:
IF( ISBLANK(Owner:User.Id), Owner:Queue.QueueEmail, Owner:User.Email )

To get User name or Queue name:
IF( ISBLANK(Owner:User.Id), Owner:Queue.Name, Owner:User.FirstName & " " & Owner:User.LastName )

User and Queue objects can be referenced on the Owner lookup, but must be explicitly selected, see screenshot below:






Salesforce: How to change field Label created by Managed Packages?

When you installed a managed package app into your Salesforce instance, you cannot edit the label of the fields. If you click Edit button, both Field Label and Field Name is disabled.



So, how to change the label? Here we go:
  1. Navigate to Setup - Translation Workbench - Override
  2. Select the right Package, Language, Setup Component = Custom Field, Object, and Aspect = Field Label
  3. It will show all custom fields for that object
  4. Double click in column 'Field Label Overwrite'
  5. Press TAB to move to next editable field or SHIFT-TAB to go to the previous editable field. 
  6. Click Save button and done.



View in object page layout, before:


After:


With the same approach, we also can do for the following components:
  • Action
  • Apex Sharing Reason
  • Button and Link Label
  • Custom Field
  • Custom Report Type
  • Lookup Filter
  • Record Type
  • Validation Error Message
  • Web Tab
  • Workflow Task



Note: you do NOT need to enable Translation Settings to do this change.


Reference



Salesforce: Simple Test Method

This blog is continuation from previous blog about simple trigger. As I mentioned earlier, you need to write Test Method to deploy apex code (including trigger) from sandbox or developer instance to production instance. Remember all activities below only in Developer or Sandbox instance.

Let us create a simple test method related to trigger to act as workflow with field update blog written earlier. Without further ado:


You can right click the image above and select 'Open image in new tab' if you are using Google Chrome to get better image resolution or get the text version from this URL.

Let me give a quick explanation on the code above:
  • We start with creation of record in reference object Iso_Country_Mapping__c and populate Country Code and Country Name
  • Continue with Account creation, then update Billing Country of Account
  • The first 2 test methods are Positive test case
  • The last one for Negative test case, USA is not valid country, only US or United States

Once the code save successfully (Salesforce will check the code for any syntax error, it will not allow you to save if any error), you can click button 'Run Test' to execute the test method and see the result.



Now, go back to your the trigger and look for Code Coverage, if nothing wrong it should be updated, remember we need at least 75%, if you can achieve 100% is perfect. Code above cover for 91% as screenshot below  


The test method show here is very simple using single record of positive and negative test case, but in many scenarios, you can enhance with multiple records test case and testing as other users. 

Reference: Testing Example


Thursday, February 6, 2014

Salesforce: Dated Exchange Rates versus Conversion Rate

Last month, we discussed on How to edit Dated Exchange Rates, today we'll share more on Dated Exchange Rates.

Remember, dated exchange rates are not currently used in:
- forecasting
- currency fields in other objects
- currency fields in other types of reports

Dated exchange rates are used for:
- opportunities
- opportunity products
- opportunity product schedules
- campaign opportunity fields
- opportunity splits, and reports related to these objects and fields.

See this reference and vote this in IdeaExchange for Multi-Currency support for All Currency Fields .

Advanced currency management allows you to manage dated exchange rates within opportunities using Salesforce. Dated exchange rates allow you to map a conversion rate to a specific date range. For example, the exchange rate on January 1 was 1 USD to 1.39 AUD, but on February 1, it changed to 1 USD to 1.42 AUD. Your opportunities that closed between January 1 and February 1 use the first exchange rate (1 = 1.39), while opportunities that closed after February 1 used the second exchange rate (1 = 1.42).

Dated exchange rates are defined using a start date and a conversion rate. Each rate is in effect until either the end of time or the day before the next start date for that currency. The time between on start date and the next start date is called the exchange rate date range. These ranges can be as small as a day and as large as all of time.

Today we get a real scenario when dated exchange rates is not align with conversion rate.

This is screenshot from Opportunity report:



and this from Forecast report:

From screenshot above, opportunity report show USD 48.04, while from forecast report USD 48.02, this is not much different, but when the numbers getting bigger, the difference will be bigger.

Let us analyse:
This is screenshot from dated exchange rate

This is screenshot from conversion rate

Let's calculate this using Ms Excel

So, this is clearly show that Conversion Rate is used in forecast, even you already used Dated Exchange Rate. It is best to keep Conversion Rate in sync with Dated Exchange Rate.


Advanced Currency Management Considerations:
  • Dated exchange rates are used for opportunities, opportunity products, opportunity product schedules, campaign opportunity fields, opportunity splits, and reports related to these objects and fields. Dated exchange rates are not used in forecasting, currency fields in other objects, or currency fields in other types of reports.
  • Organizations with advanced currency management support roll-up summary fields between two advanced currency management objects. For example, roll-up summary fields are supported from an opportunity line object to its opportunity object, because both are advanced currency management enabled. However, if you enable advanced currency management, you can’t create roll-up summary fields that calculate currency on the opportunity object rolling up to the account object, and you can’t filter on the opportunity currency field on the account object. All existing currency-related roll-up summary fields on the opportunity object are disabled and their values are no longer calculated. If your organization enables advanced currency management, you should delete any currency roll-up summary fields using opportunities and accounts or opportunities and custom objects.
  • Campaign opportunity fields use dated exchange rates when calculating the amount in the campaign currency, but are not used when converting those amounts to the user currency.
  • Cross-object formulas always use the static conversion rate for currency conversion.
  • If advanced currency management is enabled, you can't bind Visualforce pages that use <apex:inputField> or <apex:outputField> components to currency fields that support advanced currency management.


Reference: About Advanced Currency Management


Tuesday, February 4, 2014

Salesforce: Simple Trigger to Act as Workflow with Field Update

In previous blog, I discuss about how to write a simple trigger to act as validation rule. In this blog, I'll continue to use trigger to act as workflow with field update.

Scenario: it is good that we manage user only able to enter Singapore or SG, so no more SGP or Spore for the Billing Country. But, even we have only Singapore and SG, it would be best we only have SG, this will make the report even easier and better.

We can enhance existing trigger and add few lines. I'll not write about custom object and how to start write trigger. Here you go:


You can right click the image above and select 'Open image in new tab' if you are using Google Chrome to get better image resolution or get the text version from this URL.

Let me give a quick explanation line added in the code:
  • Line 3, add new list for Account object, will use it to update Account.
  • Line 20 & 21 and 39 & 40, assign Country Code from reference table into Billing Country. You may ask why we need line 39 & 40 since user already enter 2 characters only, and it match to the Country Code. Because without that 2 lines, trigger will not update Account with Country Code from reference table, so when user enter sg or Sg, system will accept it, this is not so tidy as we want all be SG, get it? 
  • Line 54 - 56 to update Account before insert or before update.


Sunday, February 2, 2014

Salesforce: Simple Trigger to Act as Validation Rule

After active for more than 18 months in Salesforce Answer Success Community and answered for more than 5000 posts (currently stay at 5,271), I see many members asking for help or advise to fix validation rules, to make sure the validation rule will block invalid data based on some criteria.

Use Case: user only allowed to enter Billing Country in Account with US only or "US or Unites States" only, but not USA or U.S.A or U.S. or etc. I concur this is a good practice to standardize data entry, so user or admin can easily run a report and group them altogether with correct result.

But, what happen if you want to validate 200 countries name in the world? Using validation rule, it will be difficult to maintain. Furthermore, if the values need to be maintained by users, not by system admin, using validation rule is not possible.

Let me introduce a simple trigger to act as validation rule. The idea is using a custom object as reference table. I'll not discuss how to create custom object and assume you are familiar with it. See this screenshot:


User can maintain the values from page layout:

Extra Tips: You can have above View with object page layout without have to create new Tab (remember you have maximum Tab limitation, except for Unlimited or Performance edition). Just enter 3 letters key prefix of the object into URL, example: https://na3.salesforce.com/a0m
Change na3 with your Salesforce instance; a0m is the key prefix for this custom object.
You can use Developer Workbench to easily get the object prefix

Back to the trigger and follow steps below to create trigger:
- Go to Setup | Customize | Accounts | Triggers
- Click New button
- Copy and paste code below into editor
- Click Save button


You can right click the image above and select 'Open image in new tab' if you are using Google Chrome to get better image resolution or get the text version from this URL.

Let me give a quick explanation for code above:
  • First, check if Billing Country is not blank, if blank than go through.
  • Second, check if Billing Country is only 2 characters, if YES check Country Code, if No check Country Name.
  • If not found, use addError() method to stop system to save and show error message.

Please note that you need to have Test Method apex class with at least 75% coverage of above trigger to enable it deploy to Salesforce Production instance.

From above quick explanation, it check both Country Code and Country Code based on length of Billing Country, using the same way, you can expand the code to check more things with more advance logic.

More samples here:
trigger DuplicateAccountNameCountryCheck1 on Account (before insert, before update)
{
    For(Account a:Trigger.New)
    {
        List<Account> acc=[SELECT Id, Name FROM Account WHERE Name=:a.Name AND BillingCountry=:a.BillingCountry];
        if(acc.size()>0)
        {
            a.addError('You are not allow to create duplicate Account Name with the same Country');
        } 
    }
}


trigger DuplicateAccountNameCountryCheck2 on Account (before insert, before update)
{
    For(Account a:Trigger.New)
    {
        Integer acc=[SELECT count() FROM Account WHERE Name=:a.Name AND BillingCountry=:a.BillingCountry];
        if( acc>0 )
        {
            a.addError('You are not allow to create duplicate Account Name with the same Country');
        } 
    }
}


Page-level ad