Skip to content

Commit 41883fa

Browse files
authored
Merge pull request #8311 from magento-l3/PR-05242023
L3- PR 05242023
2 parents 09eaf9f + 275148c commit 41883fa

File tree

34 files changed

+905
-80
lines changed

34 files changed

+905
-80
lines changed

app/code/Magento/Bundle/Test/Mftf/Section/AdminProductFormBundleSection.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,5 +125,7 @@
125125
<element name="priceType" type="select" selector="[name='product[options][0][price_type]']" />
126126
<element name="priceTypeSelectPercent" type="select" selector="//*[@name='product[options][0][price_type]']/option[2]" />
127127
<element name="weightFieldLabel" type="input" selector="//div[@data-index='weight']/div/label/span"/>
128+
<!--Errors-->
129+
<element name="fieldError" type="text" selector=".admin__field-error[data-bind='attr: {for: {{field}}}, text: error']" parameterized="true"/>
128130
</section>
129131
</sections>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AdminAddDecimalDefaultToBundleItemsTest">
12+
<annotations>
13+
<features value="Bundle"/>
14+
<stories value="Create/Edit bundle product in Admin"/>
15+
<title value="Admin should be able to set decimal default to bundle item when item allows it"/>
16+
<description value="Admin should be able to set decimal default value to new bundle option"/>
17+
<severity value="AVERAGE"/>
18+
<testCaseId value="AC-8646"/>
19+
<useCaseId value="ACP2E-1799"/>
20+
<group value="Bundle"/>
21+
</annotations>
22+
<before>
23+
<createData entity="_defaultCategory" stepKey="createPreReqCategory"/>
24+
<createData entity="SimpleProduct2" stepKey="simpleProduct1"/>
25+
<createData entity="SimpleProduct2" stepKey="simpleProduct2"/>
26+
<actionGroup stepKey="loginToAdminPanel" ref="AdminLoginActionGroup"/>
27+
</before>
28+
<after>
29+
<deleteData createDataKey="createPreReqCategory" stepKey="deletePreReqCategory"/>
30+
<deleteData createDataKey="simpleProduct1" stepKey="deleteSimpleProduct1"/>
31+
<deleteData createDataKey="simpleProduct2" stepKey="deleteSimpleProduct2"/>
32+
<actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="navigateToProductIndex"/>
33+
<actionGroup ref="ResetAdminDataGridToDefaultViewActionGroup" stepKey="clearFilters"/>
34+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
35+
</after>
36+
37+
<!-- Open simpleProduct1 in Admin -->
38+
<actionGroup ref="SearchForProductOnBackendActionGroup" stepKey="filterSimpleProduct1">
39+
<argument name="product" value="SimpleProduct2"/>
40+
</actionGroup>
41+
<click selector="{{AdminProductGridSection.productGridNameProduct('$$simpleProduct1.name$$')}}" stepKey="clickOpenProductForEdit"/>
42+
<waitForPageLoad time="30" stepKey="waitForProductEditOpen"/>
43+
<!-- Open *Advanced Inventory* pop-up (Click on *Advanced Inventory* link). Set *Qty Uses Decimals* to *Yes*. Click on button *Done* -->
44+
<actionGroup ref="AdminClickOnAdvancedInventoryLinkActionGroup" stepKey="clickOnAdvancedInventoryLink"/>
45+
<actionGroup ref="AdminSetQtyUsesDecimalsConfigActionGroup" stepKey="setQtyUsesDecimalsConfig">
46+
<argument name="value" value="Yes"/>
47+
</actionGroup>
48+
<actionGroup ref="AdminSubmitAdvancedInventoryFormActionGroup" stepKey="clickOnDoneButton"/>
49+
<actionGroup ref="AdminProductFormSaveActionGroup" stepKey="clickOnSaveButton"/>
50+
51+
<!-- Create new Bundle product -->
52+
<actionGroup ref="AdminOpenCreateBundleProductPageActionGroup" stepKey="goToBundleProductCreationPage"/>
53+
<actionGroup ref="AdminClickAddOptionOnBundleProductEditPageActionGroup" stepKey="clickAddOption1"/>
54+
<actionGroup ref="AdminFillBundleOptionTitleActionGroup" stepKey="fillOptionTitle">
55+
<argument name="optionTitle" value="{{BundleProduct.optionTitle1}}"/>
56+
</actionGroup>
57+
<actionGroup ref="AdminFillBundleOptionTypeActionGroup" stepKey="selectInputType"/>
58+
59+
<actionGroup ref="AdminClickAddProductToOptionByOptionIndexActionGroup" stepKey="clickAddProductsToOption"/>
60+
<actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterBundleProductOptions">
61+
<argument name="product" value="$$simpleProduct1$$"/>
62+
</actionGroup>
63+
<actionGroup ref="AdminCheckFirstCheckboxInAddProductsToOptionPanelGridActionGroup" stepKey="selectFirstGridRow"/>
64+
<actionGroup ref="FilterProductGridBySkuActionGroup" stepKey="filterBundleProductOptions2">
65+
<argument name="product" value="$$simpleProduct2$$"/>
66+
</actionGroup>
67+
<actionGroup ref="AdminCheckFirstCheckboxInAddProductsToOptionPanelGridActionGroup" stepKey="selectFirstGridRow2"/>
68+
<actionGroup ref="AdminClickAddSelectedProductsOnAddProductsToOptionPanelActionGroup" stepKey="clickAddSelectedBundleProducts"/>
69+
70+
<grabValueFrom selector="{{AdminProductFormBundleSection.bundleOptionXProductYQuantity('0', '0')}}" stepKey="grabbedFirstBundleOptionQuantity"/>
71+
<assertEquals stepKey="assertFirstBundleOptionDefaultQuantity">
72+
<expectedResult type="string">1</expectedResult>
73+
<actualResult type="string">$grabbedFirstBundleOptionQuantity</actualResult>
74+
</assertEquals>
75+
<grabValueFrom selector="{{AdminProductFormBundleSection.bundleOptionXProductYQuantity('0', '1')}}" stepKey="grabbedSecondBundleOptionQuantity"/>
76+
<assertEquals stepKey="assertSecondBundleOptionDefaultQuantity">
77+
<expectedResult type="string">1</expectedResult>
78+
<actualResult type="string">$grabbedSecondBundleOptionQuantity</actualResult>
79+
</assertEquals>
80+
81+
<!-- Fill first selection with decimal value -->
82+
<actionGroup ref="AdminFillBundleItemQtyActionGroup" stepKey="fillProduct1DefaultQty">
83+
<argument name="optionIndex" value="0"/>
84+
<argument name="productIndex" value="0"/>
85+
<argument name="qty" value="2.56"/>
86+
</actionGroup>
87+
88+
<!-- Check there is no error message for the slection with allowed decimal value -->
89+
<dontSee selector="{{AdminProductFormBundleSection.fieldError('uid')}}" userInput="Please enter a valid number in this field." stepKey="doNotSeeErrorMessageForProduct1"/>
90+
91+
<!-- Fill second selection with decimal value -->
92+
<actionGroup ref="AdminFillBundleItemQtyActionGroup" stepKey="fillProduct2DefaultQty">
93+
<argument name="optionIndex" value="0"/>
94+
<argument name="productIndex" value="1"/>
95+
<argument name="qty" value="2.56"/>
96+
</actionGroup>
97+
98+
<!-- Check there is an error message for the slection with not allowed decimal value -->
99+
<see selector="{{AdminProductFormBundleSection.fieldError('uid')}}" userInput="Please enter a valid number in this field." stepKey="seeErrorMessageForProduct2"/>
100+
101+
</test>
102+
</tests>

