コード例 #1
0
        /// <summary>
        /// Given a transaction and some discount processing info, activate the given offers
        ///   to the transaction if applicable
        /// </summary>
        /// <param name="retailTransaction">Transaction to process</param>
        /// <param name="concurrencyMode">For this concurrency mode, try to activate the given offers</param>
        /// <param name="offers">List of offers to attempt to activate</param>
        /// <param name="appliedOffers">Set of offers which have already been activated</param>
        /// <param name="rejectedOffers">Set of offers which have already been rejected</param>
        private static void ApplyPeriodicDiscounts(RetailTransaction retailTransaction, ConcurrencyMode concurrencyMode, List <OfferGroup> offers, HashSet <OfferGroup> appliedOffers, HashSet <OfferGroup> rejectedOffers)
        {
            foreach (var salesItem in retailTransaction.SaleItems)
            {
                if (salesItem.PeriodicDiscountPossibilities.Count == 0)
                {
                    continue;
                }

                bool wasDiscountApplied = false;
                // if there are any discounts of the given concurrency mode
                if (salesItem.PeriodicDiscountPossibilities.Any(d => d.ConcurrencyMode == concurrencyMode))
                {
                    // apply the discount and return it if applied
                    PeriodicDiscountItem registeredDiscount = ApplyValidDiscountFromOffers(salesItem, offers, appliedOffers, rejectedOffers);

                    wasDiscountApplied = (registeredDiscount != null);

                    // for exclusive and best price computations, if discount was put on item, mark the rest of possibilities as rejected
                    if (concurrencyMode != ConcurrencyMode.Compounded && registeredDiscount != null)
                    {
                        foreach (var discount in salesItem.PeriodicDiscountPossibilities)
                        {
                            if (discount != registeredDiscount)
                            {
                                rejectedOffers.Add(GetOfferGroup(discount));
                            }
                        }
                    }
                }

                // If processing compound discounts, add all non-rejected, non-compoundable, non-applied ones
                if (concurrencyMode == ConcurrencyMode.Compounded)
                {
                    foreach (PeriodicDiscountItem discount in salesItem.PeriodicDiscountPossibilities.Where(d => d.IsCompoundable && d.ConcurrencyMode == ConcurrencyMode.Compounded))
                    {
                        OfferGroup offerGroup = GetOfferGroup(discount);
                        if (!rejectedOffers.Contains(offerGroup) && !appliedOffers.Contains(offerGroup) && !salesItem.DiscountLines.Contains(discount))
                        {
                            salesItem.DiscountLines.AddLast(discount);
                            wasDiscountApplied = true;

                            NetTracer.Information("DiscountConcurrencyRules::ApplyPeriodicDiscounts: Applying periodic discount {0} for item {1} line {2}", discount.OfferId, salesItem.ItemId, salesItem.LineId);
                        }
                    }
                }

                // Set whole quantity of the row as discounted because final discount of this item has now been set
                if (wasDiscountApplied)
                {
                    salesItem.QuantityDiscounted = salesItem.Quantity;
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Given sales item, and possible offers sorted by priority (biggest discount),
        ///  activate best, valid discount on the item
        /// </summary>
        /// <param name="saleItem">Item to process</param>
        /// <param name="offers">Sorted, possible discount offers</param>
        /// <param name="appliedOffers">Set of offers already applied</param>
        /// <param name="rejectedOffers">Set of offer already rejected</param>
        /// <returns>Discount which was activated or null if none were</returns>
        private static PeriodicDiscountItem ApplyValidDiscountFromOffers(SaleLineItem saleItem, List <OfferGroup> offers, HashSet <OfferGroup> appliedOffers, HashSet <OfferGroup> rejectedOffers)
        {
            PeriodicDiscountItem selectedPeriodicDiscount = null;
            var offersToPickFrom = offers;

            // If some of this item's discounts have already been applied, they get priority
            bool someOfferAlreadyApplied = saleItem.PeriodicDiscountPossibilities.Any(d => appliedOffers.Contains(GetOfferGroup(d)));

            offersToPickFrom = someOfferAlreadyApplied ? offersToPickFrom.Where(o => appliedOffers.Contains(o)).ToList() : offersToPickFrom;

            // If some of this item's discounts have already been rejected, they shouldn't be an option to choose from
            bool someOfferAlreadyRejected = saleItem.PeriodicDiscountPossibilities.Any(d => rejectedOffers.Contains(GetOfferGroup(d)));

            offersToPickFrom = someOfferAlreadyRejected ? offersToPickFrom.Where(o => !rejectedOffers.Contains(o)).ToList() : offersToPickFrom;

            if (offersToPickFrom.Count > 0)
            {
                // Since offersToPickFrom is sorted by discount amount and filtered for availability,
                //  we need to find the first offer from the available offers which is also a possible item discount.
                selectedPeriodicDiscount = GetFirstPeriodicDiscountFromOffers(saleItem.PeriodicDiscountPossibilities, offersToPickFrom);
                if (selectedPeriodicDiscount != null && !saleItem.DiscountLines.Contains(selectedPeriodicDiscount))
                {
                    // Apply this discount to the item
                    saleItem.DiscountLines.AddLast(selectedPeriodicDiscount);
                    // Mark that we've applied this offer
                    appliedOffers.Add(GetOfferGroup(selectedPeriodicDiscount));

                    NetTracer.Information("DiscountConcurrencyRules::ApplyValidDiscountFromOffers: Applying periodic discount {0} for item {1} line {2}", selectedPeriodicDiscount.OfferId, saleItem.ItemId, saleItem.LineId);
                }
                // if not applied, make sure we return null
                else
                {
                    selectedPeriodicDiscount = null;
                }
            }

            return(selectedPeriodicDiscount);
        }
コード例 #3
0
 /// <summary>
 /// Gets the OfferGroup which is associated to this discount item
 /// </summary>
 /// <param name="discountItem"></param>
 /// <returns></returns>
 private static OfferGroup GetOfferGroup(PeriodicDiscountItem discountItem)
 {
     return(new OfferGroup {
         OfferId = discountItem.OfferId, DiscountGroup = discountItem.PeriodicDiscGroupId
     });
 }