Pages

Tuesday, August 30, 2016

Salesforce: Change Report Type

So, here is the use case: users need to change Report Type used for existing reports. But, can we change Report Type used by report?
Let's analyze, click "Customize" button and there is NO option to change the report type used for the report.


But, is there any workaround? Let's have a look with the report metadata.
 <?xml version="1.0" encoding="UTF-8"?>  
 <Report xmlns="http://soap.sforce.com/2006/04/metadata">  
   <columns>  
     <field>Account$Id</field>  
   </columns>  
   <columns>  
     <field>Account$Name</field>  
   </columns>  
   <columns>  
     <field>Account$Hello__c</field>  
   </columns>  
   <format>Tabular</format>  
   <name>Account with Hello</name>  
   <params>  
     <name>co</name>  
     <value>1</value>  
   </params>  
   <reportType>Account_Only_1__c</reportType>  
   <scope>organization</scope>  
   <showDetails>true</showDetails>  
   <timeFrameFilter>  
     <dateColumn>Account$CreatedDate</dateColumn>  
     <interval>INTERVAL_CUSTOM</interval>  
   </timeFrameFilter>  
 </Report>  
We found it and marked as bold above, is this mean we can just update it?

Next, let's see the Account_Only_1__c report type metadata:
 <?xml version="1.0" encoding="UTF-8"?>  
 <ReportType xmlns="http://soap.sforce.com/2006/04/metadata">  
   <baseObject>Account</baseObject>  
   <category>accounts</category>  
   <deployed>false</deployed>  
   <description>Account Only with Hello</description>  
   <label>Account Only 1</label>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Id</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Name</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Country__c</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Hello__c</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>CreatedDate</field>  
       <table>Account</table>  
     </columns>  
     <masterLabel>Accounts</masterLabel>  
   </sections>  
 </ReportType>  

That's okay, now let's see the new report type that we would use as replacement, it is called "Account_Only_2__c"
 <?xml version="1.0" encoding="UTF-8"?>  
 <ReportType xmlns="http://soap.sforce.com/2006/04/metadata">  
   <baseObject>Account</baseObject>  
   <category>accounts</category>  
   <deployed>false</deployed>  
   <description>Account Only without Hello</description>  
   <label>Account Only 2</label>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Id</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Name</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Country__c</field>  
       <table>Account</table>  
     </columns>  
     <masterLabel>Accounts</masterLabel>  
   </sections>  
 </ReportType>  

Next, go back to the report metadata and update <reportType> tag, from <reportType>Account_Only_1__c</reportType> to <reportType>Account_Only_2__c</reportType>

Save the metadata (in this case I am using MavensMate, the best IDE as David Liu said), hit Ctrl+S to save and will get following error:

The issue here because a custom field called Hello__c is not added to Account_Only_2__c report type, check that metadata above, so this is make sense.

Now, let's change it with other report type where Hello__c field is added, this report type called Account_Only_3__c.
 <?xml version="1.0" encoding="UTF-8"?>  
 <ReportType xmlns="http://soap.sforce.com/2006/04/metadata">  
   <baseObject>Account</baseObject>  
   <category>accounts</category>  
   <deployed>false</deployed>  
   <description>Account Only with Hello</description>  
   <label>Account Only 3</label>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Id</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Name</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Hello__c</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>CreatedDate</field>  
       <table>Account</table>  
     </columns>  
     <masterLabel>Accounts</masterLabel>  
   </sections>  
 </ReportType>  
Back to the report metadata and update <reportType> tag, from <reportType>Account_Only_1__c</reportType> to <reportType>Account_Only_3__c</reportType>
Hit Ctrl+S to save the report, and we get Success message.


Now, back to the report in Salesforce and check again the report type by click Customize button, make sure to refresh the browser, not just click Customize or Run Report button when the report is already open.



Note: default report option availability such as: "Summarize information by" and  "Timeframe" is depend on the field defined in report type as well.


Conclusion: we can update Record Type used in Report by editing the report metadata, and the replacement report type should have all fields used in the report.



Sunday, August 28, 2016

Salesforce: Report Type Object Relationships


When you relate Object in Custom Report Type, you have option of:
  1. with or without related records (may or may not have related records)
  2. with at least one related records (must have at least one record)
The 1st option require at least one child record, otherwise the parent record will not show in the report generated, while the 2nd option do not require any child record. You can easily change the relation from 1st to 2nd, or 2nd to 1st anytime.

Let's look at the metadata for the different, it is just in a <outerJoin>

