Skip to content

Commit 2f791ae

Browse files
Merge branch 2.2-develop into ENGCOM-2667-magento-magento2-17371
2 parents 97cf28d + 9a701f2 commit 2f791ae

File tree

88 files changed

+2991
-277
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+2991
-277
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
10+
<entity name="DefaultAllowCountriesConfig" type="allow_countries_config">
11+
<requiredEntity type="allow_countries_config_default">DefaultAllowCountries</requiredEntity>
12+
</entity>
13+
<entity name="DefaultAllowCountries" type="allow_countries_config_default">
14+
<data key="value">0</data>
15+
</entity>
16+
17+
<entity name="SetAllowCountriesConfigUS" type="allow_countries_config">
18+
<data key="value">US</data>
19+
</entity>
20+
</entities>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<operations xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataOperation.xsd">
10+
<operation name="AllowCountriesConfig" dataType="allow_countries_config" type="create" auth="adminFormKey" url="/admin/system_config/save/section/general/" method="POST" successRegex="/messages-message-success/">
11+
<object key="groups" dataType="allow_countries_config">
12+
<object key="country" dataType="allow_countries_config">
13+
<object key="fields" dataType="allow_countries_config">
14+
<object key="allow" dataType="allow_countries_config">
15+
<field key="value">string</field>
16+
<object key="inherit" dataType="allow_countries_config_default">
17+
<field key="value">integer</field>
18+
</object>
19+
</object>
20+
</object>
21+
</object>
22+
</object>
23+
</operation>
24+
</operations>

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,17 @@ define([
374374
function applyTierPrice(oneItemPrice, qty, optionConfig) {
375375
var tiers = optionConfig.tierPrice,
376376
magicKey = _.keys(oneItemPrice)[0],
377+
tiersFirstKey = _.keys(optionConfig)[0],
377378
lowest = false;
378379

380+
if (!tiers) {//tiers is undefined when options has only one option
381+
tiers = optionConfig[tiersFirstKey].tierPrice;
382+
}
383+
384+
tiers.sort(function (a, b) {//sorting based on "price_qty"
385+
return a['price_qty'] - b['price_qty'];
386+
});
387+
379388
_.each(tiers, function (tier, index) {
380389
if (tier['price_qty'] > qty) {
381390
return;

app/code/Magento/Catalog/Controller/Adminhtml/Product/Builder.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
use Magento\Catalog\Model\Product;
1616
use Magento\Catalog\Model\Product\Type as ProductTypes;
1717

18+
/**
19+
* Build a product based on a request.
20+
*/
1821
class Builder
1922
{
2023
/**
@@ -92,6 +95,9 @@ public function build(RequestInterface $request)
9295
if ($productId) {
9396
try {
9497
$product = $this->productRepository->getById($productId, true, $storeId);
98+
if ($attributeSetId) {
99+
$product->setAttributeSetId($attributeSetId);
100+
}
95101
} catch (\Exception $e) {
96102
$product = $this->createEmptyProduct(ProductTypes::DEFAULT_TYPE, $attributeSetId, $storeId);
97103
$this->logger->critical($e);
@@ -113,6 +119,8 @@ public function build(RequestInterface $request)
113119
}
114120

115121
/**
122+
* Create a product with the given properties
123+
*
116124
* @param int $typeId
117125
* @param int $attributeSetId
118126
* @param int $storeId

app/code/Magento/Catalog/Model/CategoryList.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ public function getList(SearchCriteriaInterface $searchCriteria)
7878
$this->collectionProcessor->process($searchCriteria, $collection);
7979

8080
$items = [];
81-
foreach ($collection->getItems() as $category) {
82-
$items[] = $this->categoryRepository->get($category->getId());
81+
foreach ($collection->getAllIds() as $id) {
82+
$items[] = $this->categoryRepository->get($id);
8383
}
8484

8585
/** @var CategorySearchResultsInterface $searchResult */
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
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\Catalog\Model\Product\Type;
9+
10+
use Magento\Store\Model\Store;
11+
use Magento\Catalog\Model\ResourceModel\Product\Price\SpecialPrice;
12+
use Magento\Catalog\Api\Data\SpecialPriceInterface;
13+
use Magento\Store\Api\Data\WebsiteInterface;
14+
15+
/**
16+
* Product special price model.
17+
*
18+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
19+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
20+
*/
21+
class FrontSpecialPrice extends Price
22+
{
23+
/**
24+
* @var SpecialPrice
25+
*/
26+
private $specialPrice;
27+
28+
/**
29+
* @param \Magento\CatalogRule\Model\ResourceModel\RuleFactory $ruleFactory
30+
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
31+
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
32+
* @param \Magento\Customer\Model\Session $customerSession
33+
* @param \Magento\Framework\Event\ManagerInterface $eventManager
34+
* @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
35+
* @param \Magento\Customer\Api\GroupManagementInterface $groupManagement
36+
* @param \Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory $tierPriceFactory
37+
* @param \Magento\Framework\App\Config\ScopeConfigInterface $config
38+
* @param SpecialPrice $specialPrice
39+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
40+
*/
41+
public function __construct(
42+
\Magento\CatalogRule\Model\ResourceModel\RuleFactory $ruleFactory,
43+
\Magento\Store\Model\StoreManagerInterface $storeManager,
44+
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
45+
\Magento\Customer\Model\Session $customerSession,
46+
\Magento\Framework\Event\ManagerInterface $eventManager,
47+
\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
48+
\Magento\Customer\Api\GroupManagementInterface $groupManagement,
49+
\Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory $tierPriceFactory,
50+
\Magento\Framework\App\Config\ScopeConfigInterface $config,
51+
SpecialPrice $specialPrice
52+
) {
53+
$this->specialPrice = $specialPrice;
54+
parent::__construct(
55+
$ruleFactory,
56+
$storeManager,
57+
$localeDate,
58+
$customerSession,
59+
$eventManager,
60+
$priceCurrency,
61+
$groupManagement,
62+
$tierPriceFactory,
63+
$config
64+
);
65+
}
66+
67+
/**
68+
* @inheritdoc
69+
*/
70+
protected function _applySpecialPrice($product, $finalPrice)
71+
{
72+
if (!$product->getSpecialPrice()) {
73+
return $finalPrice;
74+
}
75+
76+
$specialPrices = $this->getSpecialPrices($product);
77+
$specialPrice = !(empty($specialPrices)) ? min($specialPrices) : $product->getSpecialPrice();
78+
79+
$specialPrice = $this->calculateSpecialPrice(
80+
$finalPrice,
81+
$specialPrice,
82+
$product->getSpecialFromDate(),
83+
$product->getSpecialToDate(),
84+
WebsiteInterface::ADMIN_CODE
85+
);
86+
$product->setData('special_price', $specialPrice);
87+
88+
return $specialPrice;
89+
}
90+
91+
/**
92+
* Get special prices.
93+
*
94+
* @param mixed $product
95+
* @return array
96+
*/
97+
private function getSpecialPrices($product): array
98+
{
99+
$allSpecialPrices = $this->specialPrice->get([$product->getSku()]);
100+
$specialPrices = [];
101+
foreach ($allSpecialPrices as $price) {
102+
if ($this->isSuitableSpecialPrice($product, $price)) {
103+
$specialPrices[] = $price['value'];
104+
}
105+
}
106+
107+
return $specialPrices;
108+
}
109+
110+
/**
111+
* Price is suitable from default and current store + start and end date are equal.
112+
*
113+
* @param mixed $product
114+
* @param array $price
115+
* @return bool
116+
*/
117+
private function isSuitableSpecialPrice($product, array $price): bool
118+
{
119+
$priceStoreId = $price[Store::STORE_ID];
120+
if (($priceStoreId == Store::DEFAULT_STORE_ID || $product->getStoreId() == $priceStoreId)
121+
&& $price[SpecialPriceInterface::PRICE_FROM] == $product->getSpecialFromDate()
122+
&& $price[SpecialPriceInterface::PRICE_TO] == $product->getSpecialToDate()) {
123+
return true;
124+
}
125+
126+
return false;
127+
}
128+
}

app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductActionGroup.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
<scrollToTopOfPage stepKey="initScrollToTopOfThePage"/>
8787
<click selector="{{AdminProductFormSection.advancedPricingLink}}" stepKey="clickAdvancedPricingLink"/>
8888
<waitForElementVisible selector="{{AdminProductFormAdvancedPricingSection.specialPrice}}" stepKey="waitSpecialPrice"/>
89+
<conditionalClick selector="{{AdminProductFormAdvancedPricingSection.useDefaultPrice}}" dependentSelector="{{AdminProductFormAdvancedPricingSection.useDefaultPrice}}" visible="true" stepKey="checkUseDefault"/>
8990
<fillField userInput="{{price}}" selector="{{AdminProductFormAdvancedPricingSection.specialPrice}}" stepKey="fillSpecialPrice"/>
9091
<click selector="{{AdminProductFormAdvancedPricingSection.doneButton}}" stepKey="clickDone"/>
9192
<waitForElementNotVisible selector="{{AdminProductFormAdvancedPricingSection.specialPrice}}" stepKey="waitForCloseModalWindow"/>
@@ -257,4 +258,15 @@
257258
<click selector="{{AdminProductFormActionSection.saveButton}}" stepKey="clickOnSaveButton"/>
258259
<see selector="{{AdminMessagesSection.success}}" userInput="You saved the product." stepKey="seeSaveProductMessage"/>
259260
</actionGroup>
261+
262+
<actionGroup name="AdminChangeProductAttributeSet">
263+
<arguments>
264+
<argument name="attributeSet"/>
265+
</arguments>
266+
<scrollToTopOfPage stepKey="scrollToTop"/>
267+
<click selector="{{AdminProductFormSection.attributeSet}}" stepKey="startEditAttributeSet"/>
268+
<fillField selector="{{AdminProductFormSection.attributeSetFilter}}" userInput="{{attributeSet.attribute_set_name}}" stepKey="searchForAttributeSet"/>
269+
<waitForElementVisible selector="{{AdminProductFormSection.attributeSetFilterResultByName(attributeSet.attribute_set_name)}}" stepKey="waitForNewAttributeSetIsShown"/>
270+
<click selector="{{AdminProductFormSection.attributeSetFilterResultByName(attributeSet.attribute_set_name)}}" stepKey="selectAttributeSet"/>
271+
</actionGroup>
260272
</actionGroups>

app/code/Magento/Catalog/Test/Mftf/Data/CatalogStorefrontConfigData.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,26 @@
4646
<entity name="DefaultFlatCatalogProduct" type="flat_catalog_product">
4747
<data key="value">0</data>
4848
</entity>
49+
50+
<entity name="UseFlatCatalogCategoryAndProduct" type="catalog_storefront_config">
51+
<requiredEntity type="flat_catalog_product">UseFlatCatalogProduct</requiredEntity>
52+
<requiredEntity type="flat_catalog_category">UseFlatCatalogCategory</requiredEntity>
53+
</entity>
54+
55+
<entity name="UseFlatCatalogProduct" type="flat_catalog_product">
56+
<data key="value">1</data>
57+
</entity>
58+
59+
<entity name="UseFlatCatalogCategory" type="flat_catalog_category">
60+
<data key="value">1</data>
61+
</entity>
62+
63+
<entity name="DefaultFlatCatalogCategoryAndProduct" type="catalog_storefront_config">
64+
<requiredEntity type="flat_catalog_product">DefaultFlatCatalogProduct</requiredEntity>
65+
<requiredEntity type="flat_catalog_category">DefaultFlatCatalogCategory</requiredEntity>
66+
</entity>
67+
68+
<entity name="DefaultFlatCatalogCategory" type="flat_catalog_category">
69+
<data key="value">0</data>
70+
</entity>
4971
</entities>

app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
-->
88

99
<entities xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10-
xsi:noNamespaceSchemaLocation="../../../../../../../dev/tests/acceptance/vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/DataGenerator/etc/dataProfileSchema.xsd">
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:DataGenerator/etc/dataProfileSchema.xsd">
1111
<entity name="productAttributeWithTwoOptions" type="ProductAttribute">
1212
<data key="name" unique="suffix">ProductAttributeWithTwoOptions</data>
1313
<data key="attribute_code" unique="suffix">attribute</data>
@@ -74,4 +74,7 @@
7474
<data key="used_for_sort_by">true</data>
7575
<requiredEntity type="FrontendLabel">ProductAttributeFrontendLabel</requiredEntity>
7676
</entity>
77+
<entity name="ProductAttributeText" extends="productAttributeWithTwoOptions">
78+
<data key="frontend_input">text</data>
79+
</entity>
7780
</entities>

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormAdvancedPricingSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,6 @@
2121
<element name="productTierPricePercentageError" type="text" selector="div[data-index='percentage_value'] label.admin__field-error" />
2222
<element name="specialPrice" type="input" selector="input[name='product[special_price]']"/>
2323
<element name="doneButton" type="button" selector=".product_form_product_form_advanced_pricing_modal button.action-primary" timeout="5"/>
24+
<element name="useDefaultPrice" type="checkbox" selector="input[name='use_default[special_price]']"/>
2425
</section>
2526
</sections>

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
<element name="requiredNameIndicator" type="text" selector=" return window.getComputedStyle(document.querySelector('._required[data-index=name]&gt;.admin__field-label span'), ':after').getPropertyValue('content');"/>
4242
<element name="requiredSkuIndicator" type="text" selector=" return window.getComputedStyle(document.querySelector('._required[data-index=sku]&gt;.admin__field-label span'), ':after').getPropertyValue('content');"/>
4343
<element name="customAttributeDropdownField" type="select" selector="select[name='product[{{attributeCode}}]']" parameterized="true"/>
44+
<element name="customAttributeInputField" type="select" selector="input[name='product[{{attributeCode}}]']" parameterized="true"/>
4445
</section>
4546
<section name="ProductInWebsitesSection">
4647
<element name="sectionHeader" type="button" selector="div[data-index='websites']" timeout="30"/>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
9+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
10+
<test name="AdminChangeProductAttributeSetTest">
11+
<annotations>
12+
<features value="Catalog"/>
13+
<stories value="Update product"/>
14+
<title value="Attributes from the selected attribute set should be shown"/>
15+
<description value="Attributes from the selected attribute set should be shown"/>
16+
<severity value="CRITICAL"/>
17+
<testCaseId value="MC-15414"/>
18+
<useCaseId value="MAGETWO-98380"/>
19+
<group value="catalog"/>
20+
</annotations>
21+
<before>
22+
<!--Create category product, attribute, attribute set-->
23+
<createData entity="SimpleSubCategory" stepKey="createCategory"/>
24+
<createData entity="_defaultProduct" stepKey="createSimpleProduct">
25+
<requiredEntity createDataKey="createCategory"/>
26+
</createData>
27+
<createData entity="ProductAttributeText" stepKey="createProductAttribute"/>
28+
<createData entity="CatalogAttributeSet" stepKey="createAttributeSet"/>
29+
30+
<actionGroup ref="LoginAsAdmin" stepKey="login"/>
31+
<!--Assign attribute to attribute set-->
32+
<amOnPage url="{{AdminProductAttributeSetEditPage.url($$createAttributeSet.attribute_set_id$$)}}" stepKey="openAttributeSetEdit"/>
33+
<actionGroup ref="AssignAttributeToGroup" stepKey="assignAttributeToGroup">
34+
<argument name="group" value="Product Details"/>
35+
<argument name="attribute" value="$$createProductAttribute.attribute_code$$"/>
36+
</actionGroup>
37+
<actionGroup ref="SaveAttributeSet" stepKey="saveAttributeSet"/>
38+
</before>
39+
<after>
40+
<!--Delete created entities-->
41+
<deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/>
42+
<deleteData createDataKey="createCategory" stepKey="deleteCategory"/>
43+
<deleteData createDataKey="createProductAttribute" stepKey="deleteProductAttribute"/>
44+
<deleteData createDataKey="createAttributeSet" stepKey="deleteAttributeSet"/>
45+
46+
<actionGroup ref="logout" stepKey="logoutAdminUserAfterTest"/>
47+
</after>
48+
<!--Open created product-->
49+
<amOnPage url="{{AdminProductEditPage.url($$createSimpleProduct.id$$)}}" stepKey="openProductEditPage"/>
50+
<waitForPageLoad time="30" stepKey="waitForProductPageIsLoaded"/>
51+
<dontSeeElement selector="{{AdminProductFormSection.customAttributeInputField($$createProductAttribute.attribute_code$$)}}" stepKey="dontSeeCreatedAttribute"/>
52+
<!--Change product attribute set-->
53+
<actionGroup ref="AdminChangeProductAttributeSet" stepKey="changeProductAttributeSet">
54+
<argument name="attributeSet" value="$$createAttributeSet$$"/>
55+
</actionGroup>
56+
<!--Check new attribute is visible on product edit page-->
57+
<seeElement selector="{{AdminProductFormSection.customAttributeInputField($$createProductAttribute.attribute_code$$)}}" stepKey="seeAttributeInForm"/>
58+
</test>
59+
</tests>

app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,16 +86,14 @@ public function testGetList()
8686
$categoryIdSecond = 2;
8787

8888
$categoryFirst = $this->getMockBuilder(Category::class)->disableOriginalConstructor()->getMock();
89-
$categoryFirst->expects($this->atLeastOnce())->method('getId')->willReturn($categoryIdFirst);
9089
$categorySecond = $this->getMockBuilder(Category::class)->disableOriginalConstructor()->getMock();
91-
$categorySecond->expects($this->atLeastOnce())->method('getId')->willReturn($categoryIdSecond);
9290

9391
/** @var SearchCriteriaInterface|\PHPUnit_Framework_MockObject_MockObject $searchCriteria */
9492
$searchCriteria = $this->createMock(SearchCriteriaInterface::class);
9593

9694
$collection = $this->getMockBuilder(Collection::class)->disableOriginalConstructor()->getMock();
9795
$collection->expects($this->once())->method('getSize')->willReturn($totalCount);
98-
$collection->expects($this->once())->method('getItems')->willReturn([$categoryFirst, $categorySecond]);
96+
$collection->expects($this->once())->method('getAllIds')->willReturn([$categoryIdFirst, $categoryIdSecond]);
9997

10098
$this->collectionProcessorMock->expects($this->once())
10199
->method('process')

app/code/Magento/Catalog/etc/frontend/di.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,5 @@
9898
<type name="Magento\Framework\App\Action\AbstractAction">
9999
<plugin name="catalog_app_action_dispatch_controller_context_plugin" type="Magento\Catalog\Plugin\Framework\App\Action\ContextPlugin" />
100100
</type>
101+
<preference for="Magento\Catalog\Model\Product\Type\Price" type="Magento\Catalog\Model\Product\Type\FrontSpecialPrice" />
101102
</config>

0 commit comments

Comments
 (0)