예제 #1
0
            /// <summary>
            /// Implements the IPricingCalculator interface to calculate item price adjustment prices.
            /// </summary>
            /// <param name="salesLines">The item lines which need prices.</param>
            /// <param name="priceContext">The configuration of the overall pricing context for the calculation.</param>
            /// <param name="pricingDataManager">Instance of pricing data manager to access pricing data.</param>
            /// <returns>Sets of possible price lines keyed by item line Id.</returns>
            public Dictionary <string, IEnumerable <PriceLine> > CalculatePriceLines(
                IEnumerable <SalesLine> salesLines,
                PriceContext priceContext,
                IPricingDataAccessor pricingDataManager)
            {
                // get pairs of product Id and distinct variant Id from lines to search by
                var productIds = salesLines
                                 .Select(sl => new ItemUnit
                {
                    ItemId = sl.ItemId,
                    VariantInventoryDimensionId = sl.InventoryDimensionId ?? string.Empty,
                    DistinctProductVariant      = sl.Variant != null ? sl.Variant.DistinctProductVariantId : 0,
                    Product = sl.MasterProductId == 0 ? sl.ProductId : sl.MasterProductId
                })
                                 .Distinct().ToList();

                Tuple <DateTimeOffset, DateTimeOffset> dateRange = PricingEngine.GetMinAndMaxActiveDates(salesLines, priceContext.ActiveDate);

                // datetime to use depends on listing/cart scenario
                if (priceContext.PriceCalculationMode == PricingCalculationMode.Independent)
                {
                    dateRange = new Tuple <DateTimeOffset, DateTimeOffset>(dateRange.Item1, dateRange.Item2);
                }

                // fetch all price adjustments (and any related validation periods)
                ISet <string> allPriceGroups = PriceContextHelper.GetAllPriceGroupsForPrice(priceContext);
                IEnumerable <PriceAdjustment> adjustments = pricingDataManager.ReadPriceAdjustments(
                    productIds,
                    allPriceGroups,
                    dateRange.Item1,
                    dateRange.Item2,
                    QueryResultSettings.AllRecords) as IEnumerable <PriceAdjustment>;

                if (priceContext.IsDiagnosticsCollected && adjustments.Any())
                {
                    priceContext.PricingEngineDiagnosticsObject.AddPriceAdjustmentsConsidered(adjustments.Select(x => x.OfferId).ToList());
                }

                HashSet <string> offerIds = new HashSet <string>();

                foreach (PriceAdjustment adjustment in adjustments)
                {
                    offerIds.Add(adjustment.OfferId);
                }

                IDictionary <string, IList <PriceGroup> > adjustmentPriceGroupDictionary = PriceContextHelper.GetRetailDiscountPriceGroupDictionaryFilteredByTransaction(
                    pricingDataManager,
                    offerIds,
                    allPriceGroups);

                FixAdjustmentPriorityFromPriceGroups(adjustments, adjustmentPriceGroupDictionary);

                // "index" adjustments by item Id & dimensions
                var adjustmentDict = adjustments
                                     .GroupBy(a => GetItemIdInventDimIdKey(a.ItemId, a.InventoryDimensionId))
                                     .ToDictionary(grp => grp.Key, grp => grp.ToList(), StringComparer.OrdinalIgnoreCase);

                var promotionLines = new Dictionary <string, IList <PriceAdjustment> >(StringComparer.OrdinalIgnoreCase);

                foreach (var line in salesLines)
                {
                    // get item price adjustments, continue to next item if none found
                    var key = GetItemIdInventDimIdKey(line.ItemId, line.InventoryDimensionId);

                    List <PriceAdjustment> itemAdjustments;
                    if (!adjustmentDict.TryGetValue(key, out itemAdjustments))
                    {
                        continue;
                    }

                    List <PriceAdjustment> allApplicablePriceAdjustmentsForItem = new List <PriceAdjustment>();
                    foreach (var a in itemAdjustments)
                    {
                        IList <PriceGroup> priceGroups = null;
                        adjustmentPriceGroupDictionary.TryGetValue(a.OfferId, out priceGroups);

                        HashSet <string> priceGroupIdSet = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                        priceGroupIdSet.AddRange(priceGroups.Select(p => p.GroupId));
                        if (PriceContextHelper.IsApplicableForPrice(priceContext, priceGroupIdSet, line.CatalogIds) &&
                            IsAdjustmentActiveOnSalesLine(line, a, priceContext.ActiveDate) &&
                            IsMatchUnitOfMeasure(line, a) &&
                            IsMatchCurrency(priceContext.CurrencyCode, a))
                        {
                            allApplicablePriceAdjustmentsForItem.Add(a);
                        }
                    }

                    if (allApplicablePriceAdjustmentsForItem.Any())
                    {
                        // We apply price adjustment from only those with highest priority.
                        int highestPriority = allApplicablePriceAdjustmentsForItem.Max(p => p.PricingPriorityNumber);
                        IEnumerable <PriceAdjustment> priceAdjustmentsWithHighestPriorityForItem = allApplicablePriceAdjustmentsForItem.Where(p => p.PricingPriorityNumber == highestPriority);

                        // filter price adjustments by active validation periods before adding to dictionary
                        foreach (var a in priceAdjustmentsWithHighestPriorityForItem)
                        {
                            IList <PriceAdjustment> promos;
                            if (!promotionLines.TryGetValue(line.LineId, out promos))
                            {
                                promos = new List <PriceAdjustment>();
                                promotionLines.Add(line.LineId, promos);
                            }

                            promos.Add(a);
                        }
                    }
                }

                // convert price adjustments to price lines for the sales lines
                var priceLines = PriceAdjustmentsToPriceLines(salesLines, promotionLines);

                return(priceLines);
            }