Skip to content

Commit 35cea2d

Browse files
Merge remote-tracking branch 'remotes/github/MC-10966' into EPAM-PR-53
2 parents dd0f077 + eecbd32 commit 35cea2d

File tree

16 files changed

+730
-137
lines changed

16 files changed

+730
-137
lines changed

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

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,26 +1578,9 @@ public function addAttributeToFilter($attribute, $condition = null, $joinType =
15781578
$this->_allIdsCache = null;
15791579

15801580
if (is_string($attribute) && $attribute == 'is_saleable') {
1581-
$columns = $this->getSelect()->getPart(\Magento\Framework\DB\Select::COLUMNS);
1582-
foreach ($columns as $columnEntry) {
1583-
list($correlationName, $column, $alias) = $columnEntry;
1584-
if ($alias == 'is_saleable') {
1585-
if ($column instanceof \Zend_Db_Expr) {
1586-
$field = $column;
1587-
} else {
1588-
$connection = $this->getSelect()->getConnection();
1589-
if (empty($correlationName)) {
1590-
$field = $connection->quoteColumnAs($column, $alias, true);
1591-
} else {
1592-
$field = $connection->quoteColumnAs([$correlationName, $column], $alias, true);
1593-
}
1594-
}
1595-
$this->getSelect()->where("{$field} = ?", $condition);
1596-
break;
1597-
}
1598-
}
1599-
1600-
return $this;
1581+
$this->addIsSaleableAttributeToFilter($condition);
1582+
} elseif (is_string($attribute) && $attribute == 'tier_price') {
1583+
$this->addTierPriceAttributeToFilter($attribute, $condition);
16011584
} else {
16021585
return parent::addAttributeToFilter($attribute, $condition, $joinType);
16031586
}
@@ -2481,4 +2464,71 @@ public function getPricesCount()
24812464

24822465
return $this->_pricesCount;
24832466
}
2467+
2468+
/**
2469+
* Add is_saleable attribute to filter
2470+
*
2471+
* @param array|null $condition
2472+
* @return $this
2473+
*/
2474+
private function addIsSaleableAttributeToFilter(?array $condition): self
2475+
{
2476+
$columns = $this->getSelect()->getPart(Select::COLUMNS);
2477+
foreach ($columns as $columnEntry) {
2478+
list($correlationName, $column, $alias) = $columnEntry;
2479+
if ($alias == 'is_saleable') {
2480+
if ($column instanceof \Zend_Db_Expr) {
2481+
$field = $column;
2482+
} else {
2483+
$connection = $this->getSelect()->getConnection();
2484+
if (empty($correlationName)) {
2485+
$field = $connection->quoteColumnAs($column, $alias, true);
2486+
} else {
2487+
$field = $connection->quoteColumnAs([$correlationName, $column], $alias, true);
2488+
}
2489+
}
2490+
$this->getSelect()->where("{$field} = ?", $condition);
2491+
break;
2492+
}
2493+
}
2494+
2495+
return $this;
2496+
}
2497+
2498+
/**
2499+
* Add tier price attribute to filter
2500+
*
2501+
* @param string $attribute
2502+
* @param array|null $condition
2503+
* @return $this
2504+
*/
2505+
private function addTierPriceAttributeToFilter(string $attribute, ?array $condition): self
2506+
{
2507+
$attrCode = $attribute;
2508+
$connection = $this->getConnection();
2509+
$attrTable = $this->_getAttributeTableAlias($attrCode);
2510+
$entity = $this->getEntity();
2511+
$fKey = 'e.' . $this->getEntityPkName($entity);
2512+
$pKey = $attrTable . '.' . $this->getEntityPkName($entity);
2513+
$attribute = $entity->getAttribute($attrCode);
2514+
$attrFieldName = $attrTable . '.value';
2515+
$fKey = $connection->quoteColumnAs($fKey, null);
2516+
$pKey = $connection->quoteColumnAs($pKey, null);
2517+
2518+
$condArr = ["{$pKey} = {$fKey}"];
2519+
$this->getSelect()->join(
2520+
[$attrTable => $this->getTable('catalog_product_entity_tier_price')],
2521+
'(' . implode(') AND (', $condArr) . ')',
2522+
[$attrCode => $attrFieldName]
2523+
);
2524+
$this->removeAttributeToSelect($attrCode);
2525+
$this->_filterAttributes[$attrCode] = $attribute->getId();
2526+
$this->_joinFields[$attrCode] = ['table' => '', 'field' => $attrFieldName];
2527+
$field = $this->_getAttributeTableAlias($attrCode) . '.value';
2528+
$conditionSql = $this->_getConditionSql($field, $condition);
2529+
$this->getSelect()->where($conditionSql, null, Select::TYPE_CONDITION);
2530+
$this->_totalRecords = null;
2531+
2532+
return $this;
2533+
}
24842534
}

