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);
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
 /// <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);
     }
 }
Esempio n. 10
0
        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);
            }
        }
Esempio n. 11
0
        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);
            }
        }
Esempio n. 12
0
 public override PromotionContext Evaluate(PromotionFilter filter, PromotionEntriesSet sourceEntriesSet, PromotionEntriesSet targetEntriesSet, bool checkEntryLevelLimit)
 {
     return null;
 }
Esempio n. 13
0
        /// <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);
            }
        }
Esempio n. 14
0
        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);
        }
Esempio n. 15
0
        /// <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
        }
Esempio n. 16
0
        /// <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
        }
Esempio n. 18
0
 public override void Evaluate(PromotionFilter filter, bool checkEntryLevelLimit)
 {
     
 }
Esempio n. 19
0
        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);
        }
Esempio n. 20
0
 /// <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);
 }
Esempio n. 22
0
        /// <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 virtual void Evaluate(PromotionFilter filter, bool checkEntryLevelLimit)
 {
     GetPromotionHelper().Eval(filter, checkEntryLevelLimit);
 }
Esempio n. 25
0
 public override void Evaluate(PromotionFilter filter, bool checkEntryLevelLimit)
 {
 }
Esempio n. 26
0
 public override PromotionContext Evaluate(PromotionFilter filter, PromotionEntriesSet sourceEntriesSet, PromotionEntriesSet targetEntriesSet, bool checkEntryLevelLimit)
 {
     return(null);
 }
Esempio n. 27
0
 /// <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);
 }