/// <summary>
            /// Fetch all retail discounts for the given items, striped by item Id and dimension Id.
            /// </summary>
            /// <param name="items">The set of items to search by. Set of pairs of item Id and variant dimension Id. Ignores the unit.</param>
            /// <param name="priceGroups">Set of price groups to search by.</param>
            /// <param name="minActiveDate">The earliest inclusive active date to search by. Must be less than or equal to maxActiveDate.</param>
            /// <param name="maxActiveDate">The latest inclusive active date to search by. Must be greater than or equal to minActiveDate.</param>
            /// <param name="currencyCode">Currency code to filter by.</param>
            /// <param name="validationPeriods">Output all the validation periods used by the discovered price adjustments.</param>
            /// <returns>Collection of price adjustments striped by item Id and variant dimension Id (if any).</returns>
            public ReadOnlyCollection <PeriodicDiscount> ReadRetailDiscounts(
                IEnumerable <ItemUnit> items,
                IEnumerable <string> priceGroups,
                DateTimeOffset minActiveDate,
                DateTimeOffset maxActiveDate,
                string currencyCode,
                out ReadOnlyCollection <ValidationPeriod> validationPeriods)
            {
                ThrowIf.Null(items, "items");
                ThrowIf.Null(priceGroups, "priceGroups");
                ThrowIf.Null(currencyCode, "currencyCode");

                using (var context = new SqliteDatabaseContext(this.Context))
                {
                    var priceGroupCollection = PricingProcedure.GetPriceGroup(context, priceGroups);
                    var itemUnits            = PricingProcedure.GetItemsUnit(context, items);

                    IEnumerable <long> priceGroupRecIds = priceGroupCollection.Select(price => price.PriceGroupId);

                    ReadOnlyCollection <PeriodicDiscount> periodicDiscounts = DiscountProcedure.GetRetailDiscount(
                        context,
                        itemUnits.Results,
                        priceGroupRecIds,
                        minActiveDate.DateTime,
                        maxActiveDate.DateTime,
                        currencyCode);

                    // fetch any validation periods in use by the price adjustments
                    var periodIds = periodicDiscounts
                                    .Where(p => p.DateValidationType == (int)DateValidationType.Advanced && !string.IsNullOrWhiteSpace(p.ValidationPeriodId))
                                    .Select(p => p.ValidationPeriodId)
                                    .Distinct();

                    if (periodIds.Any())
                    {
                        validationPeriods = PricingProcedure.GetValidationPeriodsByIds(context, periodIds).Results;
                    }
                    else
                    {
                        validationPeriods = new ReadOnlyCollection <ValidationPeriod>(new ValidationPeriod[0]);
                    }

                    return(periodicDiscounts);
                }
            }
            /// <summary>
            /// Fetch all price adjustments for the given items, striped by item Id and dimension Id.
            /// </summary>
            /// <param name="items">The set of items to search by. Set of pairs of item Id and variant dimension Id. Ignores the unit.</param>
            /// <param name="priceGroups">Set of price groups to search by.</param>
            /// <param name="minActiveDate">The earliest inclusive active date to search by. Must be less than or equal to maxActiveDate.</param>
            /// <param name="maxActiveDate">The latest inclusive active date to search by. Must be greater than or equal to minActiveDate.</param>
            /// <param name="validationPeriods">Output all the validation periods used by the discovered price adjustments.</param>
            /// <returns>Collection of price adjustments striped by item Id and variant dimension Id (if any).</returns>
            public ReadOnlyCollection <PriceAdjustment> ReadPriceAdjustments(
                IEnumerable <ItemUnit> items,
                ISet <string> priceGroups,
                DateTimeOffset minActiveDate,
                DateTimeOffset maxActiveDate,
                out ReadOnlyCollection <ValidationPeriod> validationPeriods)
            {
                ThrowIf.Null(items, "items");
                ThrowIf.Null(priceGroups, "priceGroups");

                if (minActiveDate > maxActiveDate)
                {
                    throw new ArgumentException("minActiveDate must be less than or equal to maxActiveDate.");
                }

                PagedResult <PriceAdjustment> promotionLines = null;

                using (SqliteDatabaseContext context = new SqliteDatabaseContext(this.Context))
                {
                    var priceGroupCollection = PricingProcedure.GetPriceGroup(context, priceGroups);

                    promotionLines = PricingProcedure.GetRetailPriceAdjustments(context, items, priceGroupCollection, minActiveDate.DateTime, maxActiveDate.DateTime);

                    // fetch any validation periods in use by the price adjustments
                    var periodIds = promotionLines.Results
                                    .Where(p => p.DateValidationType == (int)DateValidationType.Advanced && !string.IsNullOrWhiteSpace(p.ValidationPeriodId))
                                    .Select(p => p.ValidationPeriodId)
                                    .Distinct();

                    if (periodIds.Any())
                    {
                        validationPeriods = PricingProcedure.GetValidationPeriodsByIds(context, periodIds).Results;
                    }
                    else
                    {
                        validationPeriods = new ReadOnlyCollection <ValidationPeriod>(new ValidationPeriod[0]);
                    }
                }

                return(promotionLines.Results);
            }