app/code/Magento/Catalog/etc/acl.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
<resource id="Magento_Backend::admin">
1212
<resource id="Magento_Catalog::catalog" title="Catalog" translate="title" sortOrder="30">
1313
<resource id="Magento_Catalog::catalog_inventory" title="Inventory" translate="title" sortOrder="10">
14-
<resource id="Magento_Catalog::products" title="Products" translate="title" sortOrder="10" />
14+
<resource id="Magento_Catalog::products" title="Products" translate="title" sortOrder="10">
15+
<resource id="Magento_Catalog::update_attributes" title="Update Attributes" translate="title" />
16+
</resource>
1517
<resource id="Magento_Catalog::categories" title="Categories" translate="title" sortOrder="20" />
1618
</resource>
1719
</resource>
@@ -23,7 +25,6 @@
2325
</resource>
2426
<resource id="Magento_Backend::stores_attributes">
2527
<resource id="Magento_Catalog::attributes_attributes" title="Product" translate="title" sortOrder="30" />
26-
<resource id="Magento_Catalog::update_attributes" title="Update Attributes" translate="title" sortOrder="35" />
2728
<resource id="Magento_Catalog::sets" title="Attribute Set" translate="title" sortOrder="40"/>
2829
</resource>
2930
</resource>

app/code/Magento/Checkout/Model/PaymentInformationManagement.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ public function savePaymentInformation(
112112
$quoteRepository = $this->getCartRepository();
113113
/** @var \Magento\Quote\Model\Quote $quote */
114114
$quote = $quoteRepository->getActive($cartId);
115+
$customerId = $quote->getBillingAddress()
116+
->getCustomerId();
117+
if (!$billingAddress->getCustomerId() && $customerId) {
118+
//It's necessary to verify the price rules with the customer data
119+
$billingAddress->setCustomerId($customerId);
120+
}
115121
$quote->removeAddress($quote->getBillingAddress()->getId());
116122
$quote->setBillingAddress($billingAddress);
117123
$quote->setDataChanges(true);

app/code/Magento/Checkout/Test/Unit/Model/PaymentInformationManagementTest.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,31 @@ public function testSavePaymentInformationAndPlaceOrderWithLocolizedException()
163163
$this->model->savePaymentInformationAndPlaceOrder($cartId, $paymentMock, $billingAddressMock);
164164
}
165165

