Overview

Salesforce.com has introduced a new tool called Flow (Setup | App Setup | Create | Workflow & Approvals | Flow) with an easy-to-use, drag-and-drop interface. You can create a flow with the flow designer with little or no programming knowledge.

Flows can be run in the designer directly, from a Visualforce page, or we can use the URL that it provides to create a button on a list view.  Response times are very fast because the information is stored on the client side.

Even better, you can use Flow to execute DML operations within your own objects, or execute more complex operations like posting by creating a new Apex class.

Once you are happy with your flow, you can package it.

Sample Scenario: Journal creation and posting from travel expenses.

This example shows how a user can enter travel expenses, create the journal that includes them, and then post it.

We could split the flow into the following sections:

  1. Enter Employee
  2. Create Expenses
  3. Enter Journal data
  4. Create Journal
  5. Post Journal

Enter Employee

Enter employee identification details and retrieve the record from the relevant Salesforce Platform objects.

ArticleEmployee

After typing employee identification details, the flow looks for the data in the relevant Salesforce Platform objects.

ArticleLookForEmployee

The decision screen helps us to validate that the employee exists. In this case it will display the employee information. However, if we enter invalid identification details, the flow will display an error message.

Article1Part

Create Expenses

Enter expenses (allowance or tickets) and store them in relevant Salesforce Platform objects.

Depending on the expense type, Allowance or Ticket, the flow will navigate to a different input screen to enter only the required information for that type.

This version of Flow doesn't allow us to get a list of objects or use any of its data to store into a variable. So this flow has another step; get the amount just inserted, and store it into a variable. At the end, the summary of all amounts is used as a journal total.

ArticleAmountSum

Enter Journal data

Flow doesn't have lookup fields, so we can enter journal data and validate it in this way.

ArticleJournal-Validations

Flow asks us if we want to create the journal now. If we decide no, we will not be able to generate a journal using Flow for the expenses created previously.

This section will validate all text information that user can enter, like Bank Account Name or Currency Name. To make it easier, Flow also allows us to set Ids as constants so that this can be used as Bank Account Id by default.

Create Journal

Create journal header and lines

ArticleCreateJournal

Note that we can create a journal directly using flow because I have Journal Extension package installed.

Once we have received all required information the flow process can then send the information to the relevant Salesforce Platform relevant objects.

ArticleInsertJournalHeader_2
ArticleInsertJournalLine1
ArticleInsertJournalLine2

JournalBAId and JournalBankAccountGLA are variables populated during the validation step.
JournalIs the record id of the previous screen. After the insertion, flow returns the Id.
BankAccount is a constant that stores Bank Account type.
minusTotalAmountForJournalLine is a formula field.

Post Journal

Post the journal and show a success or failure message.

ArticlePostJournal

Up to this point, we have not used Apex code, but Flow is not powerful enough to perform some operations like posting a journal. To do this, we have created a class that implements Process.Plugin and from there we can call our API, or perhaps an external API.

Here is the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
global class PostJournal implements Process.Plugin
{
    public ID journalId;
    public String ErrorMessage = 'No error';
    global Process.PluginResult invoke(Process.PluginRequest request)
    {
            //if we are going to have output parameters, we need to define here.
            //if not, we need to return just the empty map
            Map result = new Map();
            try
            {
                //Get values from imput Parameters (defined on describe method)
                ID jId = (ID)request.inputParameters.get('journalId');
                c2g.CODAAPICommon_6_0.Context context = new c2g.CODAAPICommon_6_0.Context();
                c2g.CODAAPICommon.Reference journal = c2g.CODAApiCommon.getRef(jId,null);
                c2g.CODAAPIJournal_6_0.PostJournal(context, journal);
                journalId = journal.Id;
        }
        catch(Exception ex)
        {
            //catch exceptions
            ErrorMessage = ex.getMessage();
        }
        finally
        {
            result.put('PostedJournalId', journalId);
            result.put('Error Message', ErrorMessage);
        }
        return new Process.PluginResult(result);
    }
    global Process.PluginDescribeResult describe()
    {
        Process.PluginDescribeResult result = new Process.PluginDescribeResult();
        //Set input parameters
        result.inputParameters = new List();
        result.inputParameters.add(new Process.PluginDescribeResult.InputParameter('journalId',Process.PluginDescribeResult.ParameterType.ID, true));
        //Set output paramenters
        result.outputParameters = new List();
        result.outputParameters.add(new Process.PluginDescribeResult.OutputParameter('PostedJournalId',Process.PluginDescribeResult.ParameterType.ID));
        result.outputParameters.add(new Process.PluginDescribeResult.OutputParameter('Error Message',Process.PluginDescribeResult.ParameterType.STRING));
        return result;
    }
}

This example is a start point that can be enhanced:

  • — Add a new step to link the expenses with the journal we have created.
  • — Run the Flow from a new tab or a Visualforce page.
  • — Navigate to the journal once the flow finishes.

Appendix

How to handle error messages:

In Salesforce Flow, the system variable {!$Flow.FaultMessage} stores error messages that occur during DML operations. When an error occurs, you can display this information on the flow.

resizedimage500204-CreateCreditNoteHandlerErrorDesign

In this example, we attempt to create a new credit note just with the account. The step that creates a new record has a FAULT path. Flow follows this path if there is an issue with the DML operation. When a DML error occurs, the system variable {!$Flow.FaultMessage} contains the error message returned by the trigger.

CreateCreditNoteHandlerErrorRun

IMPORTANT USAGE NOTICE PLEASE READ 

Copyright © 2011, FinancialForce.com, inc

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • Neither the name of the FinancialForce.com, inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.