1. with or without related records
 <?xml version="1.0" encoding="UTF-8"?>  
 <ReportType xmlns="http://soap.sforce.com/2006/04/metadata">  
   <baseObject>Account</baseObject>  
   <category>accounts</category>  
   <deployed>false</deployed>  
   <description>Account with Contacts only</description>  
   <join>  
     <outerJoin>false</outerJoin>  
     <relationship>Contacts</relationship>  
   </join>  
   <label>Account w/ Contacts</label>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Id</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>true</checkedByDefault>  
       <field>Name</field>  
       <table>Account</table>  
     </columns>  
     <masterLabel>Accounts</masterLabel>  
   </sections>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>FirstName</field>  
       <table>Account.Contacts</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>LastName</field>  
       <table>Account.Contacts</table>  
     </columns>  
     <masterLabel>Contacts</masterLabel>  
   </sections>  
 </ReportType>  

2. with at least one related records
 <?xml version="1.0" encoding="UTF-8"?>  
 <ReportType xmlns="http://soap.sforce.com/2006/04/metadata">  
   <baseObject>Account</baseObject>  
   <category>accounts</category>  
   <deployed>false</deployed>  
   <description>Account with Contacts only</description>  
   <join>  
     <outerJoin>true</outerJoin>  
     <relationship>Contacts</relationship>  
   </join>  
   <label>Account w/ Contacts</label>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Id</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>true</checkedByDefault>  
       <field>Name</field>  
       <table>Account</table>  
     </columns>  
     <masterLabel>Accounts</masterLabel>  
   </sections>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>FirstName</field>  
       <table>Account.Contacts</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>LastName</field>  
       <table>Account.Contacts</table>  
     </columns>  
     <masterLabel>Contacts</masterLabel>  
   </sections>  
 </ReportType>  

Without Object Relationship
Now, let's take a look on simpler report type metadata which contain no object relationship - only Account for this sample, there is no <join> tag and no second <section> tag for related objects.
 <?xml version="1.0" encoding="UTF-8"?>  
 <ReportType xmlns="http://soap.sforce.com/2006/04/metadata">  
   <baseObject>Account</baseObject>  
   <category>accounts</category>  
   <deployed>false</deployed>  
   <description>Account Only</description>  
   <label>Account Only</label>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Id</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>true</checkedByDefault>  
       <field>Name</field>  
       <table>Account</table>  
     </columns>  
     <masterLabel>Accounts</masterLabel>  
   </sections>  
 </ReportType>  

Second Object Relationship
When the first object relationship is "must have at least one related", you have both the same option for second object relationship.


But, when the first object relationship is "may or may not have related record", you only have option "may or may not have related record" too for second object relationship.




Let's take a look on the metadata, we have additional <join> tag within <join> tag, and additional <section> tag.
 <?xml version="1.0" encoding="UTF-8"?>  
 <ReportType xmlns="http://soap.sforce.com/2006/04/metadata">  
   <baseObject>Account</baseObject>  
   <category>accounts</category>  
   <deployed>false</deployed>  
   <description>Account with Contacts with &amp; without Campaign History</description>  
   <join>  
     <join>  
       <outerJoin>true</outerJoin>  
       <relationship>CampaignMembers</relationship>  
     </join>  
     <outerJoin>false</outerJoin>  
     <relationship>Contacts</relationship>  
   </join>  
   <label>Account w/ Contacts w/ &amp; wo/ Campaign History</label>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Id</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Name</field>  
       <table>Account</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Owner.Department</field>  
       <table>Account</table>  
     </columns>  
     <masterLabel>Accounts</masterLabel>  
   </sections>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>FirstName</field>  
       <table>Account.Contacts</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>LastName</field>  
       <table>Account.Contacts</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Account</field>  
       <table>Account.Contacts</table>  
     </columns>  
     <masterLabel>Contacts</masterLabel>  
   </sections>  
   <sections>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Name</field>  
       <table>Account.Contacts.CampaignMembers</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>CampaignMemberRecordType</field>  
       <table>Account.Contacts.CampaignMembers</table>  
     </columns>  
     <columns>  
       <checkedByDefault>false</checkedByDefault>  
       <field>Status</field>  
       <table>Account.Contacts.CampaignMembers</table>  
     </columns>  
     <masterLabel>Campaign History</masterLabel>  
   </sections>  
 </ReportType>  




Friday, August 26, 2016

Salesforce: Enable Drag-and-Drop Scheduling on List Views

In earlier blog, we discussed about how to drag and drop to edit event from Calendar. Today we will share about feature to drag and drop scheduling on List Views.

This feature will let users create events associated with records by dragging records from list views to weekly calendar views and entering event details in an interactive overlay. The fields available in the event detail and edit overlays are defined in a mini page layout.

