Skip to content

Commit 7f9a7fd

Browse files
author
Serhii Balko
committed
MC-39864: [Magento Cloud] - Tax Miscalculation
1 parent ad29452 commit 7f9a7fd

File tree

2 files changed

+156
-85
lines changed
  • app/code/Magento/Sales

2 files changed

+156
-85
lines changed

app/code/Magento/Sales/Model/Order/Creditmemo/Total/Tax.php

Lines changed: 140 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,61 +5,58 @@
55
*/
66
namespace Magento\Sales\Model\Order\Creditmemo\Total;
77

8+
use Magento\Sales\Model\Order\Creditmemo;
9+
810
/**
911
* Collects credit memo taxes.
1012
*/
1113
class Tax extends AbstractTotal
1214
{
1315
/**
14-
* Collects credit memo taxes.
15-
*
16-
* @param \Magento\Sales\Model\Order\Creditmemo $creditmemo
17-
* @return $this
18-
*
16+
* {@inheritdoc}
1917
* @SuppressWarnings(PHPMD.NPathComplexity)
2018
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
2119
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
2220
*/
23-
public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo)
21+
public function collect(Creditmemo $creditmemo)
2422
{
2523
$shippingTaxAmount = 0;
2624
$baseShippingTaxAmount = 0;
2725
$totalTax = 0;
2826
$baseTotalTax = 0;
2927
$totalDiscountTaxCompensation = 0;
3028
$baseTotalDiscountTaxCompensation = 0;
31-
3229
$order = $creditmemo->getOrder();
3330

34-
/** @var $item \Magento\Sales\Model\Order\Creditmemo\Item */
3531
foreach ($creditmemo->getAllItems() as $item) {
3632
$orderItem = $item->getOrderItem();
3733
if ($orderItem->isDummy() || $item->getQty() <= 0) {
3834
continue;
3935
}
36+
4037
$orderItemTax = (double)$orderItem->getTaxInvoiced();
4138
$baseOrderItemTax = (double)$orderItem->getBaseTaxInvoiced();
4239
$orderItemQty = (double)$orderItem->getQtyInvoiced();
4340

4441
if ($orderItemQty) {
45-
/**
46-
* Check item tax amount
47-
*/
48-
49-
$tax = $orderItemTax - $orderItem->getTaxRefunded();
50-
$baseTax = $baseOrderItemTax - $orderItem->getBaseTaxRefunded();
51-
$discountTaxCompensation = $orderItem->getDiscountTaxCompensationInvoiced() -
52-
$orderItem->getDiscountTaxCompensationRefunded();
53-
$baseDiscountTaxCompensation = $orderItem->getBaseDiscountTaxCompensationInvoiced() -
54-
$orderItem->getBaseDiscountTaxCompensationRefunded();
42+
/** Check item tax amount */
43+
$tax = ($orderItemTax - $orderItem->getTaxRefunded());
44+
$baseTax = ($baseOrderItemTax - $orderItem->getBaseTaxRefunded());
45+
$discountTaxCompensation = ($orderItem->getDiscountTaxCompensationInvoiced()
46+
- $orderItem->getDiscountTaxCompensationRefunded());
47+
$baseDiscountTaxCompensation = ($orderItem->getBaseDiscountTaxCompensationInvoiced()
48+
- $orderItem->getBaseDiscountTaxCompensationRefunded());
5549
if (!$item->isLast()) {
56-
$availableQty = $orderItemQty - $orderItem->getQtyRefunded();
50+
$availableQty = ($orderItemQty - $orderItem->getQtyRefunded());
5751
$tax = $creditmemo->roundPrice($tax / $availableQty * $item->getQty());
58-
$baseTax = $creditmemo->roundPrice($baseTax / $availableQty * $item->getQty(), 'base');
59-
$discountTaxCompensation =
60-
$creditmemo->roundPrice($discountTaxCompensation / $availableQty * $item->getQty());
61-
$baseDiscountTaxCompensation =
62-
$creditmemo->roundPrice($baseDiscountTaxCompensation / $availableQty * $item->getQty(), 'base');
52+
$baseTax = $creditmemo->roundPrice(($baseTax / $availableQty * $item->getQty()), 'base');
53+
$discountTaxCompensation = $creditmemo->roundPrice(
54+
$discountTaxCompensation / $availableQty * $item->getQty()
55+
);
56+
$baseDiscountTaxCompensation = $creditmemo->roundPrice(
57+
$baseDiscountTaxCompensation / $availableQty * $item->getQty(),
58+
'base'
59+
);
6360
}
6461

6562
$item->setTaxAmount($tax);
@@ -77,14 +74,14 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo)
7774
$isPartialShippingRefunded = false;
7875
$baseOrderShippingAmount = (float)$order->getBaseShippingAmount();
7976
if ($invoice = $creditmemo->getInvoice()) {
80-
//recalculate tax amounts in case if refund shipping value was changed
77+
// recalculate tax amounts in case if refund shipping value was changed
8178
if ($baseOrderShippingAmount && $creditmemo->getBaseShippingAmount() !== null) {
82-
$taxFactor = $creditmemo->getBaseShippingAmount() / $baseOrderShippingAmount;
83-
$shippingTaxAmount = $invoice->getShippingTaxAmount() * $taxFactor;
84-
$baseShippingTaxAmount = $invoice->getBaseShippingTaxAmount() * $taxFactor;
85-
$totalDiscountTaxCompensation += $invoice->getShippingDiscountTaxCompensationAmount() * $taxFactor;
86-
$baseTotalDiscountTaxCompensation +=
87-
$invoice->getBaseShippingDiscountTaxCompensationAmnt() * $taxFactor;
79+
$taxFactor = ($creditmemo->getBaseShippingAmount() / $baseOrderShippingAmount);
80+
$shippingTaxAmount = ($invoice->getShippingTaxAmount() * $taxFactor);
81+
$baseShippingTaxAmount = ($invoice->getBaseShippingTaxAmount() * $taxFactor);
82+
$totalDiscountTaxCompensation += ($invoice->getShippingDiscountTaxCompensationAmount() * $taxFactor);
83+
$baseTotalDiscountTaxCompensation += $invoice->getBaseShippingDiscountTaxCompensationAmnt()
84+
* $taxFactor;
8885
$shippingTaxAmount = $creditmemo->roundPrice($shippingTaxAmount);
8986
$baseShippingTaxAmount = $creditmemo->roundPrice($baseShippingTaxAmount, 'base');
9087
$totalDiscountTaxCompensation = $creditmemo->roundPrice($totalDiscountTaxCompensation);
@@ -97,61 +94,52 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo)
9794
}
9895
} else {
9996
$orderShippingAmount = $order->getShippingAmount();
100-
10197
$baseOrderShippingRefundedAmount = $order->getBaseShippingRefunded();
102-
10398
$shippingTaxAmount = 0;
10499
$baseShippingTaxAmount = 0;
105100
$shippingDiscountTaxCompensationAmount = 0;
106101
$baseShippingDiscountTaxCompensationAmount = 0;
107-
108-
$shippingDelta = $baseOrderShippingAmount - $baseOrderShippingRefundedAmount;
102+
$shippingDelta = ($baseOrderShippingAmount - $baseOrderShippingRefundedAmount);
109103

110104
if ($shippingDelta > $creditmemo->getBaseShippingAmount()) {
111-
$part = $creditmemo->getShippingAmount() / $orderShippingAmount;
112-
$basePart = $creditmemo->getBaseShippingAmount() / $baseOrderShippingAmount;
113-
$shippingTaxAmount = $order->getShippingTaxAmount() * $part;
114-
$baseShippingTaxAmount = $order->getBaseShippingTaxAmount() * $basePart;
105+
$part = ($creditmemo->getShippingAmount() / $orderShippingAmount);
106+
$basePart = ($creditmemo->getBaseShippingAmount() / $baseOrderShippingAmount);
107+
$shippingTaxAmount = ($order->getShippingTaxAmount() * $part);
108+
$baseShippingTaxAmount = ($order->getBaseShippingTaxAmount() * $basePart);
115109
$shippingDiscountTaxCompensationAmount = $order->getShippingDiscountTaxCompensationAmount() * $part;
116-
$baseShippingDiscountTaxCompensationAmount =
117-
$order->getBaseShippingDiscountTaxCompensationAmnt() * $basePart;
110+
$baseShippingDiscountTaxCompensationAmount = $order->getBaseShippingDiscountTaxCompensationAmnt()
111+
* $basePart;
118112
$shippingTaxAmount = $creditmemo->roundPrice($shippingTaxAmount);
119113
$baseShippingTaxAmount = $creditmemo->roundPrice($baseShippingTaxAmount, 'base');
120-
$shippingDiscountTaxCompensationAmount =
121-
$creditmemo->roundPrice($shippingDiscountTaxCompensationAmount);
122-
$baseShippingDiscountTaxCompensationAmount =
123-
$creditmemo->roundPrice($baseShippingDiscountTaxCompensationAmount, 'base');
114+
$shippingDiscountTaxCompensationAmount = $creditmemo->roundPrice(
115+
$shippingDiscountTaxCompensationAmount
116+
);
117+
$baseShippingDiscountTaxCompensationAmount = $creditmemo->roundPrice(
118+
$baseShippingDiscountTaxCompensationAmount,
119+
'base'
120+
);
124121
if ($part < 1 && $order->getShippingTaxAmount() > 0) {
125122
$isPartialShippingRefunded = true;
126123
}
127124
} elseif ($shippingDelta == $creditmemo->getBaseShippingAmount()) {
128125
$shippingTaxAmount = $order->getShippingTaxAmount() - $order->getShippingTaxRefunded();
129126
$baseShippingTaxAmount = $order->getBaseShippingTaxAmount() - $order->getBaseShippingTaxRefunded();
130-
$shippingDiscountTaxCompensationAmount = $order->getShippingDiscountTaxCompensationAmount() -
131-
$order->getShippingDiscountTaxCompensationRefunded();
132-
$baseShippingDiscountTaxCompensationAmount = $order->getBaseShippingDiscountTaxCompensationAmnt() -
133-
$order->getBaseShippingDiscountTaxCompensationRefunded();
127+
$shippingDiscountTaxCompensationAmount = $order->getShippingDiscountTaxCompensationAmount()
128+
- $order->getShippingDiscountTaxCompensationRefunded();
129+
$baseShippingDiscountTaxCompensationAmount = $order->getBaseShippingDiscountTaxCompensationAmnt()
130+
- $order->getBaseShippingDiscountTaxCompensationRefunded();
134131
}
132+
135133
$totalTax += $shippingTaxAmount;
136134
$baseTotalTax += $baseShippingTaxAmount;
137135
$totalDiscountTaxCompensation += $shippingDiscountTaxCompensationAmount;
138136
$baseTotalDiscountTaxCompensation += $baseShippingDiscountTaxCompensationAmount;
139137
}
140138

141-
$allowedTax = $order->getTaxInvoiced() - $order->getTaxRefunded() - $creditmemo->getTaxAmount();
142-
$allowedBaseTax = $order->getBaseTaxInvoiced() - $order->getBaseTaxRefunded() - $creditmemo->getBaseTaxAmount();
143-
$allowedDiscountTaxCompensation = $order->getDiscountTaxCompensationInvoiced() +
144-
$order->getShippingDiscountTaxCompensationAmount() -
145-
$order->getDiscountTaxCompensationRefunded() -
146-
$order->getShippingDiscountTaxCompensationRefunded() -
147-
$creditmemo->getDiscountTaxCompensationAmount() -
148-
$creditmemo->getShippingDiscountTaxCompensationAmount();
149-
$allowedBaseDiscountTaxCompensation = $order->getBaseDiscountTaxCompensationInvoiced() +
150-
$order->getBaseShippingDiscountTaxCompensationAmnt() -
151-
$order->getBaseDiscountTaxCompensationRefunded() -
152-
$order->getBaseShippingDiscountTaxCompensationRefunded() -
153-
$creditmemo->getBaseShippingDiscountTaxCompensationAmnt() -
154-
$creditmemo->getBaseDiscountTaxCompensationAmount();
139+
$allowedTax = $this->calculateAllowedTax($creditmemo);
140+
$allowedBaseTax = $this->calculateAllowedBaseTax($creditmemo);
141+
$allowedDiscountTaxCompensation = $this->calculateAllowedDiscountTaxCompensation($creditmemo);
142+
$allowedBaseDiscountTaxCompensation = $this->calculateAllowedBaseDiscountTaxCompensation($creditmemo);
155143

156144
if ($creditmemo->isLast() && !$isPartialShippingRefunded) {
157145
$totalTax = $allowedTax;
@@ -161,10 +149,11 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo)
161149
} else {
162150
$totalTax = min($allowedTax, $totalTax);
163151
$baseTotalTax = min($allowedBaseTax, $baseTotalTax);
164-
$totalDiscountTaxCompensation =
165-
min($allowedDiscountTaxCompensation, $totalDiscountTaxCompensation);
166-
$baseTotalDiscountTaxCompensation =
167-
min($allowedBaseDiscountTaxCompensation, $baseTotalDiscountTaxCompensation);
152+
$totalDiscountTaxCompensation = min($allowedDiscountTaxCompensation, $totalDiscountTaxCompensation);
153+
$baseTotalDiscountTaxCompensation = min(
154+
$allowedBaseDiscountTaxCompensation,
155+
$baseTotalDiscountTaxCompensation
156+
);
168157
}
169158

