Extensions have been out for a while now and many customers are heavily using them to customize the cart & checkout experiences. This has provided a much needed flexible layer that allows developers to customize the ability of these pages without necessarily rebuilding every component.
How do you force a recalculation of your extensions on demand?
If you're not familiar with extensions and orchestrators, i'd encourage you to review this video before you proceed, because we're going deep into the weeds in this article!
Scenario
Let's set the stage with a scenario. Let's say you or your customer have the requirement that you want to validate pricing every time you load the cart page or go directly into checkout.
Why would you want to do this? Some customers prices are very dynamic and could change between the time you added the items to cart several days (or hours) in the past and when you eventually want to order. To add to the rational, some customers want to make sure they show that prices have changed on the cart page before moving to checkout.
To recap, the requirements are:
Validate prices when you load checkout
Validate prices whenever you go to your cart
How do we do this?
Let's start with the easy one, #1 is completely native, when you load checkout for the first time the native orchestrator will validate prices based on your store configuration (standard prices by default or a pricing service if configured)
#2 is slightly more complicated. Let's assume for our use case that we have a custom price service that is handling our custom pricing needs. Natively, you aren't able to have pricing re-trigger like we want. This is where calculateCart comes into the picture to save the day!
How to recalculate with extensions
calculateCart
In API version 62.0 and after, there is a method ConnectApi.CommerceCart.calculateCart that gives us the ability to re-trigger the cart orchestrator. This opens up a ton of possibilities...
You can find the public documentation here if you'd like to review what's available. I'm a very visual learner, so let's see how this could actually be implemented.
CartPriceChange
We'll start by creating a standard apex class that we plan to call from a LWC. In our scenario we talked about doing this when the cart loads, so we'll create an apex class called
CartPriceChange.cls that we'd call onload from our cart LWC. Within that class we'll have a method that has the following line in it which calls this new public method from the ConnectApi.
ConnectApi.CalculateCartResult result = ConnectApi.CommerceCart.calculateCart(webstoreId, cartId, accountId);
CartOrchestrator
In your orchestrator, you need to listen for this new buyerAction and tell your orchestrator which extension you want to run when triggered. This line would look like this:
buyerActions.isRecalculationRequested();
To give a more full example, if we're doing this for pricing, we'd replace the standard line with the following
boolean runPricing = buyerActions.isCheckoutStarted() || buyerActions.isCartItemChanged() || buyerActions.isRecalculationRequested();
Now we have a way to trigger our orchestrator and we have a way to listen for the trigger in our orchestrator to run pricing again. We're missing one more piece though!
PriceCalculator
Within your pricing calculator or service you likely will need a way to know when it's a net new cart item or a recalculate. This will give you the ability to have more efficient code instead of start from scratch each time and more granular control over what happens between net new items and recalculation.
Our pricing calculator might look something like this:
public virtual override void calculate(CartExtension.CartCalculateCalculatorRequest request) {
CartExtension.Cart cart = request.getCart();
ChangeEvent changeEvent = processRequest(request);
switch on changeEvent.changeType {
when ADD { ..fill in with what to do on add.. }
when QUANTITY { ..fill in with what to do on quantity change.. }
when RECALCULATE {
.. this is where we can detect when our cart has been triggered to recalc
}
}
}
You can see from this example that with changeEvent.changeType we have the ability to detect what type of change type was triggered.
If you haven't already, please subscribe to my Salesforce Mojo channel and email list to get the latest updates! https://www.youtube.com/@salesforcemojo