app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414
use Magento\Framework\App\RequestInterface;
1515
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1616
use Magento\Store\Model\Store;
17+
use Magento\Ui\DataProvider\Modifier\PoolInterface;
1718
use PHPUnit\Framework\MockObject\MockObject;
1819
use PHPUnit\Framework\TestCase;
1920

2021
class BundleDataProviderTest extends TestCase
2122
{
22-
const ALLOWED_TYPE = 'simple';
23+
private const ALLOWED_TYPE = 'simple';
2324

2425
/**
2526
* @var ObjectManager
@@ -46,13 +47,21 @@ class BundleDataProviderTest extends TestCase
4647
*/
4748
protected $dataHelperMock;
4849

50+
/**
51+
* @var PoolInterface|MockObject
52+
*/
53+
private $modifierPool;
54+
4955
/**
5056
* @return void
5157
*/
5258
protected function setUp(): void
5359
{
5460
$this->objectManager = new ObjectManager($this);
5561

62+
$this->modifierPool = $this->getMockBuilder(PoolInterface::class)
63+
->getMockForAbstractClass();
64+
5665
$this->requestMock = $this->getMockBuilder(RequestInterface::class)
5766
->getMockForAbstractClass();
5867
$this->collectionMock = $this->getMockBuilder(Collection::class)
@@ -97,6 +106,7 @@ protected function getModel()
97106
'addFilterStrategies' => [],
98107
'meta' => [],
99108
'data' => [],
109+
'modifiersPool' => $this->modifierPool,
100110
]);
101111
}
102112

