Skip to content

Commit b6f626f

Browse files
author
Maksym Aposov
committed
MAGETWO-38347: Second product from bundle product is ordered as separate item after checkout
1 parent 30517b5 commit b6f626f

File tree

6 files changed

+285
-11
lines changed

6 files changed

+285
-11
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1337,8 +1337,9 @@ public function getAllItems()
13371337
{
13381338
$items = [];
13391339
foreach ($this->getItemsCollection() as $item) {
1340+
/** @var \Magento\Quote\Model\Resource\Quote\Item $item */
13401341
if (!$item->isDeleted()) {
1341-
$items[] = $item;
1342+
$items[$item->getId()] = $item;
13421343
}
13431344
}
13441345
return $items;

app/code/Magento/Quote/Model/QuoteManagement.php

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -375,15 +375,6 @@ public function submit(QuoteEntity $quote, $orderData = [])
375375
protected function resolveItems(QuoteEntity $quote)
376376
{
377377
$quoteItems = $quote->getAllItems();
378-
for ($i = 0; $i < count($quoteItems) - 1; $i++) {
379-
for ($j = 0; $j < count($quoteItems) - $i - 1; $j++) {
380-
if ($quoteItems[$i]->getParentItemId() == $quoteItems[$j]->getId()) {
381-
$tempItem = $quoteItems[$i];
382-
$quoteItems[$i] = $quoteItems[$j];
383-
$quoteItems[$j] = $tempItem;
384-
}
385-
}
386-
}
387378
$orderItems = [];
388379
foreach ($quoteItems as $quoteItem) {
389380
$parentItem = (isset($orderItems[$quoteItem->getParentItemId()])) ?
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
/**
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Quote\Model;
7+
8+
use Magento\Catalog\Model\Product\Type;
9+
use Magento\TestFramework\Helper\Bootstrap;
10+
11+
class QuoteManagementTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* Create order with product that has child items
15+
*
16+
* @magentoDataFixture Magento/Sales/_files/quote_with_bundle.php
17+
*/
18+
public function testSubmit()
19+
{
20+
/**
21+
* Preconditions:
22+
* Load quote with Bundle product that has at least to child products
23+
*/
24+
$objectManager = Bootstrap::getObjectManager();
25+
/** @var \Magento\Quote\Model\Quote $quote */
26+
$quote = $objectManager->create('\Magento\Quote\Model\Quote');
27+
$quote->load('test01', 'reserved_order_id');
28+
29+
/** Execute SUT */
30+
/** @var \Magento\Quote\Model\QuoteManagement $model */
31+
$model = $objectManager->create('\Magento\Quote\Model\QuoteManagement');
32+
$order = $model->submit($quote);
33+
34+
/** Check if SUT caused expected effects */
35+
$orderItems = $order->getItems();
36+
$this->assertCount(3, $orderItems);
37+
foreach ($orderItems as $orderItem) {
38+
if ($orderItem->getProductType() == Type::TYPE_SIMPLE) {
39+
$this->assertNotEmpty($orderItem->getParentItem(), 'Parent is not set for child product');
40+
$this->assertNotEmpty($orderItem->getParentItemId(), 'Parent is not set for child product');
41+
}
42+
}
43+
}
44+
}

dev/tests/integration/testsuite/Magento/Sales/Model/AdminOrder/CreateTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,7 @@ protected function _preparePreconditionsForCreateOrder(
550550
);
551551
$this->assertEquals(
552552
'Simple Product',
553-
$this->_model->getQuote()->getAllItems()[0]->getData('name'),
553+
$this->_model->getQuote()->getItemByProduct($product)->getData('name'),
554554
'Precondition failed: Quote items data is invalid in create order model'
555555
);
556556
$this->assertEquals(
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
<?php
2+
/**
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
\Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea('frontend');
7+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
8+
/** Create simple and bundle products for quote*/
9+
$simpleProducts[] = $objectManager->create('Magento\Catalog\Model\Product')
10+
->setTypeId(
11+
\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
12+
)->setId(
13+
1
14+
)->setAttributeSetId(
15+
4
16+
)->setWebsiteIds(
17+
[1]
18+
)->setName(
19+
'Simple Product 1'
20+
)->setSku(
21+
'simple-1'
22+
)->setPrice(
23+
10
24+
)->setDescription(
25+
'Description with <b>html tag</b>'
26+
)->setVisibility(
27+
\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH
28+
)->setStatus(
29+
\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED
30+
)->setCategoryIds(
31+
[2]
32+
)->setStockData(
33+
['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]
34+
)->save();
35+
36+
$simpleProducts[] = $objectManager->create('Magento\Catalog\Model\Product')
37+
->setTypeId(
38+
\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE
39+
)->setId(
40+
2
41+
)->setAttributeSetId(
42+
4
43+
)->setWebsiteIds(
44+
[1]
45+
)->setName(
46+
'Simple Product 2'
47+
)->setSku(
48+
'simple-2'
49+
)->setPrice(
50+
10
51+
)->setDescription(
52+
'Description with <b>html tag</b>'
53+
)->setVisibility(
54+
\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH
55+
)->setStatus(
56+
\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED
57+
)->setCategoryIds(
58+
[2]
59+
)->setStockData(
60+
['use_config_manage_stock' => 1, 'qty' => 100, 'is_qty_decimal' => 0, 'is_in_stock' => 1]
61+
)->save();
62+
63+
$product = $objectManager->create('Magento\Catalog\Model\Product');
64+
$product->setTypeId(
65+
\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
66+
)->setId(
67+
3
68+
)->setAttributeSetId(
69+
4
70+
)->setWebsiteIds(
71+
[1]
72+
)->setName(
73+
'Bundle Product'
74+
)->setSku(
75+
'bundle-product'
76+
)->setDescription(
77+
'Description with <b>html tag</b>'
78+
)->setShortDescription(
79+
'Bundle'
80+
)->setVisibility(
81+
\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH
82+
)->setStatus(
83+
\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED
84+
)->setStockData(
85+
[
86+
'use_config_manage_stock' => 0,
87+
'manage_stock' => 0,
88+
'use_config_enable_qty_increments' => 1,
89+
'use_config_qty_increments' => 1,
90+
'is_in_stock' => 0,
91+
]
92+
)->setBundleOptionsData(
93+
[
94+
[
95+
'title' => 'Bundle Product Items',
96+
'default_title' => 'Bundle Product Items',
97+
'type' => 'select',
98+
'required' => 1,
99+
'delete' => '',
100+
'position' => 0,
101+
'option_id' => '',
102+
],
103+
]
104+
)->setBundleSelectionsData(
105+
[
106+
[
107+
[
108+
'product_id' => $simpleProducts[0]->getId(),
109+
'selection_qty' => 1,
110+
'selection_can_change_qty' => 1,
111+
'delete' => '',
112+
'position' => 0,
113+
'selection_price_type' => 0,
114+
'selection_price_value' => 0.0,
115+
'option_id' => '',
116+
'selection_id' => '',
117+
'is_default' => 1,
118+
],
119+
[
120+
'product_id' => $simpleProducts[1]->getId(),
121+
'selection_qty' => 1,
122+
'selection_can_change_qty' => 1,
123+
'delete' => '',
124+
'position' => 0,
125+
'selection_price_type' => 0,
126+
'selection_price_value' => 0.0,
127+
'option_id' => '',
128+
'selection_id' => '',
129+
'is_default' => 1,
130+
]
131+
],
132+
]
133+
)->setCanSaveBundleSelections(
134+
true
135+
)->setAffectBundleProductSelections(
136+
true
137+
)->save();
138+
139+
//Load options
140+
$typeInstance = $product->getTypeInstance();
141+
$typeInstance->setStoreFilter($product->getStoreId(), $product);
142+
$optionCollection = $typeInstance->getOptionsCollection($product);
143+
$selectionCollection = $typeInstance->getSelectionsCollection($typeInstance->getOptionsIds($product), $product);
144+
145+
$bundleOptions = [];
146+
$bundleOptionsQty = [];
147+
/** @var $option \Magento\Bundle\Model\Option */
148+
foreach ($optionCollection as $option) {
149+
/** @var $selection \Magento\Bundle\Model\Selection */
150+
foreach ($selectionCollection as $selection) {
151+
$bundleOptions[$option->getId()][] = $selection->getSelectionId();
152+
$bundleOptionsQty[$option->getId()][] = 1;
153+
}
154+
}
155+
156+
$buyRequest = new \Magento\Framework\Object(
157+
['qty' => 1, 'bundle_option' => $bundleOptions, 'bundle_option_qty' => $bundleOptionsQty]
158+
);
159+
$product->setSkipCheckRequiredOption(true);
160+
161+
162+
$addressData = include __DIR__ . '/address_data.php';
163+
$billingAddress = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
164+
'Magento\Quote\Model\Quote\Address',
165+
['data' => $addressData]
166+
);
167+
$billingAddress->setAddressType('billing');
168+
169+
/** @var $rate \Magento\Quote\Model\Quote\Address\Rate */
170+
$rate = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Quote\Model\Quote\Address\Rate');
171+
$rate->setCode('freeshipping_freeshipping');
172+
$rate->getPrice(1);
173+
174+
/** @var Magento\Quote\Model\Quote\Address $shippingAddress */
175+
$shippingAddress = clone $billingAddress;
176+
$shippingAddress->setId(null)->setAddressType('shipping');
177+
$shippingAddress->setShippingMethod('freeshipping_freeshipping');
178+
$shippingAddress->addShippingRate($rate);
179+
180+
/** @var \Magento\Quote\Model\Quote $quote */
181+
$quote = $objectManager->create('Magento\Quote\Model\Quote');
182+
$quote->setCustomerIsGuest(
183+
true
184+
)->setStoreId(
185+
\Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
186+
'Magento\Store\Model\StoreManagerInterface'
187+
)->getStore()->getId()
188+
)->setReservedOrderId(
189+
'test01'
190+
)->setBillingAddress(
191+
$billingAddress
192+
)->setShippingAddress(
193+
$shippingAddress
194+
)->setCustomerEmail(
195+
'test@test.magento.com'
196+
)->addProduct(
197+
$product, $buyRequest
198+
);
199+
200+
$quote->getPayment()->setMethod('checkmo');
201+
$quote->collectTotals();
202+
$quote->save();
203+
204+
/** @var \Magento\Quote\Model\QuoteIdMask $quoteIdMask */
205+
$quoteIdMask = $objectManager->create('Magento\Quote\Model\QuoteIdMaskFactory')->create();
206+
$quoteIdMask->setQuoteId($quote->getId());
207+
$quoteIdMask->setDataChanges(true);
208+
$quoteIdMask->save();
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/** @var \Magento\Framework\Registry $registry */
8+
$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
9+
$registry->unregister('isSecureArea');
10+
$registry->register('isSecureArea', true);
11+
12+
/** @var $quote \Magento\Quote\Model\Quote */
13+
$quote = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Quote\Model\Quote');
14+
$quote->load('test01', 'reserved_order_id');
15+
if ($quote->getId()) {
16+
$quote->delete();
17+
}
18+
19+
/** @var $product \Magento\Catalog\Model\Product */
20+
$productIds = [1, 2, 3];
21+
$product = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Model\Product');
22+
foreach ($productIds as $productId) {
23+
$product->load($productId);
24+
if ($product->getId()) {
25+
$product->delete();
26+
}
27+
}
28+
29+
$registry->unregister('isSecureArea');
30+
$registry->register('isSecureArea', false);

0 commit comments

Comments
 (0)