diff --git a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js
index 22f8a2f6865f5..fcff173e7fcd4 100644
--- a/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js
+++ b/app/code/Magento/Braintree/view/adminhtml/web/js/vault.js
@@ -7,9 +7,8 @@
define([
'jquery',
'uiComponent',
- 'Magento_Ui/js/modal/alert',
- 'Magento_Checkout/js/model/full-screen-loader'
-], function ($, Class, alert, fullScreenLoader) {
+ 'Magento_Ui/js/modal/alert'
+], function ($, Class, alert) {
'use strict';
return Class.extend({
@@ -84,7 +83,7 @@ define([
submitOrder: function () {
this.$selector.validate().form();
this.$selector.trigger('afterValidate.beforeSubmit');
- fullScreenLoader.stopLoader();
+ $('body').trigger('processStop');
// validate parent form
if (this.$selector.validate().errorList.length) {
@@ -106,7 +105,7 @@ define([
getPaymentMethodNonce: function () {
var self = this;
- fullScreenLoader.startLoader();
+ $('body').trigger('processStart');
$.get(self.nonceUrl, {
'public_hash': self.publicHash
@@ -118,7 +117,7 @@ define([
self.error(failed.message);
}).always(function () {
- fullScreenLoader.stopLoader();
+ $('body').trigger('processStop');
});
},
diff --git a/app/code/Magento/Bundle/Pricing/Price/FinalPrice.php b/app/code/Magento/Bundle/Pricing/Price/FinalPrice.php
index 5be2c55d04b2a..b6d7fc40d8c2f 100644
--- a/app/code/Magento/Bundle/Pricing/Price/FinalPrice.php
+++ b/app/code/Magento/Bundle/Pricing/Price/FinalPrice.php
@@ -10,6 +10,8 @@
use Magento\Framework\Pricing\Adjustment\CalculatorInterface;
use Magento\Catalog\Pricing\Price\CustomOptionPrice;
use Magento\Bundle\Model\Product\Price;
+use Magento\Framework\App\ObjectManager;
+use Magento\Catalog\Api\ProductCustomOptionRepositoryInterface;
/**
* Final price model
@@ -36,6 +38,11 @@ class FinalPrice extends \Magento\Catalog\Pricing\Price\FinalPrice implements Fi
*/
protected $bundleOptionPrice;
+ /**
+ * @var \Magento\Catalog\Api\ProductCustomOptionRepositoryInterface
+ */
+ private $productOptionRepository;
+
/**
* @param Product $saleableItem
* @param float $quantity
@@ -81,6 +88,22 @@ public function getMaximalPrice()
return $this->maximalPrice;
}
+ /**
+ * Return ProductCustomOptionRepository
+ *
+ * @return ProductCustomOptionRepositoryInterface
+ * @deprecated
+ */
+ private function getProductOptionRepository()
+ {
+ if (!$this->productOptionRepository) {
+ $this->productOptionRepository = ObjectManager::getInstance()->get(
+ ProductCustomOptionRepositoryInterface::class
+ );
+ }
+ return $this->productOptionRepository;
+ }
+
/**
* Returns min price
*
@@ -101,6 +124,7 @@ public function getAmount()
if (!$this->minimalPrice) {
$price = parent::getValue();
if ($this->product->getPriceType() == Price::PRICE_TYPE_FIXED) {
+ $this->loadProductCustomOptions();
/** @var \Magento\Catalog\Pricing\Price\CustomOptionPrice $customOptionPrice */
$customOptionPrice = $this->priceInfo->getPrice(CustomOptionPrice::PRICE_CODE);
$price += $customOptionPrice->getCustomOptionRange(true);
@@ -110,6 +134,23 @@ public function getAmount()
return $this->minimalPrice;
}
+ /**
+ * Load product custom options
+ *
+ * @return void
+ */
+ private function loadProductCustomOptions()
+ {
+ if (!$this->product->getOptions()) {
+ $options = [];
+ foreach ($this->getProductOptionRepository()->getProductOptions($this->product) as $option) {
+ $option->setProduct($this->product);
+ $options[] = $option;
+ }
+ $this->product->setOptions($options);
+ }
+ }
+
/**
* get bundle product price without any option
*
diff --git a/app/code/Magento/Bundle/Test/Unit/Pricing/Price/FinalPriceTest.php b/app/code/Magento/Bundle/Test/Unit/Pricing/Price/FinalPriceTest.php
index 7c27e48366315..9498a501e22bb 100644
--- a/app/code/Magento/Bundle/Test/Unit/Pricing/Price/FinalPriceTest.php
+++ b/app/code/Magento/Bundle/Test/Unit/Pricing/Price/FinalPriceTest.php
@@ -9,9 +9,13 @@
use Magento\Bundle\Pricing\Price\BundleOptionPrice;
use Magento\Catalog\Pricing\Price\CustomOptionPrice;
use Magento\Bundle\Model\Product\Price;
-
+use Magento\Catalog\Api\ProductCustomOptionRepositoryInterface;
+use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+/**
+ * @SuppressWarnings(PHPMD)
+ */
class FinalPriceTest extends \PHPUnit_Framework_TestCase
{
/** @var \Magento\Bundle\Pricing\Price\FinalPrice */
@@ -45,10 +49,15 @@ class FinalPriceTest extends \PHPUnit_Framework_TestCase
protected $customOptionPriceMock;
/**
- * @var \Magento\Framework\Pricing\PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject
*/
protected $priceCurrencyMock;
+ /**
+ * @var ProductCustomOptionRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $productOptionRepositoryMock;
+
/**
* @return void
*/
@@ -96,6 +105,14 @@ protected function prepareMock()
$this->bundleCalculatorMock,
$this->priceCurrencyMock
);
+
+ $this->productOptionRepositoryMock = $this->getMockForAbstractClass(
+ ProductCustomOptionRepositoryInterface::class
+ );
+ $reflection = new \ReflectionClass(get_class($this->finalPrice));
+ $reflectionProperty = $reflection->getProperty('productOptionRepository');
+ $reflectionProperty->setAccessible(true);
+ $reflectionProperty->setValue($this->finalPrice, $this->productOptionRepositoryMock);
}
/**
@@ -172,6 +189,16 @@ public function testGetMinimalPriceFixedBundleWithOption()
$this->baseAmount = 5;
$result = 7;
$this->prepareMock();
+ $customOptions = [
+ $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductCustomOptionInterface::class)
+ ->setMethods(['setProduct'])
+ ->getMockForAbstractClass()
+ ];
+
+ $this->productOptionRepositoryMock->expects(static::once())
+ ->method('getProductOptions')
+ ->with($this->saleableInterfaceMock)
+ ->willReturn($customOptions);
$this->saleableInterfaceMock->expects($this->once())
->method('getPriceType')
diff --git a/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/View/Tab/Orders.php b/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/View/Tab/Orders.php
index 465c6c5593642..0d59e9890db2c 100644
--- a/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/View/Tab/Orders.php
+++ b/app/code/Magento/Paypal/Block/Adminhtml/Billing/Agreement/View/Tab/Orders.php
@@ -100,6 +100,16 @@ protected function _construct()
$this->setUseAjax(true);
}
+ /**
+ * Get grid url
+ *
+ * @return string
+ */
+ public function getGridUrl()
+ {
+ return $this->getUrl('paypal/billing_agreement/ordersGrid', ['_current' => true]);
+ }
+
/**
* Apply various selection filters to prepare the sales order grid collection.
*
diff --git a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml
index f892e023996d3..e32876475f824 100644
--- a/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml
+++ b/app/code/Magento/Paypal/view/adminhtml/layout/paypal_billing_agreement_ordersgrid.xml
@@ -18,6 +18,6 @@
-
+
diff --git a/app/code/Magento/Quote/Model/Quote/Payment.php b/app/code/Magento/Quote/Model/Quote/Payment.php
index cdd295114c3d5..3ef26146e6ff0 100644
--- a/app/code/Magento/Quote/Model/Quote/Payment.php
+++ b/app/code/Magento/Quote/Model/Quote/Payment.php
@@ -145,6 +145,7 @@ public function getQuote()
*/
public function importData(array $data)
{
+ $data = $this->convertPaymentData($data);
$data = new \Magento\Framework\DataObject($data);
$this->_eventManager->dispatch(
$this->_eventPrefix . '_import_data_before',
@@ -177,6 +178,37 @@ public function importData(array $data)
return $this;
}
+ /**
+ * Converts request to payment data
+ *
+ * @param array $rawData
+ * @return array
+ */
+ private function convertPaymentData(array $rawData)
+ {
+ $paymentData = [
+ PaymentInterface::KEY_METHOD => null,
+ PaymentInterface::KEY_PO_NUMBER => null,
+ PaymentInterface::KEY_ADDITIONAL_DATA => [],
+ 'checks' => []
+ ];
+
+ foreach (array_keys($rawData) as $requestKey) {
+ if (!array_key_exists($requestKey, $paymentData)) {
+ $paymentData[PaymentInterface::KEY_ADDITIONAL_DATA][$requestKey] = $rawData[$requestKey];
+ } elseif ($requestKey === PaymentInterface::KEY_ADDITIONAL_DATA) {
+ $paymentData[PaymentInterface::KEY_ADDITIONAL_DATA] = array_merge(
+ $paymentData[PaymentInterface::KEY_ADDITIONAL_DATA],
+ (array) $rawData[$requestKey]
+ );
+ } else {
+ $paymentData[$requestKey] = $rawData[$requestKey];
+ }
+ }
+
+ return $paymentData;
+ }
+
/**
* Prepare object for save
*
@@ -226,7 +258,7 @@ public function getOrderPlaceRedirectUrl()
public function getMethodInstance()
{
$method = parent::getMethodInstance();
- $method->setStore($this->getQuote()->getStore()->getStoreId());
+ $method->setStore($this->getQuote()->getStoreId());
return $method;
}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/PaymentTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/PaymentTest.php
index 53d95bda04ed3..849f45764abdc 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Quote/PaymentTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/PaymentTest.php
@@ -5,6 +5,13 @@
*/
namespace Magento\Quote\Test\Unit\Model\Quote;
+use Magento\Framework\DataObject;
+use Magento\Framework\Event\ManagerInterface;
+use Magento\Payment\Model\Checks\Composite;
+use Magento\Payment\Model\Checks\SpecificationFactory;
+use Magento\Payment\Model\MethodInterface;
+use Magento\Quote\Api\Data\PaymentInterface;
+use Magento\Quote\Model\Quote;
use \Magento\Quote\Model\Quote\Payment;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
@@ -16,11 +23,31 @@ class PaymentTest extends \PHPUnit_Framework_TestCase
*/
private $model;
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject|SpecificationFactory
+ */
+ private $specificationFactory;
+
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject|ManagerInterface
+ */
+ private $eventManager;
+
protected function setUp()
{
$objectManager = new ObjectManager($this);
+ $this->specificationFactory = $this->getMockBuilder(
+ SpecificationFactory::class
+ )->disableOriginalConstructor()
+ ->getMock();
+ $this->eventManager = $this->getMock(ManagerInterface::class);
+
$this->model = $objectManager->getObject(
- '\Magento\Quote\Model\Quote\Payment'
+ Payment::class,
+ [
+ 'methodSpecificationFactory' => $this->specificationFactory,
+ 'eventDispatcher' => $this->eventManager
+ ]
);
}
@@ -32,7 +59,7 @@ protected function setUp()
public function testGetCcExpYearReturnsValidValue($databaseValue, $expectedValue)
{
$this->model->setData('cc_exp_year', $databaseValue);
- $this->assertEquals($expectedValue, $this->model->getCcExpYear());
+ static::assertEquals($expectedValue, $this->model->getCcExpYear());
}
/**
@@ -47,4 +74,141 @@ public function yearValueDataProvider()
[1939, 1939],
];
}
+
+ /**
+ * @param array $data
+ * @param array $convertedData
+ * @param array $dataToAssign
+ * @param array $checks
+ * @dataProvider importDataPositiveCheckDataProvider
+ */
+ public function testImportDataPositiveCheck(
+ array $data,
+ array $convertedData,
+ array $dataToAssign,
+ array $checks
+ ) {
+ $quoteId = 1;
+ $storeId = 1;
+
+ $paymentMethod = $this->getMock(MethodInterface::class);
+ $quote = $this->getMockBuilder(Quote::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+ $methodSpecification = $this->getMockBuilder(Composite::class)
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $quote->expects(static::once())
+ ->method('getId')
+ ->willReturn($quoteId);
+
+ $this->model->setQuote($quote);
+ $this->model->setMethodInstance($paymentMethod);
+ $this->eventManager->expects(static::once())
+ ->method('dispatch')
+ ->with(
+ 'sales_quote_payment_import_data_before',
+ [
+ 'payment' => $this->model,
+ 'input' => new DataObject($convertedData)
+ ]
+ );
+ $quote->expects(static::once())
+ ->method('getStoreId')
+ ->willReturn($storeId);
+
+ $quote->expects(static::once())
+ ->method('collectTotals');
+
+ $this->specificationFactory->expects(static::once())
+ ->method('create')
+ ->with($checks)
+ ->willReturn($methodSpecification);
+
+ $paymentMethod->expects(static::once())
+ ->method('isAvailable')
+ ->with($quote)
+ ->willReturn(true);
+ $methodSpecification->expects(static::once())
+ ->method('isApplicable')
+ ->with($paymentMethod, $quote)
+ ->willReturn(true);
+
+ $paymentMethod->expects(static::once())
+ ->method('assignData')
+ ->with(new DataObject($dataToAssign));
+ $paymentMethod->expects(static::once())
+ ->method('validate');
+
+ $this->model->importData($data);
+ }
+
+ /**
+ * @return array
+ */
+ public function importDataPositiveCheckDataProvider()
+ {
+ return [
+ [
+ [
+ PaymentInterface::KEY_METHOD => 'payment_method_code',
+ 'cc_number' => '1111',
+ 'cc_type' => 'VI',
+ 'cc_owner' => 'John Doe'
+ ],
+ [
+ PaymentInterface::KEY_METHOD => 'payment_method_code',
+ PaymentInterface::KEY_PO_NUMBER => null,
+ PaymentInterface::KEY_ADDITIONAL_DATA => [
+ 'cc_number' => '1111',
+ 'cc_type' => 'VI',
+ 'cc_owner' => 'John Doe'
+ ],
+ 'checks' => []
+ ],
+ [
+ PaymentInterface::KEY_METHOD => 'payment_method_code',
+ PaymentInterface::KEY_PO_NUMBER => null,
+ PaymentInterface::KEY_ADDITIONAL_DATA => [
+ 'cc_number' => '1111',
+ 'cc_type' => 'VI',
+ 'cc_owner' => 'John Doe'
+ ],
+ 'checks' => []
+ ],
+ []
+ ],
+ [
+ [
+ PaymentInterface::KEY_METHOD => 'payment_method_code',
+ 'cc_number' => '1111',
+ 'cc_type' => 'VI',
+ 'cc_owner' => 'John Doe',
+ 'checks' => ['check_code1', 'check_code2']
+ ],
+ [
+ PaymentInterface::KEY_METHOD => 'payment_method_code',
+ PaymentInterface::KEY_PO_NUMBER => null,
+ PaymentInterface::KEY_ADDITIONAL_DATA => [
+ 'cc_number' => '1111',
+ 'cc_type' => 'VI',
+ 'cc_owner' => 'John Doe'
+ ],
+ 'checks' => ['check_code1', 'check_code2']
+ ],
+ [
+ PaymentInterface::KEY_METHOD => 'payment_method_code',
+ PaymentInterface::KEY_PO_NUMBER => null,
+ PaymentInterface::KEY_ADDITIONAL_DATA => [
+ 'cc_number' => '1111',
+ 'cc_type' => 'VI',
+ 'cc_owner' => 'John Doe'
+ ],
+ 'checks' => ['check_code1', 'check_code2']
+ ],
+ ['check_code1', 'check_code2']
+ ]
+ ];
+ }
}