Tom Aalbers
Tom Aalbers

Reputation: 4924

Deduct taxes from shopping cart total when delivery is in certain country

I am working on a nopcommerce webshop which standard shows all his prices including taxes (21%). So the subtotals that are shown in the shopping cart have the taxes included. After the customer decided which products to buy and starts to finishing the order it should check the location of the customer (this by the shipping address)

What I am trying to do is when a customer is finishing up the order it should deduct (or not depending on what country the customer is living.) the taxes.

e.g when living in the Netherlands it should not deduct the taxes from the total order price but when living in the United States it should remove the 21% tax en deduct that from the total order price.

I've tried playing with some settings in the nop commerce admin in

 Configuration -> Settings -> Tax Settings

My current tax settings are:

Prices include tax: YES
Allow customers to select tax display type: NO
Tax display type: Including Tax
Display tax suffix: YES
Display all applied tax rates: YES
Hide zero tax: NO
Hide tax in order summary: NO
Force tax exclusion from order subtotal: NO
Tax based on: Shipping address
Country: Netherlands
Shipping is taxable: YES
Shipping price includes tax: YES
Payment method additional fee is taxable: YES
Payment method additional fee includes tax: YES
EU VAT enabled: NO

Also

 Configuration -> Tax -> Tax Providers
 Configuration -> Tax -> Tax Categories

Options for Tax providers are Fixed tax rate provider and Tax By Country & State & Zip (which is the primary provider)

I can't seem to find the right settings. Also I have tried to debug through the code in the OrderTotalCalculationService.cs class which is used when finishing up the order. But I couldn't really find what struck me as the right code to look in.

I'm not sure if it is a settings problem or a code problem.

