public async Task <(decimal taxRate, decimal sciSubTotalInclTax, decimal sciUnitPriceInclTax, decimal warrantyUnitPriceExclTax, decimal warrantyUnitPriceInclTax)> CalculateWarrantyTaxAsync( ShoppingCartItem sci, Customer customer, decimal sciSubTotalExclTax, decimal sciUnitPriceExclTax ) { var product = await _productService.GetProductByIdAsync(sci.ProductId); var sciSubTotalInclTax = await _taxService.GetProductPriceAsync(product, sciSubTotalExclTax, true, customer); var sciUnitPriceInclTax = await _taxService.GetProductPriceAsync(product, sciUnitPriceExclTax, true, customer); var warrantyUnitPriceExclTax = decimal.Zero; (decimal price, decimal taxRate)warrantyUnitPriceInclTax; warrantyUnitPriceInclTax.price = decimal.Zero; warrantyUnitPriceInclTax.taxRate = decimal.Zero; // warranty item handling ProductAttributeMapping warrantyPam = await _attributeUtilities.GetWarrantyAttributeMappingAsync(sci.AttributesXml); if (warrantyPam != null) { warrantyUnitPriceExclTax = (await _productAttributeParser.ParseProductAttributeValuesAsync(sci.AttributesXml)) .Where(pav => pav.ProductAttributeMappingId == warrantyPam.Id) .Select(pav => pav.PriceAdjustment) .FirstOrDefault(); // get warranty "product" - this is so the warranties have a tax category Product warrProduct = _importUtilities.GetExistingProductBySku("WARRPLACE_SKU"); var isCustomerInTaxableState = await IsCustomerInTaxableStateAsync(customer); if (warrProduct == null) { // taxed warranty price warrantyUnitPriceInclTax = await _taxService.GetProductPriceAsync(product, warrantyUnitPriceExclTax, false, customer); } else { warrantyUnitPriceInclTax = await _taxService.GetProductPriceAsync(warrProduct, warrantyUnitPriceExclTax, isCustomerInTaxableState, customer); } var productUnitPriceInclTax = await _taxService.GetProductPriceAsync(product, sciUnitPriceExclTax - warrantyUnitPriceExclTax, true, customer); sciUnitPriceInclTax.price = productUnitPriceInclTax.price + warrantyUnitPriceInclTax.price; sciSubTotalInclTax.price = sciUnitPriceInclTax.price * sci.Quantity; } return(warrantyUnitPriceInclTax.taxRate, sciSubTotalInclTax.price, sciUnitPriceInclTax.price, warrantyUnitPriceExclTax, warrantyUnitPriceInclTax.price); }
public async override Task <(decimal unitPrice, decimal discountAmount, List <Discount> appliedDiscounts)> GetUnitPriceAsync( Product product, Customer customer, ShoppingCartType shoppingCartType, int quantity, string attributesXml, decimal customerEnteredPrice, DateTime?rentalStartDate, DateTime?rentalEndDate, bool includeDiscounts) { if (product == null) { throw new ArgumentNullException(nameof(product)); } if (customer == null) { throw new ArgumentNullException(nameof(customer)); } var discountAmount = decimal.Zero; var appliedDiscounts = new List <Discount>(); decimal finalPrice; var combination = await _productAttributeParser.FindProductAttributeCombinationAsync(product, attributesXml); if (combination?.OverriddenPrice.HasValue ?? false) { (_, finalPrice, discountAmount, appliedDiscounts) = await _priceCalculationService.GetFinalPriceAsync(product, customer, combination.OverriddenPrice.Value, decimal.Zero, includeDiscounts, quantity, product.IsRental?rentalStartDate : null, product.IsRental?rentalEndDate : null); } else { // custom // summarize price of all attributes except warranties (warranties processed separately) decimal warrantyPrice = decimal.Zero; ProductAttributeMapping warrantyPam = await _attributeUtilities.GetWarrantyAttributeMappingAsync(attributesXml); //summarize price of all attributes var attributesTotalPrice = decimal.Zero; var attributeValues = await _productAttributeParser.ParseProductAttributeValuesAsync(attributesXml); // custom - considers warranties if (attributeValues != null) { foreach (var attributeValue in attributeValues) { if (warrantyPam != null && attributeValue.ProductAttributeMappingId == warrantyPam.Id) { warrantyPrice = await _priceCalculationService.GetProductAttributeValuePriceAdjustmentAsync( product, attributeValue, customer, product.CustomerEntersPrice?(decimal?)customerEnteredPrice : null ); } else { attributesTotalPrice += await _priceCalculationService.GetProductAttributeValuePriceAdjustmentAsync( product, attributeValue, customer, product.CustomerEntersPrice?(decimal?)customerEnteredPrice : null ); } } } //get price of a product (with previously calculated price of all attributes) if (product.CustomerEntersPrice) { finalPrice = customerEnteredPrice; } else { int qty; if (_shoppingCartSettings.GroupTierPricesForDistinctShoppingCartItems) { //the same products with distinct product attributes could be stored as distinct "ShoppingCartItem" records //so let's find how many of the current products are in the cart qty = (await GetShoppingCartAsync(customer, shoppingCartType: shoppingCartType, productId: product.Id)) .Sum(x => x.Quantity); if (qty == 0) { qty = quantity; } } else { qty = quantity; } (_, finalPrice, discountAmount, appliedDiscounts) = await _priceCalculationService.GetFinalPriceAsync(product, customer, attributesTotalPrice, includeDiscounts, qty, product.IsRental?rentalStartDate : null, product.IsRental?rentalEndDate : null); finalPrice += warrantyPrice; } } //rounding if (_shoppingCartSettings.RoundPricesDuringCalculation) { finalPrice = await _priceCalculationService.RoundPriceAsync(finalPrice); } return(finalPrice, discountAmount, appliedDiscounts); }