/// <summary>
            /// Fetch the superset of discount trade agreements which could apply to all of these items and customer for the given dates.
            /// </summary>
            /// <param name="itemIds">The item Ids to fetch for agreements for.</param>
            /// <param name="customerAccount">Optional. Customer account number 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>
            /// <returns>Collection of trade agreements which may be applied to the given items.</returns>
            public ReadOnlyCollection <TradeAgreement> ReadDiscountTradeAgreements(
                IEnumerable <string> itemIds,
                string customerAccount,
                DateTimeOffset minActiveDate,
                DateTimeOffset maxActiveDate,
                string currencyCode)
            {
                ThrowIf.Null(itemIds, "itemIds");

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

                DateTimeOffset minActiveDateChannelTimeZone = this.Context.ConvertDateTimeToChannelDate(minActiveDate);
                DateTimeOffset maxActiveDateChannelTimeZone = this.Context.ConvertDateTimeToChannelDate(maxActiveDate);

                using (var context = new SqliteDatabaseContext(this.Context))
                {
                    return(DiscountProcedure.GetAllDiscountTradeAgreements(
                               context,
                               itemIds,
                               customerAccount,
                               minActiveDateChannelTimeZone,
                               maxActiveDateChannelTimeZone,
                               currencyCode));
                }
            }
            /// <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);
                }
            }