/// <summary>
        /// Builds a cache key for a cart operation.
        /// </summary>
        /// <param name="scope">Scope of the request.</param>
        /// <param name="cartName">Name of the cart.</param>
        /// <param name="customerId">ID of the customer to which belongs the cart.</param>
        /// <returns></returns>
        protected virtual CacheKey BuildCartCacheKey(string scope, string cartName, Guid customerId)
        {
            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Cart)
            {
                Scope = scope
            };

            cacheKey.AppendKeyParts(cartName);
            cacheKey.AppendKeyParts(customerId);

            return(cacheKey);
        }
        protected virtual CacheKey BuildPaymentMethodCacheKey(string scope, string cartName, Guid customerId, string providerName)
        {
            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.PaymentMethod)
            {
                Scope = scope,
            };

            cacheKey.AppendKeyParts(cartName);
            cacheKey.AppendKeyParts(providerName);
            cacheKey.AppendKeyParts(customerId);

            return(cacheKey);
        }
        /// <summary>
        /// Retrieve a list of InventoryItemStatusDetails represented by sku from all inventory location associated to the specific scope. The list of inventory location ids is all existing Fulfillment Locations inside the specific Scope
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public virtual async Task <InventoryItemStatusDetailsQueryResult> GetInventoryItemsBySkuAsync(GetInventoryItemsBySkuParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException("param");
            }
            if (string.IsNullOrWhiteSpace(param.Scope))
            {
                throw new ArgumentException(ArgumentNullMessageFormatter.FormatErrorMessage("Scope"), "param");
            }
            if (param.Sku == null)
            {
                throw new ArgumentException(ArgumentNullMessageFormatter.FormatErrorMessage("Sku"), "param");
            }

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.StoreInventoryItems)
            {
                Scope = param.Scope
            };

            cacheKey.AppendKeyParts("sku", param.Sku);

            var request = new GetInventoryItemsByScopeAndSkuRequest
            {
                Date               = param.Date,
                Sku                = param.Sku,
                ScopeId            = param.Scope,
                IncludeChildScopes = param.IncludeChildScopes
            };

            return(await CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(request)).ConfigureAwait(false));
        }
Exemple #4
0
        public virtual async Task <Overture.ServiceModel.Customers.Stores.Store> GetStoreByNumberAsync(GetStoreParam param)
        {
            if (string.IsNullOrWhiteSpace(param.Scope))
            {
                throw new ArgumentException("scope");
            }
            if (string.IsNullOrWhiteSpace(param.StoreNumber))
            {
                throw new ArgumentException("storeNumber");
            }

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Store)
            {
                Scope = param.Scope
            };

            cacheKey.AppendKeyParts(GETSTOREBYNUMBER_CACHE_KEYPART, param.StoreNumber);

            var request = new GetStoreByNumberRequest()
            {
                ScopeId          = param.Scope,
                Number           = param.StoreNumber,
                IncludeAddresses = param.IncludeAddresses,
                IncludeSchedules = param.IncludeSchedules
            };

            return(await CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(request)).ConfigureAwait(false));
        }
        /// <summary>
        /// Retrieve a list of regions for a specified country using its ISO code
        /// </summary>
        /// <param name="param"></param>
        /// <returns>A list of Region</returns>
        public async Task <IEnumerable <Region> > RetrieveRegions(RetrieveCountryParam param)
        {
            if (string.IsNullOrWhiteSpace(param.IsoCode))
            {
                throw new ArgumentException(GetMessageOfNullWhiteSpace(nameof(param.IsoCode)), nameof(param));
            }
            if (param.CultureInfo == null)
            {
                throw new ArgumentException(GetMessageOfNull(nameof(param.CultureInfo)), nameof(param));
            }

            var regionsCacheKey = new CacheKey(CacheConfigurationCategoryNames.Regions)
            {
                CultureInfo = param.CultureInfo
            };

            regionsCacheKey.AppendKeyParts(param.IsoCode);

            var result = await _cacheProvider.GetOrAddAsync(regionsCacheKey, () =>
            {
                var request = new GetRegionsRequest
                {
                    CountryIsoCode     = param.IsoCode,
                    CultureName        = param.CultureInfo.Name,
                    IncludeUnsupported = false
                };

                return(_overtureClient.SendAsync(request));
            }).ConfigureAwait(false);

            return(result);
        }