166+
/**
167+
* Test for save payment and place order with new billing address
168+
*
169+
* @return void
170+
*/
171+
public function testSavePaymentInformationAndPlaceOrderWithNewBillingAddress(): void
172+
{
173+
$cartId = 100;
174+
$quoteBillingAddressId = 1;
175+
$customerId = 1;
176+
$quoteMock = $this->createMock(\Magento\Quote\Model\Quote::class);
177+
$quoteBillingAddress = $this->createMock(\Magento\Quote\Model\Quote\Address::class);
178+
$billingAddressMock = $this->createMock(\Magento\Quote\Api\Data\AddressInterface::class);
179+
$paymentMock = $this->createMock(\Magento\Quote\Api\Data\PaymentInterface::class);
180+
181+
$quoteBillingAddress->method('getCustomerId')->willReturn($customerId);
182+
$quoteMock->method('getBillingAddress')->willReturn($quoteBillingAddress);
183+
$quoteBillingAddress->method('getId')->willReturn($quoteBillingAddressId);
184+
$this->cartRepositoryMock->method('getActive')->with($cartId)->willReturn($quoteMock);
185+
186+
$this->paymentMethodManagementMock->expects($this->once())->method('set')->with($cartId, $paymentMock);
187+
$billingAddressMock->expects($this->once())->method('setCustomerId')->with($customerId);
188+
$this->assertTrue($this->model->savePaymentInformation($cartId, $paymentMock, $billingAddressMock));
189+
}
190+
166191
/**
167192
* @param int $cartId
168193
* @param \PHPUnit_Framework_MockObject_MockObject $billingAddressMock
@@ -179,9 +204,10 @@ private function getMockForAssignBillingAddress($cartId, $billingAddressMock)
179204
['setLimitCarrier', 'getShippingMethod', 'getShippingRateByCode']
180205
);
181206
$this->cartRepositoryMock->expects($this->any())->method('getActive')->with($cartId)->willReturn($quoteMock);
182-
$quoteMock->expects($this->once())->method('getBillingAddress')->willReturn($quoteBillingAddress);
207+
$quoteMock->method('getBillingAddress')->willReturn($quoteBillingAddress);
183208
$quoteMock->expects($this->once())->method('getShippingAddress')->willReturn($quoteShippingAddress);
184209
$quoteBillingAddress->expects($this->once())->method('getId')->willReturn($billingAddressId);
210+
$quoteBillingAddress->expects($this->once())->method('getId')->willReturn($billingAddressId);
185211
$quoteMock->expects($this->once())->method('removeAddress')->with($billingAddressId);
186212
$quoteMock->expects($this->once())->method('setBillingAddress')->with($billingAddressMock);
187213
$quoteMock->expects($this->once())->method('setDataChanges')->willReturnSelf();
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
10+
<test name="AdminExactMatchSearchInCustomerGridTest">
11+
<annotations>
12+
<features value="Customer"/>
13+
<stories value="Customer Search"/>
14+
<title value="Admin customer grid exact match searching"/>
15+
<description value="Admin customer grid exact match searching with quotes in keyword"/>
16+
<severity value="MAJOR"/>
17+
<testCaseId value="MC-16335"/>
18+
<useCaseId value="MAGETWO-99605"/>
19+
<group value="customer"/>
20+
</annotations>
21+
<before>
22+
<createData entity="Simple_US_Customer" stepKey="createFirstCustomer"/>
23+
<createData entity="Simple_US_Customer" stepKey="createSecondCustomer">
24+
<field key="firstname">&quot;Jane Doe&quot;</field>
25+
</createData>
26+
<actionGroup ref="LoginAsAdmin" stepKey="login"/>
27+
</before>
28+
<after>
29+
<deleteData createDataKey="createFirstCustomer" stepKey="deleteFirstCustomer"/>
30+
<deleteData createDataKey="createSecondCustomer" stepKey="deleteSecondCustomer"/>
31+
<amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/>
32+
<actionGroup ref="AdminResetFilterInCustomerAddressGrid" stepKey="clearCustomerGridFilter"/>
33+
<actionGroup ref="logout" stepKey="logout"/>
34+
</after>
35+
<!--Step 1: Go to Customers > All Customers-->
36+
<amOnPage url="{{AdminCustomerPage.url}}" stepKey="openCustomersGridPage"/>
37+
<!--Step 2: On Customers grid page search customer by keyword with quotes-->
38+
<actionGroup ref="searchAdminDataGridByKeyword" stepKey="searchCustomer">
39+
<argument name="keyword" value="$$createSecondCustomer.firstname$$"/>
40+
</actionGroup>
41+
<!--Step 3: Check if customer is placed in a first row and clear grid filter-->
42+
<actionGroup ref="AdminAssertCustomerInCustomersGrid" stepKey="checkCustomerInGrid">
43+
<argument name="text" value="$$createSecondCustomer.fullname$$"/>
44+
<argument name="row" value="1"/>
45+
</actionGroup>
46+
</test>
47+
</tests>

app/code/Magento/Directory/Model/ResourceModel/Country/Collection.php

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -126,24 +126,6 @@ public function __construct(
126126
*/
127127
protected $_foregroundCountries = [];
128128

