Building a Monopoly app in Salesforce - part 7: Buying Assets from the bank

In the previous parts of this series, we built a flow for rolling the dice and moving the player. We also created flows to execute the first Rule of a Position.

Some spaces on the board don’t have any Rules attached to them but do have an Asset (such as a street) that can be purchased—provided it hasn’t already been bought by another player.

We will now build a dedicated screen flow for this process, which we will then integrate into the SCR – Roll and Move flow.

What needs to happen?

  1. Check whether the Asset is still owned by the bank.
  2. If it is, display a screen to the player showing that the Asset is for sale and—if the player has enough money—offer the option to purchase it.
  3. If the player chooses to buy it, execute the transaction:
    1. Subtract the purchase amount from the player's Cash Balance
    2. Transfer ownership of the Asset from the bank to the player

The input variable

For this flow, we need the Player record and the Position record. Since the Position is a parent record of Player through a lookup relationship, having the Player record as the input variable provides everything we need.

I prefer to avoid complex variable names with abbreviations or arbitrary "var" in them. I do like to clearly mark which variables are used for input or output. I follow camelCase, where words are joined without spaces or underscores, but readability is improved by capitalizing each new word from the second word onward. For plurals, I simply use the standard plural form of the word. For example: inputWorkOrderLineItemsA long story to explain why our input variable is named inputPlayer .

Now that we’ve created the input variable, we can save the flow and give it a name. This makes it easier to save our progress regularly while building.

Who is the Asset's owner

We start the flow with a Decision element.

  • Label: Is the Asset owned by the bank?
  • API name: Is_the_Asset_owned_by_the_bank
  • Outcome label: Y
  • Outcome API name: Is_the_Asset_owned_by_the_bank_Y
  • Criteria: inputPlayer.Position__r.Asset__r.Owned_by_Player__r.Name
  • Operator: equals
  • Value: Bank
  • Default outcome label: N

The negative outcome of this decision is where we will build the paying of rent in the next episode.

What do we show the Player

If it’s determined that the bank is selling the Asset, the next question is whether the player has enough money to buy it. We could use a Decision element for this, but an alternative approach is to display different Display text components based on conditions.

If the player has enough money, we show a message indicating that they can purchase the Asset. If not, we display a message stating that the Asset is for sale and that the player doesn’t need to pay rent, but we do not offer the option to buy it.

To control the conditional visibility of these screen components, we need a formula that outputs a boolean (true or false). The formula isPlayerCashBalanceSufficient is written like this:

inputPlayer.Position__r.Asset__r.Purchase_Price__c < inputPlayer.Cash_Balance__c

If the formula's output is true, then only the first Display text element is visible. When false we only show the element that says the user can not buy the Asset.

The icon resembling an eye indicates that conditional visibility has been configured on a Screen component. In the screenshot above, you can see that the toggle to purchase the Asset is only displayed if the player has enough money to afford it.

Action button

Since 2024, Flow Builder also offers Actions that can be called within a Screen element of a screen flow. This differs from an Apex Action or subflow, which are added as elements between two screens.

I want to use this approach here as well because it looks better than the toggle. To do this, we first create a very simple Autolaunched Flow.

Just like in the screen flow (which we’ll return to shortly), we only need the inputPlayer variable. For this subflow, we shall also check Available for Output on this variable. That way, after the purchase, I can easily display the player's updated Cash Balance on the screen.

The first element in this flow is updating the value of the Asset's Owned_by_Player__c relationship field.

Of course, we also need to subtract the purchase amount from the Player's Cash Balance. Instead of using an Update Records elementright away, I first use an Assignment elementbecause it allows me to assign the new value more easily. In the screenshot above, you can see that we can only assign field values without choosing an operator. This means we would have to write a formula specifically to calculate the new Cash Balance. However, that’s not necessary, as the Assignment element allows you to simply use the subtract operator.

The Update Records element can then be pretty simple.

