Skip to content

Commit f2dbc2c

Browse files
committed
Merge remote-tracking branch 'origin/MC-30546' into 2.4-develop-pr11
2 parents 2b63651 + b315f70 commit f2dbc2c

File tree

2 files changed

+202
-116
lines changed

2 files changed

+202
-116
lines changed

app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,11 @@ protected function processProductItems(
593593
$total->setSubtotalInclTax($subtotalInclTax);
594594
$total->setBaseSubtotalTotalInclTax($baseSubtotalInclTax);
595595
$total->setBaseSubtotalInclTax($baseSubtotalInclTax);
596-
$shippingAssignment->getShipping()->getAddress()->setBaseSubtotalTotalInclTax($baseSubtotalInclTax);
597-
$shippingAssignment->getShipping()->getAddress()->setBaseTaxAmount($baseTax);
596+
$address = $shippingAssignment->getShipping()->getAddress();
597+
$address->setBaseTaxAmount($baseTax);
598+
$address->setBaseSubtotalTotalInclTax($baseSubtotalInclTax);
599+
$address->setSubtotal($total->getSubtotal());
600+
$address->setBaseSubtotal($total->getBaseSubtotal());
598601

599602
return $this;
600603
}

dev/tests/integration/testsuite/Magento/Tax/Model/Sales/Total/Quote/SubtotalTest.php

Lines changed: 197 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -67,127 +67,207 @@ protected function getCustomerById($id)
6767
* @magentoDataFixture Magento/Catalog/_files/products.php
6868
* @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION
6969
* @dataProvider collectUnitBasedDataProvider
70+
* @param array $quoteItems
71+
* @param array $expected
72+
* @return void
7073
*/
71-
public function testCollectUnitBased($expected)
74+
public function testCollectUnitBased(array $quoteItems, array $expected): void
7275
{
73-
$customerTaxClassId = $this->getCustomerTaxClassId();
74-
$fixtureCustomerId = 1;
75-
/** @var \Magento\Customer\Model\Customer $customer */
76-
$customer = $this->objectManager->create(\Magento\Customer\Model\Customer::class)->load($fixtureCustomerId);
77-
/** @var \Magento\Customer\Model\Group $customerGroup */
78-
$customerGroup = $this->objectManager->create(
79-
\Magento\Customer\Model\Group::class
80-
)->load(
81-
'custom_group',
82-
'customer_group_code'
83-
);
84-
$customerGroup->setTaxClassId($customerTaxClassId)->save();
85-
$customer->setGroupId($customerGroup->getId())->save();
76+
$this->quote($quoteItems, $expected);
77+
}
78+
79+
public function collectUnitBasedDataProvider(): array
80+
{
81+
return [
82+
'one_item' => [
83+
[
84+
[
85+
'sku' => 'simple',
86+
'qty' => 2
87+
],
88+
],
89+
[
90+
[
91+
'subtotal' => 20,
92+
'subtotal_incl_tax' => 21.5,
93+
'base_subtotal_total_incl_tax' => 21.5,
94+
'tax_amount' => 1.5,
95+
'discount_amount' => 0,
96+
],
97+
[
98+
[
99+
'tax_amount' => 1.5,
100+
'price' => 10,
101+
'price_incl_tax' => 10.75,
102+
'row_total' => 20,
103+
'row_total_incl_tax' => 21.5,
104+
'tax_percent' => 7.5,
105+
],
106+
],
107+
],
108+
],
109+
];
110+
}
86111

