Пример #1
0
        protected virtual async Task <List <ProductVariantAttributeValue> > GetSelectedAttributeValuesAsync(CalculatorContext context, IEnumerable <ProductVariantAttribute> attributes)
        {
            var result     = new List <ProductVariantAttributeValue>();
            var bundleItem = context?.BundleItem?.Item;

            // Apply attributes selected by customer.
            var selections = context.SelectedAttributes
                             .Where(x => x.ProductId == context.Product.Id && x.BundleItemId == bundleItem?.Id)
                             .Select(x => x.Selection)
                             .ToList();

            foreach (var selection in selections)
            {
                var selectedValues = selection.MaterializeProductVariantAttributeValues(attributes);

                // Ignore attributes that are filtered out for a bundle item.
                if (bundleItem?.FilterAttributes ?? false)
                {
                    var filteredValues = selectedValues
                                         .Where(x => bundleItem.AttributeFilters.Any(af => af.AttributeId == x.ProductVariantAttributeId && af.AttributeValueId == x.Id));

                    result.AddRange(filteredValues);
                }
                else
                {
                    result.AddRange(selectedValues);
                }
            }

            // Apply attributes preselected by merchant.
            if (context.Options.ApplyPreselectedAttributes)
            {
                // Ignore already applied values.
                var appliedValueIds   = result.Select(x => x.Id).ToArray();
                var preSelectedValues = await context.GetPreSelectedAttributeValuesAsync();

                result.AddRange(preSelectedValues.Where(x => !appliedValueIds.Contains(x.Id)));
            }

            return(result);
        }
Пример #2
0
        public async Task CalculateAsync(CalculatorContext context, CalculatorDelegate next)
        {
            var options = context.Options;

            if (!options.DeterminePreselectedPrice)
            {
                // Proceed with pipeline and omit this calculator, it is made for preselected price calculation only.
                await next(context);

                return;
            }

            var selectedValues = (await context.GetPreSelectedAttributeValuesAsync())
                                 .Where(x => x.ProductVariantAttribute.IsListTypeAttribute())
                                 .ToList();

            if (selectedValues.Any())
            {
                // Create attribute selection of preselected values.
                var query        = new ProductVariantQuery();
                var product      = context.Product;
                var bundleItemId = context.BundleItem?.Item?.Id ?? 0;
                var attributes   = await options.BatchContext.Attributes.GetOrLoadAsync(product.Id);

                var combinations = await options.BatchContext.AttributeCombinations.GetOrLoadAsync(product.Id);

                foreach (var value in selectedValues)
                {
                    var productAttribute = value.ProductVariantAttribute;

                    query.AddVariant(new ProductVariantQueryItem(value.Id.ToString())
                    {
                        ProductId          = product.Id,
                        BundleItemId       = bundleItemId,
                        AttributeId        = productAttribute.ProductAttributeId,
                        VariantAttributeId = productAttribute.Id,
                        Alias      = productAttribute.ProductAttribute.Alias,
                        ValueAlias = value.Alias
                    });
                }

                var(selection, _) = await _productAttributeMaterializer.CreateAttributeSelectionAsync(query, attributes, product.Id, bundleItemId, false);

                var selectedCombination = combinations.FirstOrDefault(x => x.AttributeSelection.Equals(selection));

                // Apply attribute combination price.
                if ((selectedCombination?.IsActive ?? false) && selectedCombination.Price.HasValue)
                {
                    context.FinalPrice = selectedCombination.Price.Value;

                    // That comes too late because regular price has already been passed to child CalculatorContext:
                    //product.MergedDataValues = new Dictionary<string, object> { { "Price", selectedCombination.Price.Value } };
                }
            }

            // The product page is always loaded with the default quantity of 1.
            context.Quantity = 1;
            await next(context);

            context.PreselectedPrice = context.FinalPrice;
        }