129-
/**
130-
* Add top destinition countries to head of option array
131-
*
132-
* @param string $emptyLabel
133-
* @param array $options
134-
* @return array
135-
*/
136-
private function addForegroundCountriesToOptionArray($emptyLabel, $options)
137-
{
138-
if ($emptyLabel !== false && count($this->_foregroundCountries) !== 0 &&
139-
count($options) === count($this->_foregroundCountries)
140-
) {
141-
$options[] = ['value' => '', 'label' => $emptyLabel];
142-
return $options;
143-
}
144-
return $options;
145-
}
146-
147129
/**
148130
* Define main table
149131
*
@@ -269,24 +251,20 @@ public function addCountryIdFilter($countryId)
269251
public function toOptionArray($emptyLabel = ' ')
270252
{
271253
$options = $this->_toOptionArray('country_id', 'name', ['title' => 'iso2_code']);
272-
$sort = [];
273-
foreach ($options as $data) {
274-
$name = (string)$this->_localeLists->getCountryTranslation($data['value']);
275-
if (!empty($name)) {
276-
$sort[$name] = $data['value'];
277-
}
278-
}
254+
$sort = $this->getSort($options);
255+
279256
$this->_arrayUtils->ksortMultibyte($sort, $this->_localeResolver->getLocale());
280257
foreach (array_reverse($this->_foregroundCountries) as $foregroundCountry) {
281258
$name = array_search($foregroundCountry, $sort);
282-
unset($sort[$name]);
283-
$sort = [$name => $foregroundCountry] + $sort;
259+
if ($name) {
260+
unset($sort[$name]);
261+
$sort = [$name => $foregroundCountry] + $sort;
262+
}
284263
}
285264
$isRegionVisible = (bool)$this->helperData->isShowNonRequiredState();
286265

287266
$options = [];
288267
foreach ($sort as $label => $value) {
289-
$options = $this->addForegroundCountriesToOptionArray($emptyLabel, $options);
290268
$option = ['value' => $value, 'label' => $label];
291269
if ($this->helperData->isRegionRequired($value)) {
292270
$option['is_region_required'] = true;
@@ -366,4 +344,23 @@ public function getCountriesWithRequiredStates()
366344
}
367345
return $countries;
368346
}
347+
348+
/**
349+
* Get sort
350+
*
351+
* @param array $options
352+
* @return array
353+
*/
354+
private function getSort(array $options): array
355+
{
356+
$sort = [];
357+
foreach ($options as $data) {
358+
$name = (string)$this->_localeLists->getCountryTranslation($data['value']);
359+
if (!empty($name)) {
360+
$sort[$name] = $data['value'];
361+
}
362+
}
363+
364+
return $sort;
365+
}
369366
}

