public void MerketingSystem_BuyXGetNoffYatReducedPrice() { PromotionEntriesSet sourceSet = new PromotionEntriesSet(); PromotionEntriesSet targetSet = new PromotionEntriesSet(); PromotionEntry itemY1 = new PromotionEntry("", "Apple iPod touch 16 GB (Old)", "ELCB000JNYWBG6", 100); PromotionEntry itemY2 = new PromotionEntry("", "Apple iPod touch 16 GB (Old)", "ELCB000JNYWBG6", 100); itemY2.Quantity = 10; PromotionEntry itemXspecified = new PromotionEntry("", "Plantronics Voyager 510 - Bluetooth Headset Carrying Case", "ELCB000FOM68A6", 100); PromotionEntry itemXnotspecified = new PromotionEntry("", "510 Headset Charger", "ELCB000GKLGX46", 100); PromotionFilter filter = new PromotionFilter(); filter.IgnoreConditions = false; //Exsist promotion //X promotion entry set is ELCB000PBOWNK6, ELCB000GKLGX46 //Exclude set to off //Y promotion entry is ELCB000JNYWBG6 //Max Y quantity is 3 //Amount 15 percent //First use case. X entry not contains in promotion X entry set itemXnotspecified.Quantity = 2; sourceSet.Entries.Add(itemXnotspecified); //Two Y entry one 1 quantity , other 10 quantity targetSet.Entries.Add(itemY1); targetSet.Entries.Add(itemY2); PromotionContext context = PrepareMarketingContext(sourceSet, targetSet); MarketingContext.Current.EvaluatePromotions(true, context, filter); Assert.IsTrue(context.PromotionResult.PromotionRecords.Count == 0); //Second use case. X entry contains in promotion X entry set sourceSet.Entries.Clear(); sourceSet.Entries.Add(itemXspecified); context = PrepareMarketingContext(sourceSet, targetSet); MarketingContext.Current.EvaluatePromotions(true, context, filter); Assert.IsTrue(context.PromotionResult.PromotionRecords.Count == 1); foreach (PromotionItemRecord record in context.PromotionResult.PromotionRecords) { Assert.IsTrue(record.AffectedEntriesSet.TotalQuantity == 3); Assert.IsTrue(record.PromotionReward.AmountOff == 15); } //Third use case. X entry empty. Y entry specified. First instanse of item Y becomes the eligible item X, and charged bu regular price sourceSet.Entries.Clear(); targetSet.Entries.Clear(); itemY1.Quantity = 3; targetSet.Entries.Add(itemY1); context = PrepareMarketingContext(sourceSet, targetSet); MarketingContext.Current.EvaluatePromotions(true, context, filter); Assert.IsTrue(context.PromotionResult.PromotionRecords.Count == 1); foreach (PromotionItemRecord record in context.PromotionResult.PromotionRecords) { Assert.IsTrue(record.AffectedEntriesSet.TotalQuantity == 2); Assert.IsTrue(record.PromotionReward.AmountOff == 15); } }
public IPriceValue GetDiscountPrice(IPriceValue price, EntryContentBase entry, Currency currency, PromotionHelperFacade promotionHelper) { var promotionEntry = CreatePromotionEntry(entry, price); var filter = new PromotionFilter { IgnoreConditions = false, IgnorePolicy = false, IgnoreSegments = false, IncludeCoupons = false }; var sourceSet = new PromotionEntriesSet(); sourceSet.Entries.Add(promotionEntry); var promotionContext = promotionHelper.Evaluate(filter, sourceSet, sourceSet, false); if (promotionContext.PromotionResult.PromotionRecords.Count > 0) { return new PriceValue { CatalogKey = price.CatalogKey, CustomerPricing = CustomerPricing.AllCustomers, MarketId = price.MarketId, MinQuantity = 1, UnitPrice = new Money(price.UnitPrice.Amount - GetDiscountPrice(promotionContext), currency), ValidFrom = DateTime.UtcNow, ValidUntil = null }; } return price; }
public IPriceValue GetDiscountPrice(IPriceValue price, EntryContentBase entry, Currency currency, PromotionHelperFacade promotionHelper) { var promotionEntry = CreatePromotionEntry(entry, price); var filter = new PromotionFilter { IgnoreConditions = false, IgnorePolicy = false, IgnoreSegments = false, IncludeCoupons = false }; var sourceSet = new PromotionEntriesSet(); sourceSet.Entries.Add(promotionEntry); var promotionContext = promotionHelper.Evaluate(filter, sourceSet, sourceSet, false); if (promotionContext.PromotionResult.PromotionRecords.Count > 0) { return(new PriceValue { CatalogKey = price.CatalogKey, CustomerPricing = CustomerPricing.AllCustomers, MarketId = price.MarketId, MinQuantity = 1, UnitPrice = new Money(price.UnitPrice.Amount - GetDiscountPrice(promotionContext), currency), ValidFrom = DateTime.UtcNow, ValidUntil = null }); } return(price); }
public void MerketingSystem_BuyXOffShipment_10PercentOff() { // three Promotion #1 - 10 MinQuantity, 5$ reward; // #2 - 20 MinQuantity, 10$ Reward; // #3 - 30 MinQuantity 15$ Reward. PromotionEntriesSet sourceSet = new PromotionEntriesSet(); PromotionEntry entry = new PromotionEntry("", "", "Plasma-EDTV", 100); entry.Quantity = 20; sourceSet.Entries.Add(entry); MarketingContext ctx = MarketingContext.Current; Assert.IsNotNull(ctx); Assert.IsNotNull(ctx.MarketingProfileContext); //IDictionary<string, object> ctx = new Dictionary<string, object>(); PromotionContext context = new PromotionContext(ctx.MarketingProfileContext, sourceSet, sourceSet); PromotionFilter filter = new PromotionFilter(); filter.IgnoreConditions = false; MarketingContext.Current.EvaluatePromotions(true, context, filter); foreach (PromotionItemRecord record in context.PromotionResult.PromotionRecords) { decimal amountOff = record.PromotionReward.AmountOff; // Validate promotion Assert.IsTrue(amountOff == 10); } }
public virtual PromotionContext Evaluate(PromotionFilter filter, PromotionEntriesSet sourceEntriesSet, PromotionEntriesSet targetEntriesSet, bool checkEntryLevelLimit) { var helper = new PromotionHelper(); helper.PromotionContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Entry).Key; helper.PromotionContext.SourceEntriesSet = sourceEntriesSet; helper.PromotionContext.TargetEntriesSet = targetEntriesSet; helper.Eval(filter, checkEntryLevelLimit); return helper.PromotionContext; }
public virtual PromotionContext Evaluate(PromotionFilter filter, PromotionEntriesSet sourceEntriesSet, PromotionEntriesSet targetEntriesSet, bool checkEntryLevelLimit) { var helper = new PromotionHelper(); helper.PromotionContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Entry).Key; helper.PromotionContext.SourceEntriesSet = sourceEntriesSet; helper.PromotionContext.TargetEntriesSet = targetEntriesSet; helper.Eval(filter, checkEntryLevelLimit); return(helper.PromotionContext); }
public IQueryable <PromotionEntity> Get(PromotionFilter filter) { var linq = base.Get(Filter(filter.DataStatus, null, filter.Timestamp, filter.RecommendUser, null, filter.FilterMode, null, filter.HasProduct)); if (filter.HasBanner != null && filter.HasBanner.Value) { var banners = ServiceLocator.Current.Resolve <IBannerRepository>() .Get(null, SourceType.Promotion, DataStatus.Normal); linq = linq.Join(banners, p => p.Id, f => f.SourceId, (p, f) => p); } return(linq); }
private static void PreparePromotion(PromotionHelper helper, Entry entry, bool checkEntryLevelDiscountLimit) { var currentMarket = CurrentMarket.Service.GetCurrentMarket(); decimal minQuantity = 1; // get min quantity attribute if (entry.ItemAttributes != null) { minQuantity = entry.ItemAttributes.MinQuantity; } // we can't pass qauntity of 0, so make it default to 1 if (minQuantity <= 0) { minQuantity = 1; } var price = StoreHelper.GetSalePrice(entry, minQuantity, currentMarket) ?? new Mediachase.Commerce.Catalog.Objects.Price(new Money(0, currentMarket.DefaultCurrency)); // Create filter var filter = new PromotionFilter() { IgnoreConditions = false, IgnorePolicy = false, IgnoreSegments = false, IncludeCoupons = false }; // Create new entry // TPB: catalogNodes is determined by the front end. GetParentNodes(entry) var result = new PromotionEntry(String.Empty, String.Empty, entry.ID, price.Money.Amount); var promotionEntryPopulateService = (IPromotionEntryPopulate)MarketingContext.Current.PromotionEntryPopulateFunctionClassInfo.CreateInstance(); promotionEntryPopulateService.Populate(result, entry, currentMarket.MarketId, currentMarket.DefaultCurrency); var sourceSet = new PromotionEntriesSet(); sourceSet.Entries.Add(result); // Only target entries helper.PromotionContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Entry).Key; // Configure promotion context helper.PromotionContext.SourceEntriesSet = sourceSet; helper.PromotionContext.TargetEntriesSet = sourceSet; // Execute the promotions and filter out basic collection of promotions, we need to execute with cache disabled, so we get latest info from the database helper.Eval(filter, checkEntryLevelDiscountLimit); }
/// <summary> /// Evals the specified filter with checkEntryLevelLimit /// </summary> /// <param name="filter"> The filter</param> /// <param name="checkEntryLevelLimit"> The check Entry Level Limit</param> public void Eval(PromotionFilter filter, bool checkEntryLevelLimit) { if (checkEntryLevelLimit) { Dictionary <PromotionDto.PromotionRow, decimal?> entryDiscountApplicationCount = new Dictionary <PromotionDto.PromotionRow, decimal?>(); PromotionDto promotionDto = PromotionManager.GetPromotionDto(FrameworkContext.Current.CurrentDateTime); foreach (PromotionDto.PromotionRow promotion in promotionDto.Promotion) { if (!promotion.IsMaxEntryDiscountQuantityNull()) { entryDiscountApplicationCount.Add(promotion, promotion.MaxEntryDiscountQuantity); } } MarketingContext.Current.EvaluatePromotions(true, this.PromotionContext, filter, entryDiscountApplicationCount, true); } else { Eval(filter); } }
public void MarketingSystem_BuyXGetXDiscount() { PromotionEntriesSet sourceSet = new PromotionEntriesSet(); sourceSet.Entries.Add(new PromotionEntry("", "", "42-Plasma-EDTV", 1)); MarketingContext ctx = MarketingContext.Current; Assert.IsNotNull(ctx); Assert.IsNotNull(ctx.MarketingProfileContext); //IDictionary<string, object> ctx = new Dictionary<string, object>(); PromotionContext context = new PromotionContext(ctx.MarketingProfileContext, sourceSet, sourceSet); PromotionFilter filter = new PromotionFilter(); filter.IgnoreConditions = false; MarketingContext.Current.EvaluatePromotions(true, context, filter); foreach (PromotionItemRecord record in context.PromotionResult.PromotionRecords) { // Validate promotion Assert.IsTrue(record.PromotionReward.AmountOff == 10); } }
public void MerketingSystem_OrderVolumePromotion_10PercentOff() { PromotionEntriesSet sourceSet = new PromotionEntriesSet(); //Add entry totalCost equals 2000 sourceSet.Entries.Add(new PromotionEntry("", "", "42-Plasma-EDTV", 2000)); MarketingContext ctx = MarketingContext.Current; Assert.IsNotNull(ctx); Assert.IsNotNull(ctx.MarketingProfileContext); //IDictionary<string, object> ctx = new Dictionary<string, object>(); PromotionContext context = new PromotionContext(ctx.MarketingProfileContext, sourceSet, sourceSet); PromotionFilter filter = new PromotionFilter(); filter.IgnoreConditions = false; MarketingContext.Current.EvaluatePromotions(true, context, filter); foreach (PromotionItemRecord record in context.PromotionResult.PromotionRecords) { decimal amountOff = record.PromotionReward.AmountOff; // Validate promotion Assert.IsTrue(amountOff == 10); } }
public override PromotionContext Evaluate(PromotionFilter filter, PromotionEntriesSet sourceEntriesSet, PromotionEntriesSet targetEntriesSet, bool checkEntryLevelLimit) { return null; }
/// <summary> /// Gets the discount price by evaluating the discount rules and taking into account segments customer belongs to. /// </summary> /// <param name="entry">The entry.</param> /// <param name="catalogName">Name of the catalog.</param> /// <returns></returns> public static Price GetDiscountPrice(Entry entry, string catalogName) { if (entry == null) { throw new NullReferenceException("entry can't be null"); } decimal minQuantity = 1; // get min quantity attribute if (entry.ItemAttributes != null) { minQuantity = entry.ItemAttributes.MinQuantity; } // we can't pass qauntity of 0, so make it default to 1 if (minQuantity <= 0) { minQuantity = 1; } // Get sale price for the current user Price price = StoreHelper.GetSalePrice(entry, minQuantity); // Create new promotion helper, which will initialize PromotionContext object for us and setup context dictionary PromotionHelper helper = new PromotionHelper(); // Get current context Dictionary <string, object> context = MarketingContext.Current.MarketingProfileContext; // Create filter PromotionFilter filter = new PromotionFilter(); filter.IgnoreConditions = false; filter.IgnorePolicy = false; filter.IgnoreSegments = false; filter.IncludeCoupons = false; // Create new entry PromotionEntry promotEntry = new PromotionEntry(catalogName, String.Empty, entry.ID, price.Amount); // Populate entry parameters ((IPromotionEntryPopulate)MarketingContext.Current.PromotionEntryPopulateFunctionClassInfo.CreateInstance()).Populate(ref promotEntry, entry); PromotionEntriesSet sourceSet = new PromotionEntriesSet(); sourceSet.Entries.Add(promotEntry); // Configure promotion context helper.PromotionContext.SourceEntriesSet = sourceSet; helper.PromotionContext.TargetEntriesSet = sourceSet; // Only target entries helper.PromotionContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Entry).Key; // Execute the promotions and filter out basic collection of promotions, we need to execute with cache disabled, so we get latest info from the database helper.Eval(filter); // Check the count, and get new price if (helper.PromotionContext.PromotionResult.PromotionRecords.Count > 0) { return(ObjectHelper.CreatePrice(price.Amount - GetDiscountPrice(helper.PromotionContext.PromotionResult), price.CurrencyCode)); } else { return(price); } }
public IQueryable <PromotionEntity> Get(PagerRequest pagerRequest, out int totalCount, PromotionSortOrder sortOrder, PromotionFilter filter) { var linq = Get(filter); totalCount = linq.Count(); var skipCount = (pagerRequest.PageIndex - 1) * pagerRequest.PageSize; linq = OrderBy(linq, sortOrder); linq = skipCount == 0 ? linq.Take(pagerRequest.PageSize) : linq.Skip(skipCount).Take(pagerRequest.PageSize); return(linq); }
/// <summary> /// Calculates the discounts. /// </summary> private void CalculateDiscounts() { // Get current context Dictionary <string, object> context = MarketingContext.Current.MarketingProfileContext; // Parameter that tells if we need to use cached values for promotions or not bool useCache = false; // Constract the filter, ignore conditions for now PromotionFilter filter = new PromotionFilter(); filter.IgnoreConditions = false; filter.IgnorePolicy = false; filter.IgnoreSegments = false; filter.IncludeCoupons = false; // Get property OrderGroup order = this.OrderGroup; // Create Promotion Context PromotionEntriesSet sourceSet = null; // Reuse the same context so we can track exclusivity properly PromotionContext promoContext = new PromotionContext(context, new PromotionEntriesSet(), new PromotionEntriesSet()); promoContext.PromotionResult.RunningTotal = order.SubTotal; #region Determine Line item level discounts int totalNumberOfItems = 0; // Process line item discounts first foreach (OrderForm form in order.OrderForms) { foreach (OrderFormDiscount discount in form.Discounts) { if (!discount.DiscountName.StartsWith("@") /* && discount.DiscountId == -1*/) // ignore custom entries { discount.Delete(); } } // Create source from current form sourceSet = CreateSetFromOrderForm(form); // Now cycle through each line item one by one foreach (LineItem lineItem in form.LineItems) { // First remove items foreach (LineItemDiscount discount in lineItem.Discounts) { if (!discount.DiscountName.StartsWith("@") /* && discount.DiscountId == -1*/) // ignore custom entries { discount.Delete(); } } totalNumberOfItems++; // Target only entry promotions PromotionEntriesSet targetSet = new PromotionEntriesSet(); targetSet.OwnerId = form.OrderFormId.ToString(); //ET [16.06.2009] If order contains two item with same code, in target hit only first //targetSet.Entries.Add(sourceSet.FindEntryByCode(lineItem.CatalogEntryId)); targetSet.Entries.Add(CreatePromotionEntryFromLineItem(lineItem)); promoContext.SourceEntriesSet = sourceSet; promoContext.TargetEntriesSet = targetSet; promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Entry).Key; // Evaluate conditions MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter); // from now on use cache useCache = true; } } #endregion #region Determine Order level discounts foreach (OrderForm form in order.OrderForms) { // Now process global order discounts // Now start processing it // Create source from current form sourceSet = CreateSetFromOrderForm(form); promoContext.SourceEntriesSet = sourceSet; promoContext.TargetEntriesSet = sourceSet; promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Order).Key; } // Evaluate conditions MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter); #endregion #region Determine Shipping Discounts foreach (OrderForm form in order.OrderForms) { foreach (Shipment shipment in form.Shipments) { // Remove old discounts if any foreach (ShipmentDiscount discount in shipment.Discounts) { if (!discount.DiscountName.StartsWith("@") /* && discount.DiscountId == -1*/) // ignore custom entries { discount.Delete(); } } // Create content for current shipment /* * sourceSet = CreateSetFromOrderForm(form); * promoContext.SourceEntriesSet.Entries = sourceSet.Entries; * */ PromotionEntriesSet targetSet = CreateSetFromShipment(shipment); promoContext.SourceEntriesSet = targetSet; promoContext.TargetEntriesSet = targetSet; promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Shipping).Key; // Evaluate promotions MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter); // Set the total discount for the shipment // shipment.ShippingDiscountAmount = GetDiscountPrice(order, promoContext.PromotionResult); } } #endregion #region Start Applying Discounts decimal runningTotal = order.SubTotal; foreach (PromotionItemRecord itemRecord in promoContext.PromotionResult.PromotionRecords) { if (itemRecord.Status != PromotionItemRecordStatus.Commited) { continue; } // Pre process item record PreProcessItemRecord(order, itemRecord); // Applies discount and adjusts the running total if (itemRecord.AffectedEntriesSet.Entries.Count > 0) { runningTotal -= ApplyItemDiscount(order, itemRecord, runningTotal); } } #endregion }
/// <summary> /// 过滤 /// </summary> /// <returns></returns> private static Expression <Func <PromotionEntity, bool> > Filter(PromotionFilter promotionFilter) { var filter = PredicateBuilder.True <PromotionEntity>(); //always exclude deleted record filter = filter.And(v => v.Status != (int)DataStatus.Deleted); if (promotionFilter.DataStatus != null) { filter = filter.And(v => v.Status == (int)promotionFilter.DataStatus.Value); } //TODO: 这块值得商榷 if (promotionFilter.DateTimeRangeInfo != null) { //开始时间必须大于当前时间,才叫开始 //if (rangeInfo.StartDateTime != null) //{ // filter = filter.And(v => v.StartDate >= rangeInfo.StartDateTime); //} if (promotionFilter.DateTimeRangeInfo.EndDateTime != null) { filter = filter.And(v => v.EndDate > promotionFilter.DateTimeRangeInfo.EndDateTime); } } if (promotionFilter.Timestamp != null) { switch (promotionFilter.Timestamp.TsType) { case TimestampType.New: filter = filter.And(v => v.UpdatedDate >= promotionFilter.Timestamp.Ts); break; case TimestampType.Old: default: filter = filter.And(v => v.UpdatedDate < promotionFilter.Timestamp.Ts); break; } } if (promotionFilter.RecommendUser != null) { filter = filter.And(v => v.RecommendUser == promotionFilter.RecommendUser.Value); } if (promotionFilter.TagIds != null && promotionFilter.TagIds.Count > 0) { if (promotionFilter.TagIds.Count == 1) { filter = filter.And(v => v.Tag_Id == promotionFilter.TagIds[0]); } else { filter = filter.Or(v => promotionFilter.TagIds.Any(s => s == v.Tag_Id)); } } if (promotionFilter.FilterMode != null) { switch (promotionFilter.FilterMode) { case PromotionFilterMode.InProgress: if (promotionFilter.DateTimeRangeInfo != null && promotionFilter.DateTimeRangeInfo.EndDateTime != null) { filter = filter.And(v => v.StartDate < DateTime.Now); } else { filter = filter.And(v => v.StartDate <DateTime.Now && v.EndDate> DateTime.Now); } break; case PromotionFilterMode.NotTheEnd: if (promotionFilter.DateTimeRangeInfo != null) { if (promotionFilter.DateTimeRangeInfo.EndDateTime != null) { filter = filter.And(v => v.EndDate > promotionFilter.DateTimeRangeInfo.EndDateTime); } if (promotionFilter.DateTimeRangeInfo.StartDateTime != null) { filter = filter.And(v => v.StartDate > promotionFilter.DateTimeRangeInfo.StartDateTime); } } else { filter = filter.And(v => v.EndDate > DateTime.Now); } break; } } if (promotionFilter.Ids != null && promotionFilter.Ids.Count > 0) { filter = filter.And(v => promotionFilter.Ids.Any(s => s == v.Id)); } if (promotionFilter.HasProduct != null) { filter = filter.And(v => v.IsProdBindable == promotionFilter.HasProduct); } return(filter); }
/// <summary> /// Calculates the discounts. /// </summary> private void CalculateDiscounts() { PromotionDto promotionDto = PromotionManager.GetPromotionDto(FrameworkContext.Current.CurrentDateTime); if (promotionDto.Promotion.Count == 0) return; // Get current context Dictionary<string, object> context = MarketingContext.Current.MarketingProfileContext; // Parameter that tells if we need to use cached values for promotions or not bool useCache = false; // Constract the filter, ignore conditions for now PromotionFilter filter = new PromotionFilter(); filter.IgnoreConditions = false; filter.IgnorePolicy = false; filter.IgnoreSegments = false; filter.IncludeCoupons = false; // Get property OrderGroup order = this.OrderGroup; decimal runningTotal = 0; foreach (OrderForm orderForm in order.OrderForms) { runningTotal += orderForm.LineItems.Where(c => !IsGiftLineItem(c)).Sum(x => x.Quantity * x.PlacedPrice); } // Create Promotion Context PromotionEntriesSet sourceSet = null; // Reuse the same context so we can track exclusivity properly PromotionContext promoContext = new PromotionContext(context, new PromotionEntriesSet(), new PromotionEntriesSet()); promoContext.PromotionResult.RunningTotal = runningTotal; #region Determine Line item level discounts int totalNumberOfItems = 0; // Process line item discounts first foreach (OrderForm form in order.OrderForms) { foreach (OrderFormDiscount discount in form.Discounts) { if (!discount.DiscountName.StartsWith("@")/* && discount.DiscountId == -1*/) // ignore custom entries discount.Delete(); } // Create source from current form sourceSet = CreateSetFromOrderForm(form); // Build dictionary to keep track of entry discount limit Dictionary<PromotionDto.PromotionRow, decimal?> entryDiscountApplicationCount = new Dictionary<PromotionDto.PromotionRow, decimal?>(); foreach (PromotionDto.PromotionRow promotion in promotionDto.Promotion) { if (!promotion.IsMaxEntryDiscountQuantityNull()) { entryDiscountApplicationCount.Add(promotion, promotion.MaxEntryDiscountQuantity); } } // Now cycle through each line item one by one IOrderedEnumerable<LineItem> highPlacedPriceFirst = form.LineItems.ToArray().OrderByDescending(x => x.PlacedPrice); int lineItemCount = highPlacedPriceFirst.Count(); int i = 0; foreach (LineItem lineItem in highPlacedPriceFirst) { i++; // First remove items foreach (LineItemDiscount discount in lineItem.Discounts) { if (!discount.DiscountName.StartsWith("@")/* && discount.DiscountId == -1*/) // ignore custom entries discount.Delete(); } //Exclude gift lineItems from evaluation discounts process if (IsGiftLineItem(lineItem)) { continue; } totalNumberOfItems++; // Target only entry promotions PromotionEntriesSet targetSet = new PromotionEntriesSet(); targetSet.OrderFormId = form.OrderFormId.ToString(); //ET [16.06.2009] If order contains two item with same code, in target hit only first //targetSet.Entries.Add(sourceSet.FindEntryByCode(lineItem.CatalogEntryId)); targetSet.Entries.Add(CreatePromotionEntryFromLineItem(lineItem)); promoContext.SourceEntriesSet = sourceSet; promoContext.TargetEntriesSet = targetSet; promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Entry).Key; // Evaluate conditions bool checkEntryLevelDiscountLimit = i == lineItemCount; MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter, entryDiscountApplicationCount, checkEntryLevelDiscountLimit); // from now on use cache useCache = true; } } #endregion #region Determine Order level discounts foreach (OrderForm form in order.OrderForms) { // Now process global order discounts // Now start processing it // Create source from current form sourceSet = CreateSetFromOrderForm(form); promoContext.SourceEntriesSet = sourceSet; promoContext.TargetEntriesSet = sourceSet; promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Order).Key; } // Evaluate conditions MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter, null, false); //Removing now not aplyied Gift discounts from Order RemoveGiftPromotionFromOrder(order, promoContext); #endregion #region Determine Shipping Discounts // add shipping fee to RunningTotal after calculating item and order level discounts, in order to apply shipping discounts. foreach (OrderForm orderForm in order.OrderForms) { foreach (Shipment shipment in orderForm.Shipments) { promoContext.PromotionResult.RunningTotal += shipment.ShippingSubTotal; } } foreach (OrderForm form in order.OrderForms) { foreach (Shipment shipment in form.Shipments) { // Remove old discounts if any foreach (ShipmentDiscount discount in shipment.Discounts) { if (!discount.DiscountName.StartsWith("@")/* && discount.DiscountId == -1*/) // ignore custom entries discount.Delete(); } // Create content for current shipment /* sourceSet = CreateSetFromOrderForm(form); promoContext.SourceEntriesSet.Entries = sourceSet.Entries; * */ PromotionEntriesSet targetSet = CreateSetFromShipment(shipment); promoContext.SourceEntriesSet = targetSet; promoContext.TargetEntriesSet = targetSet; promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Shipping).Key; // Evaluate promotions MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter, null, false); // Set the total discount for the shipment // shipment.ShippingDiscountAmount = GetDiscountPrice(order, promoContext.PromotionResult); } } #endregion #region Start Applying Discounts foreach (PromotionItemRecord itemRecord in promoContext.PromotionResult.PromotionRecords) { if (itemRecord.Status != PromotionItemRecordStatus.Commited) continue; // Pre process item record PreProcessItemRecord(order, itemRecord); // Applies discount and adjusts the running total if (itemRecord.AffectedEntriesSet.Entries.Count > 0) { var discountAmount = ApplyItemDiscount(order, itemRecord, runningTotal); if (!(itemRecord.PromotionReward is GiftPromotionReward)) { runningTotal -= discountAmount; } } } #endregion #region True up order level discounts (from Mark's fix for Teleflora) decimal orderLevelAmount = 0; decimal lineItemOrderLevelTotal = 0; foreach (OrderForm form in order.OrderForms) { orderLevelAmount += form.Discounts.Cast<OrderFormDiscount>().Where(y => !y.DiscountName.StartsWith("@")).Sum(x => x.DiscountValue); lineItemOrderLevelTotal += form.LineItems.ToArray().Sum(x => x.OrderLevelDiscountAmount); if (orderLevelAmount > lineItemOrderLevelTotal) { form.LineItems[0].OrderLevelDiscountAmount += orderLevelAmount - lineItemOrderLevelTotal; } } #endregion }
public override void Evaluate(PromotionFilter filter, bool checkEntryLevelLimit) { }
public async Task <Result <PagedList <PromotionListItemModel> > > GetPromotions([FromBody] PromotionFilter filter) { var result = await _promotionService.GetPromotionsAsync(filter); var toReturn = new PagedList <PromotionListItemModel> { Items = result.Items.Select(p => new PromotionListItemModel(p)).ToList(), Count = result.Count, }; return(toReturn); }
/// <summary> /// Evals the specified filter. /// </summary> /// <param name="filter">The filter.</param> public void Eval(PromotionFilter filter) { MarketingContext.Current.EvaluatePromotions(true, this.PromotionContext, filter); }
public virtual void Evaluate(PromotionFilter filter, bool checkEntryLevelLimit) { GetPromotionHelper().Eval(filter, checkEntryLevelLimit); }
/// <summary> /// Calculates the discounts. /// </summary> private void CalculateDiscounts() { // Update manual discount amount UpdateManualDiscounts(OrderGroup); PromotionDto promotionDto = PromotionManager.GetPromotionDto(FrameworkContext.Current.CurrentDateTime); if (promotionDto.Promotion.Count == 0) { return; } // Get current context Dictionary <string, object> context = MarketingContext.Current.MarketingProfileContext; // Parameter that tells if we need to use cached values for promotions or not bool useCache = false; // Constract the filter, ignore conditions for now PromotionFilter filter = new PromotionFilter(); filter.IgnoreConditions = false; filter.IgnorePolicy = false; filter.IgnoreSegments = false; filter.IncludeCoupons = false; // Get property OrderGroup order = OrderGroup; decimal runningTotal = 0; foreach (OrderForm orderForm in order.OrderForms) { runningTotal += orderForm.LineItems.Where(c => !IsGiftLineItem(c)).Sum(x => x.Quantity * x.PlacedPrice); } // Create Promotion Context PromotionEntriesSet sourceSet = null; // Reuse the same context so we can track exclusivity properly PromotionContext promoContext = new PromotionContext(context, new PromotionEntriesSet(), new PromotionEntriesSet()); promoContext.PromotionResult.RunningTotal = runningTotal; #region Determine Line item level discounts int totalNumberOfItems = 0; // Process line item discounts first foreach (OrderForm form in order.OrderForms) { foreach (OrderFormDiscount discount in form.Discounts) { if (!discount.DiscountName.StartsWith("@") /* && discount.DiscountId == -1*/) // ignore custom entries { discount.Delete(); } } // Create source from current form sourceSet = CreateSetFromOrderForm(form); // Build dictionary to keep track of entry discount limit Dictionary <PromotionDto.PromotionRow, decimal?> entryDiscountApplicationCount = new Dictionary <PromotionDto.PromotionRow, decimal?>(); foreach (PromotionDto.PromotionRow promotion in promotionDto.Promotion) { if (!promotion.IsMaxEntryDiscountQuantityNull()) { entryDiscountApplicationCount.Add(promotion, promotion.MaxEntryDiscountQuantity); } } // Now cycle through each line item one by one IOrderedEnumerable <LineItem> highPlacedPriceFirst = form.LineItems.ToArray().OrderByDescending(x => x.PlacedPrice); int lineItemCount = highPlacedPriceFirst.Count(); List <PromotionEntriesSet> entriesSetCollection = new List <PromotionEntriesSet>(); foreach (LineItem lineItem in highPlacedPriceFirst) { // First remove items foreach (LineItemDiscount discount in lineItem.Discounts) { if (!discount.DiscountName.StartsWith("@") /* && discount.DiscountId == -1*/) // ignore custom entries { discount.Delete(); } } //Exclude gift lineItems from evaluation discounts process if (IsGiftLineItem(lineItem)) { continue; } totalNumberOfItems++; // Target only entry promotions PromotionEntriesSet targetSet = new PromotionEntriesSet(); targetSet.OrderFormId = form.OrderFormId.ToString(); //ET [16.06.2009] If order contains two item with same code, in target hit only first //targetSet.Entries.Add(sourceSet.FindEntryByCode(lineItem.CatalogEntryId)); targetSet.Entries.Add(CreatePromotionEntryFromLineItem(lineItem)); entriesSetCollection.Add(targetSet); } promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Entry).Key; // Evaluate conditions MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter, entryDiscountApplicationCount, sourceSet, entriesSetCollection, null); // from now on use cache useCache = true; } #endregion #region Determine Order level discounts List <PromotionEntriesSet> orderEntriesSetCollection = new List <PromotionEntriesSet>(); foreach (OrderForm form in order.OrderForms) { // Now process global order discounts // Now start processing it // Create source from current form sourceSet = CreateSetFromOrderForm(form); orderEntriesSetCollection.Add(sourceSet); } promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Order).Key; // Evaluate conditions MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter, null, orderEntriesSetCollection, false); //Removing now not aplyied Gift discounts from Order RemoveGiftPromotionFromOrder(order, promoContext); #endregion #region Determine Shipping Discounts // add shipping fee to RunningTotal after calculating item and order level discounts, in order to apply shipping discounts. foreach (OrderForm orderForm in order.OrderForms) { foreach (Shipment shipment in orderForm.Shipments) { promoContext.PromotionResult.RunningTotal += shipment.ShippingSubTotal; } } foreach (OrderForm form in order.OrderForms) { List <PromotionEntriesSet> shipmentEntriesSetCollection = new List <PromotionEntriesSet>(); foreach (Shipment shipment in form.Shipments) { // Remove old discounts if any foreach (ShipmentDiscount discount in shipment.Discounts) { if (!discount.DiscountName.StartsWith("@") /* && discount.DiscountId == -1*/) // ignore custom entries { discount.Delete(); } } // Create content for current shipment /* * sourceSet = CreateSetFromOrderForm(form); * promoContext.SourceEntriesSet.Entries = sourceSet.Entries; * */ PromotionEntriesSet targetSet = CreateSetFromShipment(shipment); shipmentEntriesSetCollection.Add(targetSet); } promoContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Shipping).Key; // Evaluate promotions MarketingContext.Current.EvaluatePromotions(useCache, promoContext, filter, null, shipmentEntriesSetCollection, false); } #endregion #region Start Applying Discounts foreach (PromotionItemRecord itemRecord in promoContext.PromotionResult.PromotionRecords) { if (itemRecord.Status != PromotionItemRecordStatus.Commited) { continue; } // Pre process item record PreProcessItemRecord(order, itemRecord); // Applies discount and adjusts the running total if (itemRecord.AffectedEntriesSet.Entries.Count > 0) { var discountAmount = ApplyItemDiscount(order, itemRecord, runningTotal); if (!(itemRecord.PromotionReward is GiftPromotionReward)) { runningTotal -= discountAmount; } } } #endregion #region True up order level discounts (from Mark's fix for Teleflora) decimal orderLevelAmount = 0; decimal lineItemOrderLevelTotal = 0; foreach (OrderForm form in order.OrderForms) { orderLevelAmount += form.Discounts.Cast <OrderFormDiscount>().Where(y => !y.DiscountName.StartsWith("@")).Sum(x => x.DiscountValue); lineItemOrderLevelTotal += form.LineItems.ToArray().Sum(x => x.OrderLevelDiscountAmount); if (orderLevelAmount != lineItemOrderLevelTotal) { form.LineItems[0].OrderLevelDiscountAmount += orderLevelAmount - lineItemOrderLevelTotal; } } #endregion }
// Old stuff... no demo... Legacy Promos // This is a slightly-refactored version of the StoreHelper.GetDiscountPrice() method // catalogName and catalogNodeCode... can be used to filter out certain nodes or catalogs private static Price GetDiscountPriceInternal(EntryContentBase contentSku, Entry sku, IPriceValue price, string catalogName, string catalogNodeCode) { string catalogNodes = String.Empty; string catalogs = String.Empty; // Now cycle through all the catalog nodes where this entry is present filtering by specified catalog and node code // Note: The nodes are only populated when Full or Nodes response group is specified. if (sku.Nodes != null && sku.Nodes.CatalogNode != null && sku.Nodes.CatalogNode.Length > 0) { foreach (CatalogNode node in sku.Nodes.CatalogNode) { string entryCatalogName = CatalogContext.Current.GetCatalogDto(node.CatalogId).Catalog[0].Name; // Skip filtered catalogs if (!String.IsNullOrEmpty(catalogName) && !entryCatalogName.Equals(catalogName)) { continue; } // Skip filtered catalogs nodes if (!String.IsNullOrEmpty(catalogNodeCode) && !node.ID.Equals(catalogNodeCode, StringComparison.OrdinalIgnoreCase)) { continue; } if (String.IsNullOrEmpty(catalogs)) { catalogs = entryCatalogName; } else { catalogs += ";" + entryCatalogName; } if (String.IsNullOrEmpty(catalogNodes)) { catalogNodes = node.ID; } else { catalogNodes += ";" + node.ID; } } } if (String.IsNullOrEmpty(catalogs)) { catalogs = catalogName; } if (String.IsNullOrEmpty(catalogNodes)) { catalogNodes = catalogNodeCode; } // Get current context Dictionary <string, object> context = MarketingContext.Current.MarketingProfileContext; // Create filter PromotionFilter filter = new PromotionFilter { IgnoreConditions = false, IgnorePolicy = false, IgnoreSegments = false, IncludeCoupons = false }; // Create new entry // Note: catalogNodes is determined by GetParentNodes(entry) PromotionEntry result = new PromotionEntry(catalogs, catalogNodes, sku.ID, price.UnitPrice.Amount); var promotionEntryPopulateService = (IPromotionEntryPopulate)MarketingContext.Current.PromotionEntryPopulateFunctionClassInfo.CreateInstance(); promotionEntryPopulateService.Populate(result, sku, _currentMarket.Service.GetCurrentMarket().MarketId, _currentMarket.Service.GetCurrentMarket().DefaultCurrency); PromotionEntriesSet sourceSet = new PromotionEntriesSet(); sourceSet.Entries.Add(result); // Create new promotion helper, which will initialize PromotionContext object for us and setup context dictionary PromotionHelper helper = new PromotionHelper(); // Only target entries helper.PromotionContext.TargetGroup = PromotionGroup.GetPromotionGroup(PromotionGroup.PromotionGroupKey.Entry).Key; // Configure promotion context helper.PromotionContext.SourceEntriesSet = sourceSet; helper.PromotionContext.TargetEntriesSet = sourceSet; // Execute the promotions and filter out basic collection of promotions, we need to execute with cache disabled, so we get latest info from the database helper.Eval(filter); Money discountedAmount; // Check the count, and get new price if promotion is applied if (helper.PromotionContext.PromotionResult.PromotionRecords.Count > 0) { discountedAmount = new Money(price.UnitPrice.Amount - GetDiscountPriceFromPromotionResult( helper.PromotionContext.PromotionResult), _currentMarket.Service.GetCurrentMarket().DefaultCurrency); return(new Price { UnitPrice = discountedAmount, ValidFrom = price.ValidFrom, ValidUntil = price.ValidUntil, MinQuantity = price.MinQuantity, MarketId = price.MarketId, EntryContent = contentSku, CustomerPricing = price.CustomerPricing }); } else { return(new Price(price)); } }
public override PromotionContext Evaluate(PromotionFilter filter, PromotionEntriesSet sourceEntriesSet, PromotionEntriesSet targetEntriesSet, bool checkEntryLevelLimit) { return(null); }
/// <summary> /// Evals the specified filter. /// </summary> /// <param name="filter">The filter.</param> public void Eval(PromotionFilter filter) { // gets in here...and then nothing MarketingContext.Current.EvaluatePromotions(true, this.PromotionContext, filter, null, false); }