Done! We will save this as ALF – Buy Asset from Bank. Don't forget to activate it.

Back to our SCR – Buy Asset or Pay Rent flow. We will save this and then refresh the screen with F5. Otherwise, this flow won’t be aware of the existence of the Autolaunched flow we just created.

Open the Screen element and drag the Action Button component onto the canvas.

In the Action section, you can search for and select an Apex Action or active subflow by name. For the flow itself, we also need to specify the input variable, and you must assign an API name to it as well.

Next, we determine the conditional visibility of the button. It should only be visible when the Player has sufficient funds (just like with the toggle we will remove later) and the Asset is not already owned by the Player. If we don’t implement this, the player could accidentally click the button multiple times and end up paying twice.

To confirm to the player that the purchase was succesful, we will add another Display text that shows up when the Action button disappears.

Here, I’m really taking you along in real-time as I build, showing how you deal with evolving insights. I just realized that, as a player, I’d want to see exactly how much money I have before deciding whether to buy or not. After all, it might not be ideal if I’m left with only a tiny amount after the purchase.

So, we add a Display Text that is visible before the purchase. I also realized that, for better conditional visibility, it’s more convenient to create a before purchase section and an after purchase section.

The visibility is now set up as follows:

  • When the Asset is not in the active player's possesion yet, the top Section is shown
  • Within that section the intoduction with the Purchase Price of the Asset and the active player's Cash Balance is always visible
  • Making the Buy this Asset button inside this section is only availabe if the Player has sufficient funds
  • If the player does not have enough money, then the Display text “You do not have enough cash (…)” is visible instead
  • When the player has acquired the Asset, the top section is hidden and the bottom section becomes visible.

I haven't tested this yet, but I'm unsure whether the conditional visibility based on the Asset owner will work. First of all, I definitely need to use output variables from the Screen Action. Currently, I have set the visibility of the "for sale" section as follows:

{!buyAssetSubflow.Results.Flow__InterviewGuid} Is Null True

As long as the Action Button hasn't been clicked, no flow interview has taken place, and therefore, it doesn't have an ID.

For the "Sold" section, I expect this condition to be appropriate:

{!buyAssetSubflow.IsSuccess} Equals True

Time to test it

We shall now save the flow and prepare our test data.

In the first test, the Player is on a street owned by the bank and has enough money. Unfortunately, you can't currently create Flow Tests for Screen Flows like you can for Record-Triggered Flows, so I actually need to manipulate a Player record first. I also need to ensure that the Asset is owned by the bank, which we didn't do during the import.

The screen we get to see (image below) is exactly right.

When I click the Buy this Asset button, the following happens.

Wrong: Steenstraat costs € 10,000, so our Cash Balance should now be € 140.000.

Now, let's check the records to see what actually happened. The ownership of the Asset has been correctly transferred, and in reality, the Player's Cash Balance has indeed been updated to €140,000.

This means I am just using the wrong variable in my Display text element. We modify this as follows: For the new Cash Balance we use the Screen Action's output instead of the Cash Balance from the inputPlayer variable.

To run the same test again, we first need to ensure that the Bank becomes the owner of the Asset again. After saving the change, we will debug the flow once more.

We will also test the following scenario's:

  • The Player already owns this Asset: then the Plyer will never reach this screen.
  • The Asset is for sale, but the player does not have enough money to buy it.
Result of the test where Test Player 1 already owns the Asset.
Result of the test where Test Player 1 does not have sufficient funds.

One last addition

In the next episode, we shall add the steps for the active Player to pay rent to the Asset's owner when it's not the bank. But before that, let's make one more addition to this flow. When our active Player owns the Asset themselves, they obviously shouldn't have to pay rent.

So first we modify the Decision element at the beginning of our flow.

Below this new branch we add a simple screen.

Next time

Two weeks from now we shall add paying rent to another player to this flow.

Leave a Reply

Your email address will not be published. Required fields are marked *