Exemple #6
0
        public virtual async Task <FulfillmentSchedule> GetStoreScheduleAsync(GetStoreScheduleParam param)
        {
            if (string.IsNullOrWhiteSpace(param.Scope))
            {
                throw new ArgumentException("scope");
            }
            if (param.FulfillmentLocationId == null)
            {
                throw new ArgumentException("fulfillmentLocationId");
            }

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.StoreSchedule)
            {
                Scope = param.Scope
            };

            cacheKey.AppendKeyParts(param.FulfillmentLocationId.ToString());

            var request = new GetScheduleRequest
            {
                ScopeId = param.Scope,
                FulfillmentLocationId = param.FulfillmentLocationId,
                ScheduleType          = ScheduleType.OpeningHours
            };

            return
                (await
                 CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(request)).ConfigureAwait(false));
        }
        private static CacheKey GetCacheKeyForFulfillmentLocationsByScope(GetFulfillmentLocationsByScopeParam param)
        {
            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.FulfillmentLocationsByScope, param.Scope);

            cacheKey.AppendKeyParts(param.IncludeChildScopes, param.IncludeSchedules);

            return(cacheKey);
        }
Exemple #8
0
        public virtual async Task <FindStoresQueryResult> GetStoresAsync(GetStoresParam getStoresParam)
        {
            if (string.IsNullOrWhiteSpace(getStoresParam.Scope))
            {
                throw new ArgumentException("scope");
            }

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Store)
            {
                Scope = getStoresParam.Scope
            };

            cacheKey.AppendKeyParts(GETSTORES_CACHE_KEYPART);

            var request = new FindStoresRequest
            {
                ScopeId = getStoresParam.Scope,
                Query   = new Query
                {
                    StartingIndex     = 0,
                    MaximumItems      = int.MaxValue,
                    IncludeTotalCount = false,
                    Filter            = new FilterGroup
                    {
                        Filters = GetStoreFilters()
                    }
                }
            };

            var stores = await CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(request))
                         .ConfigureAwait(false);

            // TODO: Remove this as soon as the FindStoresRequest returns localized display names.
            if (stores.Results.Any(s => s.DisplayName != null))
            {
                return(stores);
            }
            // Try get DisplayNames
            if (getStoresParam.IncludeExtraInfo)
            {
                var ids             = stores.Results.Select(x => x.Id).ToList();
                var extraStoresInfo = await GetExtraStoresInfoAsync(ids, getStoresParam).ConfigureAwait(false);

                for (var index = 0; index < stores.Results.Count; index++)
                {
                    var    store       = stores.Results[index];
                    var    extraInfo   = extraStoresInfo[index];
                    object displayName = null;
                    extraInfo?.PropertyBag.TryGetValue("DisplayName", out displayName);
                    if (displayName != null)
                    {
                        store.DisplayName = displayName as Overture.ServiceModel.LocalizedString;
                    }
                }
            }

            return(stores);
        }
Exemple #9
0
        protected virtual CacheKey BuildRecurringOrderProgramCacheKey(string scope, string recurringOrderProgramName)
        {
            var key = new CacheKey(CacheConfigurationCategoryNames.RecurringOrderPrograms)
            {
                Scope = scope
            };

            key.AppendKeyParts(recurringOrderProgramName);
            return(key);
        }
Exemple #10
0
        /// <summary>
        /// Retrieve the Product Media Settings from Overture
        /// </summary>
        /// <param name="scope"></param>
        /// <returns></returns>
        public virtual async Task <MediaSettings> GetProductMediaSettings()
        {
            var productMediaSettingsCacheKey = new CacheKey(CacheConfigurationCategoryNames.ProductSettings);

            productMediaSettingsCacheKey.AppendKeyParts("Media");

            return(await CacheProvider.GetOrAddAsync(productMediaSettingsCacheKey, () =>
                                                     OvertureClient.SendAsync(new GetMediaSettingsRequest())
                                                     ).ConfigureAwait(false));
        }
