Skip to content

Commit 2cb012b

Browse files
authored
Merge pull request #7440 from magento-l3/L3-PR-20220202
L3 pr 20220202
2 parents 72239c5 + 63738e1 commit 2cb012b

File tree

26 files changed

+835
-37
lines changed

26 files changed

+835
-37
lines changed

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Builder/Category.php

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation\Builder;
99

10+
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory;
1011
use Magento\CatalogGraphQl\DataProvider\CategoryAttributesMapper;
1112
use Magento\CatalogGraphQl\DataProvider\Category\Query\CategoryAttributeQuery;
1213
use Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation\LayerBuilderInterface;
@@ -19,7 +20,9 @@
1920
use Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation\Builder\Aggregations;
2021

2122
/**
22-
* @inheritdoc
23+
* Category layer builder
24+
*
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2326
*/
2427
class Category implements LayerBuilderInterface
2528
{
@@ -63,6 +66,11 @@ class Category implements LayerBuilderInterface
6366
*/
6467
private $layerFormatter;
6568

69+
/**
70+
* @var CollectionFactory
71+
*/
72+
private $categoryCollectionFactory;
73+
6674
/**
6775
* @var Aggregations\Category\IncludeDirectChildrenOnly
6876
*/
@@ -75,21 +83,24 @@ class Category implements LayerBuilderInterface
7583
* @param ResourceConnection $resourceConnection
7684
* @param LayerFormatter $layerFormatter
7785
* @param Aggregations\Category\IncludeDirectChildrenOnly $includeDirectChildrenOnly
86+
* @param CollectionFactory $categoryCollectionFactory
7887
*/
7988
public function __construct(
8089
CategoryAttributeQuery $categoryAttributeQuery,
8190
CategoryAttributesMapper $attributesMapper,
8291
RootCategoryProvider $rootCategoryProvider,
8392
ResourceConnection $resourceConnection,
8493
LayerFormatter $layerFormatter,
85-
Aggregations\Category\IncludeDirectChildrenOnly $includeDirectChildrenOnly
94+
Aggregations\Category\IncludeDirectChildrenOnly $includeDirectChildrenOnly,
95+
CollectionFactory $categoryCollectionFactory
8696
) {
8797
$this->categoryAttributeQuery = $categoryAttributeQuery;
8898
$this->attributesMapper = $attributesMapper;
8999
$this->resourceConnection = $resourceConnection;
90100
$this->rootCategoryProvider = $rootCategoryProvider;
91101
$this->layerFormatter = $layerFormatter;
92102
$this->includeDirectChildrenOnly = $includeDirectChildrenOnly;
103+
$this->categoryCollectionFactory = $categoryCollectionFactory;
93104
}
94105

95106
/**
@@ -112,6 +123,11 @@ function (AggregationValueInterface $value) {
112123
$bucket->getValues()
113124
);
114125

126+
if ($storeId) {
127+
$storeFilteredCategoryIds = $this->getStoreCategoryIds($storeId);
128+
$categoryIds = \array_intersect($categoryIds, $storeFilteredCategoryIds);
129+
}
130+
115131
$categoryIds = \array_diff($categoryIds, [$this->rootCategoryProvider->getRootCategory($storeId)]);
116132
$categoryLabels = \array_column(
117133
$this->attributesMapper->getAttributesValues(
@@ -158,4 +174,25 @@ private function isBucketEmpty(?BucketInterface $bucket): bool
158174
{
159175
return null === $bucket || !$bucket->getValues();
160176
}
177+
178+
/**
179+
* List of store categories
180+
*
181+
* @param int $storeId
182+
* @return array
183+
*/
184+
private function getStoreCategoryIds(int $storeId): array
185+
{
186+
$storeRootCategoryId = $this->rootCategoryProvider->getRootCategory($storeId);
187+
$collection = $this->categoryCollectionFactory->create();
188+
$select = $collection->getSelect();
189+
$connection = $collection->getConnection();
190+
$select->where(
191+
$connection->quoteInto(
192+
'e.path LIKE ? OR e.entity_id=' . $connection->quote($storeRootCategoryId, 'int'),
193+
'%/' . $storeRootCategoryId . '/%'
194+
)
195+
);
196+
return $collection->getAllIds();
197+
}
161198
}