app/code/Magento/Directory/Test/Unit/Model/ResourceModel/Country/CollectionTest.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ public function testToOptionArray($optionsArray, $emptyLabel, $foregroundCountri
9999

100100
$this->_model->setForegroundCountries($foregroundCountries);
101101
$result = $this->_model->toOptionArray($emptyLabel);
102-
$this->assertCount(count($optionsArray) + (int)(!empty($emptyLabel) && !empty($foregroundCountries)) +
103-
(int)(!empty($emptyLabel)), $result);
102+
$this->assertCount(count($optionsArray) + (int)(!empty($emptyLabel)), $result);
104103
foreach ($expectedResults as $index => $expectedResult) {
105104
$this->assertEquals($expectedResult, $result[$index]['label']);
106105
}
@@ -121,8 +120,10 @@ public function toOptionArrayDataProvider()
121120
[$optionsArray, false, [], ['AD', 'US', 'ES', 'BZ']],
122121
[$optionsArray, false, 'US', ['US', 'AD', 'ES', 'BZ']],
123122
[$optionsArray, false, ['US', 'BZ'], ['US', 'BZ', 'AD', 'ES']],
124-
[$optionsArray, ' ', 'US', [' ', 'US', ' ', 'AD', 'ES', 'BZ']],
125-
[$optionsArray, ' ', [], [' ', 'AD', 'US', 'ES', 'BZ']]
123+
[$optionsArray, ' ', 'US', [' ', 'US', 'AD', 'ES', 'BZ']],
124+
[$optionsArray, ' ', [], [' ', 'AD', 'US', 'ES', 'BZ']],
125+
[$optionsArray, ' ', 'UA', [' ', 'AD', 'US', 'ES', 'BZ']],
126+
[$optionsArray, ' ', ['AF', 'UA'], [' ', 'AD', 'US', 'ES', 'BZ']],
126127
];
127128
}
128129
}

app/code/Magento/Sales/Controller/Adminhtml/Order/AddressSave.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Backend\App\Action\Context;
1111
use Magento\Backend\Model\View\Result\Redirect;
1212
use Magento\Directory\Model\RegionFactory;
13+
use Magento\Sales\Api\OrderAddressRepositoryInterface;
1314
use Magento\Sales\Api\OrderManagementInterface;
1415
use Magento\Sales\Api\OrderRepositoryInterface;
1516
use Magento\Sales\Api\Data\OrderAddressInterface;
@@ -25,11 +26,14 @@
2526
use Magento\Framework\Controller\Result\RawFactory;
2627
use Magento\Framework\Exception\LocalizedException;
2728
use Magento\Framework\App\ObjectManager;
29+
use Magento\Framework\App\Action\HttpPostActionInterface;
2830

2931
/**
32+
* Sales address save
33+
*
3034
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
3135
*/
32-
class AddressSave extends Order
36+
class AddressSave extends Order implements HttpPostActionInterface
3337
{
3438
/**
3539
* Authorization level of a basic admin session
@@ -43,6 +47,11 @@ class AddressSave extends Order
4347
*/
4448
private $regionFactory;
4549

50+
/**
51+
* @var OrderAddressRepositoryInterface
52+
*/
53+
private $orderAddressRepository;
54+
4655
/**
4756
* @param Context $context
4857
* @param Registry $coreRegistry
@@ -56,6 +65,7 @@ class AddressSave extends Order
5665
* @param OrderRepositoryInterface $orderRepository
5766
* @param LoggerInterface $logger
5867
* @param RegionFactory|null $regionFactory
68+
* @param OrderAddressRepositoryInterface|null $orderAddressRepository
5969
*
6070
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
6171
*/
@@ -71,9 +81,12 @@ public function __construct(
7181
OrderManagementInterface $orderManagement,
7282
OrderRepositoryInterface $orderRepository,
7383
LoggerInterface $logger,
74-
RegionFactory $regionFactory = null
84+
RegionFactory $regionFactory = null,
85+
OrderAddressRepositoryInterface $orderAddressRepository = null
7586
) {
7687
$this->regionFactory = $regionFactory ?: ObjectManager::getInstance()->get(RegionFactory::class);
88+
$this->orderAddressRepository = $orderAddressRepository ?: ObjectManager::getInstance()
89+
->get(OrderAddressRepositoryInterface::class);
7790
parent::__construct(
7891
$context,
7992
$coreRegistry,
@@ -107,7 +120,7 @@ public function execute()
107120
if ($data && $address->getId()) {
108121
$address->addData($data);
109122
try {
110-
$address->save();
123+
$this->orderAddressRepository->save($address);
111124
$this->_eventManager->dispatch(
112125
'admin_sales_order_address_update',
113126
[

0 commit comments

Comments
 (0)