top of page

Rollup Summary for Salesforce Account Hierarchy with Flow

Writer's picture: Vasilis PapanikolaouVasilis Papanikolaou

Updated: Nov 6, 2024

Salesforce Account Hierarchies are great for modelling global organisations or large corporations with a complex structure and multiple subsidiaries. However, there is a catch in the way the hierarchy is modelled. You might have thought “Great, I’ll create all the accounts and then we’ll roll everything up the hierarchy”. Guess what! You can’t really do that out of the box with roll-up summary fields. Rollup summaries are really easy to setup but they only work for Master-Detail relationships and the account hierarchy is not built on Master-Detail relationships. There are 2 very popular (and old) ideas on the subject but it seems that this functionality won't be coming anytime soon.


There are 3 ways one can work around this. 


  • An AppExchange app

  • A flow

  • Apex Triggers


Each of the methods have their own pros and cons. 

Solution

Pros

Cons

AppExchange App

Easy setup

Tested

No development

More efficient for multiple fields

More advanced functionality

Has to be installed and tested

Licensing costs

Flow

No licensing

No development

Effort to build

Not triggered on deletion

Trigger

Flexible

No licensing


Needs development skills

In this article we'll build a set of flows to tackle the problem. Before going through the solution, keep in mind that we can't trigger flows on object deletion so there is one limitation we won't be able to work around. 


Rollup Summary for Salesforce Account Hierachy: The scenario


Let's work with a relatively common scenario. You have a global hierarchy of accounts and you'd like to know how the amount of closed opportunities  rolls up the hierarchy. 


There are a couple of things to consider before starting to build our flow. We can roll up the amount of closed opportuities to the related account with a rollup summary field. Let’s call that field Closed Deals (Closed_Deals__c). The roll-up type should be SUM of the Amount field and we’ll also need to filter the Opportunity records with Won equals True.


Let’s think a bit about how to roll up the Closed Deals field. I have set up an example in Figure 2 to make it easier.


Acme is a global account with a number of entities around the world. European country accounts fall under the Europe account and the Europe account falls under the global entity. There is also a US account under Acme Global. Each account has its own Closed Deals based on the opportunities directly related to it. Acme Spain has Closed Deals = $240k and Acme Europe has Closed Deals = 100k since only one opportunity is directly related to it. I’m assuming that every account in the hierarchy can have direct opportunities. Therefore we need 2 more fields. One to capture the opportunities of the account’s children (Acme Germany and Acme Spain for Acme Europe) and one to capture the sum of opportunities of children and direct opportunities.


  • Closed Deals of Children (Closed_Deals_of_Children__c): sum of opportunities of all the children related to the account. This is a simple Currency field with a default value of 0.

  • Closed Deals Total (Closed_Deals_Total__c): opportunities of all the children plus the direct opportunities. This is a simple formula field with the formula Closed_Deals_of_Children__c + Closed_Deals__c.


Using the 3 fields that we have defined, we can start building our flow.


Building the flow(s)

Let’s start by understanding the logic of our flow. When an opportunity of Acme Spain closes or its amount is modified, the rollup summary field Closed Deals changes. This change should fire our flow which should recalculate the Closed Deals of Children for Acme Europe. The change in Acme Europe should fire another instance of the flow to calculate the sums for Acme Global. This way all the sums would be kept up to date. The logic can be summarized in the following steps:


  1. Opportunity amount or status is modified

  2. Closed Deals on Account is modified

  3. Find the Account’s parent

  4. Loop through its children and sum up the Closed Deals Total field of all the children

  5. Update the Closed Deals of Children Field

  6. Do that again until there are no more parents left to update


This can be covered with one flow but there is one small complication. We have to cover the possibility of reparenting the account. Let’s say that Acme restructures its hierarchy and we want to capture that. If we change the parent of an account, our flow would run for the new parent but “forget” to run for the old parent and update it. This might not be the most common scenario but it makes sense to cover it since we can.


We basically have to call the flow we described earlier one more time for the previous parent and we’re done.


We’ll make 2 flows: one for calculating and updating the Closed Deals of Children values and one to decide if the parent was modified and we need to run it one more time for the previous parent.


Updating our rollup summary field

Let’s start building the inner flow that we’ll call Calculate Closed Deals. Below is what our flow will look like. First let’s start by creating an Auto-launched flow. We will be able to call this flow from the outer flow when the record is updated.



First let’s create an input variable for the Parent Account record and name it ParentAccount. Don’t forget to mark it as Available for Input so that the outer flow will be able to pass the parent account record to it.


The next step is to get all the children accounts of our parent account. We’ll use a Get Element for that.



This will create a collection of all the children of the parent account so that we can loop through them. Next we need to create a loop element to do exactly that. 


At this point we should also create another variable to store the value of the sum while looping. We’ll create a currency variable called Closed_Deals_of_Children with an initial value of 0.


Everytime we loop through an element, we’ll add the value of Closed_Deals_Total__c of the loop item to the Closed_Deals_Of_Children variable with an Assignment element.


  • Variable: {!Closed_Deals_Of_Children}

  • Operator: AND

  • Value: {!Sum_Loop.Closed_Deals_Total__c}




Last, we need to update the parent account record in the database. We’ll use an Update element to do that.


Our first flow is done. We can test, save and activate it. All that’s left now is to call it at the right time for the right records.


Calling the flow

The second flow must be record triggered and run every time an account is created or updated. We’ll also add some criteria to make the flow run only when the following apply:

  • Closed Deals is changed: a change in an opportunity

  • Closed Deals of Children is changed: a child account is updated 

  • ParentId is changed: the account is reparented


We’ll also select the Optimize the flow for Actions and Related Records since we want the flow to act on the parent of the account that triggered it and not the account itself.


Our flow will look like this:


Basically we need it to check a couple of things before calling the Calculate Closed Deals flow. First we need to check if the Account has a parent. If it does, we’ll get the parent and pass it to the Calculate Closed Deals flow. If it doesn’t we’ll skip this part. Next we need to check if the account has been reparented. If yes we’ll call the flow for the previous parent. Let’s dive into the details.


First we’ll use a Decision element to check if there is a parent by checking if the ParentId field is null.


Next we use a Get element to get the parent account from the database.


Now that we have the parent account we can pass it to a subflow element that calls the Calculate Closed Deals flow. Don’t forget to set the input value for the flow.


Next we need to check if the prior record’s parent is the same as the record’s parent. In other words if the record used to have a parent and has been reparented or used to have a parent and now has none. We’ll do that with a Decision element. The condition we’re checking for is: 


  • $Record.ParentId is changed 

  • $Record__Prior.ParentId is not null


If the conditions are satisfied we’ll have to get the previous parent using another Get element.


Now we can call the Calculate_Closed_Deals flow for the previous parent using a Subflow element.


And that’s it. Our flow is done! Now every time we update an opportunity or account, the account hierarchy is updated. We can also refactor these flows in the future to make them evaluate more than one rollup fields since the logic is very similar. The only case that is not covered is when an account is deleted. The rollup summaries that we calculated wouldn’t be correct until another account with the same parent is updated and triggers the process. If this is not a show stopper, a flow can be an easy way to solve the problem without resorting to development or an AppExchange app.



Comments


bottom of page