Admin need to enable this from Setup | User Interface | select Enable Drag-and-Drop Editing on Calendar Views | select Enable Click-and-Create Events on Calendar Views, then you can select Enable Drag-and-Drop Scheduling on List Views


This feature is only enable in Classic for Account, Contact, and Lead List View only, and Tab view is not count, meaning you need to select a View to see this.



1. Click the Open Calendar icon Open Calendar link at the bottom of a list view.
    A weekly view of a calendar appears below view.
 


2. Drag a record from the list to a time slot on the calendar.



3.  A popup window for creating an event appears. The event is already related to the record that you dragged from the list view.




Notes:
  • Drag-and-drop scheduling isn’t available for the Console tab, events that people have been invited to, recurring events, accessibility mode, or Connect Offline.
  • List views that include drag-and-drop scheduling can take slightly longer than usual to be displayed.
  • When you drag the bar in between the list and calendar to resize either one, the size is saved for all views in which you use drag-and-drop scheduling. You can resize the list and calendar at any time.


Reference:


Thursday, August 25, 2016

Salesforce: Enable Drag-and-Drop Editing on Calendar Views

In current era of Lightning; Classic still in the heart of many Salesforce users, and this blog is going to explain on how to use drag and drop in editing on Calendar Views, at this moment this feature only for Classic. Admin need to enable this from Setup | User Interface | select Enable Drag-and-Drop Editing on Calendar Views.

This feature will enable dragging of events on single-user, daily and weekly calendar views. This allows users to reschedule events without leaving the page



Once enabled, go to Calendar Day View or Week View (not Month View).



You should be able to drag and drop existing event for the week or day, this feature is not for Month View.



If you have Enable Click-and-Create Events on Calendar Views enabled, this will let users create events on day and week calendar views by double-clicking a specific time slot and entering event details in an interactive overlay. The fields available in the event detail and edit overlays are defined in a mini page layout. Recurring events and multi-person events aren’t supported for click-and-create events on calendar views.



Reference:


Sunday, August 21, 2016

Compilation of Salesforce Blogs with Alexa Rank

This compilation only for personal Salesforce blog with maximum Alexa rank not more than 11 millions.

You are active Salesforce blogger, but not see your name here...
You are Salesforce blogger, your name listed here, but some information is wrong...
You are Salesforce blogger, your name listed here, but you want to withdraw...

Comment below on this blog !

Thursday, August 18, 2016

Salesforce Migration Tool using ANT in Windows


Prerequisites

1. Java
Make sure JDK is installed in your computer.
Check it from Control Panel\All Control Panel Items\Programs and Features



** if you do not have JDK installed, download latest JDK from http://www.oracle.com/technetwork/java/javase/downloads/index.html

Once installed successfully, check from command prompt:
C:\>java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b15)
Java HotSpot(TM) Client VM (build 25.45-b02, mixed mode, sharing)

** if your JAVA_HOME variable and environment Path have not configured, follow this step:
- Go to Advanced system settings from Control Panel\All Control Panel Items\System, click Environment Variables... button, go to System variables
- New variable JAVA_HOME value C:\Program Files\Java\jdk1.8.0_102 
- Edit Path variable to add value %JAVA_HOME%\bin


2. ANT
Get latest Apache ANT from http://ant.apache.org/bindownload.cgi and select .zip archive file.
Download the file to a folder and extract it.

You need to add this into System variables from Advanced system settings from Control Panel\All Control Panel Items\System, click Environment Variables... button.
- New variable ANT_HOME value C:\SFDC\Ant\apache-ant-1.9.7-bin\apache-ant-1.9.7
- Edit Path variable to add value %ANT_HOME%\bin

Once installed successfully, check from command prompt:
C:\>ant -version
Apache Ant(TM) version 1.9.7 compiled on April 9 2016


3. Force.com Migration Tool
Download Migration Tool from https://developer.salesforce.com/page/Force.com_Migration_Tool, at this moment it will bring me to https://gs0.salesforce.com/dwnld/SfdcAnt/salesforce_ant_37.0.zip, this may change based on Salesforce release. Extract salesforce_ant_37.0.zip to a folder.


Concept

You need to work with 3 files:

1. build.properties
Where? to store variables: username, password, server url
You can find sample of this file from "sample" folder from salesforce_ant_37.0.zip
In this file, you need define: serverurl, username, and password. Sample:
sf.serverurl = https://login.salesforce.com
sf.username = mylogin@gmail.com
sf.password = mypassword8

2. build.xml
How to deploy? retrieve, deploy
This file also available in "sample" folder from salesforce_ant_37.0.zip
In this file, you need to define the target. The concept here is you need to retrieve the metadata from source org., then deploy it to target org.

