private void AddPrices(ISearchDocument document, IEnumerable <EntryContentBase> skuEntries) { var prices = _priceService.GetCatalogEntryPrices(skuEntries.Select(x => new CatalogKey(x.Code))).ToList(); var validPrices = prices.Where(x => x.ValidFrom <= DateTime.Now && (x.ValidUntil == null || x.ValidUntil >= DateTime.Now)); foreach (var marketPrices in validPrices.GroupBy(x => x.MarketId)) { foreach (var currencyPrices in marketPrices.GroupBy(x => x.UnitPrice.Currency)) { var topPrice = currencyPrices.OrderByDescending(x => x.UnitPrice).FirstOrDefault(); if (topPrice == null) { continue; } var variationPrice = new SearchField(IndexingHelper.GetOriginalPriceField(topPrice.MarketId, topPrice.UnitPrice.Currency), topPrice.UnitPrice.Amount); var discountedPrice = new SearchField(IndexingHelper.GetPriceField(topPrice.MarketId, topPrice.UnitPrice.Currency), _promotionService.GetDiscountPrice(topPrice.CatalogKey, topPrice.MarketId, topPrice.UnitPrice.Currency).UnitPrice.Amount); document.Add(variationPrice); document.Add(discountedPrice); } } }
private void AddPrices(RestSearchDocument document, IEnumerable <CatalogKey> catalogKeys) { var prices = _priceService.GetCatalogEntryPrices(catalogKeys).ToList(); var validPrices = prices.Where(x => x.ValidFrom <= DateTime.Now && (x.ValidUntil == null || x.ValidUntil >= DateTime.Now)); foreach (var marketPrices in validPrices.GroupBy(x => x.MarketId)) { foreach (var currencyPrices in marketPrices.GroupBy(x => x.UnitPrice.Currency)) { var topPrice = currencyPrices.OrderByDescending(x => x.UnitPrice).FirstOrDefault(); if (topPrice == null) { continue; } var variationPrice = new RestSearchField(IndexingHelper.GetOriginalPriceField(topPrice.MarketId, topPrice.UnitPrice.Currency), topPrice.UnitPrice.Amount.ToString(CultureInfo.InvariantCulture), true); var discountedPrice = new RestSearchField(IndexingHelper.GetPriceField(topPrice.MarketId, topPrice.UnitPrice.Currency), _promotionService.GetDiscountPrice(topPrice.CatalogKey, topPrice.MarketId, topPrice.UnitPrice.Currency).UnitPrice.Amount.ToString(CultureInfo.InvariantCulture), true); document.Fields.Add(variationPrice); document.Fields.Add(discountedPrice); } } }
public static IEnumerable <IPriceValue> Prices(this ProductContent productContent, IPriceService priceService) { List <VariationContent> variants = productContent.VariationContents().ToList(); return (priceService.GetCatalogEntryPrices( variants.Select(x => new CatalogKey(x.Code))).ToList()); }
public object Get(string code) { CatalogKey key = new CatalogKey(AppContext.Current.ApplicationId, code); IPriceService priceService = ServiceLocator.Current.GetInstance <IPriceService>(); IPriceDetailService priceDetailService = ServiceLocator.Current.GetInstance <IPriceDetailService>(); IEnumerable <IPriceValue> catalogEntryPrices = priceService.GetCatalogEntryPrices(key); return(catalogEntryPrices); }
protected void SetPrices(string code, List <Price> prices) { if (code == null) { throw new ArgumentNullException("code"); } if (prices == null) { return; } CatalogKey key = new CatalogKey(Mediachase.Commerce.Core.AppContext.Current.ApplicationId, code); var catalogEntryPrices = _priceService.GetCatalogEntryPrices(key); //.ToList(); List <IPriceValue> priceValues = new List <IPriceValue>(catalogEntryPrices); foreach (Price price in prices) { // Already there? IPriceValue priceValue = priceValues.FirstOrDefault(p => p.MarketId.Value == price.marketId); if (priceValue == null) { // No - add it PriceValue newPrice = new PriceValue() { CatalogKey = key, MarketId = price.marketId, UnitPrice = new Money(price.price, new Currency(price.currency)), ValidFrom = DateTime.Now, CustomerPricing = CustomerPricing.AllCustomers, MinQuantity = 0 }; priceValues.Add(newPrice); } else { // We don't touch prices for the same market } } _log.Debug("Saving {0} prices for {1}", priceValues.Count, code); // Save prices back _priceService.SetCatalogEntryPrices(key, priceValues); }
private void BuildPrices(FindDocument document, CatalogEntryDto.CatalogEntryRow entryRow, ISearchConfiguration configuration) { IPriceService instance = ServiceLocator.Current.GetInstance <IPriceService>(); CatalogKey catalogKey = new CatalogKey(entryRow); HashSet <Mediachase.Commerce.Currency> source1 = new HashSet <Mediachase.Commerce.Currency>(); HashSet <MarketId> source2 = new HashSet <MarketId>(); IFieldConfiguration <double?> field = null; foreach (IPriceValue catalogEntryPrice in instance.GetCatalogEntryPrices(catalogKey)) { HashSet <Mediachase.Commerce.Currency> currencySet = source1; Money unitPrice = catalogEntryPrice.UnitPrice; Mediachase.Commerce.Currency currency1 = unitPrice.Currency; if (currencySet.Add(currency1)) { ISearchConfiguration searchConfiguration = configuration; unitPrice = catalogEntryPrice.UnitPrice; Mediachase.Commerce.Currency currency2 = unitPrice.Currency; searchConfiguration.AddCurrency(currency2); } if (source2.Add(catalogEntryPrice.MarketId)) { configuration.AddMarket(catalogEntryPrice.MarketId); } ISearchConfiguration searchConfiguration1 = configuration; string name = "saleprice"; unitPrice = catalogEntryPrice.UnitPrice; Mediachase.Commerce.Currency currencyCode = (Mediachase.Commerce.Currency)unitPrice.Currency.CurrencyCode; MarketId marketId = (MarketId)catalogEntryPrice.MarketId.Value; ref IFieldConfiguration <double?> local = ref field; if (searchConfiguration1.TryGetPriceField(name, currencyCode, marketId, out local)) { unitPrice = catalogEntryPrice.UnitPrice; double amount = (double)unitPrice.Amount; double?nullable = field.GetValue(document); if (!nullable.HasValue || nullable.Value > amount) { field.SetValue(document, new double?(amount)); } } }
/// <summary> /// Get the previous price. Example of usage: Was 1000 now 800. /// </summary> /// <param name="priceService"></param> /// <param name="contentLink"></param> /// <param name="marketId"></param> /// <param name="currency"></param> /// <returns></returns> public static IPriceValue GetPreviousPrice(this IPriceService priceService, ContentReference contentLink, MarketId marketId, Currency currency) { var entryContent = _contentRepository.Service.Get <EntryContentBase>(contentLink); var catalogKey = new CatalogKey(entryContent.Code); var prices = priceService.GetCatalogEntryPrices(catalogKey).ToList(); var previousPrice = prices .FirstOrDefault( p => p.MarketId == marketId && p.UnitPrice.Currency == currency && p.ValidUntil.HasValue && p.ValidUntil.Value < DateTime.UtcNow); var currentPrice = prices .FirstOrDefault( p => p.MarketId == marketId && p.UnitPrice.Currency == currency && p.ValidFrom < DateTime.UtcNow && (!p.ValidUntil.HasValue || p.ValidUntil.Value > DateTime.UtcNow)); return(previousPrice?.UnitPrice.Amount < currentPrice?.UnitPrice.Amount ? previousPrice : currentPrice); }
public IEnumerable <IPriceValue> GetCatalogEntryPrices(IEnumerable <CatalogKey> catalogKeys) { return(_priceService.GetCatalogEntryPrices(catalogKeys)); }
// Demo - Fund public void CheckPrices(EntryContentBase CurrentContent) { // Pricing, a long story with many alternative /* * Two services are available for interacting with price data. * - The IPriceService API is typically used by order processing to fetch prices for actual use * - IPriceDetailService is typically used in "integration" and interface/code for display (all prices) and edit prices. * * The difference between these APIs is that the IPriceService works with optimized sets of price data, * while the IPriceDetailService works with "the truth". * The optimization in the IPriceService * removes prices that will cannot be used, and trims or splits prices that overlap. */ #region StoreHelper...does this /*Steps in StoreHelper * * Check CurrentMarket * Add AllCustomers * Add PriceType.USerName (IPrincipal) * Check Cust-Group, add ...Effiective-Cust-Group * Get the service * Set the filter * Fetch ... priceService.GetPrices + get the cheapest (note: always cheapest we want) * Get a ... IPriceValue and then... * ....return new Price(priceValue.UnitPrice); * * ...the one that does the job * public static Price GetSalePrice(Entry entry, decimal quantity, IMarket market, Currency currency) * */ #endregion // ... look in VariantController for nice extensions #region GetDefaultPrice...does this /* * Could have a look at .GetDefaultPrice in Reflector * PricingExtensions (EPiServer.Commerce.Catalog.ContentTypes) * - GetDefaultPrice() // gets the R/O-loader * - tries to figure out the Currency * - tries to figure out Market, DateTime, CatalogKey... and does... * - IPriceValue GetDefaultPrice(MarketId market, DateTime validOn, CatalogKey catalogKey, Currency currency); * ...goes to the concrete impl. för the R/O-provider and in there...creates a PriceFilter * ....and gets a "default price" for a catalog entry. The "default price" for a * ....market, currency, and catalog entry is the price available to * "all customers" at a minimum quantity of 0. * ...that in turn goes to the Provider and say GetPrices() ... with all the stuff found */ #endregion // PriceDetails ... administrative stuff, don´t use for retrieving prices for the web // 3 overloads... the 3:rd with filter & Market List <IPriceDetailValue> priceList1 = _priceDetailService.List(CurrentContent.ContentLink).ToList(); Price ppp = new Price(priceList1.First()); // this price class takes a IPriceValue in .ctor (there are 3 different Price-classes) Price aPrice = new Price(priceList1.FirstOrDefault()); // just checking // ...have a CreatePrice("theCode"); // further below /* dbo.PriceType.sql * 0 All Customers * 1 Customer * 2 Customer Price Group * ...can add custom PriceTypes */ // PriceDetail - "R/W" // PriceValue, PriceGroup - "R/O" (...but it´s not, did write to it) // Replicate...changes between the two services // !! Note: don't get it by the ServiceLocator, use injected or .ctor-injection !! // DB-side paging, GetPrices() takes start-count, is R/O ... it´s a Loader PricingLoader detailedPricingLoader = ServiceLocator.Current.GetInstance <PricingLoader>(); // detailedPricingLoader.GetPrices() // Good set of methods, no paging (GetChildrenPrices-obsoleted), gets allmost all ReadOnlyPricingLoader readOnlyPricingLoader = ServiceLocator.Current.GetInstance <ReadOnlyPricingLoader>(); // detailedPricingLoader. as the service //readOnlyPricingLoader.GetChildrenPrices(...) // deprecated var p = readOnlyPricingLoader.GetDefaultPrice(CurrentContent.ContentLink); // could use this "loader" on the front-end...instead of the service // PriceService R/O-pricing ("the optimized service" (from the good old R3-era ´:`)) // ... that´s why we have some confusing stuff left in the system (it entered here before the "Content-Model" was in place) CatalogKey catKey = new CatalogKey(CurrentContent.Code); // Catalogkey... example of legacy // Note: CatalogKey is gone when using the new Inventory system. There you can go by "code" // ...will probably file a blemish-bug on this // return full sets of price data for the specified catalog entries? // ...also takes an Enumerable var pricesByKey = _priceService.GetCatalogEntryPrices(catKey); // need catalogKey ( or IEnumerable of those ) var priceByDefault = _priceService.GetDefaultPrice( // Market, time, CatKey & Currency currentMarket.Service.GetCurrentMarket().MarketId.Value , DateTime.UtcNow , catKey , new Currency("usd")); //priceService.GetPrices( //...3:rd overload takes an IEnumerable of CatalogKeyAndQuantity // The GetPrices methods return filtered data for the specified catalog entries. Returned price values // ...will match all specified The CatalogKeyAndQuantity class may be used to get prices // ...for multiple entries, with different quantities for each, in a single request // for the R/O-PriceService CatalogKeyAndQuantity keyAndQtyExample = new CatalogKeyAndQuantity(catKey, 12); // second as an IEnumerable of keys // third as an IEnumerable of "KeysAndQty" //_priceService.GetPrices(); // If custom built "Optimized"... // ...then need a mechanism for synchronizing with a custom detail service, then it must call // IPriceDetailService.ReplicatePriceServiceChanges on all edits to update the optimized data store #region ... not much of a demo - PrintToPage and Housekeeping //Response.Write("<br/>"); //Response.Write("ContentTypeID" + CurrentContent.ContentTypeID + "<br/>"); //Response.Write("PriceRef.ID: " + CurrentContent.PriceReference.ID + "<br/>"); //Response.Write("PriceDetails <br/>"); //p1.ForEach(p => Response.Write("UnitPrice: " + p.UnitPrice.Amount.ToString() + "<br/>")); //Response.Write("PriceValueId: " + p1.FirstOrDefault().PriceValueId + "<br/>"); //Response.Write("UnitPrice: " + p1.FirstOrDefault().UnitPrice.Amount.ToString() + "<br/>"); //Response.Write("<br/>"); //Response.Write("PriceService <br/>"); // + "<br/>" //p2.ToList().ForEach(p => Response.Write("UnitPrice: " + p.UnitPrice.Amount.ToString() + "<br/>")); //Response.Write("<br/>"); //// node //Response.Write("PriceList at ParentNode: " + contentLoader.Get<IContent>(CurrentContent.ParentLink).Name + "<br/>"); //List<IPriceDetailValue> listFromNode = priceDetails.List(CurrentContent.ParentLink).ToList(); //listFromNode.ForEach(nl => Response.Write( // "CatalogKey: " + nl.CatalogKey.CatalogEntryCode // + " :: " + // "UnitPrice: " + nl.UnitPrice.Amount.ToString() + "<br/>")); //Response.Write("<br/>"); // EPiServer.Commerce.Catalog.ContentTypes.PricingExtensions // ...getPrices() ... by the "ReadOnlyPricingLoader" // Below, get all prices //EPiServer.Commerce.SpecializedProperties.ItemCollection // <EPiServer.Commerce.SpecializedProperties.Price> // prices = CurrentContent.GetPrices(); // 5 overloads, the third takes "Market" and "CustomerPricing" //var pp = CurrentContent.GetPrices(MarketId.Default, new CustomerPricing(CustomerPricing.PriceType.PriceGroup, "SpecialFriends")); //// PriceType & PriceCode in API , SaleType & SaleCode in UI //// should have the qty here ... ? //Response.Write("By Extesion methods <br/>"); //prices.ToList().ForEach(p => Response.Write(p.UnitPrice.Amount + "<br/>")); //pp.ToList().ForEach(p => Response.Write("SpecialFriends: " + p.UnitPrice.Amount.ToString() + "<br/>")); #endregion /* Price Filter - good stuff */ List <Currency> currencies = new List <Currency>(); List <CustomerPricing> custprices = new List <CustomerPricing>(); // SaleCode (UI) or PriceGroup (code) (string) ... the Cust-Group // CM / CMS UI: SaleType - SaleCode // API: PriceType, PriceCode (string) PriceFilter filter = new PriceFilter() { Quantity = 2, Currencies = new Currency[] { "USD", "SEK" }, CustomerPricing = new CustomerPricing[] { new CustomerPricing(CustomerPricing.PriceType.AllCustomers, null), new CustomerPricing(CustomerPricing.PriceType.UserName, "Kalle"), new CustomerPricing(CustomerPricing.PriceType.PriceGroup, "MyBuddies") // or several... // may also want to add the personal account and/or custom price-types }, ReturnCustomerPricing = false // ...see below for info // interpretation of the CustomerPricing property... if true; gets all that applies }; #region Info ReturnCustomerPricing /* The ReturnCustomerPricing property controls the interpretation of the CustomerPricing property. * If the value of this property is false, and multiple price values that are identical except for the customer pricing * (but both match the prices targeted by the method call) could be returned, then only the entry in that grouping with * the lowest price will be returned (this is the more common use case). If the value of this property is true, * then all prices will be returned individually. The default value is false. As an example, * suppose a catalog entry has a price of $10.00 for all customers, and $9.00 for one particular customer. * A call to a GetPrices method that would match both prices, and has ReturnCustomerPricing set to false, * would only get the $9.00 price in the result set. If ReturnCustomerPricing was set to true for the same call, * both the $9.00 and $10.00 price would be returned. */ #endregion // The rest needed, CatKey, Market, TimeStamp CatalogKey catalogKey = new CatalogKey(CurrentContent.Code); // 4 overloads App-ID is gone IEnumerable <IPriceValue> priceValues = _priceService.GetPrices( // overloaded - one or more CatKey or CatalogKeyAndQuantity MarketId.Default, FrameworkContext.Current.CurrentDateTime , catalogKey, filter); Price pp = new Price(priceValues.First()); PriceValue pv2 = new PriceValue(priceValues.First()); // ppp is a Price (above), created from an IPriceDetailValue IPriceValue PV3 = ppp.ToPriceValue(); // // just checking decimal onePrice = priceValues.FirstOrDefault().UnitPrice.Amount; }
// Demo - Fund public void CheckPrices(EntryContentBase CurrentContent) { // Pricing, a long story with many alternative /* * Two services are available for interacting with price data. * - The IPriceService API is typically used by order processing to fetch prices for actual use * - IPriceDetailService is typically used in "integration" and interface/code for display (all prices) and edit prices. * * The difference between these APIs is that the IPriceService works with optimized sets of price data, * while the IPriceDetailService works with "the truth". * The optimization in the IPriceService * removes prices that will cannot be used, and trims or splits prices that overlap. */ #region StoreHelper...does this /*Steps in StoreHelper * * - Add AllCustomers * Check Cust-Group * ...Effective-Cust-Group * Get the service * Set the filter * Fetch ... priceService.GetPrices + get the cheapest (note: always cheapest) * Get a ... IPriceValue and then... * ....return new Price(priceValue.UnitPrice); * * public static Price GetSalePrice(Entry entry, decimal quantity, IMarket market, Currency currency) * */ #endregion // ... look in VariantController for nice extensions #region GetDefaultPrice...does this /* * Could have a look at .GetDefaultPrice in Reflector * PricingExtensions (EPiServer.Commerce.Catalog.ContentTypes) * - GetDefaultPrice() // gets the R/O-loader * * - tries to figure out the Currency * - tries to figure out Market, DateTime, CatalogKey... and does... * - IPriceValue GetDefaultPrice(MarketId market, DateTime validOn, CatalogKey catalogKey, Currency currency); * ...goes to the concrete impl. för the R/O-provider and creates a PriceFilter * ....and gets a "default price" for a catalog entry. The "default price" for a * ....market, currency, and catalog entry is the price available to * "all customers" at a minimum quantity of 0. * ...that in turn goes to the Provider and say GetPrices() ... with all the stuff found */ #endregion // PriceDetails ... administrative stuff, don´t use for retrieving prices for the store // 3 overloads... the 3:rd with filter & Market List <IPriceDetailValue> priceList1 = _priceDetailService.List(CurrentContent.ContentLink).ToList(); EPiServer.Commerce.SpecializedProperties.Price aPrice = new EPiServer.Commerce.SpecializedProperties.Price(priceList1.FirstOrDefault()); // just checking // ...have a CreatePrice("theCode"); // further below /* dbo.PriceType.sql * 0 All Customers * 1 Customer * 2 Customer Price Group */ // DB-side paging, GetPrices() takes start-count, is R/O ... it´s a Loader PricingLoader detailedPricingLoader = ServiceLocator.Current.GetInstance <PricingLoader>(); // detailedPricingLoader.GetPrices() // Good set of methods, no paging (GetChildrenPrices-obsoleted), gets it all ReadOnlyPricingLoader readOnlyPricingLoader = ServiceLocator.Current.GetInstance <ReadOnlyPricingLoader>(); // detailedPricingLoader. as the service var p = readOnlyPricingLoader.GetDefaultPrice(CurrentContent.ContentLink); // use this "loader" on the front-end...instead of the service // PriceService R/O-pricing ("the optimized service" (from the good old R3-era ´:`)) // ... that´s why we have some confusing stuff left in the system (it entered here before the "Content-Model" was in place) CatalogKey catKey = new CatalogKey(CurrentContent.Code); // Catalogkey... example of legacy // return full sets of price data for the specified catalog entries? // ...also takes an Enumerable var pricesByKey = _priceService.GetCatalogEntryPrices(catKey); // need catalogKey ( or IEnumerable of those ) var priceByDefault = _priceService.GetDefaultPrice( // Market, time, CatKey & Currency currentMarket.Service.GetCurrentMarket().MarketId // ...better than MarketId.Default , DateTime.UtcNow , catKey , new Currency("usd")); CatalogKeyAndQuantity keyAndQtyExample = new CatalogKeyAndQuantity(catKey, 12); // first overload as GetDefaultPrice // second as an IEnumerable of keys // third as an IEnumerable of keysAndQty // If custom built "Optimized"... // ...then need a mechanism for synchronizing with a custom detail service, then it must call // IPriceDetailService.ReplicatePriceServiceChanges on all edits to update the optimized data store /* Price Filter */ List <Currency> currencies = new List <Currency>(); List <CustomerPricing> custprices = new List <CustomerPricing>(); // SaleCode (UI) or PriceGroup (code) (string) ... the Cust-Group // CM / CMS UI: SaleType - SaleCode // API: PriceType, PriceCode (string) PriceFilter filter = new PriceFilter() { Quantity = 2M, Currencies = new Currency[] { "USD", "SEK" }, CustomerPricing = new CustomerPricing[] { new CustomerPricing(CustomerPricing.PriceType.AllCustomers, null), new CustomerPricing(CustomerPricing.PriceType.PriceGroup, "MyBuddies") // or several... }, ReturnCustomerPricing = true // ...see below for info // interpretation of the CustomerPricing property... if true; gets all that applies }; #region Info ReturnCustomerPricing /* The ReturnCustomerPricing property controls the interpretation of the CustomerPricing property. * If the value of this property is false, and multiple price values that are identical except for the customer pricing * (but both match the prices targeted by the method call) could be returned, then only the entry in that grouping with * the lowest price will be returned (this is the more common use case). If the value of this property is true, * then all prices will be returned individually. The default value is false. As an example, * suppose a catalog entry has a price of $10.00 for all customers, and $9.00 for one particular customer. * A call to a GetPrices method that would match both prices, and has ReturnCustomerPricing set to false, * would only get the $9.00 price in the result set. If ReturnCustomerPricing was set to true for the same call, * both the $9.00 and $10.00 price would be returned. */ #endregion // The rest needed, CatKey, Market, TimeStamp CatalogKey catalogKey = new CatalogKey(CurrentContent.Code); // 2 useful overloads IEnumerable <IPriceValue> priceValues = _priceService.GetPrices( MarketId.Default, FrameworkContext.Current.CurrentDateTime, catalogKey, filter); decimal onePrice = priceValues.FirstOrDefault().UnitPrice.Amount; // just checking }
public IEnumerable <IPriceValue> GetThePrices() { return(_priceService.GetCatalogEntryPrices(MyCatalogKey)); }