Sitecore Experience Commerce - Filtering Shipping Methods per Country
How to Filter Shipping Methods Based on Selected Country
If you're building a Multi-Country Sitecore Commerce Solution, you will need the ability to filter Fulfillment Methods based on the selected Shipping Address / Country. I am sure there are many ways to implement this feature with Sitecore Commerce. In this blog, I will be sharing a simple solution I implemented recently for one of my clients.
To be able to filter the shipping methods per country, here are the steps you needed to follow:
- Extend 'Fulfillment Method' Template with a 'Countries' Multilist Field.
- Extend FulfillmentMethod Commerce Entity with a Countries Filter Component.
- Replace FilterCartFulfillmentMethodsBlock and FilterCartLineFulfillmentMethodsBlock with a custom implementation to filter methods based on Shipping Country.
- Assign appropriate countries to each Fulfillment Method.
- Sync Commerce Control Panel using Postman.
Let's now go through each of these steps in more detail:
1- Extend 'Fulfillment Method' Template with a 'Countries' Multilist Field.
Update this template: /sitecore/templates/CommerceConnect/Sitecore Commerce/Commerce Control Panel/Shared Settings/Fulfillment/Fulfillment Method by adding a Countries Multilist Field with Source ?/sitecore/Commerce/Commerce Control Panel/Shared Settings/Countries-Regions ?as displayed below:
2-Extend FulfillmentMethod Commerce Entity with a Countries Filter Component.
2-A) Create CountriesFilterComponent:
public class CountriesFilterComponent : Component { public List CountryCodes { get; set; } = new List(); }
2-B) Override/Replace TranslateItemsToFulfillmentMethodsBlock:
Replace TranslateItemsToFulfillmentMethodsBlock with a custom block, in which you will add the following logic:
if (itemModel.ContainsKey("Countries") && !string.IsNullOrEmpty(itemModel["Countries"] as string)) { var countries = itemModel["Countries"].ToString().Split('|'); var countryCodeList = new List(); foreach (var countryId in countries) { var countryItem = await this.Commander.Pipeline().Run(new ItemModelArgument(countryId), context); if (countryItem.ContainsKey("Country Code") && !string.IsNullOrWhiteSpace(countryItem["Country Code"] as string)) { countryCodeList.Add(countryItem["Country Code"].ToString().TrimEnd()); } } if (countryCodeList.Any()) { var countriesFilterComponent = fulfillmentMethod.GetComponent(); countriesFilterComponent.CountryCodes = countryCodeList; } }
3-Replace FilterCartFulfillmentMethodsBlock and FilterCartLineFulfillmentMethodsBlock with a custom implementation to filter methods based on Shipping Country
Replace the blocks mentioned above with Custom ones, and use the following method to filter the IGetFulfillmentMethodsPipeline call result:
public IEnumerable FilterFulfillmentPerCountry(Party party, IEnumerable fulfillmentMethods) { return fulfillmentMethods.Where(f => !f.HasComponent() || !f.GetComponent().CountryCodes.Any() || f.GetComponent().CountryCodes.Contains(party.CountryCode)); }
4-Assign appropriate countries to each Fulfillment Method.
Using Sitecore Content Editor Update Fulfillment methods to assign Specific Countries where applies:
5-Sync Commerce Control Panel using Postman.
For these changes to apply, you need to sync the Commerce Control Panel using Postman.
Here's how: https://doc.sitecore.com/developers/90/sitecore-experience-commerce/en/synchronize-content-items.html
And we're all set.
Your Shipping/Fulfillment methods can now be filtered per country.
This solution was implemented and tested on Sitecore Experience Commerce 9.0.2.