Skip to content

Commit 899bc53

Browse files
committed
Merge branch 'MAGETWO-65734' into MAGETWO-65734-PR
2 parents c212b94 + a61029b commit 899bc53

File tree

8 files changed

+309
-26
lines changed

8 files changed

+309
-26
lines changed

app/code/Magento/Sales/Model/Order/Creditmemo/RefundOperation.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ public function execute(CreditmemoInterface $creditmemo, OrderInterface $order,
114114
$order->getBaseTotalInvoicedCost() - $creditmemo->getBaseCost()
115115
);
116116

117-
$creditmemo->setDoTransaction($online);
117+
$creditmemo->setDoTransaction(!$creditmemo->getPaymentRefundDisallowed() && $online);
118118
$order->getPayment()->refund($creditmemo);
119119

120120
$this->eventManager->dispatch('sales_order_creditmemo_refund', ['creditmemo' => $creditmemo]);

app/code/Magento/Sales/Model/Order/Payment.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88

99
namespace Magento\Sales\Model\Order;
1010

11+
use Magento\Framework\App\ObjectManager;
1112
use Magento\Framework\Pricing\PriceCurrencyInterface;
1213
use Magento\Sales\Api\OrderRepositoryInterface;
1314
use Magento\Sales\Model\Order\Payment\Info;
1415
use Magento\Sales\Api\Data\OrderPaymentInterface;
1516
use Magento\Sales\Model\Order;
1617
use Magento\Sales\Model\Order\Payment\Transaction;
1718
use Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface;
19+
use Magento\Sales\Api\CreditmemoManagementInterface as CreditmemoManager;
1820

1921
/**
2022
* Order payment information
@@ -105,6 +107,11 @@ class Payment extends Info implements OrderPaymentInterface
105107
*/
106108
protected $orderRepository;
107109

