Incorrect percentage discounts when prices are entered with tax, but displayed without (or vice-versa)

Created on 28 June 2018, over 6 years ago
Updated 26 April 2023, over 1 year ago

#2897190: Tax calculations do not take discounts (promotions) into account fixed the interaction between taxes and discounts for cases where prices are both entered and displayed with/without taxes.

However, if the prices are entered with tax but displayed without (also including tax-exempt prices), or vice-versa, the discounts are incorrect.
This is because LocalTaxTypeBase / TaxOrderProcessor modify the unit price (which modifies the total price) after the discounts were already calculated. So a 10% discount on 12 eur gets calculated and added as 1.2, then the price gets lowered to 10 eur. The discount is no longer correct, it is too large.

This means we probably need to process taxes in two phases:
1) Resolve rates, figure out if unit price needs to be modified, modify it
2) Calculate discounts
3) Now calculate taxes based on the resolved rates

🐛 Bug report
Status

Needs work

Version

2.0

Component

Tax

Created by

🇷🇸Serbia bojanz

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇨🇭Switzerland Lukas von Blarer

    This needs a re-roll.

    The patch has got BC. I have this error, because i have commerce_shipping promotions:

    ArgumentCountError: Too few arguments to function Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\PromotionOfferBase::__construct(), 4 passed in /app/web/modules/contrib/commerce_shipping/src/Plugin/Commerce/PromotionOffer/ShipmentPromotionOfferBase.php on line 53 and exactly 5 expected in Drupal\commerce_promotion\Plugin\Commerce\PromotionOffer\PromotionOfferBase->__construct() (line 52 of modules/contrib/commerce/modules/promotion/src/Plugin/Commerce/PromotionOffer/PromotionOfferBase.php).

    Can we achieve this without BC?

    The patch fixes the tax and promotion calculations. But since applying it, I see rounding errors.

  • 🇫🇷France Micka

    Hi,
    Do you have a solution for stack : PHP 8.1 - D9.5.9 - Drupal Commerce 8.x-2.36
    With a clean install and following parameters :
    - Custom Tax config : include in the product price (10%)
    - Promotion config : not include in the product price (displayed in total summary) (10%)
    - original product variation price : 100$

    Tax is not well if we consider it is calculated on without tax price.

    VAT : ((priceTTC - actual VAT) - discount) * actual VAT percentage
    VAT : ((110 - 9.09) - 10) * 0.1 = 9.09

    Subtotal : $110.00
    Discount : -$10.00
    VAT : $9.09
    Total : $100.00

    Expected :
    VAT : ((priceTTC - old VAT) - discount) * actual VAT percentage
    VAT : ((110 - 10) - 10) * 0.1 = 9

    Subtotal : $110.00
    Discount : -$10.00
    VAT : $9
    Total : $100.00

    Thanks in advance for your answer.
    And sorry if i misunderstood this issue (french english ^^).

  • 🇪🇸Spain aarnau

    New re-roll here

  • 🇷🇴Romania cslevy

    I recreated this patch to work with the latest commerce.

    But I also encounter rounding issues, and I think that the discount amounts should be always rounded half down, not up. I'm not sure if it's correct or not, but I created the patch in 2 versions. one as it was in the previous comment with round up, and one with round down.

    Please advise on this

  • 🇩🇪Germany Anybody Porta Westfalica
  • 🇫🇷France johaziel

    I had the same probleme too but I 'don't use promotion module to manage promotions,
    my config :
    product price entered without VAT (I didn't find where you manage prices are displayed with or without VAT )
    I using also commerce_tax_product
    one field_discount added to an order item type

    I directly add promotions in module like this

              $promotion = $order_item->get('field_promotion')->value;
              if($promotion > 0){
    
                // Calculate promotion
                $unit_price = $order_item->getUnitPrice();
                $discount_amount = $unit_price->multiply($order_item->getQuantity())->multiply('-' . strval( $promotion/100)); 
    
                $adjustment = new Adjustment([
                  'type' => 'promotion',
                  'label' => t('Discount'),
                  'amount' => $discount_amount,
                  'percentage' => strval($discount/100),
                  'source_id' => 'custom_discount',
                  'locked' => TRUE,
                ]);
                $order_item->addAdjustment($adjustment);
              }
    

    So I separated the patch to only be applied to tax module and calculations of price a ok
    my price without VAT is 50 €

  • 🇧🇪Belgium matthiasm11

    @ #47: I would advise against the mixing of excluding taxes in products and including taxes in promotions at the same time.

    A webshop including taxes in products, is often a B2C webshop, where the product price is something rounded (€50 incl. 21% VAT for example). The fixed amount of promotion should thus be € -10 incl. 21% VAT.

    A webshop excluding taxes in products, is often a B2B webshop, where both product prices and promotions can be communicated excluding VAT.

    Depending on the webshop requirements, one could argue to change this.

    At the moment, the tax setting is called "Prices are entered with taxes included.". It does not differentiate between products or promotions. I therefore rerolled patch #45 against 3.0.0-beta2.

    I also rerolled patch #45 against 3.0.0-beta2 containing merge request 371 from 🐛 Can't distinguish two taxes of different percentages in the order summary Needs review .

    IF we allow mixing this, the incl/excluding of VAT in promotions should be configurable, just like the VAT incl/excluded in products. It should fallback to the same setting as the incl/excluded VAT of products in an update hook. The todo based on the attached patch would then be:

    • Rename "Prices are entered with taxes included." to "Product prices are entered with taxes included."
    • Add setting "Promotion prices are entered with taxes included."
    • Alter TaxCalculator.php to use if ($store->get('prices_include_tax')->value || $store->get('promotion_prices_include_tax')->value) {
    • Add an update hook to set promotion_prices_include_tax based on prices_include_tax
Production build 0.71.5 2024