Skip to content

Commit 30883ea

Browse files
author
Sergey Semenov
committed
Merge remote-tracking branch 'mainline/develop' into MAGETWO-47017
2 parents c0b879b + b67cf43 commit 30883ea

File tree

77 files changed

+2136
-524
lines changed

Some content is hidden

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

77 files changed

+2136
-524
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Bundle\Model\Sales\Order\Plugin;
8+
9+
/**
10+
* Plugin to calculate bundle item qty available for cancel
11+
*/
12+
class Item
13+
{
14+
/**
15+
* Retrieve item qty available for cancel
16+
*
17+
* @param \Magento\Sales\Model\Order\Item $subject
18+
* @param float|integer $result
19+
* @return float|integer
20+
*/
21+
public function afterGetQtyToCancel(\Magento\Sales\Model\Order\Item $subject, $result)
22+
{
23+
if ($subject->getProductType() === \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE || $subject->getParentItem()
24+
&& $subject->getParentItem()->getProductType() === \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
25+
) {
26+
$qtyToCancel = $this->getQtyToCancelBundle($subject);
27+
return max($qtyToCancel, 0);
28+
}
29+
return $result;
30+
}
31+
32+
/**
33+
* Retrieve item qty available for ship
34+
*
35+
* @param \Magento\Sales\Model\Order\Item $subject
36+
* @param float|integer $result
37+
* @return bool
38+
*/
39+
public function afterIsProcessingAvailable(\Magento\Sales\Model\Order\Item $subject, $result)
40+
{
41+
if ($subject->getProductType() === \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE || $subject->getParentItem()
42+
&& $subject->getParentItem()->getProductType() === \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE
43+
) {
44+
return $subject->getSimpleQtyToShip() > $subject->getQtyToCancel();
45+
}
46+
return $result;
47+
}
48+
49+
/**
50+
* Retrieve Bundle child item qty available for cancel
51+
* getQtyToShip() always returns 0 for BundleItems that ship together
52+
*
53+
* @param \Magento\Sales\Model\Order\Item $item
54+
* @return float|integer
55+
*/
56+
private function getQtyToCancelBundle($item)
57+
{
58+
if ($item->isDummy(true)) {
59+
return min($item->getQtyToInvoice(), $item->getSimpleQtyToShip());
60+
}
61+
return min($item->getQtyToInvoice(), $item->getQtyToShip());
62+
}
63+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Bundle\Test\Unit\Model\Sales\Order\Plugin;
8+
9+
class ItemTest extends \PHPUnit_Framework_TestCase
10+
{
11+
private $plugin;
12+
13+
private $itemMock;
14+
15+
protected function setUp()
16+
{
17+
$this->itemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
18+
->disableOriginalConstructor()
19+
->getMock();
20+
$this->plugin = new \Magento\Bundle\Model\Sales\Order\Plugin\Item();
21+
}
22+
23+
public function testAfterGetQtyToCancelIfProductIsBundle()
24+
{
25+
$qtyToCancel = 10;
26+
$result = 5;
27+
28+
$this->itemMock
29+
->expects($this->once())
30+
->method('getProductType')
31+
->willReturn(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE);
32+
$this->itemMock->expects($this->once())->method('isDummy')->willReturn(true);
33+
$this->itemMock->expects($this->once())->method('getQtyToInvoice')->willReturn(15);
34+
$this->itemMock->expects($this->once())->method('getSimpleQtyToShip')->willReturn($qtyToCancel);
35+
$this->assertEquals($qtyToCancel, $this->plugin->afterGetQtyToCancel($this->itemMock, $result));
36+
}
37+
38+
public function testAfterGetQtyToCancelIfParentProductIsBundle()
39+
{
40+
$qtyToCancel = 10;
41+
$result = 5;
42+
$parentItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
43+
->disableOriginalConstructor()
44+
->getMock();
45+
$this->itemMock
46+
->expects($this->once())
47+
->method('getProductType')
48+
->willReturn(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE);
49+
$this->itemMock->expects($this->any())->method('getParentItem')->willReturn($parentItemMock);
50+
$parentItemMock->expects($this->once())
51+
->method('getProductType')
52+
->willReturn(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE);
53+
$this->itemMock->expects($this->once())->method('isDummy')->willReturn(false);
54+
$this->itemMock->expects($this->once())->method('getQtyToInvoice')->willReturn(15);
55+
$this->itemMock->expects($this->once())->method('getQtyToShip')->willReturn($qtyToCancel);
56+
$this->assertEquals($qtyToCancel, $this->plugin->afterGetQtyToCancel($this->itemMock, $result));
57+
}
58+
public function testAfterGetQtyToCancelForSimpleProduct()
59+
{
60+
$result = 5;
61+
$this->itemMock
62+
->expects($this->once())
63+
->method('getProductType')
64+
->willReturn(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE);
65+
$this->itemMock->expects($this->any())->method('getParentItem')->willReturn(false);
66+
$this->itemMock->expects($this->never())->method('isDummy');
67+
$this->itemMock->expects($this->never())->method('getQtyToInvoice');
68+
$this->assertEquals($result, $this->plugin->afterGetQtyToCancel($this->itemMock, $result));
69+
}
70+
71+
public function testAfterIsProcessingAvailableForProductWithoutParent()
72+
{
73+
$this->itemMock->expects($this->once())->method('getParentItem')->willReturn(false);
74+
$this->assertFalse($this->plugin->afterIsProcessingAvailable($this->itemMock, false));
75+
}
76+
77+
public function testAfterIsProcessingAvailableForProductWhenParentIsBundle()
78+
{
79+
$parentItemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class)
80+
->disableOriginalConstructor()
81+
->getMock();
82+
$this->itemMock->expects($this->any())->method('getParentItem')->willReturn($parentItemMock);
83+
$parentItemMock->expects($this->once())
84+
->method('getProductType')
85+
->willReturn(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE);
86+
$this->itemMock->expects($this->once())->method('getSimpleQtyToShip')->willReturn(10);
87+
$this->itemMock->expects($this->once())->method('getQtyToCancel')->willReturn(5);
88+
$this->assertTrue($this->plugin->afterIsProcessingAvailable($this->itemMock, false));
89+
}
90+
91+
public function testAfterIsProcessingAvailableForBundleProduct()
92+
{
93+
$this->itemMock->expects($this->once())
94+
->method('getProductType')
95+
->willReturn(\Magento\Catalog\Model\Product\Type::TYPE_BUNDLE);
96+
$this->itemMock->expects($this->once())->method('getSimpleQtyToShip')->willReturn(10);
97+
$this->itemMock->expects($this->once())->method('getQtyToCancel')->willReturn(5);
98+
$this->assertTrue($this->plugin->afterIsProcessingAvailable($this->itemMock, false));
99+
}
100+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@
8181
<type name="Magento\Catalog\Model\Product">
8282
<plugin name="bundle" type="Magento\Bundle\Model\Plugin\Product" sortOrder="100" />
8383
</type>
84+
<type name="Magento\Sales\Model\Order\Item">
85+
<plugin name="bundle" type="Magento\Bundle\Model\Sales\Order\Plugin\Item" sortOrder="100" />
86+
</type>
8487
<type name="Magento\Framework\EntityManager\Operation\ExtensionPool">
8588
<arguments>
8689
<argument name="extensionActions" xsi:type="array">

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

Lines changed: 2 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,55 +1841,12 @@ protected function _productLimitationJoinStore()
18411841
$this->getSelect()->columns('visibility', 'cat_index');
18421842
}
18431843