EDIT: Sorry that I didn't mention any code. But I've been looking through this function from nopcommerce.

    public virtual decimal? GetShoppingCartTotal(IList<ShoppingCartItem> cart,
        out decimal discountAmount, out Discount appliedDiscount,
        out List<AppliedGiftCard> appliedGiftCards,
        out int redeemedRewardPoints, out decimal redeemedRewardPointsAmount,
        bool ignoreRewardPonts = false, bool usePaymentMethodAdditionalFee = true)
    {
        redeemedRewardPoints = 0;
        redeemedRewardPointsAmount = decimal.Zero;

        var customer = cart.GetCustomer();
        string paymentMethodSystemName = "";
        if (customer != null)
        {
            paymentMethodSystemName = customer.GetAttribute<string>(
                SystemCustomerAttributeNames.SelectedPaymentMethod,
                _genericAttributeService,
                _storeContext.CurrentStore.Id);
        }


        //subtotal without tax
        decimal subtotalBase = decimal.Zero;
        decimal orderSubTotalDiscountAmount = decimal.Zero;
        Discount orderSubTotalAppliedDiscount = null;
        decimal subTotalWithoutDiscountBase = decimal.Zero;
        decimal subTotalWithDiscountBase = decimal.Zero;
        GetShoppingCartSubTotal(cart, false,
            out orderSubTotalDiscountAmount, out orderSubTotalAppliedDiscount,
            out subTotalWithoutDiscountBase, out subTotalWithDiscountBase);
        //subtotal with discount
        subtotalBase = subTotalWithDiscountBase;



        //shipping without tax
        decimal? shoppingCartShipping = GetShoppingCartShippingTotal(cart, false);



        //payment method additional fee without tax
        decimal paymentMethodAdditionalFeeWithoutTax = decimal.Zero;
        if (usePaymentMethodAdditionalFee && !String.IsNullOrEmpty(paymentMethodSystemName))
        {
            decimal paymentMethodAdditionalFee = _paymentService.GetAdditionalHandlingFee(cart, paymentMethodSystemName);
            paymentMethodAdditionalFeeWithoutTax = _taxService.GetPaymentMethodAdditionalFee(paymentMethodAdditionalFee,
                false, customer);
        }




        //tax
        decimal shoppingCartTax = GetTaxTotal(cart, usePaymentMethodAdditionalFee);




        //order total
        decimal resultTemp = decimal.Zero;
        resultTemp += subtotalBase;
        if (shoppingCartShipping.HasValue)
        {
            resultTemp += shoppingCartShipping.Value;
        }
        resultTemp += paymentMethodAdditionalFeeWithoutTax;
        resultTemp += shoppingCartTax;
        if (_shoppingCartSettings.RoundPricesDuringCalculation) 
            resultTemp = Math.Round(resultTemp, 2);

        #region Order total discount

        discountAmount = GetOrderTotalDiscount(customer, resultTemp, out appliedDiscount);

        //sub totals with discount        
        if (resultTemp < discountAmount)
            discountAmount = resultTemp;

        //reduce subtotal
        resultTemp -= discountAmount;

        if (resultTemp < decimal.Zero)
            resultTemp = decimal.Zero;
        if (_shoppingCartSettings.RoundPricesDuringCalculation) 
            resultTemp = Math.Round(resultTemp, 2);

        #endregion

        #region Applied gift cards

        //let's apply gift cards now (gift cards that can be used)
        appliedGiftCards = new List<AppliedGiftCard>();
        if (!cart.IsRecurring())
        {
            //we don't apply gift cards for recurring products
            var giftCards = _giftCardService.GetActiveGiftCardsAppliedByCustomer(customer);
            if (giftCards!=null)
                foreach (var gc in giftCards)
                    if (resultTemp > decimal.Zero)
                    {
                        decimal remainingAmount = gc.GetGiftCardRemainingAmount();
                        decimal amountCanBeUsed = decimal.Zero;
                        if (resultTemp > remainingAmount)
                            amountCanBeUsed = remainingAmount;
                        else
                            amountCanBeUsed = resultTemp;

                        //reduce subtotal
                        resultTemp -= amountCanBeUsed;

                        var appliedGiftCard = new AppliedGiftCard();
                        appliedGiftCard.GiftCard = gc;
                        appliedGiftCard.AmountCanBeUsed = amountCanBeUsed;
                        appliedGiftCards.Add(appliedGiftCard);
                    }
        }

        #endregion

        if (resultTemp < decimal.Zero)
            resultTemp = decimal.Zero;
        if (_shoppingCartSettings.RoundPricesDuringCalculation)
            resultTemp = Math.Round(resultTemp, 2);

        decimal? orderTotal = null;
        if (!shoppingCartShipping.HasValue)
        {
            //return null if we have errors
            orderTotal = null;
            return orderTotal;
        }
        else
        {
            //return result if we have no errors
            orderTotal = resultTemp;
        }

        #region Reward points

        if (_rewardPointsSettings.Enabled && 
            !ignoreRewardPonts &&
            customer.GetAttribute<bool>(SystemCustomerAttributeNames.UseRewardPointsDuringCheckout,
            _genericAttributeService, _storeContext.CurrentStore.Id))
        {
            int rewardPointsBalance = customer.GetRewardPointsBalance();
            if (CheckMinimumRewardPointsToUseRequirement(rewardPointsBalance))
            {
                decimal rewardPointsBalanceAmount = ConvertRewardPointsToAmount(rewardPointsBalance);
                if (orderTotal.HasValue && orderTotal.Value > decimal.Zero)
                {
                    if (orderTotal.Value > rewardPointsBalanceAmount)
                    {
                        redeemedRewardPoints = rewardPointsBalance;
                        redeemedRewardPointsAmount = rewardPointsBalanceAmount;
                    }
                    else
                    {
                        redeemedRewardPointsAmount = orderTotal.Value;
                        redeemedRewardPoints = ConvertAmountToRewardPoints(redeemedRewardPointsAmount);
                    }
                }
            }
        }
        #endregion

        if (orderTotal.HasValue)
        {
            orderTotal = orderTotal.Value - redeemedRewardPointsAmount;
            if (_shoppingCartSettings.RoundPricesDuringCalculation) 
                orderTotal = Math.Round(orderTotal.Value, 2);
            return orderTotal;
        }
        else
            return null;
    }

This piece of code seems to calculate the total of the shoppingcart in the order flow. But I can't find the part that checks the shipping address and deducts the tax from the order total when in the united states. Does anybody know where the code checks for the tax?

Upvotes: 1

Views: 1084

Answers (2)

Tassisto
Tassisto

Reputation: 10345

@TomAalbers

I enabled the default tax plugin (Tax.CountryStateZip) & made it primary tax provider. I configured the plugin by applying 0% on (existing) tax categories for the countries that are free from taxations. And for the countries I want to receive taxes I've set a percentage per tax category.

I hope this is clear, if not I can update my answer with screenshots.

Upvotes: 0

wooncherk
wooncherk

Reputation: 1364

Other than OrderTotalCalculationService, you should also be looking at TaxService. Also, Tax By Country plugin should be flexible enough to handle the scenario you mentioned.

Upvotes: 1

Related Questions