public async Task <TaxTotalResult> GetTaxTotalAsync(TaxTotalRequest taxTotalRequest) { if (_httpContextAccessor.HttpContext.Items.TryGetValue("nop.TaxTotal", out var result) && result is (TaxTotalResult taxTotalResult, decimal paymentTax)) { //short-circuit to avoid circular reference when calculating payment method additional fee during the checkout process if (!taxTotalRequest.UsePaymentMethodAdditionalFee) { return new TaxTotalResult { TaxTotal = taxTotalResult.TaxTotal - paymentTax } } ; return(taxTotalResult); } var taxRates = new SortedDictionary <decimal, decimal>(); var taxTotal = decimal.Zero; taxTotal += await GetSubtotalTaxTotalAsync(taxRates, taxTotalRequest); taxTotal += await GetShippingTaxAsync(taxRates, taxTotalRequest); //short-circuit to avoid circular reference when calculating payment method additional fee during the checkout process if (!taxTotalRequest.UsePaymentMethodAdditionalFee) { return new TaxTotalResult { TaxTotal = taxTotal } } ; var paymentMethodAdditionalFeeTax = await GetPaymentMethodAdditionalFeeTaxAsync(taxRates, taxTotalRequest); taxTotal += paymentMethodAdditionalFeeTax; //add at least one tax rate (0%) if (!taxRates.Any()) { taxRates.Add(decimal.Zero, decimal.Zero); } if (taxTotal < decimal.Zero) { taxTotal = decimal.Zero; } taxTotalResult = new TaxTotalResult { TaxTotal = taxTotal, TaxRates = taxRates, }; //store values within the scope of the request to avoid duplicate calculations _httpContextAccessor.HttpContext.Items.TryAdd("nop.TaxTotal", (taxTotalResult, paymentMethodAdditionalFeeTax)); return(taxTotalResult); }
/// <summary> /// Gets tax total /// </summary> /// <param name="taxTotalRequest">Tax total request</param> /// <returns> /// A task that represents the asynchronous operation /// The task result contains the ax total /// </returns> public async Task <TaxTotalResult> GetTaxTotalAsync(TaxTotalRequest taxTotalRequest) { //cache tax total within the request var key = $"nop.TaxTotal-{taxTotalRequest.UsePaymentMethodAdditionalFee}"; if (!(_actionContextAccessor.ActionContext.HttpContext.Items.TryGetValue(key, out var result) && result is TaxTotalResult taxTotalResult)) { //create a transaction var transaction = await _avalaraTaxManager.CreateTaxTotalTransactionAsync(taxTotalRequest); if (transaction?.totalTax == null) { return new TaxTotalResult { Errors = new List <string> { "No response from the service" } } } ; //and get tax details taxTotalResult = new TaxTotalResult { TaxTotal = transaction.totalTax.Value }; transaction.summary? .Where(summary => summary.rate.HasValue && summary.tax.HasValue) .Select(summary => new { Rate = summary.rate.Value * 100, Value = summary.tax.Value }) .ToList().ForEach(taxRate => { if (taxTotalResult.TaxRates.ContainsKey(taxRate.Rate)) { taxTotalResult.TaxRates[taxRate.Rate] += taxRate.Value; } else { taxTotalResult.TaxRates.Add(taxRate.Rate, taxRate.Value); } }); _actionContextAccessor.ActionContext.HttpContext.Items.TryAdd(key, taxTotalResult); } return(taxTotalResult); }
/// <summary> /// Gets tax total /// </summary> /// <param name="taxTotalRequest">Tax total request</param> /// <returns>Tax total</returns> public TaxTotalResult GetTaxTotal(TaxTotalRequest taxTotalRequest) { if (!(_httpContextAccessor.HttpContext.Items.TryGetValue("nop.TaxTotal", out var result) && result is TaxTotalResult taxTotalResult)) { var taxRates = new SortedDictionary <decimal, decimal>(); //order sub total (items + checkout attributes) _orderTotalCalculationService .GetShoppingCartSubTotal(taxTotalRequest.ShoppingCart, false, out _, out _, out _, out _, out var orderSubTotalTaxRates); var subTotalTaxTotal = decimal.Zero; foreach (var kvp in orderSubTotalTaxRates) { var taxRate = kvp.Key; var taxValue = kvp.Value; subTotalTaxTotal += taxValue; if (taxRate > decimal.Zero && taxValue > decimal.Zero) { if (!taxRates.ContainsKey(taxRate)) { taxRates.Add(taxRate, taxValue); } else { taxRates[taxRate] = taxRates[taxRate] + taxValue; } } } //shipping var shippingTax = decimal.Zero; if (_taxSettings.ShippingIsTaxable) { var shippingExclTax = _orderTotalCalculationService .GetShoppingCartShippingTotal(taxTotalRequest.ShoppingCart, false, out _); var shippingInclTax = _orderTotalCalculationService .GetShoppingCartShippingTotal(taxTotalRequest.ShoppingCart, true, out var taxRate); if (shippingExclTax.HasValue && shippingInclTax.HasValue) { shippingTax = shippingInclTax.Value - shippingExclTax.Value; if (shippingTax < decimal.Zero) { shippingTax = decimal.Zero; } if (taxRate > decimal.Zero && shippingTax > decimal.Zero) { if (!taxRates.ContainsKey(taxRate)) { taxRates.Add(taxRate, shippingTax); } else { taxRates[taxRate] = taxRates[taxRate] + shippingTax; } } } } //add at least one tax rate (0%) if (!taxRates.Any()) { taxRates.Add(decimal.Zero, decimal.Zero); } var taxTotal = subTotalTaxTotal + shippingTax; if (taxTotal < decimal.Zero) { taxTotal = decimal.Zero; } taxTotalResult = new TaxTotalResult { TaxTotal = taxTotal, TaxRates = taxRates }; _httpContextAccessor.HttpContext.Items.TryAdd("nop.TaxTotal", taxTotalResult); } //payment method additional fee if (taxTotalRequest.UsePaymentMethodAdditionalFee && _taxSettings.PaymentMethodAdditionalFeeIsTaxable) { var paymentMethodSystemName = taxTotalRequest.Customer != null ? _genericAttributeService.GetAttribute <string>(taxTotalRequest.Customer, NopCustomerDefaults.SelectedPaymentMethodAttribute, taxTotalRequest.StoreId) : string.Empty; var paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(taxTotalRequest.ShoppingCart, paymentMethodSystemName); var paymentMethodAdditionalFeeExclTax = _taxService .GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, false, taxTotalRequest.Customer, out _); var paymentMethodAdditionalFeeInclTax = _taxService .GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee, true, taxTotalRequest.Customer, out var taxRate); var paymentMethodAdditionalFeeTax = paymentMethodAdditionalFeeInclTax - paymentMethodAdditionalFeeExclTax; if (paymentMethodAdditionalFeeTax < decimal.Zero) { paymentMethodAdditionalFeeTax = decimal.Zero; } taxTotalResult.TaxTotal += paymentMethodAdditionalFeeTax; if (taxRate > decimal.Zero && paymentMethodAdditionalFeeTax > decimal.Zero) { if (!taxTotalResult.TaxRates.ContainsKey(taxRate)) { taxTotalResult.TaxRates.Add(taxRate, paymentMethodAdditionalFeeTax); } else { taxTotalResult.TaxRates[taxRate] = taxTotalResult.TaxRates[taxRate] + paymentMethodAdditionalFeeTax; } } } return(taxTotalResult); }
/// <summary> /// Ctor /// </summary> /// <param name="taxTotalRequest">Tax total request</param> /// <param name="taxTotalResult">Tax total result</param> public TaxTotalCalculatedEvent(TaxTotalRequest taxTotalRequest, TaxTotalResult taxTotalResult) { TaxTotalRequest = taxTotalRequest; TaxTotalResult = taxTotalResult; }
/// <summary> /// Gets tax total /// </summary> /// <param name="taxTotalRequest">Tax total request</param> /// <returns> /// A task that represents the asynchronous operation /// The task result contains the ax total /// </returns> public async Task <TaxTotalResult> GetTaxTotalAsync(TaxTotalRequest taxTotalRequest) { if (_httpContextAccessor.HttpContext.Items.TryGetValue("nop.TaxTotal", out var result) && result is (TaxTotalResult taxTotalResult, decimal paymentTax)) { //short-circuit to avoid circular reference when calculating payment method additional fee during the checkout process if (!taxTotalRequest.UsePaymentMethodAdditionalFee) { return new TaxTotalResult { TaxTotal = taxTotalResult.TaxTotal - paymentTax } } ; return(taxTotalResult); } var taxRates = new SortedDictionary <decimal, decimal>(); var taxTotal = decimal.Zero; //order sub total (items + checkout attributes) var(_, _, _, _, orderSubTotalTaxRates) = await _orderTotalCalculationService .GetShoppingCartSubTotalAsync(taxTotalRequest.ShoppingCart, false); var subTotalTaxTotal = decimal.Zero; foreach (var kvp in orderSubTotalTaxRates) { var taxRate = kvp.Key; var taxValue = kvp.Value; subTotalTaxTotal += taxValue; if (taxRate > decimal.Zero && taxValue > decimal.Zero) { if (!taxRates.ContainsKey(taxRate)) { taxRates.Add(taxRate, taxValue); } else { taxRates[taxRate] = taxRates[taxRate] + taxValue; } } } taxTotal += subTotalTaxTotal; //shipping var shippingTax = decimal.Zero; if (_taxSettings.ShippingIsTaxable) { var(shippingExclTax, _, _) = await _orderTotalCalculationService .GetShoppingCartShippingTotalAsync(taxTotalRequest.ShoppingCart, false); var(shippingInclTax, taxRate, _) = await _orderTotalCalculationService .GetShoppingCartShippingTotalAsync(taxTotalRequest.ShoppingCart, true); if (shippingExclTax.HasValue && shippingInclTax.HasValue) { shippingTax = shippingInclTax.Value - shippingExclTax.Value; if (shippingTax < decimal.Zero) { shippingTax = decimal.Zero; } if (taxRate > decimal.Zero && shippingTax > decimal.Zero) { if (!taxRates.ContainsKey(taxRate)) { taxRates.Add(taxRate, shippingTax); } else { taxRates[taxRate] = taxRates[taxRate] + shippingTax; } } } } taxTotal += shippingTax; //short-circuit to avoid circular reference when calculating payment method additional fee during the checkout process if (!taxTotalRequest.UsePaymentMethodAdditionalFee) { return new TaxTotalResult { TaxTotal = taxTotal } } ; //payment method additional fee var paymentMethodAdditionalFeeTax = decimal.Zero; if (_taxSettings.PaymentMethodAdditionalFeeIsTaxable) { var paymentMethodSystemName = taxTotalRequest.Customer != null ? await _genericAttributeService .GetAttributeAsync <string>(taxTotalRequest.Customer, NopCustomerDefaults.SelectedPaymentMethodAttribute, taxTotalRequest.StoreId) : string.Empty; var paymentMethodAdditionalFee = await _paymentService .GetAdditionalHandlingFeeAsync(taxTotalRequest.ShoppingCart, paymentMethodSystemName); var(paymentMethodAdditionalFeeExclTax, _) = await _taxService .GetPaymentMethodAdditionalFeeAsync(paymentMethodAdditionalFee, false, taxTotalRequest.Customer); var(paymentMethodAdditionalFeeInclTax, taxRate) = await _taxService .GetPaymentMethodAdditionalFeeAsync(paymentMethodAdditionalFee, true, taxTotalRequest.Customer); paymentMethodAdditionalFeeTax = paymentMethodAdditionalFeeInclTax - paymentMethodAdditionalFeeExclTax; if (paymentMethodAdditionalFeeTax < decimal.Zero) { paymentMethodAdditionalFeeTax = decimal.Zero; } if (taxRate > decimal.Zero && paymentMethodAdditionalFeeTax > decimal.Zero) { if (!taxRates.ContainsKey(taxRate)) { taxRates.Add(taxRate, paymentMethodAdditionalFeeTax); } else { taxRates[taxRate] = taxRates[taxRate] + paymentMethodAdditionalFeeTax; } } } taxTotal += paymentMethodAdditionalFeeTax; //add at least one tax rate (0%) if (!taxRates.Any()) { taxRates.Add(decimal.Zero, decimal.Zero); } if (taxTotal < decimal.Zero) { taxTotal = decimal.Zero; } taxTotalResult = new TaxTotalResult { TaxTotal = taxTotal, TaxRates = taxRates, }; //store values within the scope of the request to avoid duplicate calculations _httpContextAccessor.HttpContext.Items.TryAdd("nop.TaxTotal", (taxTotalResult, paymentMethodAdditionalFeeTax)); return(taxTotalResult); }
/// <summary> /// Ctor /// </summary> /// <param name="taxTotalResult">Tax total result</param> public TaxTotalCalculatedEvent(TaxTotalResult taxTotalResult) { TaxTotalResult = taxTotalResult; }