Skip to content

Commit 4f807b1

Browse files
committed
MAGETWO-54365: [GitHub] Bundle Products - The price calculation fails for user defined quantity #4446
1 parent 0c6227d commit 4f807b1

File tree

18 files changed

+478
-42
lines changed

18 files changed

+478
-42
lines changed

app/code/Magento/Bundle/view/base/web/js/price-bundle.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ define([
295295
case 'hidden':
296296
optionHash = 'bundle-option-' + optionName + '##' + optionValue;
297297
optionQty = optionConfig[optionValue].qty || 0;
298+
canQtyCustomize = optionConfig[optionValue].customQty === '1';
299+
qtyField = element.data('qtyField');
300+
qtyField.data('option', element);
301+
toggleQtyField(qtyField, optionQty, optionId, optionValue, canQtyCustomize);
298302
tempChanges = utils.deepClone(optionConfig[optionValue].prices);
299303
tempChanges = applyTierPrice(tempChanges, optionQty, optionConfig);
300304
tempChanges = applyQty(tempChanges, optionQty);

dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Adminhtml/Catalog/Product/Edit/Section/Bundle/Option/Selection.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
<selection_qty>
2222
<selector>[name$='[selection_qty]']</selector>
2323
</selection_qty>
24+
<user_defined>
25+
<selector>[name$='[selection_can_change_qty]']</selector>
26+
<input>checkbox</input>
27+
</user_defined>
2428
<getProductName>
2529
<selector>span[data-index="name"]</selector>
2630
</getProductName>

dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View.php

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66

77
namespace Magento\Bundle\Test\Block\Catalog\Product;
88

9+
use Magento\Bundle\Test\Block\Catalog\Product\View\Summary;
910
use Magento\Bundle\Test\Block\Catalog\Product\View\Type\Bundle;
10-
use Magento\Bundle\Test\Fixture\BundleProduct;
1111
use Magento\Mtf\Client\Locator;
1212
use Magento\Mtf\Fixture\FixtureInterface;
13-
use Magento\Mtf\Fixture\InjectableFixture;
1413

1514
/**
1615
* Class View
@@ -46,6 +45,13 @@ class View extends \Magento\Catalog\Test\Block\Product\View
4645
*/
4746
protected $newsletterFormSelector = '#newsletter-validate-detail[novalidate="novalidate"]';
4847

48+
/**
49+
* Summary Block selector.
50+
*
51+
* @var string
52+
*/
53+
private $summaryBlockSelector = '#bundleSummary';
54+
4955
/**
5056
* Get bundle options block.
5157
*
@@ -59,6 +65,19 @@ public function getBundleBlock()
5965
);
6066
}
6167

68+
/**
69+
* Get bundle Summary block.
70+
*
71+
* @return Summary
72+
*/
73+
public function getBundleSummaryBlock()
74+
{
75+
return $this->blockFactory->create(
76+
Summary::class,
77+
['element' => $this->_rootElement->find($this->summaryBlockSelector)]
78+
);
79+
}
80+
6281
/**
6382
* Click "Customize and add to cart button".
6483
*
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Bundle\Test\Block\Catalog\Product\View;
8+
9+
use Magento\Bundle\Test\Block\Catalog\Product\View\Summary\ConfiguredPrice;
10+
11+
/**
12+
* Bundle Summary block.
13+
*/
14+
class Summary extends \Magento\Catalog\Test\Block\Product\View
15+
{
16+
/**
17+
* Configured Price block selector.
18+
*
19+
* @var string
20+
*/
21+
private $configuredPriceBlockSelector = '.price-configured_price';
22+
23+
/**
24+
* Get configured price block.
25+
*
26+
* @return ConfiguredPrice
27+
*/
28+
public function getConfiguredPriceBlock()
29+
{
30+
return $this->blockFactory->create(
31+
ConfiguredPrice::class,
32+
['element' => $this->_rootElement->find($this->configuredPriceBlockSelector)]
33+
);
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Bundle\Test\Block\Catalog\Product\View\Summary;
8+
9+
/**
10+
* This class is used to access the price related information from the storefront.
11+
*/
12+
class ConfiguredPrice extends \Magento\Catalog\Test\Block\AbstractPriceBlock
13+
{
14+
/**
15+
* Mapping for different type of price.
16+
*
17+
* @var array
18+
*/
19+
protected $mapTypePrices = [
20+
'configured_price' => [
21+
'selector' => '.price',
22+
]
23+
];
24+
25+
/**
26+
* This method returns the price represented by the block.
27+
*
28+
* @param string $currency
29+
* @return string|null
30+
*/
31+
public function getPrice($currency = '$')
32+
{
33+
return $this->getTypePrice('configured_price', $currency);
34+
}
35+
}

dev/tests/functional/tests/app/Magento/Bundle/Test/Block/Catalog/Product/View/Type/Bundle.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,11 @@ public function getOptions(FixtureInterface $product)
107107

108108
/** @var SimpleElement $optionElement */
109109
$optionElement = $listFormOptions[$title];
110-
$getTypeData = 'get' . $this->optionNameConvert($option['type']) . 'Data';
110+
$getTypeData = 'get' . $this->optionNameConvert($option['frontend_type']) . 'Data';
111111

112112
$optionData = $this->$getTypeData($optionElement);
113113
$optionData['title'] = $title;
114-
$optionData['type'] = $option['type'];
114+
$optionData['type'] = $option['frontend_type'];
115115
$optionData['is_require'] = $optionElement->find($this->required, Locator::SELECTOR_XPATH)->isVisible()
116116
? 'Yes'
117117
: 'No';
@@ -266,7 +266,7 @@ public function fillBundleOptions($bundleOptions)
266266
/** @var Option $optionBlock */
267267
$optionBlock = $this->blockFactory->create(
268268
'Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\\'
269-
. $this->optionNameConvert($option['type']),
269+
. $this->optionNameConvert($option['frontend_type']),
270270
['element' => $this->_rootElement->find($selector, Locator::SELECTOR_XPATH)]
271271
);
272272
$optionBlock->fillOption($option['value']);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\Element;
8+
9+
use Magento\Mtf\Client\Element\SimpleElement;
10+
11+
/**
12+
* Typified element class for qty element.
13+
*/
14+
class Qty extends SimpleElement
15+
{
16+
/**
17+
* "Backspace" key code.
18+
*/
19+
const BACKSPACE = "\xEE\x80\x83";
20+
21+
/**
22+
* "RIGHT" key code.
23+
*/
24+
const RIGHT = "\xEE\x80\x94";
25+
26+
/**
27+
* Set the value.
28+
*
29+
* @param string|array $value
30+
* @return void
31+
*/
32+
public function setValue($value)
33+
{
34+
$this->keys([self::RIGHT, self::BACKSPACE, $value]);
35+
$this->context->click();
36+
}
37+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
8+
9+
use Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option;
10+
11+
/**
12+
* Bundle option hidden type.
13+
*/
14+
class Hidden extends Option
15+
{
16+
//
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" ?>
2+
<!--
3+
/**
4+
* Copyright © 2016 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<mapping strict="1">
9+
<fields>
10+
<qty>
11+
<selector>//input[contains(@class,"qty")]</selector>
12+
<strategy>xpath</strategy>
13+
<class>Magento\Bundle\Test\Block\Catalog\Product\View\Type\Option\Element\Qty</class>
14+
</qty>
15+
</fields>
16+
</mapping>

dev/tests/functional/tests/app/Magento/Bundle/Test/Constraint/AssertBundleItemsOnProductPage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ protected function prepareBundleOptions(BundleProduct $product)
6161
foreach ($bundleOptions as $optionKey => $bundleOption) {
6262
$optionData = [
6363
'title' => $bundleOption['title'],
64-
'type' => $bundleOption['type'],
64+
'type' => $bundleOption['frontend_type'],
6565
'is_require' => $bundleOption['required'],
6666
];
6767

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Bundle\Test\Constraint;
8+
9+
use Magento\Bundle\Test\Fixture\BundleProduct;
10+
use Magento\Catalog\Test\Page\Product\CatalogProductView;
11+
use Magento\Catalog\Test\TestStep\ConfigureProductOnProductPageStep;
12+
use Magento\Mtf\Constraint\AbstractConstraint;
13+
use Magento\Mtf\TestStep\TestStepFactory;
14+
15+
/**
16+
* Assert calculated price after configure bundle product on product page.
17+
*/
18+
class AssertBundlePriceCalculatedOnProductPage extends AbstractConstraint
19+
{
20+
/**
21+
* Assert calculated price after configure bundle product on product page.
22+
*
23+
* @param TestStepFactory $stepFactory
24+
* @param BundleProduct $product
25+
* @param CatalogProductView $catalogProductView
26+
*/
27+
public function processAssert(
28+
TestStepFactory $stepFactory,
29+
BundleProduct $product,
30+
CatalogProductView $catalogProductView
31+
) {
32+
$stepFactory->create(ConfigureProductOnProductPageStep::class, ['product' => $product])->run();
33+
34+
//Process assertions
35+
$this->assertPrice($product, $catalogProductView);
36+
}
37+
38+
/**
39+
* Assert prices on the product view Page.
40+
*
41+
* @param BundleProduct $product
42+
* @param CatalogProductView $productView
43+
* @return void
44+
*/
45+
protected function assertPrice(BundleProduct $product, CatalogProductView $productView)
46+
{
47+
$checkoutData = $product->getCheckoutData();
48+
\PHPUnit_Framework_Assert::assertEquals(
49+
$checkoutData['cartItem']['configuredPrice'],
50+
$productView->getBundleViewBlock()->getBundleSummaryBlock()->getConfiguredPriceBlock()->getPrice(),
51+
'Bundle price calculated is not correct.'
52+
);
53+
}
54+
55+
/**
56+
* Returns a string representation of the object.
57+
*
58+
* @return string
59+
*/
60+
public function toString()
61+
{
62+
return 'Bundle price calculates right on product view page.';
63+
}
64+
}

dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ public function __construct(DataInterface $configuration, EventManagerInterface
6868
'gift_message_available' => [
6969
'Yes' => 1,
7070
'No' => 0
71+
],
72+
'user_defined' => [
73+
'Yes' => 1,
74+
'No' => 0
7175
]
7276
];
7377
}

dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Webapi.php

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,8 @@ protected function prepareBundleItems()
6464
'title' => $bundleOption['title'],
6565
'type' => $bundleOption['type'],
6666
'required' => $bundleOption['required'],
67-
'product_links' => [],
67+
'product_links' => $this->prepareLinksInfo($bundleSelections, $key)
6868
];
69-
70-
$productLinksInfo = $bundleOption['assigned_products'];
71-
$products = $bundleSelections['products'][$key];
72-
foreach ($productLinksInfo as $linkKey => $productLink) {
73-
$product = $products[$linkKey];
74-
$bundleProductOptions[$key]['product_links'][] = [
75-
'sku' => $product->getSku(),
76-
'qty' => $productLink['data']['selection_qty'],
77-
'is_default' => false,
78-
'price' => isset($productLink['data']['selection_price_value'])
79-
? $productLink['data']['selection_price_value']
80-
: null,
81-
'price_type' => isset($productLink['data']['selection_price_type'])
82-
? $productLink['data']['selection_price_type']
83-
: null,
84-
];
85-
}
8669
}
8770
}
8871

@@ -92,6 +75,39 @@ protected function prepareBundleItems()
9275
unset($this->fields['product']['bundle_selections']);
9376
}
9477

78+
/**
79+
* Prepare links info field.
80+
*
81+
* @param array $bundleSelections
82+
* @param int $key
83+
* @return array
84+
*/
85+
private function prepareLinksInfo(array $bundleSelections, $key)
86+
{
87+
$result = [];
88+
$productLinksInfo = $bundleSelections['bundle_options'][$key]['assigned_products'];
89+
$products = $bundleSelections['products'][$key];
90+
foreach ($productLinksInfo as $linkKey => $productLink) {
91+
$product = $products[$linkKey];
92+
$result[] = [
93+
'sku' => $product->getSku(),
94+
'qty' => $productLink['data']['selection_qty'],
95+
'is_default' => false,
96+
'price' => isset($productLink['data']['selection_price_value'])
97+
? $productLink['data']['selection_price_value']
98+
: null,
99+
'price_type' => isset($productLink['data']['selection_price_type'])
100+
? $productLink['data']['selection_price_type']
101+
: null,
102+
'can_change_quantity' => isset($productLink['data']['user_defined'])
103+
? $productLink['data']['user_defined']
104+
: 0,
105+
];
106+
}
107+
108+
return $result;
109+
}
110+
95111
/**
96112
* Parse response.
97113
*

0 commit comments

Comments
 (0)