Exemple #11
0
        /// <summary>
        /// Builds the cache key for a WishList.
        /// </summary>
        protected virtual CacheKey BuildWishListCacheKey(string scope, Guid customerId, string cartName)
        {
            var key = new CacheKey(CacheConfigurationCategoryNames.Cart)
            {
                Scope = scope
            };

            key.AppendKeyParts(customerId, cartName);
            return(key);
        }
        protected virtual CacheKey BuildProvidersCacheKey(string scope, ProviderType providerType)
        {
            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Providers)
            {
                Scope = scope,
            };

            cacheKey.AppendKeyParts(providerType);

            return(cacheKey);
        }
        /// <summary>
        /// Gets all the available product lookups.
        /// </summary>
        /// <returns></returns>
        public virtual Task <List <Lookup> > GetLookupsAsync()
        {
            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Lookup);

            cacheKey.AppendKeyParts("productlookups");

            // the request type uniquely identifies what type of lookup is being searched
            var request = new GetProductLookupsRequest();

            //removed await because there is no logic after return from the call
            return(_cacheProvider.GetOrAddAsync(cacheKey, () => _overtureClient.SendAsync(request)));
        }
        public virtual async Task DeleteAddressAsync(Guid addressId)
        {
            var request = new RemoveAddressRequest
            {
                AddressId = addressId
            };

            await OvertureClient.SendAsync(request).ConfigureAwait(false);

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Address);

            cacheKey.AppendKeyParts(addressId);
            CacheProvider.Remove(cacheKey);
        }
        public Task <Lookup> GetLookupAsync(string name)
        {
            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Lookup);

            cacheKey.AppendKeyParts(name);

            // the request type uniquely identifies what type of lookup is being searched
            var request = new GetOrderLookupRequest {
                LookupName = name
            };

            //removed await because there is no logic after return from the call
            return(_cacheProvider.GetOrAddAsync(cacheKey, () => _overtureClient.SendAsync(request)));
        }
Exemple #16
0
        /// <summary>
        /// Search  Customers by email
        /// </summary>
        /// <param name="getCustomerByEmailParam">The Repository call params <see cref="GetCustomerByEmailParam"/></param>
        /// <returns>
        /// The Customer matching the requested Email, or null
        /// </returns>
        public virtual Task <CustomerQueryResult> GetCustomerByEmailAsync(GetCustomerByEmailParam getCustomerByEmailParam)
        {
            if (getCustomerByEmailParam == null)
            {
                throw new ArgumentNullException(nameof(getCustomerByEmailParam));
            }
            if (getCustomerByEmailParam.CultureInfo == null)
            {
                throw new ArgumentException(nameof(getCustomerByEmailParam.CultureInfo));
            }
            if (string.IsNullOrWhiteSpace(getCustomerByEmailParam.Scope))
            {
                throw new ArgumentException(nameof(getCustomerByEmailParam.Scope));
            }
            if (string.IsNullOrWhiteSpace(getCustomerByEmailParam.Email))
            {
                throw new ArgumentException(nameof(getCustomerByEmailParam.Email));
            }

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Customer + "Search")
            {
                Scope       = getCustomerByEmailParam.Scope,
                CultureInfo = getCustomerByEmailParam.CultureInfo,
            };

            cacheKey.AppendKeyParts(getCustomerByEmailParam.Email);

            var request = new FindCustomersRequest
            {
                SearchTerms     = getCustomerByEmailParam.Email,
                FilteringScopes = getCustomerByEmailParam.Scope,
                ScopeId         = getCustomerByEmailParam.Scope,
                Query           = new Query
                {
                    IncludeTotalCount = true,
                    Sortings          = new List <QuerySorting>
                    {
                        new QuerySorting {
                            PropertyName = "AccountStatus", Direction = SortDirection.Ascending
                        },
                        new QuerySorting {
                            PropertyName = "LastActivityDate", Direction = SortDirection.Descending
                        }
                    }
                }
            };

            return(CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(request)));
        }