112+
/**
113+
* @magentoDataFixture Magento/Customer/_files/customer.php
114+
* @magentoDataFixture Magento/Customer/_files/customer_address.php
115+
* @magentoDataFixture Magento/Tax/_files/tax_classes.php
116+
* @magentoDataFixture Magento/Customer/_files/customer_group.php
117+
* @magentoDataFixture Magento/Bundle/_files/product.php
118+
* @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION
119+
* @dataProvider collectUnitBasedBundleProductDataProvider
120+
* @param array $quoteItems
121+
* @param array $expected
122+
* @return void
123+
*/
124+
public function testCollectUnitBasedBundleProduct(array $quoteItems, array $expected): void
125+
{
87126
$productTaxClassId = $this->getProductTaxClassId();
88127
/** @var \Magento\Catalog\Model\Product $product */
89-
$product = $this->productRepository->get('simple');
90-
$product->setTaxClassId($productTaxClassId)->save();
91-
92-
$quoteShippingAddressDataObject = $this->getShippingAddressDataObject($fixtureCustomerId);
93-
94-
/** @var \Magento\Quote\Model\Quote\Address $quoteShippingAddress */
95-
$quoteShippingAddress = $this->objectManager->create(\Magento\Quote\Model\Quote\Address::class);
96-
$quoteShippingAddress->importCustomerAddressData($quoteShippingAddressDataObject);
97-
$quantity = 2;
98-
99-
/** @var \Magento\Quote\Model\Quote $quote */
100-
$quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class);
101-
$quote->setStoreId(
102-
1
103-
)->setIsActive(
104-
true
105-
)->setIsMultiShipping(
106-
false
107-
)->assignCustomerWithAddressChange(
108-
$this->getCustomerById($customer->getId())
109-
)->setShippingAddress(
110-
$quoteShippingAddress
111-
)->setBillingAddress(
112-
$quoteShippingAddress
113-
)->setCheckoutMethod(
114-
$customer->getMode()
115-
)->setPasswordHash(
116-
$customer->encryptPassword($customer->getPassword())
117-
)->addProduct(
118-
$product->load($product->getId()),
119-
$quantity
120-
);
121-
$address = $quote->getShippingAddress();
122-
/** @var \Magento\Quote\Model\ShippingAssignment $shippingAssignment */
123-
$shippingAssignment = $this->objectManager->create(\Magento\Quote\Model\ShippingAssignment::class);
124-
$shipping = $this->objectManager->create(\Magento\Quote\Model\Shipping::class);
125-
$shipping->setAddress($address);
126-
$shippingAssignment->setShipping($shipping);
127-
$shippingAssignment->setItems($address->getAllItems());
128-
/** @var \Magento\Quote\Model\Quote\Address\Total $total */
129-
$total = $this->objectManager->create(\Magento\Quote\Model\Quote\Address\Total::class);
130-
/** @var \Magento\Quote\Model\Quote\Address\Total\Subtotal $addressSubtotalCollector */
131-
$addressSubtotalCollector = $this->objectManager->create(
132-
\Magento\Quote\Model\Quote\Address\Total\Subtotal::class
133-
);
134-
$addressSubtotalCollector->collect($quote, $shippingAssignment, $total);
135-
136-
/** @var \Magento\Tax\Model\Sales\Total\Quote\Subtotal $subtotalCollector */
137-
$subtotalCollector = $this->objectManager->create(\Magento\Tax\Model\Sales\Total\Quote\Subtotal::class);
138-
$subtotalCollector->collect($quote, $shippingAssignment, $total);
139-
140-
$this->assertEquals($expected['subtotal'], $total->getSubtotal());
141-
$this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $total->getSubtotalInclTax());
142-
$this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $address->getBaseSubtotalTotalInclTax());
143-
$this->assertEquals($expected['discount_amount'], $total->getDiscountAmount());
144-
$items = $address->getAllItems();
145-
/** @var \Magento\Quote\Model\Quote\Address\Item $item */
146-
$item = $items[0];
147-
$this->assertEquals($expected['items'][0]['price'], $item->getPrice());
148-
$this->assertEquals($expected['items'][0]['price_incl_tax'], $item->getPriceInclTax());
149-
$this->assertEquals($expected['items'][0]['row_total'], $item->getRowTotal());
150-
$this->assertEquals($expected['items'][0]['row_total_incl_tax'], $item->getRowTotalInclTax());
151-
$this->assertEquals($expected['items'][0]['tax_percent'], $item->getTaxPercent());
128+
$childProduct = $this->productRepository->get('simple');
129+
$childProduct->setTaxClassId($productTaxClassId)->save();
130+
/** @var \Magento\Catalog\Model\Product $product */
131+
$product = $this->productRepository->get('bundle-product');
132+
$product->setTaxClassId($productTaxClassId)
133+
->setPriceType(\Magento\Catalog\Model\Product\Type\AbstractType::CALCULATE_CHILD)
134+
->save();
135+
$quoteItems[0]['product'] = $product;
136+
$this->quote($quoteItems, $expected);
152137
}
153138

