diff --git a/src/Smartstore.Modules/Smartstore.PayPal/Client/PayPalHttpClient.cs b/src/Smartstore.Modules/Smartstore.PayPal/Client/PayPalHttpClient.cs index 9993bec541..b0ed0fdd8b 100644 --- a/src/Smartstore.Modules/Smartstore.PayPal/Client/PayPalHttpClient.cs +++ b/src/Smartstore.Modules/Smartstore.PayPal/Client/PayPalHttpClient.cs @@ -386,6 +386,8 @@ private async Task> GetPurchaseUnitItemsAsync(ShoppingCar var batchContext = _productService.CreateProductBatchContext(cartProducts, null, customer, false); var calculationOptions = _priceCalculationService.CreateDefaultOptions(false, customer, _currencyService.PrimaryCurrency, batchContext); + var isVatExempt = await _taxService.IsVatExemptAsync(customer); + foreach (var item in model.Items) { var cartItem = cart.Items.Where(x => x.Item.ProductId == item.ProductId).FirstOrDefault(); @@ -399,7 +401,7 @@ private async Task> GetPurchaseUnitItemsAsync(ShoppingCar var productName = item.ProductName?.Value?.Truncate(126); var productDescription = item.ShortDesc?.Value?.Truncate(126); - purchaseUnitItems.Add(new PurchaseUnitItem + var purchaseUnitItem = new PurchaseUnitItem { UnitAmount = new MoneyMessage { @@ -410,14 +412,20 @@ private async Task> GetPurchaseUnitItemsAsync(ShoppingCar Description = productDescription, Category = item.IsEsd ? ItemCategoryType.DigitalGoods : ItemCategoryType.PhysicalGoods, Quantity = item.EnteredQuantity.ToString(), - Sku = item.Sku, - Tax = new MoneyMessage + Sku = item.Sku + }; + + if (!isVatExempt) + { + purchaseUnitItem.Tax = new MoneyMessage { Value = convertedUnitPriceTax.Amount.ToStringInvariant("F"), CurrencyCode = currency.CurrencyCode - }, - TaxRate = taxRate.Rate.ToStringInvariant("F") - }); + }; + purchaseUnitItem.TaxRate = taxRate.Rate.ToStringInvariant("F"); + } + + purchaseUnitItems.Add(purchaseUnitItem); } return purchaseUnitItems; @@ -432,10 +440,11 @@ private async Task> GetPurchaseUnitItemsAsync(ShoppingCar var currency = _workContext.WorkingCurrency; var purchaseUnitItems = await GetPurchaseUnitItemsAsync(cart, customer, currency); + var isVatExempt = await _taxService.IsVatExemptAsync(customer); // Get subtotal var cartSubTotalExclTax = await _orderCalculationService.GetShoppingCartSubtotalAsync(cart, false); - var cartSubTotalinklTax = await _orderCalculationService.GetShoppingCartSubtotalAsync(cart, true); + var cartSubTotalInklTax = await _orderCalculationService.GetShoppingCartSubtotalAsync(cart, true); var subTotalConverted = _currencyService.ConvertFromPrimaryCurrency(cartSubTotalExclTax.SubtotalWithoutDiscount.Amount, currency); // Get tax @@ -452,7 +461,7 @@ private async Task> GetPurchaseUnitItemsAsync(ShoppingCar purchaseUnitItems.Each(x => itemTotal += x.UnitAmount.Value.Convert() * x.Quantity.ToInt()); decimal itemTotalTax = 0; - purchaseUnitItems.Each(x => itemTotalTax += x.Tax.Value.Convert() * x.Quantity.ToInt()); + purchaseUnitItems.Each(x => itemTotalTax += x.Tax != null ? x.Tax.Value.Convert() * x.Quantity.ToInt() : 0); var purchaseUnit = new PurchaseUnit { @@ -492,7 +501,16 @@ private async Task> GetPurchaseUnitItemsAsync(ShoppingCar orderTotalDiscountAmount = _currencyService.ConvertFromPrimaryCurrency(cartTotal.DiscountAmount.Amount, currency); } - decimal discountAmount = _roundingHelper.Round(orderTotalDiscountAmount.Amount + cartSubTotalinklTax.DiscountAmount.Amount); + var subTotalDiscountAmount = new Money(); + if (cartSubTotalInklTax.DiscountAmount > decimal.Zero) + { + subTotalDiscountAmount = _currencyService.ConvertFromPrimaryCurrency( + isVatExempt ? cartSubTotalExclTax.DiscountAmount.Amount : cartSubTotalInklTax.DiscountAmount.Amount, + currency); + } + + decimal discountAmount = _roundingHelper.Round(orderTotalDiscountAmount.Amount + subTotalDiscountAmount.Amount); + purchaseUnit.Amount.AmountBreakdown.Discount = new MoneyMessage { Value = discountAmount.ToStringInvariant("F"), @@ -500,14 +518,14 @@ private async Task> GetPurchaseUnitItemsAsync(ShoppingCar }; // Get shipping cost - var shippingTotal = await _orderCalculationService.GetShoppingCartShippingTotalAsync(cart, true); - decimal shippingTotalAmount = 0; + var shippingTotal = await _orderCalculationService.GetShoppingCartShippingTotalAsync(cart, !isVatExempt); + var shippingTotalAmount = new Money(); if (shippingTotal.ShippingTotal != null) { - shippingTotalAmount = _roundingHelper.Round(shippingTotal.ShippingTotal.Value.Amount); + shippingTotalAmount = _currencyService.ConvertFromPrimaryCurrency(_roundingHelper.Round(shippingTotal.ShippingTotal.Value.Amount), currency); purchaseUnit.Amount.AmountBreakdown.Shipping = new MoneyMessage { - Value = shippingTotal.ShippingTotal.Value.Amount.ToStringInvariant("F"), + Value = shippingTotalAmount.Amount.ToStringInvariant("F"), CurrencyCode = currency.CurrencyCode }; } @@ -519,7 +537,7 @@ private async Task> GetPurchaseUnitItemsAsync(ShoppingCar // TODO: (mh) (core) This is very hackish. PayPal was contacted and requested for a correct solution. // Lets check for rounding issues. - var calculatedAmount = itemTotal + itemTotalTax + shippingTotalAmount - discountAmount; + var calculatedAmount = itemTotal + itemTotalTax + shippingTotalAmount.Amount - discountAmount; var amountMismatch = calculatedAmount != purchaseUnit.Amount.Value.Convert(); if (amountMismatch) {