app/code/Magento/CatalogUrlRewrite/Model/Products/AdaptUrlRewritesToVisibilityAttribute.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,12 @@ public function __construct(
6565
*
6666
* @param array $productIds
6767
* @param int $visibility
68+
* @param int $storeId
6869
* @throws UrlAlreadyExistsException
6970
*/
70-
public function execute(array $productIds, int $visibility): void
71+
public function execute(array $productIds, int $visibility, int $storeId): void
7172
{
72-
$products = $this->getProductsByIds($productIds);
73+
$products = $this->getProductsByIds($productIds, $storeId);
7374

7475
/** @var Product $product */
7576
foreach ($products as $product) {
@@ -110,11 +111,13 @@ public function execute(array $productIds, int $visibility): void
110111
* Get Product Models by Id's
111112
*
112113
* @param array $productIds
114+
* @param int $storeId
113115
* @return array
114116
*/
115-
private function getProductsByIds(array $productIds): array
117+
private function getProductsByIds(array $productIds, int $storeId): array
116118
{
117119
$productCollection = $this->productCollectionFactory->create();
120+
$productCollection->setStoreId($storeId);
118121
$productCollection->addAttributeToSelect(ProductInterface::VISIBILITY);
119122
$productCollection->addAttributeToSelect('url_key');
120123
$productCollection->addFieldToFilter(

app/code/Magento/CatalogUrlRewrite/Observer/ProcessUrlRewriteOnChangeProductVisibilityObserver.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,13 @@ public function execute(Observer $observer)
4343
$event = $observer->getEvent();
4444
$attrData = $event->getAttributesData();
4545
$productIds = $event->getProductIds();
46+
$storeIdFromScope = $event->getStoreId();
4647
$visibility = $attrData[ProductInterface::VISIBILITY] ?? 0;
4748

4849
if (!$visibility || !$productIds) {
4950
return;
5051
}
5152

52-
$this->adaptUrlRewritesToVisibility->execute($productIds, (int)$visibility);
53+
$this->adaptUrlRewritesToVisibility->execute($productIds, (int)$visibility, (int)$storeIdFromScope);
5354
}
5455
}

app/code/Magento/Config/Test/Mftf/Section/StoreConfigSection.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,8 @@
1313
<element name="StoreInformation" type="button" selector="#general_store_information-head"/>
1414
<element name="City" type="input" selector="#general_store_information_city"/>
1515
<element name="Save" type="button" selector="#save" timeout="30"/>
16+
<element name="Country" type="select" selector="#general_store_information_country_id"/>
17+
<element name="fillVATNumber" type="input" selector="#general_store_information_merchant_vat_number"/>
18+
<element name="validateVATNumber" type="button" selector="#general_store_information_validate_vat_number" timeout="30"/>
1619
</section>
1720
</sections>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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="AdminCheckVATNumberValidationButtonForEUCountryTest">
12+
<annotations>
13+
<title value="Validate VAT Number button for United Kingdom should work same as for non-EU countries after Brexit 2021"/>
14+
<description value="Validate VAT Number button for United Kingdom (GB) should work same as for non-EU countries after Brexit 2021"/>
15+
<features value="Config"/>
16+
<severity value="CRITICAL"/>
17+
<testCaseId value="ACP2E-355"/>
18+
<useCaseId value="ACP2E-182"/>
19+
<stories value="Store VAT Number Validation"/>
20+
<group value="configuration"/>
21+
</annotations>
22+
<before>
23+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
24+
</before>
25+
<after>
26+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
27+
</after>
28+
29+
<!-- Go to the general configuration tab of store-->
30+
<actionGroup ref="AdminOpenStoreConfigPageActionGroup" stepKey="openStoreConfigPage"/>
31+
32+
<!-- Expand the store information tab -->
33+
<conditionalClick selector="{{StoreConfigSection.StoreInformation}}" dependentSelector="{{StoreConfigSection.CheckIfTabExpand}}" visible="true" stepKey="checkIfTabOpen"/>
34+
35+
<!-- Verify that `Validate VAT Number` button is not visible when no Country selected-->
36+
<dontSeeElement selector="{{StoreConfigSection.validateVATNumber}}" stepKey="dontSeeVATNumberButton"/>
37+
38+
<!--Open country options section and select an EU Country (`Germany`) -->
39+
<selectOption userInput="{{DE_Address_Berlin_Not_Default_Address.country}}" selector="{{StoreConfigSection.Country}}" stepKey="selectEUStoreCountry"/>
40+
<waitForAjaxLoad stepKey="waitForAjaxToLoadRegionForEuCountry"/>
41+
42+
<!--Fill valid VAT Number for the selected EU Country (Germany)-->
43+
<fillField selector="{{StoreConfigSection.fillVATNumber}}" userInput="{{DE_Address_Berlin_Not_Default_Address.vatNumber}}" stepKey="fillValidVatNumberForEuCountry"/>
44+
45+
<!-- Verify that the `Validate VAT Number` button is visible for EU Country-->
46+
<seeElement selector="{{StoreConfigSection.validateVATNumber}}" stepKey="validateVatNumberButtonEnabledForEuCountry"/>
47+
48+
<!-- Click the `Validate VAT Number` button. -->
49+
<click selector="{{StoreConfigSection.validateVATNumber}}" stepKey="clickValidateVatNumberButton"/>
50+
<waitForAjaxLoad stepKey="waitForAjaxToLoadVatValidationResult"/>
51+
<waitForElementVisible selector="#validation_result" time="20" stepKey="waitForRenderingVatValidationResult"/>
52+
<see selector="#validation_result" userInput="VAT Number is valid." stepKey="seeValidVatNumberResult"/>
53+
54+
<!-- Disable `Validate VAT Number` button for non-EU Country (United Kingdom)-->
55+
<selectOption userInput="{{UK_With_State_Default_Billing.country}}" selector="{{StoreConfigSection.Country}}" stepKey="selectNonEUStoreCountry"/>
56+
<waitForAjaxLoad stepKey="waitForAjaxToLoadRegionForNonEuCountry"/>
57+
<fillField selector="{{StoreConfigSection.fillVATNumber}}" userInput="{{UK_With_State_Default_Billing.vatNumber}}" stepKey="fillVATNumberForNonEU"/>
58+
59+
<!-- Verify that the `Validate VAT Number` button disappears for selection of non-EU Country-->
60+
<dontSeeElement selector="{{StoreConfigSection.validateVATNumber}}" stepKey="validateVatNumberButtonDisabledAgain"/>
61+
</test>
62+
</tests>
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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\Config\ViewModel;
9+
10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\View\Element\Block\ArgumentInterface;
12+
use Magento\Store\Model\ScopeInterface;
13+
14+
class CountryFilter implements ArgumentInterface
15+
{
16+
/**
17+
* Config path to UE country list
18+
*/
19+
private const XML_PATH_EU_COUNTRIES_LIST = 'general/country/eu_countries';
20+
21+
/**
22+
* @var ScopeConfigInterface
23+
*/
24+
private $scopeConfig;
25+
26+
/**
27+
* @param ScopeConfigInterface $scopeConfig
28+
*/
29+
public function __construct(
30+
ScopeConfigInterface $scopeConfig
31+
) {
32+
$this->scopeConfig = $scopeConfig;
33+
}
34+
35+
/**
36+
* Fetch EU countries list
37+
*
38+
* @param Int|null $storeId
39+
* @return array
40+
*/
41+
public function getEuCountryList(int $storeId = null): array
42+
{
43+
$euCountries = explode(
44+
',',
45+
$this->scopeConfig->getValue(
46+
self::XML_PATH_EU_COUNTRIES_LIST,
47+
ScopeInterface::SCOPE_STORE,
48+
$storeId
49+
)
50+
);
51+
52+
return $euCountries;
53+
}
54+
}

app/code/Magento/Config/view/adminhtml/layout/adminhtml_system_config_edit.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-2columns-left" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
99
<body>
1010
<referenceContainer name="js">
11-
<block class="Magento\Backend\Block\Template" name="js.system_config_js" template="Magento_Config::system/config/js.phtml"/>
11+
<block class="Magento\Backend\Block\Template" name="js.system_config_js" template="Magento_Config::system/config/js.phtml">
12+
<arguments>
13+
<argument name="countryFilter" xsi:type="object">Magento\Config\ViewModel\CountryFilter</argument>
14+
</arguments>
15+
</block>
1216
<block class="Magento\Backend\Block\Template" name="js.system_shipping_applicable_country" template="Magento_Backend::system/shipping/applicable_country.phtml"/>
1317
</referenceContainer>
1418
<referenceContainer name="page.main.actions">

app/code/Magento/Config/view/adminhtml/templates/system/config/js.phtml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
/**
88
* @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer
9+
* @var \Magento\Config\ViewModel\CountryFilter $countryFilter
910
*/
1011
?>
1112

@@ -76,10 +77,82 @@ originModel.prototype = {
7677
script;
7778

7879
$scriptString .= 'this.regionsUrl = "' . $block->escapeJs($block->getUrl('directory/json/countryRegion')) . '";';
80+
$countryFilter = $block->getData('countryFilter');
81+
$euCountries = $countryFilter->getEuCountryList();
82+
$scriptString .= 'this.euCountryList = Object.values(' . json_encode($euCountries) . ');';
83+
7984
$scriptString .= <<<script
8085
86+
this.bindCountryVatNumberRelation();
8187
this.bindCountryRegionRelation();
8288
},
89+
bindCountryVatNumberRelation : function(parentId)
90+
{
91+
if (parentId) {
92+
// todo: fix bug in IE
93+
var countryElements = $$('#'+parentId+' .countries');
94+
} else {
95+
var countryElements = $$('.countries');
96+
}
97+
for(var i=0; i<countryElements.size(); i++) {
98+
Event.observe(countryElements[i], 'change', this.reloadVatNumberField.bind(this));
99+
this.initVatNumberField(countryElements[i]);
100+
}
101+
},
102+
reloadVatNumberField : function(event)
103+
{
104+
var countryElement = Event.element(event);
105+
if (countryElement && countryElement.id) {
106+
this.refreshVatNumberField(countryElement);
107+
this.refreshValidateVatNumberButton(countryElement);
108+
}
109+
},
110+
initVatNumberField : function(element)
111+
{
112+
var countryElement = element;
113+
if (countryElement && countryElement.id) {
114+
this.refreshValidateVatNumberButton(countryElement);
115+
}
116+
},
117+
refreshVatNumberField : function(countryElement)
118+
{
119+
var vatNumberElement = $(countryElement.id.replace(/country_id/, 'merchant_vat_number'));
120+
if (vatNumberElement) {
121+
this.vatNumberElement = vatNumberElement;
122+
if (vatNumberElement.value.length) {
123+
vatNumberElement.value = '';
124+
}
125+
}
126+
},
127+
refreshValidateVatNumberButton : function(countryElement)
128+
{
129+
var btnVatNumberElement = $(countryElement.id.replace(/country_id/, 'validate_vat_number'));
130+
if (btnVatNumberElement) {
131+
this.btnVatNumberElement = btnVatNumberElement;
132+
if (countryElement.value.length) {
133+
this.renderValidateVatNumberButton(countryElement.value);
134+
}
135+
}
136+
},
137+
renderValidateVatNumberButton: function(countryCode)
138+
{
139+
var resultElement = document.getElementById("validation_result");
140+
if (this.euCountryList.includes(countryCode)) {
141+
this.btnVatNumberElement.style.display = "block";
142+
if (resultElement) {
143+
resultElement.style.display = "block";
144+
resultElement.innerHTML = '';
145+
if (resultElement.classList.contains('admin__field-error')) {
146+
resultElement.classList.remove('admin__field-error');
147+
}
148+
}
149+
} else {
150+
this.btnVatNumberElement.style.display = "none";
151+
if (resultElement) {
152+
resultElement.style.display = "none";
153+
}
154+
}
155+
},
83156
bindCountryRegionRelation : function(parentId)
84157
{
85158
if (parentId) {

app/code/Magento/Customer/Test/Mftf/Data/AddressData.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@
332332
<data key="telephone">333-33-333-33</data>
333333
<data key="country">Germany</data>
334334
<data key="state">Berlin</data>
335+
<data key="vatNumber">DE265675123</data>
335336
</entity>
336337
<entity name="US_Address_California">
337338
<data key="firstname">John</data>
@@ -385,5 +386,6 @@
385386
<data key="country">United Kingdom</data>
386387
<data key="state">Greater London</data>
387388
<data key="default_billing">Yes</data>
389+
<data key="vatNumber">GB571903731</data>
388390
</entity>
389391
</entities>

0 commit comments

Comments
 (0)