How To

Update Opportunities for an Inactive Opp Owner Using Salesforce Flow

InactiveUser

This blog post was inspired by blog reader Melissa.

Business Use Case:  Addison Dogster is the system administrator at Universal Containers. Mary Markle is the Director of Operations. When an opportunity owner leaves the company and is deactivated, she would like to update the stage of the inactive user’s opportunities to “Pending Reassignment.”

DemoView image full screen

Solution: Being the #AwesomeAdmin that Addison is, she was able to solution this declaratively using Salesforce Flow. She builds the first part of the process using Process Builder run on the User Object when the user is deactivated and invokes the latter part of the process in Flow Builder.

The outcome looks like this:

Process created in Process Builder on the User object that runs when the active field is changed and the active field is false. Then, 0 hours after the Last Modified Date, invoke the flow.

Process-UpdateUser

View image full screen

The flow (1) looks up the opportunities owned by the user; (2) if opportunities are found, (3) for each opportunity found, assign “Pending Reassignment” to the opportunity stage and (4) add the opportunity to a collection of records to be updated; and (5) after all the opportunities have gone through the process, update all the opportunity records in the collection.

Note: The update records action is performed OUTSIDE the loop, not inside it. Similar to apex, when DML statements (insert, update, delete, undelete) are placed inside a for loop, database operations are invoked once per iteration of the loop making it very easy to reach these governor limits. Instead, move any database operations outside of for loop. The same applies to flow (remember, Salesforce translates flow into code behind the scenes).

UpdateStageforInactiveOppOwner-Flow

View image full screen

Highlighted Steps: 

1. Add “Pending Reassignment” as a new picklist item in the Opportunity Stage.

2. Create an autolaunched flow shown above. In Lightning Experience, it is found under Process Automation | Flows. Click on New Flow. Select Autolaunched Flow. Click on the Create button.

In the flow, we would configure the following flow resources.

A. We need to create a variable resource called varUserId to store the user’s id, which will be passed as an input variable from the process builder. This is the userId of the deactivated user.

Best practice tip: Provide a description so you and other/future admins know what this flow resource is used for.

This is how the flow resource is configured.

  • Resource Type: Variable
  • API Name: varUserId
  • Data Type: Type
  • Availability Outside the Flow: Available for input is checked

varUserId

B. First, we need to perform a lookup to pull all the contacts associated with the deactivated user. We are using the Get Records resource called Lookup opps owned by inactive user because we are pulling a collection of Salesforce records. We are looking up the Opportunity object where the OwnerId equals the deactivated userId (variable varUserId). Once found, we will store the all records and store the Id and the StageName.

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Configure the Get Records to look like the below:

  • Object: Opportunity
  • Condition Requirements: All Conditions Are Met (AND)
    • OwnerId Equals {!VarUserId}
  • How Many Records To Store: All records
  • How to Store Record Data: Choose fields and let Salesforce do the rest
    • ID
    • StageName

UpdateStageforInactiveOppOwner-Flow-GetRecords

View image full screen

C. Next, we will a Decision flow element called Opps Found? to determine whether the Get Records in the previous step yielded any opportunities. The “Found” outcome looks at the items in the {!Lookup_opps_owned_by_inactive_user} (collection from the Get Records) is null {!$GlobalConstant.False}. Two negatives equal a positive, which means the collection has at least one or more opportunity records.

Best practice tip: Provide a description so you and other/future admins know what this flow element is used for.

Configure the Decision to look like the below:

  • Outcome: Found
    • Condition Requirements to Execute Outcome: All Conditions Are Met (AND)
    • {!Lookup_opps_owned_by_inactive_user} Is Null {!$GlobalConstant.False}
  • Default Outcome: None Found

UpdateStageforInactiveOppOwner-Flow-DecisionView image full screen

D. We now need to create a Loop flow element called Loop de loop so that we can go through each opportunity record in the Get Records collection. It looks at the sObject Collection Variable from the Get Records {!Lookup_opps_owned_by_inactive_user} and put each contact record into a loop variable {!Loop_de_loop}.

Configure the Loop to look like the below:

  • Collection Variable: {!Lookup_opps_owned_by_inactive_user}