1844-
$fromPart = $this->getSelect()->getPart(\Magento\Framework\DB\Select::FROM);
1845-
if (!isset($fromPart['store_index'])) {
1846-
$this->getSelect()->joinLeft(
1847-
['store_index' => $this->getTable('store')],
1848-
'store_index.store_id = ' . $filters['store_table'] . '.store_id',
1849-
[]
1850-
);
1851-
}
1852-
if (!isset($fromPart['store_group_index'])) {
1853-
$this->getSelect()->joinLeft(
1854-
['store_group_index' => $this->getTable('store_group')],
1855-
'store_index.group_id = store_group_index.group_id',
1856-
[]
1857-
);
1858-
}
1859-
if (!isset($fromPart['store_cat_index'])) {
1860-
$this->getSelect()->joinLeft(
1861-
['store_cat_index' => $this->categoryProductIndexerFrontend->getMainTable()],
1862-
join(
1863-
' AND ',
1864-
[
1865-
'store_cat_index.product_id = e.entity_id',
1866-
'store_cat_index.store_id = ' . $filters['store_table'] . '.store_id',
1867-
'store_cat_index.category_id=store_group_index.root_category_id'
1868-
]
1869-
),
1870-
['store_visibility' => 'visibility']
1871-
);
1872-
}
18731844
// Avoid column duplication problems
18741845
$this->_resourceHelper->prepareColumnsList($this->getSelect());
18751846