Exemple #17
0
        protected virtual async Task <List <CustomProfile> > GetExtraStoresInfoAsync(List <Guid> storesIds, GetStoresParam getStoresParam)
        {
            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Store)
            {
                Scope = getStoresParam.Scope
            };

            cacheKey.AppendKeyParts(GETEXSTRASTORESINFO_CACHE_KEYPART);

            var request = new GetProfileInstancesRequest
            {
                Ids            = storesIds,
                EntityTypeName = "Store",
                ScopeId        = getStoresParam.Scope
            };

            return(await CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(request)).ConfigureAwait(false));
        }
Exemple #18
0
        /// <summary>
        /// Gets a single Address based on it's unique identifier
        /// </summary>
        /// <param name="addressId">The unique Id for the address to find</param>
        /// <returns>
        /// The Address matching the requested ID, or null
        /// </returns>
        public Task <Address> GetAddressByIdAsync(Guid addressId)
        {
            if (addressId == Guid.Empty)
            {
                throw new ArgumentNullException("addressId");
            }

            var request = new GetAddressRequest
            {
                AddressId = addressId
            };

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Address);

            cacheKey.AppendKeyParts(addressId);

            return(CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(request)));
        }
        /// <summary>
        /// Gets a product.
        /// </summary>
        /// <param name="param">The parameter.</param>
        /// <returns>
        /// Instance of <see cref="Orckestra.Overture.ServiceModel.Products.Product" />.
        /// </returns>
        /// <exception cref="System.ArgumentNullException">param</exception>
        /// <exception cref="System.ArgumentException"></exception>
        public virtual async Task <Overture.ServiceModel.Products.Product> GetProductAsync(GetProductParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException("param");
            }

            if (string.IsNullOrWhiteSpace(param.Scope))
            {
                throw new ArgumentException("param.Scope must not be null or whitespace.", "param");
            }

            if (string.IsNullOrWhiteSpace(param.ProductId))
            {
                throw new ArgumentException("param.ProductId must not be null or whitespace.", "param");
            }

            var productCacheKey = new CacheKey(CacheConfigurationCategoryNames.Product)
            {
                Scope = param.Scope,
            };

            productCacheKey.AppendKeyParts(param.ProductId);

            var result = await CacheProvider.GetOrAddAsync(productCacheKey, () =>
            {
                var request = new GetProductV2Request
                {
                    //get all cultures to avoid reloading product page to retrieve new product details
                    CultureName          = string.Empty,
                    IncludePriceLists    = false,
                    IncludeRelationships = true,
                    IncludeVariants      = true,
                    ProductId            = param.ProductId,
                    ScopeId         = param.Scope,
                    IncludeMedia    = true,
                    IncludeImageUrl = true
                };

                return(OvertureClient.SendAsync(request));
            }).ConfigureAwait(false);

            return(param.ReturnInactive || (result?.Active ?? false) ? result : null);
        }
        public virtual async Task <Address> UpdateAddressAsync(Guid customerId, Address address)
        {
            var request = new UpdateAddressRequest(address)
            {
                RelatedEntityId   = customerId.ToString(),
                RelatedEntityType = "Customer"
            };

            var result = await OvertureClient.SendAsync(request).ConfigureAwait(false);

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Address);

            cacheKey.AppendKeyParts(result.Id);
            //3.8 upgrade
            //CacheProvider.Replace(cacheKey, result);
            await CacheProvider.SetAsync(cacheKey, result).ConfigureAwait(false);

            return(result);
        }