170159
$creditmemo->setTaxAmount($creditmemo->getTaxAmount() + $totalTax);
@@ -177,9 +166,91 @@ public function collect(\Magento\Sales\Model\Order\Creditmemo $creditmemo)
177166

178167
$creditmemo->setGrandTotal($creditmemo->getGrandTotal() + $totalTax + $totalDiscountTaxCompensation);
179168
$creditmemo->setBaseGrandTotal(
180-
$creditmemo->getBaseGrandTotal() +
181-
$baseTotalTax + $baseTotalDiscountTaxCompensation
169+
$creditmemo->getBaseGrandTotal() + $baseTotalTax + $baseTotalDiscountTaxCompensation
182170
);
183171
return $this;
172+
173+
}
174+
175+
/**
176+
* Calculate allowed to Credit Memo tax amount
177+
*
178+
* @param Creditmemo $creditMemo
179+
* @return float
180+
*/
181+
private function calculateAllowedTax(Creditmemo $creditMemo): float
182+
{
183+
$invoice = $creditMemo->getInvoice();
184+
$order = $creditMemo->getOrder();
185+
$amount = $invoice !== null ? $invoice->getTaxAmount() : $order->getTaxInvoiced();
186+
187+
return (float) $amount - $order->getTaxRefunded() - $creditMemo->getTaxAmount();
188+
}
189+
190+
/**
191+
* Calculate allowed to Credit Memo tax amount in the base currency
192+
*
193+
* @param Creditmemo $creditMemo
194+
* @return float
195+
*/
196+
private function calculateAllowedBaseTax(Creditmemo $creditMemo): float
197+
{
198+
$invoice = $creditMemo->getInvoice();
199+
$order = $creditMemo->getOrder();
200+
$amount = $invoice !== null ? $invoice->getBaseTaxAmount() : $order->getBaseTaxInvoiced();
201+
202+
return (float) $amount - $order->getBaseTaxRefunded() - $creditMemo->getBaseTaxAmount();
203+
}
204+
205+
/**
206+
* Calculate allowed to Credit Memo discount tax compensation amount
207+
*
208+
* @param Creditmemo $creditMemo
209+
* @return float
210+
*/
211+
private function calculateAllowedDiscountTaxCompensation(Creditmemo $creditMemo): float
212+
{
213+
$invoice = $creditMemo->getInvoice();
214+
$order = $creditMemo->getOrder();
215+
216+
if ($invoice) {
217+
$amount = $invoice->getDiscountTaxCompensationAmount()
218+
+ $invoice->getShippingDiscountTaxCompensationAmount();
219+
} else {
220+
$amount = $order->getDiscountTaxCompensationInvoiced()
221+
+ $order->getShippingDiscountTaxCompensationAmount();
222+
}
223+
224+
return (float) $amount
225+
- $order->getDiscountTaxCompensationRefunded()
226+
- $order->getShippingDiscountTaxCompensationRefunded()
227+
- $creditMemo->getDiscountTaxCompensationAmount()
228+
- $creditMemo->getShippingDiscountTaxCompensationAmount();
229+
}
230+
231+
/**
232+
* Calculate allowed to Credit Memo discount tax compensation amount in the base currency
233+
*
234+
* @param Creditmemo $creditMemo
235+
* @return float
236+
*/
237+
private function calculateAllowedBaseDiscountTaxCompensation(Creditmemo $creditMemo): float
238+
{
239+
$invoice = $creditMemo->getInvoice();
240+
$order = $creditMemo->getOrder();
241+
242+
if ($invoice) {
243+
$amount = $invoice->getBaseDiscountTaxCompensationAmount()
244+
+ $invoice->getBaseShippingDiscountTaxCompensationAmnt();
245+
} else {
246+
$amount = $order->getBaseDiscountTaxCompensationInvoiced()
247+
+ $order->getBaseShippingDiscountTaxCompensationAmnt();
248+
}
249+
250+
return (float) $amount
251+
- $order->getBaseDiscountTaxCompensationRefunded()
252+
- $order->getBaseShippingDiscountTaxCompensationRefunded()
253+
- $creditMemo->getBaseShippingDiscountTaxCompensationAmnt()
254+
- $creditMemo->getBaseDiscountTaxCompensationAmount();
184255
}
185256
}