154-
public function collectUnitBasedDataProvider()
139+
public function collectUnitBasedBundleProductDataProvider(): array
155140
{
156141
return [
157142
'one_item' => [
158143
[
159-
'subtotal' => 20,
160-
'tax_amount' => 1.5,
161-
'discount_amount' => 0,
162-
'items' => [
144+
[
145+
'sku' => 'bundle-product',
146+
'qty' => 2
147+
],
148+
],
149+
[
150+
[
151+
'subtotal' => 20,
152+
'subtotal_incl_tax' => 21.5,
153+
'base_subtotal_total_incl_tax' => 21.5,
154+
'tax_amount' => 1.5,
155+
'discount_amount' => 0,
156+
],
157+
[
163158
[
164159
'tax_amount' => 1.5,
165160
'price' => 10,
166161
'price_incl_tax' => 10.75,
167162
'row_total' => 20,
168163
'row_total_incl_tax' => 21.5,
169-
'taxable_amount' => 10,
170-
'code' => 'simple',
171-
'type' => 'product',
172-
'tax_percent' => 7.5,
164+
'tax_percent' => null,
173165
],
166+
[
167+
'tax_amount' => 1.5,
168+
'price' => 10,
169+
'price_incl_tax' => 10.75,
170+
'row_total' => 20,
171+
'row_total_incl_tax' => 21.5,
172+
'tax_percent' => 7.5,
173+
]
174174
],
175175
],
176176
],
177177
];
178178
}
179179

180180
/**
181-
* @magentoDbIsolation disabled
181+
* @magentoAppIsolation enabled
182+
* @magentoDbIsolation enabled
183+
* @magentoConfigFixture current_store tax/calculation/cross_border_trade_enabled 1
182184
* @magentoDataFixture Magento/Customer/_files/customer.php
183185
* @magentoDataFixture Magento/Customer/_files/customer_address.php
184186
* @magentoDataFixture Magento/Tax/_files/tax_classes.php
185187
* @magentoDataFixture Magento/Customer/_files/customer_group.php
186-
* @magentoDataFixture Magento/Bundle/_files/product.php
188+
* @magentoDataFixture Magento/Catalog/_files/products.php
187189
* @magentoConfigFixture current_store tax/calculation/algorithm UNIT_BASE_CALCULATION
188-
* @dataProvider collectUnitBasedDataProvider
190+
* @magentoConfigFixture current_store tax/calculation/price_includes_tax 1
191+
* @dataProvider collectUnitBasedPriceIncludesTaxDataProvider
192+
* @param array $quoteItems
193+
* @param array $expected
194+
*/
195+
public function testCollectUnitBasedPriceIncludesTax(array $quoteItems, array $expected): void
196+
{
197+
$this->quote($quoteItems, $expected);
198+
}
199+
200+
/**
201+
* @return array
202+
*/
203+
public function collectUnitBasedPriceIncludesTaxDataProvider(): array
204+
{
205+
return [
206+
[
207+
[
208+
[
209+
'sku' => 'simple',
210+
'qty' => 1
211+
],
212+
],
213+
[
214+
[
215+
'subtotal' => 9.3,
216+
'subtotal_incl_tax' => 10,
217+
'base_subtotal_total_incl_tax' => 10,
218+
'tax_amount' => 0.7,
219+
'discount_amount' => 0,
220+
],
221+
[
222+
[
223+
'tax_amount' => 0.7,
224+
'price' => 9.3,
225+
'price_incl_tax' => 10,
226+
'row_total' => 9.3,
227+
'row_total_incl_tax' => 10,
228+
'tax_percent' => 7.5,
229+
],
230+
],
231+
],
232+
],
233+
[
234+
[
235+
[
236+
'sku' => 'simple',
237+
'qty' => 2
238+
],
239+
],
240+
[
241+
[
242+
'subtotal' => 18.6,
243+
'subtotal_incl_tax' => 20,
244+
'base_subtotal_total_incl_tax' => 20,
245+
'tax_amount' => 1.4,
246+
'discount_amount' => 0,
247+
],
248+
[
249+
[
250+
'tax_amount' => 1.4,
251+
'price' => 9.3,
252+
'price_incl_tax' => 10,
253+
'row_total' => 18.6,
254+
'row_total_incl_tax' => 20,
255+
'tax_percent' => 7.5,
256+
],
257+
],
258+
],
259+
],
260+
];
261+
}
262+
263+
/**
264+
* Create quote and assert totals values
265+
*
266+
* @param array $quoteItems
267+
* @param array $expected
268+
* @return void
189269
*/
190-
public function testCollectUnitBasedBundleProduct($expected)
270+
private function quote(array $quoteItems, array $expected): void
191271
{
192272
$customerTaxClassId = $this->getCustomerTaxClassId();
193273
$fixtureCustomerId = 1;
@@ -202,23 +282,14 @@ public function testCollectUnitBasedBundleProduct($expected)
202282
);
203283
$customerGroup->setTaxClassId($customerTaxClassId)->save();
204284
$customer->setGroupId($customerGroup->getId())->save();
205-
206285
$productTaxClassId = $this->getProductTaxClassId();
207-
/** @var \Magento\Catalog\Model\Product $product */
208-
$childProduct = $this->productRepository->get('simple');
209-
$childProduct->setTaxClassId($productTaxClassId)->save();
210-
/** @var \Magento\Catalog\Model\Product $product */
211-
$product = $this->productRepository->get('bundle-product');
212-
$product->setTaxClassId($productTaxClassId)
213-
->setPriceType(\Magento\Catalog\Model\Product\Type\AbstractType::CALCULATE_CHILD)
214-
->save();
286+
215287

216288
$quoteShippingAddressDataObject = $this->getShippingAddressDataObject($fixtureCustomerId);
217289

218290
/** @var \Magento\Quote\Model\Quote\Address $quoteShippingAddress */
219291
$quoteShippingAddress = $this->objectManager->create(\Magento\Quote\Model\Quote\Address::class);
220292
$quoteShippingAddress->importCustomerAddressData($quoteShippingAddressDataObject);
221-
$quantity = 2;
222293

223294
/** @var \Magento\Quote\Model\Quote $quote */
224295
$quote = $this->objectManager->create(\Magento\Quote\Model\Quote::class);
@@ -238,17 +309,25 @@ public function testCollectUnitBasedBundleProduct($expected)
238309
$customer->getMode()
239310
)->setPasswordHash(
240311
$customer->encryptPassword($customer->getPassword())
241-
)->addProduct(
242-
$product->load($product->getId()),
243-
$quantity
244312
);
313+
314+
foreach ($quoteItems as $quoteItem) {
315+
$product = $quoteItem['product'] ?? null;
316+
if ($product === null) {
317+
/** @var \Magento\Catalog\Model\Product $product */
318+
$product = $this->productRepository->get($quoteItem['sku'] ?? 'simple');
319+
$product->setTaxClassId($productTaxClassId)->save();
320+
}
321+
$quote->addProduct($product, $quoteItem['qty']);
322+
}
323+
245324
$address = $quote->getShippingAddress();
246325
/** @var \Magento\Quote\Model\ShippingAssignment $shippingAssignment */
247326
$shippingAssignment = $this->objectManager->create(\Magento\Quote\Model\ShippingAssignment::class);
248327
$shipping = $this->objectManager->create(\Magento\Quote\Model\Shipping::class);
249328
$shipping->setAddress($address);
250329
$shippingAssignment->setShipping($shipping);
251-
$shippingAssignment->setItems($quote->getAllItems());
330+
$shippingAssignment->setItems($address->getAllItems());
252331
/** @var \Magento\Quote\Model\Quote\Address\Total $total */
253332
$total = $this->objectManager->create(\Magento\Quote\Model\Quote\Address\Total::class);
254333
/** @var \Magento\Quote\Model\Quote\Address\Total\Subtotal $addressSubtotalCollector */
@@ -261,16 +340,20 @@ public function testCollectUnitBasedBundleProduct($expected)
261340
$subtotalCollector = $this->objectManager->create(\Magento\Tax\Model\Sales\Total\Quote\Subtotal::class);
262341
$subtotalCollector->collect($quote, $shippingAssignment, $total);
263342

