Skip to content

Commit b5d0533

Browse files
committed
MC-38460: Setting custom price on bundle product causes wrong prices on attached simple products when reordering.
1 parent a284b63 commit b5d0533

File tree

5 files changed

+204
-7
lines changed

5 files changed

+204
-7
lines changed

app/code/Magento/Quote/Model/Quote/Item/Processor.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,12 @@ public function prepare(Item $item, DataObject $request, Product $candidate): vo
9696
}
9797
$item->addQty($candidate->getCartQty());
9898

99-
$customPrice = $request->getCustomPrice();
10099
if (!$item->getParentItem() || $item->getParentItem()->isChildrenCalculated()) {
101100
$item->setPrice($candidate->getFinalPrice());
102101
}
103-
if (!empty($customPrice)) {
102+
103+
$customPrice = $request->getCustomPrice();
104+
if (!empty($customPrice) && !$candidate->getParentProductId()) {
104105
$item->setCustomPrice($customPrice);
105106
$item->setOriginalCustomPrice($customPrice);
106107
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Bundle\Model\Sales\AdminOrder;
9+
10+
use Magento\Framework\ObjectManagerInterface;
11+
use Magento\Quote\Model\Quote\Address\Rate;
12+
use Magento\Quote\Model\Quote\Item as QuoteItem;
13+
use Magento\Sales\Model\AdminOrder\Create;
14+
use Magento\Sales\Model\Order;
15+
use Magento\Sales\Model\Order\Item as OrderItem;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* Reorder with Bundle product integration tests.
21+
*
22+
* @see Create
23+
* @magentoAppArea adminhtml
24+
*/
25+
class ReorderTest extends TestCase
26+
{
27+
/**
28+
* @var ObjectManagerInterface
29+
*/
30+
private $objectManager;
31+
32+
/**
33+
* @var Create
34+
*/
35+
private $model;
36+
37+
/**
38+
* @inheritDoc
39+
*/
40+
protected function setUp(): void
41+
{
42+
$this->objectManager = Bootstrap::getObjectManager();
43+
$this->model =$this->objectManager->get(Create::class);
44+
}
45+
46+
/**
47+
* Check Custom Price after reordering with Bundle product.
48+
*
49+
* @return void
50+
* @magentoDataFixture Magento/Bundle/_files/order_item_with_bundle_and_options.php
51+
*/
52+
public function testReorderBundleProductWithCustomPrice(): void
53+
{
54+
$customPrice = 300;
55+
/** @var $order Order */
56+
$order = $this->objectManager->create(Order::class);
57+
$order->loadByIncrementId('100000001');
58+
$this->model->initFromOrder($order);
59+
60+
/** @var QuoteItem[] $quoteItems */
61+
$quoteItems = $this->model->getQuote()->getAllItems();
62+
$firstQuoteItem = array_shift($quoteItems);
63+
self::assertNull($firstQuoteItem->getParentItemId());
64+
self::assertEquals($customPrice, (int)$firstQuoteItem->getCustomPrice());
65+
foreach ($quoteItems as $quoteItem) {
66+
self::assertEquals($firstQuoteItem->getId(), $quoteItem->getParentItemId());
67+
self::assertEquals(0, (int)$quoteItem->getCustomPrice());
68+
}
69+
70+
$shippingMethod = 'freeshipping_freeshipping';
71+
/** @var Rate $rate */
72+
$rate = $this->objectManager->create(Rate::class);
73+
$rate->setCode($shippingMethod);
74+
$this->model->getQuote()->getShippingAddress()->addShippingRate($rate);
75+
$this->model->setPaymentData(['method' => 'checkmo']);
76+
$this->model->setIsValidate(true)->importPostData(['shipping_method' => $shippingMethod]);
77+
$newOrder = $this->model->createOrder();
78+
79+
/** @var OrderItem[] $orderItems */
80+
$orderItems = $newOrder->getAllItems();
81+
$firstOrderItem = array_shift($orderItems);
82+
self::assertNull($firstOrderItem->getParentItemId());
83+
self::assertEquals($customPrice, (int)$firstOrderItem->getPrice());
84+
foreach ($orderItems as $orderItem) {
85+
self::assertEquals($firstOrderItem->getId(), $orderItem->getParentItemId());
86+
self::assertEquals(0, (int)$orderItem->getPrice());
87+
}
88+
}
89+
}

dev/tests/integration/testsuite/Magento/Bundle/_files/order_item_with_bundle_and_options.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
'bundle_option' => $bundleOptions,
4949
'bundle_option_qty' => $bundleOptionsQty,
5050
'qty' => 1,
51+
'custom_price' => 300,
5152
];
5253

5354
/** @var \Magento\Sales\Model\Order\Item $orderItem */
@@ -58,7 +59,14 @@
5859
$orderItem->setPrice($product->getPrice());
5960
$orderItem->setRowTotal($product->getPrice());
6061
$orderItem->setProductType($product->getTypeId());
61-
$orderItem->setProductOptions(['info_buyRequest' => $requestInfo]);
62+
$orderItem->setProductOptions([
63+
'info_buyRequest' => $requestInfo,
64+
'bundle_options' => [
65+
[
66+
'value' => [['title' => $product->getName()]]
67+
]
68+
]
69+
]);
6270

6371
/** @var \Magento\Sales\Model\Order $order */
6472
$order = $objectManager->create(\Magento\Sales\Model\Order::class);
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\ConfigurableProduct\Model\Sales\AdminOrder;
9+
10+
use Magento\Framework\ObjectManagerInterface;
11+
use Magento\Quote\Model\Quote\Address\Rate;
12+
use Magento\Quote\Model\Quote\Item as QuoteItem;
13+
use Magento\Sales\Model\AdminOrder\Create;
14+
use Magento\Sales\Model\Order;
15+
use Magento\Sales\Model\Order\Item as OrderItem;
16+
use Magento\TestFramework\Helper\Bootstrap;
17+
use PHPUnit\Framework\TestCase;
18+
19+
/**
20+
* Reorder with Configurable product integration tests.
21+
*
22+
* @see Create
23+
* @magentoAppArea adminhtml
24+
*/
25+
class ReorderTest extends TestCase
26+
{
27+
/**
28+
* @var ObjectManagerInterface
29+
*/
30+
private $objectManager;
31+
32+
/**
33+
* @var Create
34+
*/
35+
private $model;
36+
37+
/**
38+
* @inheritDoc
39+
*/
40+
protected function setUp(): void
41+
{
42+
$this->objectManager = Bootstrap::getObjectManager();
43+
$this->model =$this->objectManager->get(Create::class);
44+
}
45+
46+
/**
47+
* Check Custom Price after reordering with Configurable product.
48+
*
49+
* @return void
50+
* @magentoDataFixture Magento/ConfigurableProduct/_files/order_item_with_configurable_and_options.php
51+
*/
52+
public function testReorderConfigurableProductWithCustomPrice(): void
53+
{
54+
$customPrice = 300;
55+
/** @var $order Order */
56+
$order = $this->objectManager->create(Order::class);
57+
$order->loadByIncrementId('100000001');
58+
$this->model->initFromOrder($order);
59+
60+
/** @var QuoteItem[] $quoteItems */
61+
$quoteItems = $this->model->getQuote()->getAllItems();
62+
$firstQuoteItem = array_shift($quoteItems);
63+
self::assertNull($firstQuoteItem->getParentItemId());
64+
self::assertEquals($customPrice, (int)$firstQuoteItem->getCustomPrice());
65+
foreach ($quoteItems as $quoteItem) {
66+
self::assertEquals($firstQuoteItem->getId(), $quoteItem->getParentItemId());
67+
self::assertEquals(0, (int)$quoteItem->getCustomPrice());
68+
}
69+
70+
$shippingMethod = 'freeshipping_freeshipping';
71+
/** @var Rate $rate */
72+
$rate = $this->objectManager->create(Rate::class);
73+
$rate->setCode($shippingMethod);
74+
$this->model->getQuote()->getShippingAddress()->addShippingRate($rate);
75+
$this->model->setPaymentData(['method' => 'checkmo']);
76+
$this->model->setIsValidate(true)->importPostData(['shipping_method' => $shippingMethod]);
77+
$newOrder = $this->model->createOrder();
78+
79+
/** @var OrderItem[] $orderItems */
80+
$orderItems = $newOrder->getAllItems();
81+
$firstOrderItem = array_shift($orderItems);
82+
self::assertNull($firstOrderItem->getParentItemId());
83+
self::assertEquals($customPrice, (int)$firstOrderItem->getPrice());
84+
foreach ($orderItems as $orderItem) {
85+
self::assertEquals($firstOrderItem->getId(), $orderItem->getParentItemId());
86+
self::assertEquals(0, (int)$orderItem->getPrice());
87+
}
88+
}
89+
}

dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/order_item_with_configurable_and_options.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
7+
use Magento\Catalog\Api\Data\ProductInterface;
8+
use Magento\Catalog\Api\ProductRepositoryInterface;
69
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
710

811
Resolver::getInstance()->requireDataFixture('Magento/ConfigurableProduct/_files/product_configurable.php');
@@ -20,9 +23,11 @@
2023
$payment = $objectManager->create(\Magento\Sales\Model\Order\Payment::class);
2124
$payment->setMethod('checkmo');
2225

23-
/** @var $product \Magento\Catalog\Model\Product */
24-
$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
25-
$product->load(1);
26+
/** @var ProductRepositoryInterface $productRepository */
27+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
28+
$product = $productRepository->get('configurable');
29+
/** @var ProductInterface $firstChildProduct */
30+
$firstChildProduct = current($product->getTypeInstance()->getUsedProducts($product));
2631

2732
/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
2833
$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Eav\Model\Config::class);
@@ -38,6 +43,7 @@
3843
'super_attribute' => [
3944
$attribute->getId() => $option->getId(),
4045
],
46+
'custom_price' => 300,
4147
];
4248
/** @var \Magento\Sales\Model\Order $order */
4349
$order = $objectManager->create(\Magento\Sales\Model\Order::class);
@@ -54,7 +60,11 @@
5460
$orderItem->setPrice($product->getPrice());
5561
$orderItem->setRowTotal($product->getPrice());
5662
$orderItem->setProductType($product->getTypeId());
57-
$orderItem->setProductOptions(['info_buyRequest' => $requestInfo]);
63+
$orderItem->setProductOptions([
64+
'info_buyRequest' => $requestInfo,
65+
'simple_sku' => $firstChildProduct->getSku(),
66+
'simple_name' => $firstChildProduct->getName(),
67+
]);
5868

5969
/** @var \Magento\Sales\Model\Order $order */
6070
$order = $objectManager->create(\Magento\Sales\Model\Order::class);

0 commit comments

Comments
 (0)