110+
/**
111+
* @var CreditmemoManager
112+
*/
113+
private $creditmemoManager = null;
114+
108115
/**
109116
* @param \Magento\Framework\Model\Context $context
110117
* @param \Magento\Framework\Registry $registry
@@ -122,6 +129,7 @@ class Payment extends Info implements OrderPaymentInterface
122129
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
123130
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
124131
* @param array $data
132+
* @param CreditmemoManager|null $creditmemoManager
125133
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
126134
*/
127135
public function __construct(
@@ -140,7 +148,8 @@ public function __construct(
140148
OrderRepositoryInterface $orderRepository,
141149
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
142150
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
143-
array $data = []
151+
array $data = [],
152+
CreditmemoManager $creditmemoManager = null
144153
) {
145154
$this->priceCurrency = $priceCurrency;
146155
$this->creditmemoFactory = $creditmemoFactory;
@@ -149,6 +158,7 @@ public function __construct(
149158
$this->transactionBuilder = $transactionBuilder;
150159
$this->orderPaymentProcessor = $paymentProcessor;
151160
$this->orderRepository = $orderRepository;
161+
$this->creditmemoManager = $creditmemoManager ?: ObjectManager::getInstance()->get(CreditmemoManager::class);
152162
parent::__construct(
153163
$context,
154164
$registry,
@@ -169,7 +179,7 @@ public function __construct(
169179
*/
170180
protected function _construct()
171181
{
172-
$this->_init('Magento\Sales\Model\ResourceModel\Order\Payment');
182+
$this->_init(\Magento\Sales\Model\ResourceModel\Order\Payment::class);
173183
}
174184

175185
/**
@@ -762,7 +772,8 @@ public function registerRefundNotification($amount)
762772
)->addComment(
763773
__('The credit memo has been created automatically.')
764774
);
765-
$creditmemo->save();
775+
776+
$this->creditmemoManager->refund($creditmemo, false);
766777

767778
$this->_updateTotals(
768779
['amount_refunded' => $creditmemo->getGrandTotal(), 'base_amount_refunded_online' => $amount]

app/code/Magento/Sales/Test/Unit/Model/Order/Creditmemo/RefundOperationTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ protected function setUp()
5050

5151
$this->creditmemoMock = $this->getMockBuilder(\Magento\Sales\Api\Data\CreditmemoInterface::class)
5252
->disableOriginalConstructor()
53-
->setMethods(['getBaseCost', 'setDoTransaction'])
53+
->setMethods(['getBaseCost', 'setDoTransaction', 'getPaymentRefundDisallowed'])
5454
->getMockForAbstractClass();
5555

5656
$this->paymentMock = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)

app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
use Magento\Sales\Model\Order;
99
use Magento\Sales\Model\Order\Payment;
1010
use Magento\Sales\Model\Order\Payment\Transaction;
11+
use Magento\Sales\Api\CreditmemoManagementInterface;
12+
use Magento\Sales\Model\Order\Creditmemo;
1113

1214
/**
1315
* Class PaymentTest
@@ -102,6 +104,11 @@ class PaymentTest extends \PHPUnit_Framework_TestCase
102104
*/
103105
protected $orderRepository;
104106

107+
/**
108+
* @var CreditmemoManagementInterface
109+
*/
110+
private $creditmemoManagerMock;
111+
105112
/**
106113
* @return void
107114
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
@@ -252,25 +259,31 @@ function ($value) {
252259
'',
253260
false
254261
);
255-
$this->creditMemoMock = $this->getMock(
256-
'Magento\Sales\Model\Order\Creditmemo',
257-
[
258-
'setPaymentRefundDisallowed',
259-
'getItemsCollection',
260-
'getItems',
261-
'setAutomaticallyCreated',
262-
'register',
263-
'addComment',
264-
'save',
265-
'getGrandTotal',
266-
'getBaseGrandTotal',
267-
'getDoTransaction',
268-
'getInvoice'
269-
],
270-
[],
271-
'',
272-
false
273-
);
262+
263+
$this->creditMemoMock = $this->getMockBuilder(Creditmemo::class)
264+
->disableOriginalConstructor()
265+
->setMethods(
266+
[
267+
'setPaymentRefundDisallowed',
268+
'getItemsCollection',
269+
'getItems',
270+
'setAutomaticallyCreated',
271+
'register',
272+
'addComment',
273+
'save',
274+
'getGrandTotal',
275+
'getBaseGrandTotal',
276+
'getDoTransaction',
277+
'getInvoice',
278+
'getOrder',
279+
'getPaymentRefundDisallowed'
280+
]
281+
)
282+
->getMock();
283+
284+
$this->creditmemoManagerMock = $this->getMockBuilder(CreditmemoManagementInterface::class)
285+
->disableOriginalConstructor()
286+
->getMockForAbstractClass();
274287

275288
$this->payment = $this->initPayment();
276289
$this->payment->setMethod('any');
@@ -1340,7 +1353,12 @@ public function testRegisterRefundNotification()
13401353
$this->creditMemoMock->expects($this->once())->method('setPaymentRefundDisallowed')->willReturnSelf();
13411354
$this->creditMemoMock->expects($this->once())->method('setAutomaticallyCreated')->willReturnSelf();
13421355
$this->creditMemoMock->expects($this->once())->method('addComment')->willReturnSelf();
1343-
$this->creditMemoMock->expects($this->once())->method('save')->willReturnSelf();
1356+
1357+
$this->creditmemoManagerMock->expects($this->once())
1358+
->method('refund')
1359+
->with($this->creditMemoMock, false)
1360+
->willReturn($this->creditMemoMock);
1361+
13441362
$this->orderMock->expects($this->once())->method('getBaseCurrency')->willReturn($this->currencyMock);
13451363

13461364
$parentTransaction = $this->getMock(
@@ -1553,7 +1571,8 @@ protected function initPayment()
15531571
'transactionManager' => $this->transactionManagerMock,
15541572
'transactionBuilder' => $this->transactionBuilderMock,
15551573
'paymentProcessor' => $this->paymentProcessor,
1556-
'orderRepository' => $this->orderRepository
1574+
'orderRepository' => $this->orderRepository,
1575+
'creditmemoManager' => $this->creditmemoManagerMock
15571576
]
15581577
);
15591578
}

dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
*/
66
namespace Magento\Paypal\Model;
77

8+
use Magento\Paypal\Model\IpnFactory;
9+
use Magento\Sales\Api\Data\OrderInterface;
10+
use Magento\Sales\Model\Order;
11+
use Magento\Sales\Model\Order\Creditmemo;
12+
813
/**
914
* @magentoAppArea frontend
1015
*/
@@ -33,6 +38,126 @@ public function testProcessIpnRequestExpressCurrency($currencyCode)
3338
$this->_processIpnRequestCurrency($currencyCode);
3439
}
3540

41+
/**
42+
* Refund full order amount by Paypal Express IPN message service.
43+
*
44+
* @magentoDataFixture Magento/Paypal/_files/order_express_with_invoice_and_shipping.php
45+
* @magentoConfigFixture current_store payment/paypal_express/active 1
46+
* @magentoConfigFixture current_store paypal/general/merchant_country US
47+
*/
48+
public function testProcessIpnRequestFullRefund()
49+
{
50+
$ipnData = require __DIR__ . '/../_files/ipn_refund.php';
51+
$ipnFactory = $this->_objectManager->create(IpnFactory::class);
52+
$ipnModel = $ipnFactory->create(
53+
[
54+
'data' => $ipnData,
55+
'curlFactory' => $this->_createMockedHttpAdapter()
56+
]
57+
);
58+
59+
$ipnModel->processIpnRequest();
60+
61+
$order = $this->_objectManager->create(Order::class);
62+
$order->loadByIncrementId('100000001');
63+
64+
$creditmemoItems = $order->getCreditmemosCollection()->getItems();
65+
$creditmemo = current($creditmemoItems);
66+
67+
$this->assertEquals(Order::STATE_CLOSED, $order->getState()) ;
68+
$this->assertEquals(1, count($creditmemoItems));
69+
$this->assertEquals(Creditmemo::STATE_REFUNDED, $creditmemo->getState());
70+
$this->assertEquals(10, $order->getSubtotalRefunded());
71+
$this->assertEquals(10, $order->getBaseSubtotalRefunded());
72+
$this->assertEquals(20, $order->getShippingRefunded());
73+
$this->assertEquals(20, $order->getBaseShippingRefunded());
74+
$this->assertEquals(30, $order->getTotalRefunded());
75+
$this->assertEquals(30, $order->getBaseTotalRefunded());
76+
$this->assertEquals(30, $order->getTotalOnlineRefunded());
77+
$this->assertEmpty($order->getTotalOfflineRefunded());
78+
}
79+
80+
/**
81+
* Partial refund of order amount by Paypal Express IPN message service.
82+
*
83+
* @magentoDataFixture Magento/Paypal/_files/order_express_with_invoice_and_shipping.php
84+
* @magentoConfigFixture current_store payment/paypal_express/active 1
85+
* @magentoConfigFixture current_store paypal/general/merchant_country US
86+
*/
87+
public function testProcessIpnRequestPartialRefund()
88+
{
89+
$ipnData = require __DIR__ . '/../_files/ipn_refund.php';
90+
91+
$refundAmount = -15;
92+
$ipnData['mc_gross'] = $refundAmount;
93+
94+
$ipnFactory = $this->_objectManager->create(IpnFactory::class);
95+
$ipnModel = $ipnFactory->create(
96+
[
97+
'data' => $ipnData,
98+
'curlFactory' => $this->_createMockedHttpAdapter()
99+
]
100+
);
101+
102+
$ipnModel->processIpnRequest();
103+
104+
$order = $this->_objectManager->create(Order::class);
105+
$order->loadByIncrementId('100000001');
106+
107+
$creditmemoItems = $order->getCreditmemosCollection()->getItems();
108+
$comments = $order->load($order->getId())->getAllStatusHistory();
109+
$commentData = reset($comments);
110+
$commentOrigin = sprintf(
111+
'IPN "Refunded". Refund issued by merchant. Registered notification about refunded amount of $%d.00. '.
112+
'Transaction ID: "%s". Credit Memo has not been created. Please create offline Credit Memo.',
113+
abs($refundAmount),
114+
$ipnData['txn_id']
115+
);
116+
117+
$this->assertEquals(Order::STATE_PROCESSING, $order->getState()) ;
118+
$this->assertEmpty(count($creditmemoItems));
119+
$this->assertEquals(1, count($comments));
120+
$this->assertEquals($commentOrigin, $commentData->getComment());
121+
}
122+
123+
/**
124+
* Refund rest of order amount by Paypal Express IPN message service.
125+
*
126+
* @magentoDataFixture Magento/Paypal/_files/order_express_with_invoice_and_creditmemo.php
127+
* @magentoConfigFixture current_store payment/paypal_express/active 1
128+
* @magentoConfigFixture current_store paypal/general/merchant_country US
129+
*/
130+
public function testProcessIpnRequestRestRefund()
131+
{
132+
$ipnData = require __DIR__ . '/../_files/ipn_refund.php';
133+
134+
$ipnFactory = $this->_objectManager->create(IpnFactory::class);
135+
$ipnModel = $ipnFactory->create(
136+
[
137+
'data' => $ipnData,
138+
'curlFactory' => $this->_createMockedHttpAdapter()
139+
]
140+
);
141+
142+
$ipnModel->processIpnRequest();
143+
144+
$order = $this->_objectManager->create(Order::class);
145+
$order->loadByIncrementId('100000001');
146+
147+
$creditmemoItems = $order->getCreditmemosCollection()->getItems();
148+
149+
$this->assertEquals(Order::STATE_CLOSED, $order->getState()) ;
150+
$this->assertEquals(2, count($creditmemoItems));
151+
$this->assertEquals(10, $order->getSubtotalRefunded());
152+
$this->assertEquals(10, $order->getBaseSubtotalRefunded());
153+
$this->assertEquals(20, $order->getShippingRefunded());
154+
$this->assertEquals(20, $order->getBaseShippingRefunded());
155+
$this->assertEquals(30, $order->getTotalRefunded());
156+
$this->assertEquals(30, $order->getBaseTotalRefunded());
157+
$this->assertEquals(30, $order->getTotalOnlineRefunded());
158+
$this->assertEmpty($order->getTotalOfflineRefunded());
159+
}
160+
36161
/**
37162
* Test processIpnRequest() currency check for paypal_express and paypal_standard payment methods
38163
*
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
return [
8+
'mc_gross' => -30.00,
9+
'invoice' => '100000001',
10+
'payment_status' => 'Refunded',
11+
'auth_status' => 'Completed',
12+
'reason_code' => 'refund',
13+
'receiver_email' => 'merchant_2012050718_biz@example.com',
14+
'parent_txn_id' => '84J11393WC835693U',
15+
'txn_id' => '1P566839F9694230H'
16+
];
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\Sales\Api\CreditmemoRepositoryInterface;
8+
use Magento\Sales\Model\Order\Creditmemo;
9+
use Magento\Sales\Model\Order\CreditmemoFactory;
10+
11+
require __DIR__ . '/order_express_with_invoice_and_shipping.php';
12+
13+
/** @var CreditmemoFactory $creditmemoFactory */
14+
$creditmemoFactory = $objectManager->create(CreditmemoFactory::class);
15+
/** @var Creditmemo $creditmemo */
16+
$creditmemo = $creditmemoFactory->createByInvoice($invoice, $invoice->getData());
17+
18+
$creditmemo->setOrder($order);
19+
$creditmemo->setState(Creditmemo::STATE_REFUNDED);
20+
$creditmemo->setIncrementId('100000001');
21+
$creditmemo->setGrandTotal($itemsAmount);
22+
23+
/** @var CreditmemoRepositoryInterface $creditMemoRepository */
24+
$creditMemoRepository = $objectManager->get(CreditmemoRepositoryInterface::class);
25+
$creditMemoRepository->save($creditmemo);

0 commit comments

Comments
 (0)