For retrieve
<target name="retrieve">  
  <!--<mkdir dir="retrieve_folder"/> -->
  <sf:retrieve username="${sf.username}" 
               password="${sf.password}" 
               sessionId="${sf.sessionId}"                 
               serverurl="${sf.serverurl}" 
               maxPoll="${sf.maxPoll}" 
               retrieveTarget="retrieve_folder" 
               unpackaged="package.xml" />
</target>

** mkdir retrieve_folder, this line is just needed if you need the script to create the folder prior retrieval, you can change retrieve_folder to other folder as you want.

For deployment
<target name="deploy"> 
  <sf:deploy username="${sf.username}" 
             password="${sf.password}" 
             sessionId="${sf.sessionId}" 
             serverurl="${sf.serverurl}" 
             maxPoll="${sf.maxPoll}" 
             deployRoot="retrieve_folder" 
             rollbackOnError="true"/>
</target>

** see more parameters here

3. package.xml
What to Deploy?
You can find sample of this file from "sample\codepkg" folder from salesforce_ant_37.0.zip
You need to manually add/update all the components you want to deploy.
Sample:
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata"> 
  <types>        
    <members>Access_Account</members>
    <members>View_All_Data</members>
    <name>PermissionSet</name>
  </types>
  <types>
    <members>Change__c</members>
    <name>CustomObject</name>
  </types> 
  <types>
    <members>Sales Regional</members>
    <name>Profile</name>
  </types> 
  <version>37.0</version>
</Package>

For me personally, I prefer to create a folder and put all 3 files above into that folder for each deployment.

For complete Metadata Components and Types, see https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_objects_intro.htm


Action

This is exciting part where you will start using ANT

To retieve
C:\SFDC\Ant\salesforce_ant_37.0\sample>ant retrieve
Buildfile: C:\SFDC\Ant\salesforce_ant_37.0\sample\build.xml

retrieve:
[sf:retrieve] Request for a retrieve submitted successfully.
[sf:retrieve] Request ID for the current retrieve task: 09S17000001OuaREAS
[sf:retrieve] Waiting for server to finish processing the request...
[sf:retrieve] Request Status: Pending
[sf:retrieve] Request Status: Succeeded
[sf:retrieve] Finished request 09S17000001OuaREAS successfully.

BUILD SUCCESSFUL
Total time: 28 seconds

To deploy
C:\SFDC\Ant\salesforce_ant_37.0\sample>ant deploy
Buildfile: C:\SFDC\Ant\salesforce_ant_37.0\sample\build.xml

deploy:
[sf:deploy] Request for a deploy submitted successfully.
[sf:deploy] Request ID for the current deploy task: 0Af21000002F9xACAS
[sf:deploy] Waiting for server to finish processing the request...
[sf:deploy] Request Status: Pending
[sf:deploy] Request Status: InProgress
[sf:deploy] Request Status: Succeeded
[sf:deploy] *********** DEPLOYMENT SUCCEEDED ***********
[sf:deploy] Finished request 0Af21000002F9xACAS successfully.

BUILD SUCCESSFUL
Total time: 30 seconds



Reference:


Wednesday, August 17, 2016

Salesforce: Working with Minute, Hour, Day in Workflow, Validation Rule and Formula Field


Use Case: based on some criteria, Event Reminder must be set to 30 minutes prior Event Start date time.

Solution:
Use Workflow with Field Update or Process Builder, but the logic should be the same. In this case, I'll use Workflow with Field Update for simplicity.

1. Create Workflow Rule and determine the business logic when Field Update action should trigger.

2. Create Field Update action with following formula: ActivityDateTime - 0.020833

Desc:
- ActivityDateTime = Event Start
- 0.020833 come from 0.5 / 24, where 0.5 = 30 minutes

Notes: when we use a number in Workflow or Formula or Validation Rule for Date or Date/Time field, it is for 1 day count. So for 2 hours, it would be 2/24 = 0.083333

So, when you try to calculate fields of date (date/time), example: NOW() - CreatedDate, this will produce number in days, example: 32.50 meaning 32 days 12 hours.


ReferenceDate/Time Calculations in Formula Fields, Workflow Field Updates and Validation Rules



Tuesday, August 16, 2016

Salesforce: Data Import Wizard to update Account

Data Import Wizard may not be so famous compare to Data Loader or other 3rd party tools, such as: dataloader.io or workbench. But, for simplicity and to be used by super user (not system admin), Data Import Wizard may be an option.

Use case: super user need to mass update certain fields. List View is not an option because the fields will be update with different values and for multiple fields.

Step-by-Step:
1. Navigate to Data Import Wizard menu: Setup | Data Management | Data Import Wizard

2. Click Launch Wizard! button