@@ -128,6 +138,9 @@ public function testGetData()
128138
$this->collectionMock->expects($this->once())
129139
->method('getSize')
130140
->willReturn(count($items));
141+
$this->modifierPool->expects($this->once())
142+
->method('getModifiersInstances')
143+
->willReturn([]);
131144

132145
$this->assertEquals($expectedData, $this->getModel()->getData());
133146
}

app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
99
use Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider;
1010
use Magento\Bundle\Helper\Data;
11+
use Magento\Framework\App\ObjectManager;
12+
use Magento\Ui\DataProvider\Modifier\ModifierInterface;
13+
use Magento\Ui\DataProvider\Modifier\PoolInterface;
1114

1215
class BundleDataProvider extends ProductDataProvider
1316
{
@@ -16,6 +19,11 @@ class BundleDataProvider extends ProductDataProvider
1619
*/
1720
protected $dataHelper;
1821

22+
/**
23+
* @var PoolInterface
24+
*/
25+
private $modifiersPool;
26+
1927
/**
2028
* Construct
2129
*
@@ -24,10 +32,12 @@ class BundleDataProvider extends ProductDataProvider
2432
* @param string $requestFieldName
2533
* @param CollectionFactory $collectionFactory
2634
* @param Data $dataHelper
27-
* @param \Magento\Ui\DataProvider\AddFieldToCollectionInterface[] $addFieldStrategies
28-
* @param \Magento\Ui\DataProvider\AddFilterToCollectionInterface[] $addFilterStrategies
2935
* @param array $meta
3036
* @param array $data
37+
* @param \Magento\Ui\DataProvider\AddFieldToCollectionInterface[] $addFieldStrategies
38+
* @param \Magento\Ui\DataProvider\AddFilterToCollectionInterface[] $addFilterStrategies
39+
* @param PoolInterface|null $modifiersPool
40+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
3141
*/
3242
public function __construct(
3343
$name,
@@ -38,7 +48,8 @@ public function __construct(
3848
array $meta = [],
3949
array $data = [],
4050
array $addFieldStrategies = [],
41-
array $addFilterStrategies = []
51+
array $addFilterStrategies = [],
52+
PoolInterface $modifiersPool = null
4253
) {
4354
parent::__construct(
4455
$name,
@@ -52,6 +63,7 @@ public function __construct(
5263
);
5364

5465
$this->dataHelper = $dataHelper;
66+
$this->modifiersPool = $modifiersPool ?: ObjectManager::getInstance()->get(PoolInterface::class);
5567
}
5668

5769
/**
@@ -72,11 +84,34 @@ public function getData()
7284
);
7385
$this->getCollection()->load();
7486
}
87+
7588
$items = $this->getCollection()->toArray();
7689

77-
return [
90+
$data = [
7891
'totalRecords' => $this->getCollection()->getSize(),
7992
'items' => array_values($items),
8093
];
94+
95+
/** @var ModifierInterface $modifier */
96+
foreach ($this->modifiersPool->getModifiersInstances() as $modifier) {
97+
$data = $modifier->modifyData($data);
98+
}
99+
100+
return $data;
101+
}
102+
103+
/**
104+
* @inheritdoc
105+
*/
106+
public function getMeta()
107+
{
108+
$meta = parent::getMeta();
109+
110+
/** @var ModifierInterface $modifier */
111+
foreach ($this->modifiersPool->getModifiersInstances() as $modifier) {
112+
$meta = $modifier->modifyMeta($meta);
113+
}
114+
115+
return $meta;
81116
}
82117
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Magento\Bundle\Ui\DataProvider\Product\Form\Modifier;
10+
11+
use Magento\Framework\App\ObjectManager;
12+
use Magento\Framework\Exception\NoSuchEntityException;
13+
use Magento\Ui\DataProvider\Modifier\ModifierInterface;
14+
use Magento\CatalogInventory\Model\StockRegistryPreloader;
15+
16+
/**
17+
* Affects Qty field for newly added selection
18+
*/
19+
class AddSelectionQtyTypeToProductsData implements ModifierInterface
20+
{
21+
/**
22+
* @var StockRegistryPreloader
23+
*/
24+
private StockRegistryPreloader $stockRegistryPreloader;
25+
26+
/**
27+
* Initializes dependencies
28+
*
29+
* @param StockRegistryPreloader $stockRegistryPreloader
30+
*/
31+
public function __construct(StockRegistryPreloader $stockRegistryPreloader)
32+
{
33+
$this->stockRegistryPreloader = $stockRegistryPreloader;
34+
}
35+
36+
/**
37+
* Modify Meta
38+
*
39+
* @param array $meta
40+
* @return array
41+
*/
42+
public function modifyMeta(array $meta)
43+
{
44+
return $meta;
45+
}
46+
47+
/**
48+
* Modify Data - checks if new selection can have decimal quantity
49+
*
50+
* @param array $data
51+
* @return array
52+
* @throws NoSuchEntityException
53+
*/
54+
public function modifyData(array $data): array
55+
{
56+
$productIds = array_column($data['items'], 'entity_id');
57+
58+
$stockItems = [];
59+
if ($productIds) {
60+
$stockItems = $this->stockRegistryPreloader->preloadStockItems($productIds);
61+
}
62+
63+
$isQtyDecimals = [];
64+
foreach ($stockItems as $stockItem) {
65+
$isQtyDecimals[$stockItem->getProductId()] = $stockItem->getIsQtyDecimal();
66+
}
67+
68+
foreach ($data['items'] as &$item) {
69+
if (isset($isQtyDecimals[$item['entity_id']])) {
70+
$item['selection_qty_is_integer'] = !$isQtyDecimals[$item['entity_id']];
71+
}
72+
}
73+
74+
return $data;
75+
}
76+
}

app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ protected function getBundleOptions()
403403
'selection_price_type' => '',
404404
'selection_price_value' => '',
405405
'selection_qty' => '',
406+
'selection_qty_is_integer'=> 'selection_qty_is_integer',
406407
],
407408
'links' => [
408409
'insertData' => '${ $.provider }:${ $.dataProvider }',

app/code/Magento/Bundle/etc/adminhtml/di.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,21 @@
7676
</argument>
7777
</arguments>
7878
</type>
79+
<virtualType name="Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\ModifiersPool" type="Magento\Ui\DataProvider\Modifier\Pool">
80+
<arguments>
81+
<argument name="modifiers" xsi:type="array">
82+
<item name="add_selection_qty_type_to_products_data" xsi:type="array">
83+
<item name="class" xsi:type="string">Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\AddSelectionQtyTypeToProductsData</item>
84+
<item name="sortOrder" xsi:type="number">200</item>
85+
</item>
86+
</argument>
87+
</arguments>
88+
</virtualType>
89+
<type name="Magento\Bundle\Ui\DataProvider\Product\BundleDataProvider">
90+
<arguments>
91+
<argument name="modifiersPool" xsi:type="object">
92+
Magento\Bundle\Ui\DataProvider\Product\Form\Modifier\ModifiersPool
93+
</argument>
94+
</arguments>
95+
</type>
7996
</config>

app/code/Magento/Catalog/Test/Mftf/Test/AddNewProductAttributeInProductPageTest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<before>
2222
<!-- Login as admin -->
2323
<actionGroup ref="AdminLoginActionGroup" stepKey="login"/>
24+
<actionGroup ref="AdminOpenProductIndexPageActionGroup" stepKey="openProductIndexPageBefore"/>
2425
<!-- remove the Filter From the page-->
2526
<amOnPage url="{{AdminProductIndexPage.url}}" stepKey="visitAdminProductPage"/>
2627
<actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearFilterFromProductIndex"/>

app/code/Magento/Catalog/Test/Mftf/Test/AdminUpdateVirtualProductWithRegularPriceInStockWithCustomOptionsVisibleInSearchOnlyTest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
<createData entity="SimpleSubCategory" stepKey="categoryEntity"/>
3030
</before>
3131
<after>
32+
<actionGroup ref="AdminProductCatalogPageOpenActionGroup" stepKey="openProductCatalogPage1"/>
33+
<actionGroup ref="AdminDeleteAllProductsFromGridActionGroup" stepKey="selectAndDeleteProducts"/>
34+
<actionGroup ref="ClearFiltersAdminProductGridActionGroup" stepKey="clearFilterFromProductIndex"/>
3235
<deleteData stepKey="deleteSimpleSubCategory" createDataKey="initialCategoryEntity"/>
3336
<deleteData stepKey="deleteSimpleSubCategory2" createDataKey="categoryEntity"/>
3437
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>

0 commit comments

Comments
 (0)