Tuesday, April 26, 2016

Salesforce: Store Approval Comments to Notes

Use Case: we need to capture Comments type by approver when approve or reject in Approval process as Notes.

Assume that you already have the following:
- Status picklist field: Draft, In Progress, Rejected, Approved
- Approval Process with actions to update status to Rejected or Approved

1. Process Builder 
Process to trigger when the status change to Approved or Rejected

a. Select the object and make sure to select "when a record is created or edited"
b. Criteria: make sure both values captured with OR logic

c. Action: call Flow with passing Record Id as flow variable

2. Autolaunched Flow
Flow designer:

a. Lookup to Process Instance object, filter to Record Id and Approval Process Id, you need to store Approval Process Id into a constant.
Store the result (Id and Status) to a sobject variables, as this will always return only 1 record, we can use Sobject Variables.

b. Lookup to Process Instance Step object, filter to Process Instance Id, Step Status equal to Rejected and Approved. Store the result (Comments, StepStatus, and ActorId) to a sobject Collecton variables, this lookup may return more than 1 record, so we should use Sobject Collection Variables.

c. Loop the Process Instance Step object
Copy each record from Sobject Collection Variables to Sobject Variables.

d. Assign Sobject Variables
Populated fields to a new Sobject Variables.

formulaBody is a formula resource = {!lvProcessInstanceSteps.ActorId} & " | " &
 TEXT({!lvProcessInstanceSteps.StepStatus}) & " | " &
Approval Comment is just a text for note title.

e. Assign Sobject Collection Variables
Add Sobject Variables to new Sobject Collection Variables

f. Create Notes

So, when it is approved / rejected, a note will be automatically created.

Here is the notes content:

With slight adjustment in the Flow, you can change the flow to store approval history into a custom object.

Monday, April 25, 2016

Salesforce: Retrieving Metadata with Developer Workbench

Use Case: as time goes by, we have more and more Process Builder calling Auto Launched Flow, we found an Auto Launched Flow and not sure is called by Process Builder.

Use IDE or MavensMate to download the metadata file, but if your machine is not installed with any IDE, you can use Developer Workbench to download the metadata XML file -- huge thanks to Doug Ayers for the tips.

1. Prepare the Package 

A. Using Package XML file
Save the file as package.xml or any other name
 <?xml version="1.0" encoding="UTF-8"?>  
 <Package xmlns="">  
** to get the name tag, you can use this free tool Package Builder

B. Create Package
Instead of creating XML file as above, the other option is by creating Package from Salesforce menu Setup | Create | Packages, see this blog for complete reference Getting Unstuck.

2. Developer Workbench
- Click Migration | Retrieve
- Select the XML file created for "Unpackaged Manifest"
- or enter the Package Name, if you use option B - Create Package
- Check "Single Package"

- Click Next button
- Click Retrieve button

- Click "Download ZIP File" link when done

3. Extract and Find
A zip file will be download, you need to extract it and using tool like Notepad++ to find the metadata you need. In my use case as above, I am looking for <actionType>flow</actionType> to find all Flow called by Process Builder.


Salesforce: Not allow Opportunity back to the previous Stage

Use Case: biz team decide to set a rule that Opportunity Stage are not allowed back to the previous Stage and team decide not to add number in the Stage as prefix.

Solution: create a validation rule with hard code each stage with a number, but the number only valid for the validation rule.

Let's say this is our Stage for open Opportunity from beginning till before closed.
  • Prospecting
  • Qualification
  • Needs Analysis
  • Value Proposition
  • Id. Decision Makers
  • Perception Analysis
  • Proposal/Price Quote
  • Negotiation/Review

Validation rule:

      StageName ,   
           "Prospecting", 1,   
           "Qualification", 2,   
           "Needs Analysis", 3,   
           "Value Proposition", 4,   
           "Id. Decision Makers", 5,   
           "Perception Analysis", 6,       
           "Proposal/Price Quote", 7,   
           "Negotiation/Review", 8,   
      PRIORVALUE(StageName) ,   
           "Prospecting", 1,   
           "Qualification", 2,   
           "Needs Analysis", 3,   
           "Value Proposition", 4,   
           "Id. Decision Makers", 5,   
           "Perception Analysis", 6,       
           "Proposal/Price Quote", 7,   
           "Negotiation/Review", 8,   

Wednesday, April 20, 2016

Testing Outbound Message in Salesforce

