TAX CALCULATED BEFORE DISCOUNT TAKEN, CUSTOMER PAYS TAX ON NOTHING

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
13 anos atrás
I'm not sure if this is a bug or if it is by design, but when you have a discount set using a code word/ the discount is applied AFTER the tax has been calculated on the order total. So this happens:

Order total: $10.00
Order Tax (7%): $0.70
Order discount (20%): $2.00
Order total after discount: $8.00
Order tax after discount: $0.70 <-- should be $0.56
Order total after discount plus tax: $8.70 <-- should be $8.56

The customer ends up paying tax on the discount, which is money that they don't have to pay - so why are they paying tax on it?? This may not be a big deal on small orders, but it makes a big difference in large orders. Not to mention the difference in tax amount if you have a payment processor that does its own tax calculation - like Paypal - and that calculation is different from nopCommerce's and the customer can see that.

Anyway... I have a fix for this, but it is complicated, maybe too complicated to post the code here... I don't think anyone would understand it. Is this something that an issue can be created for and the nopCommerce team can fix?

To explain shorty, my fix is this:

I send the OrderSubTotal with GetTaxTotal. I use OrderSubTotal and this code:

Discount orderDiscount; //<-- requires .promo.discounts import
Decimal appliedDiscount = decimal.Zero;
appliedDiscount = ShoppingCartManager.GetOrderDiscount(NopContext.Current.User, OrderSubTotal, out orderDiscount);
Decimal discountTax = 1m;
discountTax = discountTax - (appliedDiscount / OrderSubTotal);

to obtain discountTax, which is the percentage of the order that should be taxed. The formula goes:

OrderSubTotal ($10.00)
appliedDiscount ($2.00)
discountTax = 1 - ($2.00 / $10.00) = .80 <-- amount of order that should be charged tax

I then take discountTax and multiply it by the different tax totals at the end of each tax total section:

itemsTaxTotal = itemsTaxTotal * discountTax;
checkoutAttributesTax = checkoutAttributesTax * discountTax;
shippingTax = shippingTax * discountTax;
paymentMethodAdditionalFeeTax = paymentMethodAdditionalFeeTax * discountTax;

This gives me the correct amount of tax for each section, or so I thought. It turns out that there was a variance between this and what is SHOULD be. I found the variance when I noticed that TaxManager.GetPrice rounds the price... giving you something like this:

Price: $2.09
Tax: 7%
Price with tax (in decimal): 2.2363
GetPrice says: price = Math.Round(price, 2);
Price = $2.24

Difference = 0.0037

If you have a bunch of items this can add up. Even one penny off and it can lose you a sale with a customer.

I fixed this by adding a boolean flag to GetPrice called roundTax that determines if I need to round the tax or not. I had to do this for GetCheckoutAttributePrice too. In TaxManager the total tax is rounded before it is sent back, so each item does not need to be rounded individually.

If you understand that, you can fix it. If you don't then there is a LOT of code to post and you can try to figure out... or the nopCommerce team can fix it.

Can the nopCommerce team fix it?
13 anos atrás
I didn't realize that there was a topic on this already here:

https://www.nopcommerce.com/boards/t/5249/tax-is-calculated-on-pre-discount-amount.aspx

Apparently this has been an issue for awhile. Going back to version 1.30, getting fixed in 1.40, and apparetly showing back up in 1.70.

My fix is for 1.70... MAY work for 1.80, I don't know. I haven't played with 1.80 yet.
13 anos atrás
Here is my answer to this:

Ok... after going about it all wrong for two days, I finally figured out how to do this.

All you have to do it figure out what the discount percent is in relation to the order total (i.e. 20%, 30%) and multiply that by the tax total.

This fix requires minor changes to TaxManager.cs, ShoppingCartManager.cs, OrderTotals.ascx.cs, and OrderManager.cs.

The first thing you need to do is add the order subtotal to the GetTaxTotal method in TaxManager (around line 180).

public static decimal GetTaxTotal(ShoppingCart cart, int paymentMethodId, Customer customer, decimal OrderSubTotal, ref String error)
{
   ...
}

I use "OrderSubTotal", but you can use whatever you like.

This change will require fixing the broken method calls in other pages:

OrderManger.cs line 3095

paymentInfo.PaymentMethodId, customer, orderSubTotalExclTax, ref taxerror);

OrderTotals.ascx.cs line 143

decimal shoppingCartTaxBase = TaxManager.GetTaxTotal(cart, paymentMethodId, NopContext.Current.User, subtotalBaseWithoutPromo, ref TaxError);

ShoppingCartManager.cs line 342

decimal shoppingCartTax = TaxManager.GetTotalTax(cart, paymentMentodId, customer, subtotalBaseWithoutPromo, ref taxerror);

Next we go back to TaxManager and add this to the using/imports section:

using NopSolutions.NopCommerce.BusinessLogic.Promo.Discounts;

For the last step we go down to the end of GetTaxTotal (around line 276) and find the lines:

taxTotal = itemsTaxTotal + checkoutAttributesTax + shippingTax + paymentMethodAdditionalFeeTax;
taxTotal = Math.Round(taxTotal, 2);
return taxTotal;

and add a few lines in between them like this:

taxTotal = itemsTaxTotal + checkoutAttributesTax + shippingTax + paymentMethodAdditionalFeeTax;
Discount orderDiscount = null;
Decimal appliedDiscount = ShoppingCartManager.GetOrderDiscount(NopContext.Current.User, OrderSubTotal, out orderDiscount);
if (taxTotal > 0) {
taxTotal = taxTotal - (taxTotal * (appliedDiscount / OrderSubTotal));
}
taxTotal = Math.Round(taxTotal, 2);
return taxTotal;

I'm using 1.70 by the way.

This fix presupposes that no matter what the total or tax or discount amount is, the discount CAN be broken down into a percent of the total. This discount percent is then subtracted from the tax total leaving you with the proper tax.

I know of one alternative way to get OrderSubTotal without having to add it to the GetTaxTotal method, but it requires totalling up the order myself inside GetTaxTotal and I didn't like that way. Does anyone know of a way to get the order subtotal without having to import it in using GetTaxTotal? I'd be happy to know that... otherwise this should work just fine.

I have it working correctly with a discount on product variants in a cart that has a discount code applied to it with two different taxes on two different items as well as and item that has no tax on it. And to the best of my knowledge, when I figure out what the tax should be with a calulator, it matches up.

Any problems with this, let me know.
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.