Exemple #21
0
        public virtual Dictionary <int, CheckoutStepPageInfo> GetCheckoutStepPageInfos(BaseUrlParameter parameters)
        {
            CacheKey cacheKey = new CacheKey(CacheConfigurationCategoryNames.CheckoutStepUrls)
            {
                CultureInfo = parameters.CultureInfo
            };

            cacheKey.AppendKeyParts(WebsiteContext.WebsiteId.ToString());

            Dictionary <int, CheckoutStepPageInfo> stepUrls = CacheProvider.Get <Dictionary <int, CheckoutStepPageInfo> >(cacheKey);

            if (stepUrls != null)
            {
                return(stepUrls);
            }

            stepUrls = new Dictionary <int, CheckoutStepPageInfo>();

            var items    = PageService.GetCheckoutStepPages(WebsiteContext.WebsiteId, parameters.CultureInfo);
            var navItems = PageService.GetCheckoutNavigationPages(WebsiteContext.WebsiteId, parameters.CultureInfo);
            var index    = 0;

            foreach (var checkoutStepItem in items)
            {
                var pageGuid = Guid.Parse(checkoutStepItem);
                stepUrls.Add(index, new CheckoutStepPageInfo
                {
                    Url = PageService.GetPageUrl(pageGuid, parameters.CultureInfo),
                    IsDisplayedInHeader = navItems != null && navItems.Contains(checkoutStepItem),
                    Title  = PageService.GetPage(pageGuid, parameters.CultureInfo).MenuTitle,
                    PageId = pageGuid
                });
                index++;
            }

            stepUrls = stepUrls.OrderBy(x => x.Key).ToDictionary(x => x.Key, y => y.Value);

            CacheProvider.Set(cacheKey, stepUrls);

            return(stepUrls);
        }
        public virtual async Task <Address> CreateAddressAsync(Guid customerId, Address address, string scope)
        {
            //TODO: We can get rid of the await by using the extension method ExecuteAndSet on CacheProvider.

            var request = new AddAddressToCustomerRequest(customerId, address, scope);

            //TODO: Remove this when the bug #3694 is fixed:
            //TODO: [Blocker SEG #2879] When adding a new address in CheckOut > set as default does not work
            request.IsPreferredBilling  = address.IsPreferredBilling || address.IsPreferredShipping;
            request.IsPreferredShipping = address.IsPreferredShipping || address.IsPreferredShipping;

            var result = await OvertureClient.SendAsync(request).ConfigureAwait(false);

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Address);

            cacheKey.AppendKeyParts(result.Id);
            //3.8 upgrade
            //CacheProvider.Add(cacheKey, result);
            await CacheProvider.SetAsync(cacheKey, result).ConfigureAwait(false);

            return(result);
        }
        /// <summary>
        /// Retrieve the Product Settings from Overture
        /// </summary>
        /// <param name="scope"></param>
        /// <returns></returns>
        public virtual async Task <ProductSettings> GetProductSettings(string scope)
        {
            if (string.IsNullOrWhiteSpace(scope))
            {
                throw new ArgumentException("scope");
            }

            var productSettingsCacheKey = new CacheKey(CacheConfigurationCategoryNames.ProductSettings);

            productSettingsCacheKey.AppendKeyParts(scope);

            var result = await CacheProvider.GetOrAddAsync(productSettingsCacheKey, () =>
            {
                var request = new GetProductSettingsRequest
                {
                    ScopeId = scope
                };

                return(OvertureClient.SendAsync(request));
            }).ConfigureAwait(false);

            return(result);
        }