Salesforce provide out of the box functionality to send data out from Salesforce to other system based on workflow or approval process. We just need to enter Endpoint URL of the external system.  Each message Notification also has the object ID, and this needs to be used to track re-delivery attempts of notifications. The other system need to response "ack" that the message has been received, otherwise Salesforce will try keep deliver the message until expired.

With Outbound Message, we do not need to write any code in Salesforce to make this integration happen. But, the other party need to consume message in SOAP web service sent by Salesforce, whether by writing code to consume Endpoint WSDL generated in Salesforce, or using kinds of middleware that able to parse and consume web service sent.

We can include Session Id for the other system to access Salesforce, example: when an Account flip from Prospect to Customer, we send Account information to external system, the external system receive the message and send ack response. After that, the external system create the same Account in their system and send back to the ID created to Salesforce as External ID by update Salesforce Account.

Integration is never be simple, but to test and make sure that Salesforce is sending the right fields, sessionId, etc. We can use API traffic monitoring tool such as Runscope to collect requests made and let you inspect them in a human-friendly way. Runscope is not free, but a scale down version RequestBin available for free, although it will store the incoming message in short period only.

1. Create bucket in Runscope
It will create a key for bucket created, such as: qzmf6xszmqqb
Click Captured menu and you should see the URL, example:

2. Setup Outbound Message
Navigate to Setup | Create | Workflow & Approvals | Outbound Messages
Create New Outbound Message
Enter the Outbound Message Name, Object, Endpoint URL would be above URL, Send Session Id (if needed), and Fields to Send.

3. Setup Workflow or Approval Process
This is standard Salesforce Workflow or Approval Process, just add Outbound Message created as the action.

4. Test
When the record triggered by Workflow or Approval Process, Outbound Message will send SOAP web service to defined URL.
Open Runscope and click Captured menu, you should see captured POST request in SOAP message format. You can compare the messages here, with the configuration in Salesforce Outbound Message.

As you see the message will include:
  • OrganizationId
  • ActionId - 04k
  • SessionId (we enable this in the configuration)
  • EnterpriseUrl
  • PartnerUrl
  • OutboundMessageId - 04l
  • ObjectName
  • ObjectId 

But, because Runscope or RequestBin cannot reply ack notification, Salesforce will keep send the message until expired, you can monitor and delete them manually from Setup | Monitor | Outbound Messages.

The outbound messaging service also features a retry mechanism on failed outbound messages, Salesforce waits for an acknowledgment from the remote system for up to 10 seconds. The retry interval increases exponentially over time, starting with 15-second intervals and ending with 60-minute intervals. Administrators must monitor this queue for any messages exceeding the 24 hour delivery period and retry manually, if required. Salesforce retries sending the outbound message request for up to 24 hours.

Instead of Runscope or RequestBin, use Integration Playground provided by Salesforce for testing. With this tool, you can play monitor incoming message, and to toggle on and off for the "ack" notification.


Monday, April 18, 2016

Chatter Poll: How to Get the Detail?

Chatter Poll is a nice feature for Salesforce and Chatter user to do simple poll.

Use Case: Universal Container conducting a poll in a Chatter Group 'All Employee' and would like all employee to vote on a product name.

Issue: we only see the vote result for each choice and total user has vote, but we do not know who has vote and has not vote.

  • There is no report type for Chatter Poll :(
  • To write apex code for this --- we have no in house developer :(
  • SOQL --- this is possible :)

So here we go, you can use developer workbench to run this query:

1. Query FeedItem 
First. we need to find FeedItemId to get the Id of the poll feed.
Example: SELECT Id, Body FROM FeedItem ORDER BY CreatedDate DESC

2. Query FeedPollVote 
Second, query FeedPollVote to know who has vote on that poll / feed, so in this case, looks for CreatedById.
Example: SELECT Id, CreatedById, CreatedDate, ChoiceId FROM FeedPollVote Where FeedItemId = '0D590000037CHTSCA4'

3. Query FeedPollChoice (Optional)
This query only needed if you would like to know which choice is voted by each users.
Example: SELECT Id, ChoiceBody FROM FeedPollChoice Where FeedItemId = '0D590000037CHTSCA4'

From last query we know that user 00590000000OoB0AAK vote for Strawberry and 00590000000YIE2AAO vote for Banana.

So, if you would like to know who has not vote, just export 2nd query and look for CreatedById, using Ms Excel and do a simple VLOOKUP() to compare will all Salesforce / Chatter users.

Page-level ad