264-
$this->assertEquals($expected['subtotal'], $total->getSubtotal());
265-
$this->assertEquals($expected['subtotal'] + $expected['tax_amount'], $total->getSubtotalInclTax());
266-
$this->assertEquals($expected['discount_amount'], $total->getDiscountAmount());
267-
$items = $address->getAllItems();
268-
/** @var \Magento\Quote\Model\Quote\Address\Item $item */
269-
$item = $items[0];
270-
$this->assertEquals($expected['items'][0]['price'], $item->getPrice());
271-
$this->assertEquals($expected['items'][0]['price_incl_tax'], $item->getPriceInclTax());
272-
$this->assertEquals($expected['items'][0]['row_total'], $item->getRowTotal());
273-
$this->assertEquals($expected['items'][0]['row_total_incl_tax'], $item->getRowTotalInclTax());
343+
$this->assertEquals($address->getSubtotal(), $total->getSubtotal());
344+
$this->assertEquals($address->getBaseSubtotal(), $total->getBaseSubtotal());
345+
$this->assertEquals($address->getBaseSubtotalTotalInclTax(), $total->getBaseSubtotalTotalInclTax());
346+
347+
$this->assertEquals($expected[0], $total->toArray(array_keys($expected[0])));
348+
$actualAddressItemsData = [];
349+
if ($expected[1]) {
350+
$keys = array_keys($expected[1][0]);
351+
/** @var \Magento\Quote\Model\Quote\Address\Item $addressItem */
352+
foreach ($address->getAllItems() as $addressItem) {
353+
$actualAddressItemsData[] = array_intersect_key($addressItem->toArray($keys), array_flip($keys));
354+
}
355+
}
356+
$this->assertEquals($expected[1], $actualAddressItemsData);
274357
}
275358

276359
/**

0 commit comments

Comments
 (0)