Skip to content

Commit e8909c9

Browse files
committed
Merge branch 'develop' of github.com:magento/magento2ce into MAGETWO-59661
2 parents 6411eb5 + 397fde4 commit e8909c9

File tree

40 files changed

+925
-75
lines changed

40 files changed

+925
-75
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/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,

app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ define([
1515
'./postcode-validator',
1616
'mage/translate',
1717
'uiRegistry',
18+
'Magento_Checkout/js/model/shipping-address/form-popup-state',
1819
'Magento_Checkout/js/model/quote'
1920
], function (
2021
$,
@@ -24,7 +25,8 @@ define([
2425
selectShippingAddress,
2526
postcodeValidator,
2627
$t,
27-
uiRegistry
28+
uiRegistry,
29+
formPopUpState
2830
) {
2931
'use strict';
3032

@@ -127,11 +129,13 @@ define([
127129
});
128130
} else {
129131
element.on('value', function () {
130-
clearTimeout(self.validateAddressTimeout);
131-
self.validateAddressTimeout = setTimeout(function () {
132-
self.postcodeValidation();
133-
self.validateFields();
134-
}, delay);
132+
if (!formPopUpState.isVisible()) {
133+
clearTimeout(self.validateAddressTimeout);
134+
self.validateAddressTimeout = setTimeout(function () {
135+
self.postcodeValidation();
136+
self.validateFields();
137+
}, delay);
138+
}
135139
});
136140
observedElements.push(element);
137141
}

app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ define([
114114
if (shippingAddressData) {
115115
checkoutProvider.set(
116116
'shippingAddress',
117-
$.extend({}, checkoutProvider.get('shippingAddress'), shippingAddressData)
117+
$.extend(true, {}, checkoutProvider.get('shippingAddress'), shippingAddressData)
118118
);
119119
}
120120
checkoutProvider.on('shippingAddress', function (shippingAddrsData) {
@@ -153,22 +153,39 @@ define([
153153
class: buttons.cancel.class ? buttons.cancel.class : 'action secondary action-hide-popup',
154154

155155
/** @inheritdoc */
156-
click: function () {
157-
this.closeModal();
158-
}
156+
click: this.onClosePopUp.bind(this)
159157
}
160158
];
161159

162160
/** @inheritdoc */
163161
this.popUpForm.options.closed = function () {
164162
self.isFormPopUpVisible(false);
165163
};
164+
165+
this.popUpForm.options.modalCloseBtnHandler = this.onClosePopUp.bind(this);
166+
this.popUpForm.options.keyEventHandlers = {
167+
escapeKey: this.onClosePopUp.bind(this)
168+
};
169+
170+
/** @inheritdoc */
171+
this.popUpForm.options.opened = function () {
172+
// Store temporary address for revert action in case when user click cancel action
173+
self.temporaryAddress = $.extend(true, {}, checkoutData.getShippingAddressFromData());
174+
};
166175
popUp = modal(this.popUpForm.options, $(this.popUpForm.element));
167176
}
168177

169178
return popUp;
170179
},
171180

181+
/**
182+
* Revert address and close modal.
183+
*/
184+
onClosePopUp: function () {
185+
checkoutData.setShippingAddressFromData($.extend(true, {}, this.temporaryAddress));
186+
this.getPopUp().closeModal();
187+
},
188+
172189
/**
173190
* Show address form popup
174191
*/
@@ -195,7 +212,7 @@ define([
195212
newShippingAddress = createShippingAddress(addressData);
196213
selectShippingAddress(newShippingAddress);
197214
checkoutData.setSelectedShippingAddress(newShippingAddress.getKey());
198-
checkoutData.setNewCustomerShippingAddress(addressData);
215+
checkoutData.setNewCustomerShippingAddress($.extend(true, {}, addressData));
199216
this.getPopUp().closeModal();
200217
this.isNewAddressAdded(true);
201218
}

0 commit comments

Comments
 (0)