Skip to content

Commit acef25f

Browse files
committed
MAGETWO-99587: Custom options price from website scope rewrites prices on all scopes
1 parent 6494c9f commit acef25f

File tree

3 files changed

+76
-31
lines changed

3 files changed

+76
-31
lines changed

app/code/Magento/Catalog/Model/ResourceModel/Product/Option.php

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
namespace Magento\Catalog\Model\ResourceModel\Product;
77

88
use Magento\Catalog\Api\Data\ProductInterface;
9+
use Magento\Store\Model\Store;
910

1011
/**
1112
* Catalog product custom option resource model
@@ -106,7 +107,7 @@ protected function _saveValuePrices(\Magento\Framework\Model\AbstractModel $obje
106107
*/
107108

108109
if (in_array($object->getType(), $this->getPriceTypes())) {
109-
//save for store_id = 0
110+
// save for store_id = 0
110111
if (!$object->getData('scope', 'price')) {
111112
$statement = $connection->select()->from(
112113
$priceTable,
@@ -116,11 +117,24 @@ protected function _saveValuePrices(\Magento\Framework\Model\AbstractModel $obje
116117
$object->getId()
117118
)->where(
118119
'store_id = ?',
119-
\Magento\Store\Model\Store::DEFAULT_STORE_ID
120+
Store::DEFAULT_STORE_ID
120121
);
121122
$optionId = $connection->fetchOne($statement);
122123

123-
if ($optionId) {
124+
if (!$optionId) {
125+
$data = $this->_prepareDataForTable(
126+
new \Magento\Framework\DataObject(
127+
[
128+
'option_id' => $object->getId(),
129+
'store_id' => Store::DEFAULT_STORE_ID,
130+
'price' => $object->getPrice(),
131+
'price_type' => $object->getPriceType(),
132+
]
133+
),
134+
$priceTable
135+
);
136+
$connection->insert($priceTable, $data);
137+
} elseif ((int)$object->getStoreId() === Store::DEFAULT_STORE_ID) {
124138
$data = $this->_prepareDataForTable(
125139
new \Magento\Framework\DataObject(
126140
['price' => $object->getPrice(), 'price_type' => $object->getPriceType()]
@@ -133,31 +147,18 @@ protected function _saveValuePrices(\Magento\Framework\Model\AbstractModel $obje
133147
$data,
134148
[
135149
'option_id = ?' => $object->getId(),
136-
'store_id = ?' => \Magento\Store\Model\Store::DEFAULT_STORE_ID
150+
'store_id = ?' => Store::DEFAULT_STORE_ID
137151
]
138152
);
139-
} else {
140-
$data = $this->_prepareDataForTable(
141-
new \Magento\Framework\DataObject(
142-
[
143-
'option_id' => $object->getId(),
144-
'store_id' => \Magento\Store\Model\Store::DEFAULT_STORE_ID,
145-
'price' => $object->getPrice(),
146-
'price_type' => $object->getPriceType(),
147-
]
148-
),
149-
$priceTable
150-
);
151-
$connection->insert($priceTable, $data);
152153
}
153154
}
154155

155156
$scope = (int)$this->_config->getValue(
156-
\Magento\Store\Model\Store::XML_PATH_PRICE_SCOPE,
157+
Store::XML_PATH_PRICE_SCOPE,
157158
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
158159
);
159160

160-
if ($object->getStoreId() != '0' && $scope == \Magento\Store\Model\Store::PRICE_SCOPE_WEBSITE) {
161+
if ($object->getStoreId() != '0' && $scope == Store::PRICE_SCOPE_WEBSITE) {
161162
$baseCurrency = $this->_config->getValue(
162163
\Magento\Directory\Model\Currency::XML_PATH_CURRENCY_BASE,
163164
'default'
@@ -216,7 +217,7 @@ protected function _saveValuePrices(\Magento\Framework\Model\AbstractModel $obje
216217
}
217218
}
218219
}
219-
} elseif ($scope == \Magento\Store\Model\Store::PRICE_SCOPE_WEBSITE && $object->getData('scope', 'price')
220+
} elseif ($scope == Store::PRICE_SCOPE_WEBSITE && $object->getData('scope', 'price')
220221
) {
221222
$connection->delete(
222223
$priceTable,
@@ -239,20 +240,20 @@ protected function _saveValueTitles(\Magento\Framework\Model\AbstractModel $obje
239240
{
240241
$connection = $this->getConnection();
241242
$titleTableName = $this->getTable('catalog_product_option_title');
242-
foreach ([\Magento\Store\Model\Store::DEFAULT_STORE_ID, $object->getStoreId()] as $storeId) {
243+
foreach ([Store::DEFAULT_STORE_ID, $object->getStoreId()] as $storeId) {
243244
$existInCurrentStore = $this->getColFromOptionTable($titleTableName, (int)$object->getId(), (int)$storeId);
244-
$existInDefaultStore = (int)$storeId == \Magento\Store\Model\Store::DEFAULT_STORE_ID ?
245+
$existInDefaultStore = (int)$storeId == Store::DEFAULT_STORE_ID ?
245246
$existInCurrentStore :
246247
$this->getColFromOptionTable(
247248
$titleTableName,
248249
(int)$object->getId(),
249-
\Magento\Store\Model\Store::DEFAULT_STORE_ID
250+
Store::DEFAULT_STORE_ID
250251
);
251252

252253
if ($object->getTitle()) {
253254
$isDeleteStoreTitle = (bool)$object->getData('is_delete_store_title');
254255
if ($existInCurrentStore) {
255-
if ($isDeleteStoreTitle && (int)$storeId != \Magento\Store\Model\Store::DEFAULT_STORE_ID) {
256+
if ($isDeleteStoreTitle && (int)$storeId != Store::DEFAULT_STORE_ID) {
256257
$connection->delete($titleTableName, ['option_title_id = ?' => $existInCurrentStore]);
257258
} elseif ($object->getStoreId() == $storeId) {
258259
$data = $this->_prepareDataForTable(
@@ -270,9 +271,9 @@ protected function _saveValueTitles(\Magento\Framework\Model\AbstractModel $obje
270271
}
271272
} else {
272273
// we should insert record into not default store only of if it does not exist in default store
273-
if (($storeId == \Magento\Store\Model\Store::DEFAULT_STORE_ID && !$existInDefaultStore) ||
274+
if (($storeId == Store::DEFAULT_STORE_ID && !$existInDefaultStore) ||
274275
(
275-
$storeId != \Magento\Store\Model\Store::DEFAULT_STORE_ID &&
276+
$storeId != Store::DEFAULT_STORE_ID &&
276277
!$existInCurrentStore &&
277278
!$isDeleteStoreTitle
278279
)
@@ -291,7 +292,7 @@ protected function _saveValueTitles(\Magento\Framework\Model\AbstractModel $obje
291292
}
292293
}
293294
} else {
294-
if ($object->getId() && $object->getStoreId() > \Magento\Store\Model\Store::DEFAULT_STORE_ID
295+
if ($object->getId() && $object->getStoreId() > Store::DEFAULT_STORE_ID
295296
&& $storeId
296297
) {
297298
$connection->delete(
@@ -470,7 +471,7 @@ public function getSearchableData($productId, $storeId)
470471
'option_title_default.option_id=product_option.option_id',
471472
$connection->quoteInto(
472473
'option_title_default.store_id = ?',
473-
\Magento\Store\Model\Store::DEFAULT_STORE_ID
474+
Store::DEFAULT_STORE_ID
474475
)
475476
]
476477
);
@@ -517,7 +518,7 @@ public function getSearchableData($productId, $storeId)
517518
'option_title_default.option_type_id=option_type.option_type_id',
518519
$connection->quoteInto(
519520
'option_title_default.store_id = ?',
520-
\Magento\Store\Model\Store::DEFAULT_STORE_ID
521+
Store::DEFAULT_STORE_ID
521522
)
522523
]
523524
);

dev/tests/integration/testsuite/Magento/Catalog/Model/Product/OptionTest.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory;
1010
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Store\Model\Store;
12+
use Magento\Store\Model\StoreManagerInterface;
1113
use Magento\TestFramework\Helper\Bootstrap;
1214

1315
/**
@@ -31,13 +33,20 @@ class OptionTest extends \PHPUnit\Framework\TestCase
3133
*/
3234
private $customOptionFactory;
3335

36+
/**
37+
* @var StoreManagerInterface
38+
*/
39+
private $storeManager;
40+
41+
3442
/**
3543
* @inheritdoc
3644
*/
3745
protected function setUp()
3846
{
3947
$this->productRepository = Bootstrap::getObjectManager()->create(ProductRepositoryInterface::class);
4048
$this->customOptionFactory = Bootstrap::getObjectManager()->create(ProductCustomOptionInterfaceFactory::class);
49+
$this->storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class);
4150
}
4251

4352
/**
@@ -103,4 +112,39 @@ private function createFileOption(string $rawExtensions)
103112

104113
return $this->customOptionFactory->create(['data' => $data]);
105114
}
115+
116+
/**
117+
* Test to save option price by store
118+
*
119+
* @magentoDataFixture Magento/Catalog/_files/product_with_options.php
120+
* @magentoDataFixture Magento/Store/_files/core_second_third_fixturestore.php
121+
* @magentoConfigFixture default_store catalog/price/scope 1
122+
* @magentoConfigFixture secondstore_store catalog/price/scope 1
123+
*/
124+
public function testSaveOptionPriceByStore()
125+
{
126+
$secondWebsitePrice = 22.0;
127+
$defaultStoreId = $this->storeManager->getStore()->getId();
128+
$secondStoreId = $this->storeManager->getStore('secondstore')->getId();
129+
130+
/** @var \Magento\Catalog\Model\Product $product */
131+
$product = $this->productRepository->get('simple');
132+
$option = $product->getOptions()[0];
133+
$defaultPrice = $option->getPrice();
134+
135+
$option->setPrice($secondWebsitePrice);
136+
$product->setStoreId($secondStoreId);
137+
// set Current store='secondstore' to correctly save product options for 'secondstore'
138+
$this->storeManager->setCurrentStore($secondStoreId);
139+
$this->productRepository->save($product);
140+
$this->storeManager->setCurrentStore($defaultStoreId);
141+
142+
$product = $this->productRepository->get('simple', false, Store::DEFAULT_STORE_ID, true);
143+
$option = $product->getOptions()[0];
144+
$this->assertEquals($defaultPrice, $option->getPrice(), 'Price value by default store is wrong');
145+
146+
$product = $this->productRepository->get('simple', false, $secondStoreId, true);
147+
$option = $product->getOptions()[0];
148+
$this->assertEquals($secondWebsitePrice, $option->getPrice(), 'Price value by store_id=1 is wrong');
149+
}
106150
}

dev/tests/integration/testsuite/Magento/Store/_files/core_second_third_fixturestore.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
/** @var \Magento\Store\Model\Store $store */
1515
$store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class);
16-
$store->setCode('secondstore')->setName('Second Store')->setSortOrder(10)->setIsActive(1);
16+
$store->setCode('secondstore')->setWebsiteId($websiteId)->setName('Second Store')->setSortOrder(10)->setIsActive(1);
1717
$store->save();
1818

1919
/** @var \Magento\Store\Model\Website $website */
@@ -25,5 +25,5 @@
2525

2626
/** @var \Magento\Store\Model\Store $store */
2727
$store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(\Magento\Store\Model\Store::class);
28-
$store->setCode('thirdstore')->setName('Third Store')->setSortOrder(10)->setIsActive(1);
28+
$store->setCode('thirdstore')->setWebsiteId($websiteId)->setName('Third Store')->setSortOrder(10)->setIsActive(1);
2929
$store->save();

0 commit comments

Comments
 (0)