Exemple #24
0
        /// <summary>
        /// Gets a single Customer based on it's unique identifier
        /// </summary>
        /// <getCustomerByIdParam name="getCustomerByIdParam">The Repository call params <see cref="GetCustomerByIdParam"/></getCustomerByIdParam>
        /// <returns>
        /// The Customer matching the requested ID, or null
        /// </returns>
        public virtual Task <Customer> GetCustomerByIdAsync(GetCustomerByIdParam getCustomerByIdParam)
        {
            if (getCustomerByIdParam == null)
            {
                throw new ArgumentNullException(nameof(getCustomerByIdParam));
            }
            if (getCustomerByIdParam.CultureInfo == null)
            {
                throw new ArgumentException(GetMessageOfNull(nameof(getCustomerByIdParam.CultureInfo)), nameof(getCustomerByIdParam));
            }
            if (string.IsNullOrWhiteSpace(getCustomerByIdParam.Scope))
            {
                throw new ArgumentException(GetMessageOfNullWhiteSpace(nameof(getCustomerByIdParam.Scope)), nameof(getCustomerByIdParam));
            }
            if (getCustomerByIdParam.CustomerId == Guid.Empty)
            {
                throw new ArgumentException(GetMessageOfEmpty(nameof(getCustomerByIdParam.CustomerId)), nameof(getCustomerByIdParam));
            }

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Customer)
            {
                Scope       = getCustomerByIdParam.Scope,
                CultureInfo = getCustomerByIdParam.CultureInfo,
            };

            cacheKey.AppendKeyParts(getCustomerByIdParam.CustomerId);

            var getCustomerByUsernameRequest = new GetCustomerRequest
            {
                IncludeAddresses = getCustomerByIdParam.IncludeAddresses,
                ScopeId          = getCustomerByIdParam.Scope,
                CustomerId       = getCustomerByIdParam.CustomerId,
            };

            return(CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(getCustomerByUsernameRequest)));
        }
        public virtual async Task <ProductDefinition> GetProductDefinitionAsync(GetProductDefinitionParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException("param");
            }

            var productDefinitionCacheKey = new CacheKey(CacheConfigurationCategoryNames.ProductDefinition);

            productDefinitionCacheKey.AppendKeyParts(param.Name);

            var result = await CacheProvider.GetOrAddAsync(productDefinitionCacheKey, () =>
            {
                var request = new GetProductDefinitionRequest
                {
                    Name        = param.Name,
                    CultureName = param.CultureInfo.Name
                };

                return(OvertureClient.SendAsync(request));
            }).ConfigureAwait(false);

            return(result);
        }
        /// <summary>
        /// Retrieve a country using its ISO code
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public async Task <Overture.ServiceModel.Country> RetrieveCountry(RetrieveCountryParam param)
        {
            if (string.IsNullOrWhiteSpace(param.IsoCode))
            {
                throw new ArgumentException(GetMessageOfNullWhiteSpace(nameof(param.IsoCode)), nameof(param));
            }

            var countryCacheKey = new CacheKey(CacheConfigurationCategoryNames.Country);

            countryCacheKey.AppendKeyParts(param.IsoCode);

            var result = await _cacheProvider.GetOrAddAsync(countryCacheKey, () =>
            {
                var request = new GetCountryRequest
                {
                    CountryIsoCode = param.IsoCode,
                    IncludeRegions = true
                };

                return(_overtureClient.SendAsync(request));
            }).ConfigureAwait(false);

            return(result);
        }
Exemple #27
0
        public virtual async Task <FindStoresQueryResult> GetStoresAsync(GetStoresParam param)
        {
            if (param == null)
            {
                throw new ArgumentNullException(nameof(param));
            }
            if (param.CultureInfo == null)
            {
                throw new ArgumentException(GetMessageOfNull(nameof(param.CultureInfo)), nameof(param));
            }
            if (string.IsNullOrWhiteSpace(param.Scope))
            {
                throw new ArgumentException(GetMessageOfNullWhiteSpace(nameof(param.Scope)), nameof(param));
            }

            var cacheKey = new CacheKey(CacheConfigurationCategoryNames.Store)
            {
                Scope = param.Scope
            };

            cacheKey.AppendKeyParts(GETSTORES_CACHE_KEYPART);

            var request = new FindStoresRequest
            {
                ScopeId            = param.Scope,
                IncludeChildScopes = true,
                CultureName        = param.CultureInfo.Name,
                Query = new Query
                {
                    StartingIndex     = 0,
                    MaximumItems      = int.MaxValue,
                    IncludeTotalCount = false,
                    Filter            = new FilterGroup
                    {
                        Filters = GetStoreFilters()
                    }
                }
            };

            var stores = await CacheProvider.GetOrAddAsync(cacheKey, () => OvertureClient.SendAsync(request)).ConfigureAwait(false);

            // TODO: Remove this as soon as the FindStoresRequest returns localized display names.
            if (stores.Results.Any(s => s.DisplayName != null))
            {
                return(stores);
            }
            // Try get DisplayNames
            if (param.IncludeExtraInfo)
            {
                var ids             = stores.Results.Select(x => x.Id).ToList();
                var extraStoresInfo = await GetExtraStoresInfoAsync(ids, param).ConfigureAwait(false);

                extraStoresInfo?.ForEach(extraStoreInfo => {
                    extraStoreInfo.PropertyBag.TryGetValue("DisplayName", out object displayName);
                    if (displayName == null)
                    {
                        return;
                    }

                    var store = stores.Results.FirstOrDefault(st => st.Id == extraStoreInfo.Id);
                    if (store == null)
                    {
                        return;
                    }
                    store.DisplayName = displayName as Overture.ServiceModel.LocalizedString;
                });
            }

            return(stores);
        }