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()); }
/// <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; } } } }