app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/Total/TaxTest.php

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
use PHPUnit\Framework\MockObject\MockObject;
1818
use PHPUnit\Framework\TestCase;
1919

20+
/**
21+
* Class to test Collecting credit memo taxes
22+
*/
2023
class TaxTest extends TestCase
2124
{
2225
/**
@@ -44,6 +47,9 @@ class TaxTest extends TestCase
4447
*/
4548
protected $invoice;
4649

50+
/**
51+
* @inheritdoc
52+
*/
4753
protected function setUp(): void
4854
{
4955
$this->objectManager = new ObjectManager($this);
@@ -188,6 +194,8 @@ public function collectDataProvider()
188194
'base_tax_amount' => 0.82,
189195
'invoice' => new MagentoObject(
190196
[
197+
'tax_amount' => 24.33,
198+
'base_tax_amount' => 24.33,
191199
'shipping_tax_amount' => 2.45,
192200
'base_shipping_tax_amount' => 2.45,
193201
'shipping_discount_tax_compensation_amount' => 0,
@@ -277,6 +285,8 @@ public function collectDataProvider()
277285
'base_tax_amount' => 0.82,
278286
'invoice' => new MagentoObject(
279287
[
288+
'tax_amount' => 24.33 * $currencyRatio,
289+
'base_tax_amount' => 24.33,
280290
'shipping_tax_amount' => 2.45 * $currencyRatio,
281291
'base_shipping_tax_amount' => 2.45,
282292
'shipping_discount_tax_compensation_amount' => 0,
@@ -352,6 +362,8 @@ public function collectDataProvider()
352362
'base_tax_amount' => 1.65,
353363
'invoice' => new MagentoObject(
354364
[
365+
'tax_amount' => 11.14,
366+
'base_tax_amount' => 11.14,
355367
'shipping_tax_amount' => 1.24,
356368
'base_shipping_tax_amount' => 1.24,
357369
'shipping_discount_tax_compensation_amount' => 0,
@@ -428,6 +440,8 @@ public function collectDataProvider()
428440
'base_tax_amount' => 0.82,
429441
'invoice' => new MagentoObject(
430442
[
443+
'tax_amount' => 16.09,
444+
'base_tax_amount' => 16.09,
431445
'shipping_tax_amount' => 1.24,
432446
'base_shipping_tax_amount' => 1.24,
433447
'shipping_discount_tax_compensation_amount' => 0,
@@ -507,14 +521,6 @@ public function collectDataProvider()
507521
'base_shipping_amount' => 0,
508522
'tax_amount' => 0.76,
509523
'base_tax_amount' => 0.76,
510-
'invoice' => new MagentoObject(
511-
[
512-
'shipping_tax_amount' => 0,
513-
'base_shipping_tax_amount' => 0,
514-
'shipping_discount_tax_compensation_amount' => 0,
515-
'base_shipping_discount_tax_compensation_amount' => 0,
516-
]
517-
),
518524
],
519525
],
520526
'expected_results' => [
@@ -583,6 +589,8 @@ public function collectDataProvider()
583589
'base_tax_amount' => 0.82,
584590
'invoice' => new MagentoObject(
585591
[
592+
'tax_amount' => 16.09,
593+
'base_tax_amount' => 16.09,
586594
'shipping_tax_amount' => 1.24,
587595
'base_shipping_tax_amount' => 1.24,
588596
'shipping_discount_tax_compensation_amount' => 0,
@@ -712,14 +720,6 @@ public function collectDataProvider()
712720
'base_shipping_amount' => 0,
713721
'tax_amount' => 0,
714722
'base_tax_amount' => 0,
715-
'invoice' => new MagentoObject(
716-
[
717-
'shipping_tax_amount' => 0,
718-
'base_shipping_tax_amount' => 0,
719-
'shipping_discount_tax_compensation_amount' => 0,
720-
'base_shipping_discount_tax_compensation_amount' => 0,
721-
]
722-
),
723723
],
724724
],
725725
'expected_results' => [

0 commit comments

Comments
 (0)