UpdateStageforInactiveOppOwner-Flow-Loop

E. For each loop record, in the Assignment flow element called Update Stage. We will assign the Pending Reassignment as the new opportunity stage.

Best practice tip: Provide a description so you and other/future admins know what this flow is used for.

Configure the Assignment to look like the below:

  • {!Loop_de_loop.StageName} (i.e. loop record’s stage name field) equals Pending Reassignment.

UpdateUserFlow-Assignment

F. For each loop record, in the Assignment flow element called Assign to the collection, we will add the loop opportunity record {!Loop_de_loop} to a new collection that will be updated {!CollectionofOppsToUpdate}.

Best practice tip: Provide a description so you and other/future admins know what this flow is used for.

Configure the Assignment resource to look like this:

  • {!CollectionofOppsToUpdate} add {!Loop_de_loop}

UpdateStageforInactiveOppOwner-Flow-Assignment1

G. Now, we need to create the Update Records flow element called Update Collection to update all the opportunities in the sObject Collection Variable {!CollectionofOppsToUpdate}.

Best practice tip: Provide a description so you and other/future admins know what this flow is used for.

Configure the Update Records to look like this:

  • How to Find Records to Update and Set Their Values: Use the IDs and all field values from a record or record collection
  • Record or Record Collection: {!CollectionofOppsToUpdate}

UpdateStageforInactiveOppOwner-Flow-UpdateRecords

View image full screen

H. Set your flow starting point. And connect the flow elements, outcome connector and loop connector to match the below…

UpdateStageforInactiveOppOwner-Flow-Connectors

I. Save/Save As and provide the following properties.

Best practice tip: Provide a description so you and other/future admins know what this flow is used for.

UpdateStageforInactiveOppOwner-Flow-Properties

J. Click the Activate button.

3. Now, create a new process using process builder. In setup, go to Create | Workflows & Approvals | Process Builder in Salesforce Classic or Process Automation | Process Builder in Lightning Experience.

A. Click on the New button to create our new process. Complete the information below and select A record changes.

Best practice tip: Provide a description so you and other/future admins know what this process is used for.

Process-UpdateUser-Properties

B. Specify User as the object, when a record is created or edited.

Process-UpdateUser-Object

C. Specify the Criteria Node. This needs to evaluate to true for it to execute. We will call the criteria Inactive. In this situation, we are going to use the formula as we cannot specify the IsChanged condition with the Conditions are met specification. The criteria is if the user’s active field is changed AND the user’s active field is false (unchecked).

We have to check the box to Yes under Advanced “Do you want to execute the actions only when specified changes are made to the record.” If this is not checked, you will not see the Scheduled Actions.

ISCHANGED([User].IsActive) &&
[User].IsActive = false

Process-UpdateUser-CriteriaNode

View image full screen

D. To avoid the mixed DML action on standard and setup objects that would result if you invoke the flow from an immediate action, we will configure a scheduled action to take place “0 hours after the LastModifiedDate.”

Process-UpdateUser-ScheduledActionView image full screen

Call the Action Name Invoke Flow. Select Flow as the action, select the flow created in Step 2. Specific the flow variable varUserId and pass in the field reference [User].Id onto the flow.

Process-UpdateUser-ScheduledAction-InvokeFlowView image full screen

E.  Click on the Activate button to activate the process builder.

Now, before you deploy the changes to Production, don’t forget to test your configuration changes.

  1. Make a user the opportunity owner for several opportunity records.
  2. Deactivate the user.
  3. Verify that all the opportunities owned by the deactivated user have the stage updated to Pending Reassignment. (You may need to give this a few seconds before refreshing the records to see the change.)

Deployment Notes/Tips:

  • Flow can be deployed to Production in a change set (or can be deployed using a tool such as Metazoa’s Snapshot).
  • You will find the flow in a change set under the Flow Definition component type.
  • Activate the flow post deployment as flows deploy inactive in Production, unless you have opted in on the Process Automation Settings screen, to “Deploy processes and flows as active.” NOTE: With this change, in order to successfully deploy a process or flow, your org’s Apex tests must cover at least 75% of the total number of active processes and active autolaunched flows in your org or you can select 0%, which will run the apex classes not related to your flow.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s