1876-
$whereCond = join(
1877-
' OR ',
1878-
[
1879-
$this->getConnection()->quoteInto('cat_index.visibility IN(?)', $filters['visibility']),
1880-
$this->getConnection()->quoteInto('store_cat_index.visibility IN(?)', $filters['visibility'])
1881-
]
1882-
);
1883-
1847+
$whereCond = $this->getConnection()->quoteInto('cat_index.visibility IN(?)', $filters['visibility']);
18841848
$wherePart = $this->getSelect()->getPart(\Magento\Framework\DB\Select::WHERE);
1885-
$hasCond = false;
1886-
foreach ($wherePart as $cond) {
1887-
if ($cond == '(' . $whereCond . ')') {
1888-
$hasCond = true;
1889-
}
1890-
}
1891-
1892-
if (!$hasCond) {
1849+
if (array_search('(' . $whereCond . ')', $wherePart) === false) {
18931850
$this->getSelect()->where($whereCond);
18941851
}
18951852

app/code/Magento/Checkout/view/frontend/web/js/action/redirect-on-success.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
*/
99
define(
1010
[
11-
'mage/url'
11+
'mage/url',
12+
'Magento_Checkout/js/model/full-screen-loader'
1213
],
13-
function (url) {
14+
function (url, fullScreenLoader) {
1415
'use strict';
1516

1617
return {
@@ -20,6 +21,7 @@ define(
2021
* Provide redirect to page
2122
*/
2223
execute: function () {
24+
fullScreenLoader.startLoader();
2325
window.location.replace(url.build(this.redirectUrl));
2426
}
2527
};

app/code/Magento/Checkout/view/frontend/web/js/checkout-data.js

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,36 @@ define([
1515
'use strict';
1616

1717
var cacheKey = 'checkout-data',
18-
checkoutData,
19-
20-
/**
21-
* @return {*}
22-
*/
23-
getData = function () {
24-
return storage.get(cacheKey)();
25-
},
2618

2719
/**
2820
* @param {Object} data
2921
*/
3022
saveData = function (data) {
3123
storage.set(cacheKey, data);
32-
};
24+
},
3325

34-
if ($.isEmptyObject(getData())) {
35-
checkoutData = {
36-
'selectedShippingAddress': null,
37-
'shippingAddressFromData': null,
38-
'newCustomerShippingAddress': null,
39-
'selectedShippingRate': null,
40-
'selectedPaymentMethod': null,
41-
'selectedBillingAddress': null,
42-
'billingAddressFormData': null,
43-
'newCustomerBillingAddress': null
26+
/**
27+
* @return {*}
28+
*/
29+
getData = function () {
30+
var data = storage.get(cacheKey)();
31+
32+
if ($.isEmptyObject(data)) {
33+
data = {
34+
'selectedShippingAddress': null,
35+
'shippingAddressFromData': null,
36+
'newCustomerShippingAddress': null,
37+
'selectedShippingRate': null,
38+
'selectedPaymentMethod': null,
39+
'selectedBillingAddress': null,
40+
'billingAddressFormData': null,
41+
'newCustomerBillingAddress': null
42+
};
43+
saveData(data);
44+
}
45+
46+
return data;
4447
};
45-
saveData(checkoutData);
46-
}
4748

4849
return {
4950
/**

app/code/Magento/Checkout/view/frontend/web/js/model/cart/cache.js

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,28 @@ define([
2626
},
2727

2828
/**
29-
* Get data from local storage.
29+
* Set data to local storage.
3030
*
31-
* @param {String} [key]
32-
* @returns {*}
31+
* @param {Object} checkoutData
3332
*/
34-
getData = function (key) {
35-
return key ? storage.get(cacheKey)()[key] : storage.get(cacheKey)();
33+
setData = function (checkoutData) {
34+
storage.set(cacheKey, checkoutData);
3635
},
3736

3837
/**
39-
* Set data to local storage.
38+
* Get data from local storage.
4039
*
41-
* @param {Object} checkoutData
40+
* @param {String} [key]
41+
* @returns {*}
4242
*/
43-
setData = function (checkoutData) {
44-
storage.set(cacheKey, checkoutData);
43+
getData = function (key) {
44+
var data = key ? storage.get(cacheKey)()[key] : storage.get(cacheKey)();
45+
46+
if (_.isEmpty(storage.get(cacheKey)())) {
47+
setData(utils.copy(cartData));
48+
}
49+
50+
return data;
4551
},
4652

4753
/**
@@ -59,10 +65,6 @@ define([
5965
return prefix + name.charAt(0).toUpperCase() + name.slice(1) + suffix;
6066
};
6167

62-
if (_.isEmpty(getData())) {
63-
setData(utils.copy(cartData));
64-
}
65-
6668
/**
6769
* Provides get/set/isChanged/clear methods for work with cart data.
6870
* Can be customized via mixin functionality.

app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
/**
66
* @api
77
*/
8-
define([], function () {
8+
define([
9+
'underscore'
10+
], function (_) {
911
'use strict';
1012

1113
/**
@@ -29,7 +31,7 @@ define([], function () {
2931
regionCode: addressData.region ? addressData.region['region_code'] : null,
3032
region: addressData.region ? addressData.region.region : null,
3133
customerId: addressData['customer_id'] || addressData.customerId,
32-
street: addressData.street,
34+
street: addressData.street ? _.compact(addressData.street) : addressData.street,
3335
company: addressData.company,
3436
telephone: addressData.telephone,
3537
fax: addressData.fax,

0 commit comments

Comments
 (0)