-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #12584 Bundle Item price cannot differ per website #27315
Changes from 15 commits
b25a34f
fc9559e
a59b0e8
8cca552
49c261e
659beb2
f75a78b
fd40a7b
d7f283c
56ef44b
b5c9757
9f622ee
64db19a
dc7cc2c
ed0f987
ac37ae1
975c0c1
171c54d
a2a9cba
ea54519
377e070
605fb88
6cc13cc
88ea963
dc3226b
7da12c1
c57d4d0
f6bb216
27627ca
b00b423
eb5e30c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,13 +7,16 @@ | |
|
||
namespace Magento\Bundle\Model\Option; | ||
|
||
use Magento\Bundle\Api\Data\LinkInterface; | ||
use Magento\Bundle\Api\Data\OptionInterface; | ||
use Magento\Bundle\Model\ResourceModel\Option; | ||
use Magento\Catalog\Api\Data\ProductInterface; | ||
use Magento\Framework\App\ObjectManager; | ||
use Magento\Framework\EntityManager\MetadataPool; | ||
use Magento\Framework\Exception\CouldNotSaveException; | ||
use Magento\Bundle\Model\Product\Type; | ||
use Magento\Bundle\Api\ProductLinkManagementInterface; | ||
use Magento\Store\Model\StoreManagerInterface; | ||
|
||
/** | ||
* Encapsulates logic for saving a bundle option, including coalescing the parent product's data. | ||
|
@@ -40,22 +43,31 @@ class SaveAction | |
*/ | ||
private $linkManagement; | ||
|
||
/** | ||
* @var StoreManagerInterface | ||
*/ | ||
private $storeManager; | ||
|
||
/** | ||
* @param Option $optionResource | ||
* @param MetadataPool $metadataPool | ||
* @param Type $type | ||
* @param ProductLinkManagementInterface $linkManagement | ||
* @param StoreManagerInterface|null $storeManager | ||
*/ | ||
public function __construct( | ||
Option $optionResource, | ||
MetadataPool $metadataPool, | ||
Type $type, | ||
ProductLinkManagementInterface $linkManagement | ||
ProductLinkManagementInterface $linkManagement, | ||
?StoreManagerInterface $storeManager = null | ||
) { | ||
$this->optionResource = $optionResource; | ||
$this->metadataPool = $metadataPool; | ||
$this->type = $type; | ||
$this->linkManagement = $linkManagement; | ||
$this->storeManager = $storeManager | ||
?: ObjectManager::getInstance()->get(StoreManagerInterface::class); | ||
} | ||
|
||
/** | ||
|
@@ -69,7 +81,7 @@ public function __construct( | |
*/ | ||
public function save(ProductInterface $bundleProduct, OptionInterface $option) | ||
{ | ||
$metadata = $this->metadataPool->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class); | ||
$metadata = $this->metadataPool->getMetadata(ProductInterface::class); | ||
|
||
$option->setStoreId($bundleProduct->getStoreId()); | ||
$parentId = $bundleProduct->getData($metadata->getLinkField()); | ||
|
@@ -93,7 +105,7 @@ public function save(ProductInterface $bundleProduct, OptionInterface $option) | |
} | ||
} else { | ||
if (!$existingOption->getOptionId()) { | ||
throw new NoSuchEntityException( | ||
throw new \Magento\Framework\Exception\NoSuchEntityException( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we import this instead of having the full path? Just to align with other changes on the PR. |
||
__("The option that was requested doesn't exist. Verify the entity and try again.") | ||
); | ||
} | ||
|
@@ -108,7 +120,7 @@ public function save(ProductInterface $bundleProduct, OptionInterface $option) | |
throw new CouldNotSaveException(__("The option couldn't be saved."), $e); | ||
} | ||
|
||
/** @var \Magento\Bundle\Api\Data\LinkInterface $linkedProduct */ | ||
/** @var LinkInterface $linkedProduct */ | ||
foreach ($linksToAdd as $linkedProduct) { | ||
$this->linkManagement->addChild($bundleProduct, $option->getOptionId(), $linkedProduct); | ||
} | ||
|
@@ -121,8 +133,8 @@ public function save(ProductInterface $bundleProduct, OptionInterface $option) | |
/** | ||
* Update option selections | ||
* | ||
* @param \Magento\Catalog\Api\Data\ProductInterface $product | ||
* @param \Magento\Bundle\Api\Data\OptionInterface $option | ||
* @param ProductInterface $product | ||
* @param OptionInterface $option | ||
* @return void | ||
*/ | ||
private function updateOptionSelection(ProductInterface $product, OptionInterface $option) | ||
|
@@ -135,13 +147,14 @@ private function updateOptionSelection(ProductInterface $product, OptionInterfac | |
if (is_array($option->getProductLinks())) { | ||
$productLinks = $option->getProductLinks(); | ||
foreach ($productLinks as $productLink) { | ||
$productLink->setWebsiteId($this->storeManager->getStore($product->getStoreId())->getWebsiteId()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we add such set on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gabrieldagama I believe it is only relevant when updating an option, unless I am missing something. The only time this isn't called from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method |
||
if (!$productLink->getId() && !$productLink->getSelectionId()) { | ||
$linksToAdd[] = $productLink; | ||
} else { | ||
$linksToUpdate[] = $productLink; | ||
} | ||
} | ||
/** @var \Magento\Bundle\Api\Data\LinkInterface[] $linksToDelete */ | ||
/** @var LinkInterface[] $linksToDelete */ | ||
$linksToDelete = $this->compareLinks($existingLinks, $linksToUpdate); | ||
} | ||
foreach ($linksToUpdate as $linkedProduct) { | ||
|
@@ -162,8 +175,8 @@ private function updateOptionSelection(ProductInterface $product, OptionInterfac | |
/** | ||
* Compute the difference between given arrays. | ||
* | ||
* @param \Magento\Bundle\Api\Data\LinkInterface[] $firstArray | ||
* @param \Magento\Bundle\Api\Data\LinkInterface[] $secondArray | ||
* @param LinkInterface[] $firstArray | ||
* @param LinkInterface[] $secondArray | ||
* | ||
* @return array | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,8 @@ | |
* @method \Magento\Bundle\Model\Selection setPosition(int $value) | ||
* @method int getIsDefault() | ||
* @method \Magento\Bundle\Model\Selection setIsDefault(int $value) | ||
* @method int getWebsiteId() | ||
* @method \Magento\Bundle\Model\Selection setWebsiteId(int $value) | ||
Comment on lines
+23
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we aren't using this approach anymore, this can probably be removed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These methods are still used in another classes. |
||
* @method int getSelectionPriceType() | ||
* @method \Magento\Bundle\Model\Selection setSelectionPriceType(int $value) | ||
* @method float getSelectionPriceValue() | ||
|
@@ -74,18 +76,35 @@ protected function _construct() | |
/** | ||
* Processing object before save data | ||
* | ||
* @return void | ||
*/ | ||
public function beforeSave() | ||
{ | ||
if (!$this->_catalogData->isPriceGlobal() && $this->getWebsiteId()) { | ||
$this->setData('tmp_selection_price_value', $this->getSelectionPriceValue()); | ||
$this->setSelectionPriceValue($this->getOrigData('selection_price_value')); | ||
} | ||
parent::beforeSave(); | ||
} | ||
|
||
/** | ||
* Processing object after save data | ||
* | ||
* @return $this | ||
*/ | ||
public function afterSave() | ||
{ | ||
if (!$this->_catalogData->isPriceGlobal() && $this->getWebsiteId()) { | ||
if (null !== $this->getData('tmp_selection_price_value')) { | ||
$this->setSelectionPriceValue($this->getData('tmp_selection_price_value')); | ||
} | ||
$this->getResource()->saveSelectionPrice($this); | ||
|
||
if (!$this->getDefaultPriceScope()) { | ||
$this->unsSelectionPriceValue(); | ||
$this->unsSelectionPriceType(); | ||
} | ||
} | ||
parent::afterSave(); | ||
return parent::afterSave(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
--> | ||
|
||
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> | ||
<test name="StorefrontCheckBundleProductTwoWebsiteDifferentPriceOptionTest"> | ||
<annotations> | ||
<title value="Verify bundle item price different websites."/> | ||
<stories value="Github issue: #12584 Bundle Item price cannot differ per website"/> | ||
<description value="Verify bundle item price different websites. Change bundle item price on second website."/> | ||
<features value="Bundle"/> | ||
<severity value="MAJOR"/> | ||
<group value="bundle"/> | ||
</annotations> | ||
<before> | ||
<magentoCLI command="config:set {{WebsiteCatalogPriceScopeConfigData.path}} {{WebsiteCatalogPriceScopeConfigData.value}}" stepKey="setPriceScopeWebsite"/> | ||
<actionGroup ref="AdminLoginActionGroup" stepKey="logInAsAdmin"/> | ||
|
||
<actionGroup ref="AdminCreateWebsiteActionGroup" stepKey="createWebsite"> | ||
<argument name="newWebsiteName" value="{{customWebsite.name}}"/> | ||
<argument name="websiteCode" value="{{customWebsite.code}}"/> | ||
</actionGroup> | ||
<actionGroup ref="CreateCustomStoreActionGroup" stepKey="createCustomStoreGroup"> | ||
<argument name="website" value="{{customWebsite.name}}"/> | ||
<argument name="store" value="{{customStoreGroup.name}}"/> | ||
<argument name="rootCategory" value="Default Category"/> | ||
</actionGroup> | ||
<actionGroup ref="AdminCreateStoreViewActionGroup" stepKey="createCustomStoreView"> | ||
<argument name="StoreGroup" value="customStoreGroup"/> | ||
<argument name="customStore" value="customStore"/> | ||
</actionGroup> | ||
|
||
<createData entity="SimpleProduct2" stepKey="simpleProduct"/> | ||
<createData entity="ApiFixedBundleProduct" stepKey="createBundleProduct" /> | ||
<createData entity="CheckboxOption" stepKey="createBundleOption"> | ||
<requiredEntity createDataKey="createBundleProduct"/> | ||
</createData> | ||
<createData entity="ApiBundleLinkFixed" stepKey="linkOptionToProduct"> | ||
<requiredEntity createDataKey="createBundleProduct"/> | ||
<requiredEntity createDataKey="createBundleOption"/> | ||
<requiredEntity createDataKey="simpleProduct"/> | ||
</createData> | ||
</before> | ||
<after> | ||
<magentoCLI command="config:set {{GlobalCatalogPriceScopeConfigData.path}} {{GlobalCatalogPriceScopeConfigData.value}}" stepKey="setPriceScopeGlobal"/> | ||
|
||
<deleteData createDataKey="simpleProduct" stepKey="deleteSimpleProduct"/> | ||
<deleteData createDataKey="createBundleProduct" stepKey="deleteBundleProduct"/> | ||
|
||
<actionGroup ref="AdminDeleteWebsiteActionGroup" stepKey="deleteWebsite"> | ||
<argument name="websiteName" value="{{customWebsite.name}}"/> | ||
</actionGroup> | ||
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/> | ||
|
||
<actionGroup ref="CliIndexerReindexActionGroup" stepKey="reindex"> | ||
<argument name="indices" value=""/> | ||
</actionGroup> | ||
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanFullPageCache"> | ||
<argument name="tags" value="config full_page"/> | ||
</actionGroup> | ||
</after> | ||
|
||
<actionGroup ref="NavigateToCreatedProductEditPageActionGroup" stepKey="openEditBundleProduct"> | ||
<argument name="product" value="$$createBundleProduct$$"/> | ||
</actionGroup> | ||
|
||
<actionGroup ref="AdminAssignProductInWebsiteActionGroup" stepKey="selectProductInWebsites"> | ||
<argument name="website" value="{{customWebsite.name}}"/> | ||
</actionGroup> | ||
<actionGroup ref="SaveProductFormActionGroup" stepKey="clickSaveButton"/> | ||
<actionGroup ref="SwitchToTheNewStoreViewActionGroup" stepKey="SwitchNewStoreView"> | ||
<argument name="storeViewName" value="{{customStore.name}}"/> | ||
</actionGroup> | ||
|
||
<fillField selector="{{AdminProductFormBundleSection.bundleOptionXProductYPrice('0', '0')}}" userInput="100" stepKey="fillBundleOption1Price"/> | ||
|
||
<actionGroup ref="SaveProductFormActionGroup" stepKey="saveNewPrice"/> | ||
<actionGroup ref="StorefrontOpenProductPageActionGroup" stepKey="openProductPage"> | ||
<argument name="productUrl" value="$$createBundleProduct.custom_attributes[url_key]$$"/> | ||
</actionGroup> | ||
|
||
<click selector="{{StorefrontBundledSection.addToCart}}" stepKey="clickCustomizeAndAddToCart"/> | ||
|
||
<grabTextFrom selector="{{StorefrontBundledSection.bundleProductsPrice}}" stepKey="grabPriceText"/> | ||
<assertEquals stepKey="assertPriceText"> | ||
<expectedResult type="string">$31.23</expectedResult> | ||
<actualResult type="variable">$grabPriceText</actualResult> | ||
</assertEquals> | ||
|
||
</test> | ||
</tests> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently we are not using the
storeManager
in this class, can we remove it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done