Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions app/code/Magento/SalesRule/Model/Utility.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ public function deltaRoundingFix(
) {
$discountAmount = $discountData->getAmount();
$baseDiscountAmount = $discountData->getBaseAmount();
$rowTotalInclTax = $item->getRowTotalInclTax();
$baseRowTotalInclTax = $item->getBaseRowTotalInclTax();

//TODO Seems \Magento\Quote\Model\Quote\Item\AbstractItem::getDiscountPercent() returns float value
//that can not be used as array index
Expand All @@ -205,6 +207,23 @@ public function deltaRoundingFix(
- $this->priceCurrency->round($baseDiscountAmount);
}

/**
* When we have 100% discount check if totals will not be negative
*/

if ($percentKey == 100) {
$discountDelta = $rowTotalInclTax - $discountAmount;
$baseDiscountDelta = $baseRowTotalInclTax - $baseDiscountAmount;

if ($discountDelta < 0) {
$discountAmount += $discountDelta;
}

if ($baseDiscountDelta < 0) {
$baseDiscountAmount += $baseDiscountDelta;
}
}

$discountData->setAmount($this->priceCurrency->round($discountAmount));
$discountData->setBaseAmount($this->priceCurrency->round($baseDiscountAmount));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ protected function calculateWithTaxNotInPrice(QuoteDetailsItemInterface $item, $
$rowTaxBeforeDiscount = array_sum($rowTaxesBeforeDiscount);
$rowTotalInclTax = $rowTotal + $rowTaxBeforeDiscount;
$priceInclTax = $rowTotalInclTax / $quantity;

if ($round) {
$priceInclTax = $this->calculationTool->round($priceInclTax);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

require_once __DIR__ . '/SetupUtil.php';
require_once __DIR__ . '/../../../../_files/tax_calculation_data_aggregated.php';
require_once __DIR__ . '/../../../../_files/full_discount_with_tax.php';

/**
* Class TaxTest
Expand Down Expand Up @@ -124,6 +125,40 @@ public function testCollect()
);
}

/**
* Test taxes collection with full discount for quote.
*
* Test tax calculation and price when the discount may be bigger than total
* This method will test the collector through $quote->collectTotals() method
*
* @see \Magento\SalesRule\Model\Utility::deltaRoundingFix
* @magentoDataFixture Magento/Tax/_files/full_discount_with_tax.php
* @magentoDbIsolation enabled
* @magentoAppIsolation enabled
*/
public function testFullDiscountWithDeltaRoundingFix()
{
global $fullDiscountIncTax;
$configData = $fullDiscountIncTax['config_data'];
$quoteData = $fullDiscountIncTax['quote_data'];
$expectedResults = $fullDiscountIncTax['expected_result'];

/** @var \Magento\Framework\ObjectManagerInterface $objectManager */
$objectManager = Bootstrap::getObjectManager();

//Setup tax configurations
$this->setupUtil = new SetupUtil($objectManager);
$this->setupUtil->setupTax($configData);

$quote = $this->setupUtil->setupQuote($quoteData);

$quote->collectTotals();

$quoteAddress = $quote->getShippingAddress();

$this->verifyResult($quoteAddress, $expectedResults);
}

/**
* Verify fields in quote item
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

use Magento\Tax\Model\Config;
use Magento\Tax\Model\Sales\Total\Quote\SetupUtil;

$fullDiscountIncTax = [
'config_data' => [
'config_overrides' => [
Config::CONFIG_XML_PATH_APPLY_AFTER_DISCOUNT => 0,
Config::CONFIG_XML_PATH_DISCOUNT_TAX => 1,
Config::XML_PATH_ALGORITHM => 'ROW_BASE_CALCULATION',
Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS => SetupUtil::SHIPPING_TAX_CLASS,
],
'tax_rate_overrides' => [
SetupUtil::TAX_RATE_TX => 18,
SetupUtil::TAX_RATE_SHIPPING => 0,
],
'tax_rule_overrides' => [
[
'code' => 'Product Tax Rule',
'product_tax_class_ids' => [
SetupUtil::PRODUCT_TAX_CLASS_1
],
],
[
'code' => 'Shipping Tax Rule',
'product_tax_class_ids' => [
SetupUtil::SHIPPING_TAX_CLASS
],
'tax_rate_ids' => [
SetupUtil::TAX_RATE_SHIPPING,
],
],
],
],
'quote_data' => [
'billing_address' => [
'region_id' => SetupUtil::REGION_TX,
],
'shipping_address' => [
'region_id' => SetupUtil::REGION_TX,
],
'items' => [
[
'sku' => 'simple1',
'price' => 2542.37,
'qty' => 2,
]
],
'shipping_method' => 'free',
'shopping_cart_rules' => [
[
'discount_amount' => 100
],
],
],
'expected_result' => [
'address_data' => [
'subtotal' => 5084.74,
'base_subtotal' => 5084.74,
'subtotal_incl_tax' => 5999.99,
'base_subtotal_incl_tax' => 5999.99,
'tax_amount' => 915.25,
'base_tax_amount' => 915.25,
'shipping_amount' => 0,
'base_shipping_amount' => 0,
'shipping_incl_tax' => 0,
'base_shipping_incl_tax' => 0,
'shipping_tax_amount' => 0,
'base_shipping_tax_amount' => 0,
'discount_amount' => -5999.99,
'base_discount_amount' => -5999.99,
'discount_tax_compensation_amount' => 0,
'base_discount_tax_compensation_amount' => 0,
'shipping_discount_tax_compensation_amount' => 0,
'base_shipping_discount_tax_compensation_amount' => 0,
'grand_total' => 0,
'base_grand_total' => 0,
'applied_taxes' => [
SetupUtil::TAX_RATE_TX => [
'percent' => 18,
'amount' => 915.25,
'base_amount' => 915.25,
'rates' => [
[
'code' => SetupUtil::TAX_RATE_TX,
'title' => SetupUtil::TAX_RATE_TX,
'percent' => 18,
],
],
]
],
],
'items_data' => [
'simple1' => [
'row_total' => 5084.74,
'base_row_total' => 5084.74,
'tax_percent' => 18,
'price' => 2542.37,
'base_price' => 2542.37,
'price_incl_tax' => 3000,
'base_price_incl_tax' => 3000,
'row_total_incl_tax' => 5999.99,
'base_row_total_incl_tax' => 5999.99,
'tax_amount' => 915.25,
'base_tax_amount' => 915.25,
'discount_amount' => 5999.99,
'base_discount_amount' => 5999.99,
'discount_percent' => 100,
'discount_tax_compensation_amount' => 0,
'base_discount_tax_compensation_amount' => 0,
],
],
]
];