VAT not being deducted from total

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
12 anos atrás
I've set up the VAT exempt status for orders outside of the EU, however, when doing a dummy checkout, the tax line reads "include tax of £0.00" but the VAT amount is not deducted from the price.

Any suggestions? I followed this guide here: https://www.nopcommerce.com/boards/t/7455/vat-configuration-guide.aspx

but seem to have overlooked a rather crucial and obvious step!

My settings are:
Prices include tax: YES
Tax display type: INCLUDING TAX
Display tax suffix: NO
Display all applied tax rates: NO
Hide zero tax: NO
Hide tax in order summary: NO
Tax based on: SHIPPING ADDRESS
Default Country: UK
Shipping is taxable: NO
Payment method additional fee is taxable: NO
EU VAT enabled: YES
Your shop country: UK
Allow VAT exemption: YES
Use web service: NO
Notify admin when a new VAT number is submitted: NO


Many thanks!
11 anos atrás
I think I have encountered the same issue.
When "Prices include tax" and "Allow VAT exemption" are set to True, the VAT calculation seems to be wrong.
The tax is not substracted of the prices (wich include VAT), while it should when there's (valid) VAT number entered.

I suspect that if "Allow VAT exemption" is checked all VAT calculations are discarded?
Can someone please verify that this a bug or submit a resolution for this problem?

Many thanks.
11 anos atrás
In Nop.Services\Tax\TaxService.cs in Method  GetTaxRate:


            //make EU VAT exempt validation (the European Union Value Added Tax)
            if (_taxSettings.EuVatEnabled)
            {
                if (IsVatExempt(calculateTaxRequest.Address, calculateTaxRequest.Customer))
                {
                    //return zero if VAT is not chargeable
                    return decimal.Zero;
                }
            }

This will return 0 if "Allow VAT exemption" customer is has VAT exemption.


        protected decimal CalculatePrice(decimal price, decimal percent, bool increase)
        {
            decimal result = decimal.Zero;
            if (percent == decimal.Zero)
                return price;

            if (increase)
            {
                result = price * (1 + percent / 100);
            }
            else
            {
                result = price - (price) / (100 + percent) * percent;
            }
            return result;
        }

Then the CalculatePrice will return the price without the VAT substracted.

Can someone confirm this is wrong or am i missing something?
11 anos atrás
Hi,

i've had the same issue here:
When the store is set up for end customers i.e. with all prices including the VAT
and there is a company in a foreign EU country with a valid VAT number placing an order,
the VAT was indeed not deducted from the end total.

I changed following two classes to fix this:

In OrderTotalCalculationService.cs:

            // approx. on line 839
            // don't add VAT when EU VAT exempt validation is active (the European Union Value Added Tax)
            // and customer has valid VAT nr
            //
                   // GetTaxAddress method will be created/extracted in TaxService
            if (_taxSettings.EuVatEnabled && _taxService.IsVatExempt(_taxService.GetTaxAddress(customer), customer))
            {
                // add nothing to total then (easier to read this way without negations)
            }
            else
            {
                // only add VAT in all other situations
                resultTemp += shoppingCartTax;
            }



In TaxService.cs:
     1. extracted method  "public Address GetTaxAddress(Customer customer)" out of CreateCalculateTaxRequest
           (needs to be available for TaxService too)
           (approx. on line 78)

        protected CalculateTaxRequest CreateCalculateTaxRequest(ProductVariant productVariant,
            int taxCategoryId, Customer customer)
        {
            var calculateTaxRequest = new CalculateTaxRequest();
            calculateTaxRequest.Customer = customer;
            if (taxCategoryId > 0)
            {
                calculateTaxRequest.TaxCategoryId = taxCategoryId;
            }
            else
            {
                if (productVariant != null)
                    calculateTaxRequest.TaxCategoryId = productVariant.TaxCategoryId;
            }

            

            calculateTaxRequest.Address = GetTaxAddress(customer);
            return calculateTaxRequest;
        }

        // also needed for OrderTotalCalculationService
        public Address GetTaxAddress(Customer customer) {

            var basedOn = _taxSettings.TaxBasedOn;

            if (basedOn == TaxBasedOn.BillingAddress)
            {
                if (customer == null || customer.BillingAddress == null)
                {
                    basedOn = TaxBasedOn.DefaultAddress;
                }
            }
            if (basedOn == TaxBasedOn.ShippingAddress)
            {
                if (customer == null || customer.ShippingAddress == null)
                {
                    basedOn = TaxBasedOn.DefaultAddress;
                }
            }

            Address address = null;

            switch (basedOn)
            {
                case TaxBasedOn.BillingAddress:
                    {
                        address = customer.BillingAddress;
                    }
                    break;
                case TaxBasedOn.ShippingAddress:
                    {
                        address = customer.ShippingAddress;
                    }
                    break;
                case TaxBasedOn.DefaultAddress:
                default:
                    {
                        address = _addressService.GetAddressById(_taxSettings.DefaultTaxAddressId);
                    }
                    break;
            }

            return address;

        }

      2. in GetTaxRate disable following two blocks (approx. on line 223), because tax rate should be calculated just as always, but should only not be added in the end total <- this will be done in OrderTotalCalculationService

        public virtual decimal GetTaxRate(ProductVariant productVariant, int taxCategoryId,
            Customer customer)
        {
            
            //tax exempt
            //if (IsTaxExempt(productVariant, customer))
            //{
            //    return decimal.Zero;
            //}

            //tax request
            var calculateTaxRequest = CreateCalculateTaxRequest(productVariant, taxCategoryId, customer);

            
            //make EU VAT exempt validation (the European Union Value Added Tax)
            //if (_taxSettings.EuVatEnabled)
            //{
            //    if (IsVatExempt(calculateTaxRequest.Address, calculateTaxRequest.Customer))
            //    {
            //        //return zero if VAT is not chargeable
            //        return decimal.Zero;
            //    }
            //}

        ... etc.


       3. in GetProductPrice (approx. on line 310) to get the product price, it should always take the correct TaxCategory

        public virtual decimal GetProductPrice(ProductVariant productVariant, decimal price,
            bool includingTax, Customer customer, out decimal taxRate)
        {
            bool priceIncludesTax = _taxSettings.PricesIncludeTax;
            int taxCategoryId = productVariant.TaxCategoryId; // instead of int taxCategoryId = 0;
            return GetProductPrice(productVariant, taxCategoryId, price, includingTax,
                customer, priceIncludesTax, out taxRate);
        }



This should do the trick:

i tested following four scenario's for a Belgian shop with VAT exemption enabled (Belgium and Netherlands both in EU):

Belgian end customer buys something, sees VAT amount + has to pay total price with VAT
Dutch end customer buys something, sees VAT amount + has to pay total price with VAT
Belgian company with valid VAT nr buys something, sees VAT amount + has to pay total price with VAT
Dutch company with valid VAT nr buys something, sees VAT amount, but total price is WITHOUT VAT


Hopefully this can help, does not break other functionallity or logic for other countries
and maybe it could be taken into the core version so that it's there for following Nop releases ?

Thanx to the Nop guys anyway for there very nice job on this system !!

kind regards, Bart
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.