3. Select "Accounts and Contacts" under Standard object, if the user does not see "Accounts and
Contacts", make sure the user have Import Personal Contacts permission.


4. Select "Update existing records" under "What do you want to do?"

5. Leave "Match Contact by" to default value since we are not updating Contact

6. Change "Match Account by" to "Salesforce.com ID" since I have Salesforce Account Id

7. Make sure to select "Update existing Account information"


8. Drag CSV file to upload

9. Click Next to continue

10. Click Change link under "Account: Salesforce.com ID, Contact: Salesforce.com ID"



11. Remove Contact Id from mapping



12. Click Next, then Start Import button


Once done, user should get email from Salesforce with:

Subject: Salesforce import of "filename.csv" has finished. 999 rows were processed.
Content:
Your Accounts import is complete. Here are your results:
Accounts Created: 0
Accounts Updated: 999
Accounts Failed:  0 (We couldn't import these due to errors.) Processed job information for
imported Accounts: No link is available because you do not have the correct permissions to
manage Bulk Api jobs.

If user have Bulk Api jobs permission, they will see:
Accounts Failed:  0 (We couldn't import these due to errors.) Processed job information for
imported Accounts: https://na3.salesforce.com/75017000001eNj3AAE?fromEmail=1


Permissions
- Permission to manage Bulk Api jobs is Manage Data Integrations
- User will only see Data Import Wizard setup menu from Setup | Data Management, if only user have any of the following permissions:
  • Import Custom Objects
  • Import Leads
  • Import Personal Contacts
  • Import Solutions

Reference:

Blog last update: 23 Oct 2016


Sunday, August 14, 2016

Salesforce: Validation Rule in Workflow and Process Builder

Based on Salesforce Triggers and Order of Execution "If the record was updated with workflow field updates, fires before update triggers and after update triggers one more time (and only one more time), in addition to standard validations. Custom validation rules, duplicate rules, and escalation rules are not run again."

This mean, when a user hit save button, all Validation Rules will fired, if nothing fit into custom validation rules defined, workflow will kick-in and if there is any field update, validation rules will not fired again.



Rule: Account Number should be not blank, but workflow able to set Account Number to blank.

Scenario: Initially Account Number is not blank, user edit the Account, and Workflow rule will fired with Field Update action to set Account Number to blank.

Let's debug this workflow:
37.0 APEX_CODE,DEBUG;APEX_PROFILING,DEBUG;CALLOUT,DEBUG;DB,DEBUG;SYSTEM,DEBUG;VALIDATION,DEBUG;VISUALFORCE,DEBUG;WORKFLOW,DEBUG
14:23:35.0 (82155)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
14:23:35.0 (114745)|EXECUTION_STARTED
14:23:35.0 (120056)|CODE_UNIT_STARTED|[EXTERNAL]|Validation:Account:0012800000gyUy6
14:23:35.0 (130074)|VALIDATION_RULE|03d28000000EPIz|Validation_Rule_Check_Account_Number
14:23:35.0 (228425)|VALIDATION_FORMULA|ISBLANK( AccountNumber )|AccountNumber=4
14:23:35.0 (237103)|VALIDATION_PASS
14:23:35.0 (269418)|CODE_UNIT_FINISHED|Validation:Account:0012800000gyUy6
14:23:35.0 (274425)|EXECUTION_FINISHED
14:23:35.30 (30037797)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
14:23:35.30 (30056259)|EXECUTION_STARTED
14:23:35.30 (30061600)|CODE_UNIT_STARTED|[EXTERNAL]|Workflow:Account
14:23:35.30 (50813798)|WF_RULE_EVAL_BEGIN|Workflow
14:23:35.30 (50860348)|WF_CRITERIA_BEGIN|[Account: Ke 4 0012800000gyUy6]|Account Name not blank|01Q28000000Cc09|ON_ALL_CHANGES|0
14:23:35.30 (54819564)|WF_RULE_FILTER|[Account : Account Name not equal to ]
14:23:35.30 (54838482)|WF_RULE_EVAL_VALUE|Ke 4
14:23:35.30 (54843398)|WF_CRITERIA_END|true
14:23:35.30 (73750806)|WF_SPOOL_ACTION_BEGIN|Workflow
14:23:35.30 (73896415)|WF_FIELD_UPDATE|[Account: Ke 4 0012800000gyUy6]|Field:Account: Account Number|Value:null|Id=04Y280000002Bz8|CurrentRule:Account Name not blank (Id=01Q28000000Cc09)
14:23:35.30 (73918213)|WF_ACTION| Field Update: 1;
14:23:35.30 (73920533)|WF_RULE_EVAL_END
14:23:35.30 (88370151)|WF_ACTIONS_END| Field Update: 1;
14:23:35.30 (88385818)|CODE_UNIT_FINISHED|Workflow:Account
14:23:35.30 (88392301)|EXECUTION_FINISHED

legend:
  • Red highlight 03d28000000EPIz = Validation Rule Id
  • Orange highlight 01Q28000000Cc09 = Workflow Rule Id
  • Cyan highlight 04Y280000002Bz8 = Field Update action Id
After workflow action end, execution finished.


Let's convert above Workflow rule to Process Builder with Update Records action, it should be pretty straight forward, let see the result when we edit and save the Account from Salesforce UI:

Workflow Action Failed to Trigger Flow
The record couldn’t be saved because it failed to trigger a flow. A flow trigger failed to execute the flow with version ID 30128000000AgZ7. Contact your administrator for help.

Click here to return to the previous page. 

Note: 301 prefix ID above is refer to an object call "InteractionDefinitionVersion", but you cannot easily know this Id is refer to which Process Builder. 

Instead of getting the same result, we will see above error message. But, only admin who create the Process Builder / Flow will receive fault email with more detail information, such as:

An error occurred at element myRule_1_A1 (FlowRecordUpdate).
UPDATE --- UPDATE FAILED --- ERRORS : (FIELD_CUSTOM_VALIDATION_EXCEPTION) Validation Rule Account_Number is blank
________________________________________
This report lists the elements that the flow interview executed. The report is a beta feature.
We welcome your feedback on IdeaExchange.
Flow Details
Flow Name: Account_Name_not_blank
Type: Workflow
Version: 1
Status: Active
Flow Interview Details
Interview Label: Account_Name_not_blank-1_Account
Current User: ABC Playground (00528000002ILq8)
Start time: 8/14/2016 2:34 PM
Duration: 0 seconds
How the Interview Started
Admin Playground (00528000002ILq8) started the flow interview.
Some of this flow's variables were set when the interview started.
myVariable_old = 0012800000gyUy6AAE
myVariable_current = 0012800000gyUy6AAE
ASSIGNMENT: myVariable_waitStartTimeAssignment
{!myVariable_waitStartTimeVariable} Equals {!Flow.CurrentDateTime}
Result
{!myVariable_waitStartTimeVariable} = "8/14/2016 2:34 PM"
DECISION: myDecision
Executed this outcome: myRule_1
Outcome conditions: and
1. {!myVariable_current.Name} (Ke 4) Does not equal null
Logic: All conditions must be true (AND)
RECORD UPDATE: myRule_1_A1
Find all Account records where:
Id Equals {!myVariable_current.Id} (0012800000gyUy6AAE)
Update the records’ field values.
AccountNumber = 
Result
Failed to update records that meet the filter criteria.
________________________________________
Error Occurred: UPDATE --- UPDATE FAILED --- ERRORS : (FIELD_CUSTOM_VALIDATION_EXCEPTION) Validation Rule Account_Number is blank 

legend:
- Red text = Process Builder API Name
- Blue text = Validation Rule error message

Prefix 301 can be referred to a Process Builder or Flow. The workaround is to use Flow Designer to check if that Id is refer to which Process Builder or Flow -- remember that Process Builder is using Flow as it engine. Follow this Url https://na3.salesforce.com/designer/designer.apexp#Id=30128000000AgZ7, change na3 to your salesforce instance.

In my sample, I see Flow Designer below, it show the Process Builder is Account Name not blank.



Let's analyze this Process Builder debug log:

37.0 APEX_CODE,DEBUG;APEX_PROFILING,DEBUG;CALLOUT,DEBUG;DB,DEBUG;SYSTEM,DEBUG;VALIDATION,DEBUG;VISUALFORCE,DEBUG;WORKFLOW,DEBUG
14:34:47.0 (558162)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
14:34:47.0 (592212)|EXECUTION_STARTED
14:34:47.0 (598100)|CODE_UNIT_STARTED|[EXTERNAL]|Validation:Account:0012800000gyUy6
14:34:47.0 (606907)|VALIDATION_RULE|03d28000000EPIz|Validation_Rule_Check_Account_Number
14:34:47.0 (776191)|VALIDATION_FORMULA|ISBLANK( AccountNumber )|AccountNumber=4
14:34:47.0 (781498)|VALIDATION_PASS
14:34:47.0 (804187)|CODE_UNIT_FINISHED|Validation:Account:0012800000gyUy6
14:34:47.0 (809205)|EXECUTION_FINISHED
14:34:47.59 (59552281)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
14:34:47.59 (59569571)|EXECUTION_STARTED
14:34:47.59 (59575357)|CODE_UNIT_STARTED|[EXTERNAL]|Workflow:Account
14:34:47.59 (82062195)|WF_RULE_EVAL_BEGIN|Workflow
14:34:47.59 (82101694)|WF_CRITERIA_BEGIN|[Account: Ke 4 0012800000gyUy6]|Account_Name_not_blank30128000000AgZ7|01Q28000000Cc0E|ON_ALL_CHANGES|0
14:34:47.59 (82345496)|WF_FORMULA|Formula:ENCODED:[treatNullAsNull]true|Values:
14:34:47.59 (82352535)|WF_CRITERIA_END|true
14:34:47.59 (97686928)|WF_SPOOL_ACTION_BEGIN|Workflow
14:34:47.59 (97718850)|WF_ACTION| Flow Trigger: 1;
14:34:47.59 (97721792)|WF_RULE_EVAL_END
14:34:47.59 (103758514)|WF_FLOW_ACTION_BEGIN|09L28000000Dx9D
14:34:47.105 (105390847)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
14:34:47.105 (105416019)|FLOW_CREATE_INTERVIEW_BEGIN|00D28000001GqzS|30028000000DADN|30128000000AgZ7
14:34:47.105 (328513776)|FLOW_CREATE_INTERVIEW_END|2218d9911a59768798c816adb579156879d9ea4-3fe3|Account Name not blank
14:34:47.328 (328991140)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
14:34:47.328 (329016464)|FLOW_START_INTERVIEWS_BEGIN|1
14:34:47.328 (356679048)|FLOW_START_INTERVIEW_BEGIN|2218d9911a59768798c816adb579156879d9ea4-3fe3|Account Name not blank
14:34:47.328 (357910736)|FLOW_START_INTERVIEW_END|2218d9911a59768798c816adb579156879d9ea4-3fe3|Account Name not blank
14:34:47.632 (632463208)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
14:34:47.632 (632488241)|CODE_UNIT_STARTED|[EXTERNAL]|Validation:Account:0012800000gyUy6
14:34:47.632 (632503881)|VALIDATION_RULE|03d28000000EPIz|Validation_Rule_Check_Account_Number
14:34:47.632 (632613125)|VALIDATION_FORMULA|ISBLANK( AccountNumber )|AccountNumber=null
14:34:47.632 (632625147)|VALIDATION_FAIL
14:34:47.632 (632678806)|CODE_UNIT_FINISHED|Validation:Account:0012800000gyUy6
14:34:47.328 (634577332)|FLOW_ELEMENT_ERROR|UPDATE --- UPDATE FAILED ---  ERRORS :  (FIELD_CUSTOM_VALIDATION_EXCEPTION) Validation Rule Account_Number is blank, |FlowRecordUpdate|myRule_1_A1
14:34:47.328 (663434606)|FLOW_START_INTERVIEWS_END|1
14:34:47.59 (663505014)|WF_FLOW_ACTION_ERROR|09L28000000Dx9D|30028000000DADN|Error executing flow: Account_Name_not_blank, FlowDefId: 30028000000DADN, FlowVersionId: 30128000000AgZ7
14:34:47.59 (663520003)|WF_FLOW_ACTION_ERROR_DETAIL|<b>An unhandled fault has occurred in this flow</b><br>An unhandled fault has occurred while processing the flow.  Please contact your system administrator for more information.
14:34:47.59 (663596389)|WF_FLOW_ACTION_END|09L28000000Dx9D
14:34:47.59 (663613069)|CODE_UNIT_FINISHED|Workflow:Account
14:34:47.59 (665545797)|EXECUTION_FINISHED

legend:
  • Red highlight 03d28000000EPIz = Validation Rule Id, this is the same validation rule
  • Green highlight 30128000000AgZ7= Interaction Definition Version Id, this is the Id show in error message (cannot open directly)
  • Orange highlight 01Q28000000Cc0E = workflow Id, (cannot open directly, because this is Flow)
  • Blue highlight 09L28000000Dx9D = Action Flow Id  (cannot open directly)
  • Yellow highlight 30028000000DADN = Flow Definition Id (cannot open directly)

If we analyze the log above, within Flow Action, it will call Validation Rule and this will stop Process Builder to update record.

Let's compare to a successful Process Builder with Record Update and Validation Rule.
37.0 APEX_CODE,FINEST;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW,INFO
15:24:54.0 (95867)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
15:24:54.0 (129750)|EXECUTION_STARTED
15:24:54.0 (135441)|CODE_UNIT_STARTED|[EXTERNAL]|Validation:Account:0012800000gyUy6
15:24:54.0 (146785)|VALIDATION_RULE|03d28000000EPIz|Validation_Rule_Check_Account_Number
15:24:54.0 (309565)|VALIDATION_FORMULA|ISBLANK( Name )|Name=Ke 4
15:24:54.0 (314519)|VALIDATION_PASS
15:24:54.0 (334878)|CODE_UNIT_FINISHED|Validation:Account:0012800000gyUy6
15:24:54.0 (339757)|EXECUTION_FINISHED
15:24:54.30 (30239766)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
15:24:54.30 (30253350)|EXECUTION_STARTED
15:24:54.30 (30258265)|CODE_UNIT_STARTED|[EXTERNAL]|Workflow:Account
15:24:54.30 (42750062)|WF_RULE_EVAL_BEGIN|Workflow
15:24:54.30 (42795063)|WF_CRITERIA_BEGIN|[Account: Ke 4 0012800000gyUy6]|Account_Name_not_blank30128000000AgZ7|01Q28000000Cc0E|ON_ALL_CHANGES|0
15:24:54.30 (43029449)|WF_FORMULA|Formula:ENCODED:[treatNullAsNull]true|Values:
15:24:54.30 (43036888)|WF_CRITERIA_END|true
15:24:54.30 (44033222)|WF_SPOOL_ACTION_BEGIN|Workflow
15:24:54.30 (44056720)|WF_ACTION| Flow Trigger: 1;
15:24:54.30 (44058614)|WF_RULE_EVAL_END
15:24:54.30 (44682997)|WF_FLOW_ACTION_BEGIN|09L28000000Dx9D
15:24:54.46 (46193540)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
15:24:54.46 (46218553)|FLOW_CREATE_INTERVIEW_BEGIN|00D28000001GqzS|30028000000DADN|30128000000AgZ7
15:24:54.46 (47747434)|FLOW_CREATE_INTERVIEW_END|1940b7d42414e1d9dcfb404801f715687e6cde0-3f6f|Account Name not blank
15:24:54.48 (48073487)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
15:24:54.48 (48088578)|FLOW_START_INTERVIEWS_BEGIN|1
15:24:54.48 (48766530)|FLOW_START_INTERVIEW_BEGIN|1940b7d42414e1d9dcfb404801f715687e6cde0-3f6f|Account Name not blank
15:24:54.48 (49602259)|FLOW_START_INTERVIEW_END|1940b7d42414e1d9dcfb404801f715687e6cde0-3f6f|Account Name not blank
15:24:54.91 (91366282)|USER_INFO|[EXTERNAL]|00528000002ILq8|abc@playground.com|Singapore Time|GMT+08:00
15:24:54.91 (91385208)|CODE_UNIT_STARTED|[EXTERNAL]|Validation:Account:0012800000gyUy6
15:24:54.91 (91397228)|VALIDATION_RULE|03d28000000EPIz|Validation_Rule_Check_Account_Number
15:24:54.91 (91481561)|VALIDATION_FORMULA|ISBLANK( Name )|Name=Ke 4
15:24:54.91 (91487538)|VALIDATION_PASS
15:24:54.91 (91509480)|CODE_UNIT_FINISHED|Validation:Account:0012800000gyUy6
15:24:54.48 (109154474)|FLOW_START_INTERVIEWS_END|1
15:24:54.30 (110713941)|WF_FLOW_ACTION_END|09L28000000Dx9D
15:24:54.30 (110757222)|WF_RULE_EVAL_BEGIN|Workflow
15:24:54.30 (110768818)|WF_SPOOL_ACTION_BEGIN|Workflow
15:24:54.30 (110774246)|WF_ACTION| None
15:24:54.30 (110776310)|WF_RULE_EVAL_END
15:24:54.30 (110844992)|WF_ACTIONS_END| Flow Trigger: 1;
15:24:54.30 (110852765)|CODE_UNIT_FINISHED|Workflow:Account
15:24:54.30 (112112867)|EXECUTION_FINISHED




Reference:

Tuesday, August 9, 2016

Salesforce: Auto Enable Marketing User

Use Case: some user need to be auto enable with Marketing User in the user detail because they need to add Contact / Lead to Campaign, see this blog for detail.

Solution:
1. Create Auto-launched Flow
2. Create Process Builder

Auto-launched Flow
We need this flow called by Process Builder because field UserPermissionsMarketingUser in User object is not accessible from Process Builder, you need to have a Record Update process with a variable use as input of User Id.

Vote for this idea to allow Process Builder able to access all fields in the object.


Process Builder
With Process Builder on User creation, call above Flow and pass the User Id to that flow.



With simple Process Builder + Auto-launched Flow above, new user created will be have Marketing User auto check, you can add criteria in Process Builder if need to evaluate certain Profile or Role or etc.

Note: deactivate and re-activate user will not effect Marketing User checkbox, so it is not necessary to run the Process Builder on user update.



Page-level ad