예제 #1
0
        public string Process(string[] args)
        {
            // read input from user
            IBasketInputReader basketInputReader = new BasketInputReader();
            ShoppingBasket     shoppingBasket    = basketInputReader.CreateBasketFromInput(args, _productsDL);

            // calculate snopping basket price
            IBasketCalculator basketCalculator = new BasketCalculator(_specialOffersDL);
            CalculatedPrice   calculatedPrice  = basketCalculator.CalculatePrice(shoppingBasket);

            // write output
            IBasketPriceWriter basketPriceWriter = new BasketPriceWriter();

            return(basketPriceWriter.GetOutputString(calculatedPrice));
        }
        public string GetOutputString(CalculatedPrice calculatedPrice)
        {
            StringBuilder output = new StringBuilder();

            output.AppendLine($"Subtotal: {ToMoneyString(calculatedPrice.Subtotal)}");
            if (calculatedPrice.SpecialOffersApplied.Count == 0)
            {
                output.AppendLine("(No offers available)");
            }
            else
            {
                foreach (var specialOfferApplied in calculatedPrice.SpecialOffersApplied)
                {
                    var productName   = specialOfferApplied.SpecialOfferRule.SpecialOfferDiscountRule.Product.Description;
                    var percentageOff = specialOfferApplied.SpecialOfferRule.SpecialOfferDiscountRule.DiscountPercent;
                    var amountOff     = decimal.Round(specialOfferApplied.DiscountedAmount, 2, MidpointRounding.AwayFromZero);
                    //Apples 10 % off: -10p
                    output.AppendLine($"{productName} {percentageOff}% off: -{ToMoneyString(amountOff)}");
                }
            }
            output.AppendLine("Total: " + ToMoneyString(calculatedPrice.Total));
            return(output.ToString());
        }
예제 #3
0
        /// <summary>
        /// Applies extra data to an expando object.
        /// Export feature flags set by the export provider controls whether and what to be exported here.
        /// </summary>
        private async Task ApplyExportFeatures(
            dynamic dynObject,
            Product product,
            CalculatedPrice price,
            IEnumerable <ProductMediaFile> mediaFiles,
            DataExporterContext ctx,
            DynamicProductContext productContext)
        {
            if (ctx.Supports(ExportFeatures.CanProjectDescription))
            {
                await ApplyProductDescription(dynObject, product, ctx);
            }

            if (ctx.Supports(ExportFeatures.OffersBrandFallback))
            {
                string brand        = null;
                var    productManus = await ctx.ProductBatchContext.ProductManufacturers.GetOrLoadAsync(product.Id);

                if (productManus?.Any() ?? false)
                {
                    var manufacturer = productManus.First().Manufacturer;
                    brand = ctx.GetTranslation(manufacturer, nameof(manufacturer.Name), manufacturer.Name);
                }
                if (brand.IsEmpty())
                {
                    brand = ctx.Projection.Brand;
                }

                dynObject._Brand = brand;
            }

            if (ctx.Supports(ExportFeatures.CanIncludeMainPicture))
            {
                var imageQuery = ctx.Projection.PictureSize > 0 ? new ProcessImageQuery {
                    MaxWidth = ctx.Projection.PictureSize
                } : null;

                if (mediaFiles?.Any() ?? false)
                {
                    var file = _mediaService.ConvertMediaFile(mediaFiles.Select(x => x.MediaFile).First());

                    dynObject._MainPictureUrl         = _mediaService.GetUrl(file, imageQuery, ctx.Store.GetHost());
                    dynObject._MainPictureRelativeUrl = _mediaService.GetUrl(file, imageQuery);
                }
                else if (!_catalogSettings.HideProductDefaultPictures)
                {
                    // Get fallback image URL.
                    dynObject._MainPictureUrl         = _mediaService.GetUrl(null, imageQuery, ctx.Store.GetHost());
                    dynObject._MainPictureRelativeUrl = _mediaService.GetUrl(null, imageQuery);
                }
                else
                {
                    dynObject._MainPictureUrl         = null;
                    dynObject._MainPictureRelativeUrl = null;
                }
            }

            if (ctx.Supports(ExportFeatures.UsesSkuAsMpnFallback) && product.ManufacturerPartNumber.IsEmpty())
            {
                dynObject.ManufacturerPartNumber = product.Sku;
            }

            if (ctx.Supports(ExportFeatures.OffersShippingTimeFallback))
            {
                dynamic deliveryTime = dynObject.DeliveryTime;
                dynObject._ShippingTime = deliveryTime == null ? ctx.Projection.ShippingTime : deliveryTime.Name;
            }

            if (ctx.Supports(ExportFeatures.OffersShippingCostsFallback))
            {
                dynObject._FreeShippingThreshold = ctx.Projection.FreeShippingThreshold;

                dynObject._ShippingCosts = product.IsFreeShipping || (ctx.Projection.FreeShippingThreshold.HasValue && (decimal)dynObject.Price >= ctx.Projection.FreeShippingThreshold.Value)
                    ? decimal.Zero
                    : ctx.Projection.ShippingCosts;
            }

            if (ctx.Supports(ExportFeatures.UsesOldPrice))
            {
                if (product.OldPrice != decimal.Zero && product.OldPrice != (decimal)dynObject.Price && !(product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing))
                {
                    if (ctx.Projection.ConvertNetToGrossPrices)
                    {
                        var tax = await _taxCalculator.CalculateProductTaxAsync(product, product.OldPrice, true, ctx.ContextCustomer, ctx.ContextCurrency);

                        dynObject._OldPrice = tax.Price;
                    }
                    else
                    {
                        dynObject._OldPrice = product.OldPrice;
                    }
                }
                else
                {
                    dynObject._OldPrice = null;
                }
            }

            if (ctx.Supports(ExportFeatures.UsesSpecialPrice))
            {
                dynObject._SpecialPrice       = null;   // Special price which is valid now.
                dynObject._FutureSpecialPrice = null;   // Special price which is valid now and in future.
                dynObject._RegularPrice       = null;   // Price as if a special price would not exist.

                if (!(product.ProductType == ProductType.BundledProduct && product.BundlePerItemPricing))
                {
                    if (price.OfferPrice.HasValue && product.SpecialPriceEndDateTimeUtc.HasValue)
                    {
                        var endDate = DateTime.SpecifyKind(product.SpecialPriceEndDateTimeUtc.Value, DateTimeKind.Utc);
                        if (endDate > DateTime.UtcNow)
                        {
                            dynObject._FutureSpecialPrice = price.OfferPrice.Value.Amount;
                        }
                    }

                    dynObject._SpecialPrice = price.OfferPrice?.Amount ?? null;

                    if (price.OfferPrice.HasValue || dynObject._FutureSpecialPrice != null)
                    {
                        var clonedOptions = ctx.PriceCalculationOptions.Clone();
                        clonedOptions.IgnoreOfferPrice = true;

                        var calculationContext = new PriceCalculationContext(product, clonedOptions);
                        calculationContext.AddSelectedAttributes(productContext?.Combination?.AttributeSelection, product.Id);
                        var priceWithoutOfferPrice = await _priceCalculationService.CalculatePriceAsync(calculationContext);

                        dynObject._RegularPrice = priceWithoutOfferPrice.FinalPrice.Amount;
                    }
                }
            }
        }