Skip to content

Commit 7afc1a0

Browse files
merge magento/2.3-develop into magento-chaika/Chaika-PR-2019-08-29
2 parents 145a0a0 + 71d6954 commit 7afc1a0

File tree

39 files changed

+927
-97
lines changed

39 files changed

+927
-97
lines changed

app/code/Magento/AuthorizenetAcceptjs/Gateway/Command/RefundTransactionStrategyCommand.php

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,45 @@ public function execute(array $commandSubject): void
5959
* @param array $commandSubject
6060
* @return string
6161
* @throws CommandException
62+
* @throws \Magento\Framework\Exception\NotFoundException
6263
*/
6364
private function getCommand(array $commandSubject): string
6465
{
6566
$details = $this->commandPool->get('get_transaction_details')
6667
->execute($commandSubject)
6768
->get();
6869

69-
if ($details['transaction']['transactionStatus'] === 'capturedPendingSettlement') {
70+
if ($this->canVoid($details, $commandSubject)) {
7071
return self::VOID;
71-
} elseif ($details['transaction']['transactionStatus'] !== 'settledSuccessfully') {
72+
}
73+
74+
if ($details['transaction']['transactionStatus'] !== 'settledSuccessfully') {
7275
throw new CommandException(__('This transaction cannot be refunded with its current status.'));
7376
}
7477

7578
return self::REFUND;
7679
}
80+
81+
/**
82+
* Checks if void command can be performed.
83+
*
84+
* @param array $details
85+
* @param array $commandSubject
86+
* @return bool
87+
* @throws CommandException
88+
*/
89+
private function canVoid(array $details, array $commandSubject) :bool
90+
{
91+
if ($details['transaction']['transactionStatus'] === 'capturedPendingSettlement') {
92+
if ((float) $details['transaction']['authAmount'] !== (float) $commandSubject['amount']) {
93+
throw new CommandException(
94+
__('The transaction has not been settled, a partial refund is not yet available.')
95+
);
96+
}
97+
98+
return true;
99+
}
100+
101+
return false;
102+
}
77103
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\AuthorizenetAcceptjs\Gateway\Response;
9+
10+
use Magento\Sales\Model\Order\Payment;
11+
12+
/**
13+
* Determines that parent transaction should be close for partial refund operation.
14+
*/
15+
class ClosePartialTransactionHandler extends CloseTransactionHandler
16+
{
17+
/**
18+
* Whether parent transaction should be closed.
19+
*
20+
* @param Payment $payment
21+
* @return bool
22+
*/
23+
public function shouldCloseParentTransaction(Payment $payment)
24+
{
25+
return !(bool)$payment->getCreditmemo()->getInvoice()->canRefund();
26+
}
27+
}

app/code/Magento/AuthorizenetAcceptjs/Gateway/Response/CloseTransactionHandler.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,19 @@ public function handle(array $handlingSubject, array $response): void
4747

4848
if ($payment instanceof Payment) {
4949
$payment->setIsTransactionClosed($this->closeTransaction);
50-
$payment->setShouldCloseParentTransaction(true);
50+
$payment->setShouldCloseParentTransaction($this->shouldCloseParentTransaction($payment));
5151
}
5252
}
53+
54+
/**
55+
* Whether parent transaction should be closed.
56+
*
57+
* @param Payment $payment
58+
* @return bool
59+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
60+
*/
61+
public function shouldCloseParentTransaction(Payment $payment)
62+
{
63+
return true;
64+
}
5365
}

app/code/Magento/AuthorizenetAcceptjs/Test/Unit/Gateway/Command/RefundTransactionStrategyCommandTest.php

Lines changed: 96 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,75 @@ public function testCommandWillVoidWhenTransactionIsPendingSettlement()
6262
->method('execute');
6363

6464
$this->commandPoolMock->method('get')
65-
->willReturnMap([
66-
['get_transaction_details', $this->transactionDetailsCommandMock],
67-
['void', $this->commandMock]
68-
]);
65+
->willReturnMap(
66+
[
67+
[
68+
'get_transaction_details',
69+
$this->transactionDetailsCommandMock
70+
],
71+
[
72+
'void',
73+
$this->commandMock
74+
]
75+
]
76+
);
6977

7078
$this->transactionResultMock->method('get')
71-
->willReturn([
72-
'transaction' => [
73-
'transactionStatus' => 'capturedPendingSettlement'
79+
->willReturn(
80+
[
81+
'transaction' => [
82+
'transactionStatus' => 'capturedPendingSettlement',
83+
'authAmount' => '20.19',
84+
]
7485
]
75-
]);
86+
);
7687

7788
$buildSubject = [
78-
'foo' => '123'
89+
'foo' => '123',
90+
'amount' => '20.19',
91+
];
92+
93+
$this->transactionDetailsCommandMock->expects($this->once())
94+
->method('execute')
95+
->with($buildSubject)
96+
->willReturn($this->transactionResultMock);
97+
98+
$this->command->execute($buildSubject);
99+
}
100+
101+
/**
102+
* @expectedException \Magento\Payment\Gateway\Command\CommandException
103+
* @expectedExceptionMessage The transaction has not been settled, a partial refund is not yet available.
104+
*/
105+
public function testCommandWillThrowExceptionWhenVoidTransactionIsPartial()
106+
{
107+
// Assert command is executed
108+
$this->commandMock->expects($this->never())
109+
->method('execute');
110+
111+
$this->commandPoolMock->method('get')
112+
->willReturnMap(
113+
[
114+
[
115+
'get_transaction_details',
116+
$this->transactionDetailsCommandMock
117+
],
118+
]
119+
);
120+
121+
$this->transactionResultMock->method('get')
122+
->willReturn(
123+
[
124+
'transaction' => [
125+
'transactionStatus' => 'capturedPendingSettlement',
126+
'authAmount' => '20.19',
127+
]
128+
]
129+
);
130+
131+
$buildSubject = [
132+
'foo' => '123',
133+
'amount' => '10.19',
79134
];
80135

81136
$this->transactionDetailsCommandMock->expects($this->once())
@@ -93,17 +148,27 @@ public function testCommandWillRefundWhenTransactionIsSettled()
93148
->method('execute');
94149

95150
$this->commandPoolMock->method('get')
96-
->willReturnMap([
97-
['get_transaction_details', $this->transactionDetailsCommandMock],
98-
['refund_settled', $this->commandMock]
99-
]);
151+
->willReturnMap(
152+
[
153+
[
154+
'get_transaction_details',
155+
$this->transactionDetailsCommandMock
156+
],
157+
[
158+
'refund_settled',
159+
$this->commandMock
160+
]
161+
]
162+
);
100163

101164
$this->transactionResultMock->method('get')
102-
->willReturn([
103-
'transaction' => [
104-
'transactionStatus' => 'settledSuccessfully'
165+
->willReturn(
166+
[
167+
'transaction' => [
168+
'transactionStatus' => 'settledSuccessfully'
169+
]
105170
]
106-
]);
171+
);
107172

108173
$buildSubject = [
109174
'foo' => '123'
@@ -128,16 +193,23 @@ public function testCommandWillThrowExceptionWhenTransactionIsInInvalidState()
128193
->method('execute');
129194

130195
$this->commandPoolMock->method('get')
131-
->willReturnMap([
132-
['get_transaction_details', $this->transactionDetailsCommandMock],
133-
]);
196+
->willReturnMap(
197+
[
198+
[
199+
'get_transaction_details',
200+
$this->transactionDetailsCommandMock
201+
],
202+
]
203+
);
134204

135205
$this->transactionResultMock->method('get')
136-
->willReturn([
137-
'transaction' => [
138-
'transactionStatus' => 'somethingIsWrong'
206+
->willReturn(
207+
[
208+
'transaction' => [
209+
'transactionStatus' => 'somethingIsWrong'
210+
]
139211
]
140-
]);
212+
);
141213

142214
$buildSubject = [
143215
'foo' => '123'

app/code/Magento/AuthorizenetAcceptjs/etc/config.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<can_capture_partial>0</can_capture_partial>
2525
<can_authorize>1</can_authorize>
2626
<can_refund>1</can_refund>
27+
<can_refund_partial_per_invoice>1</can_refund_partial_per_invoice>
2728
<can_capture>1</can_capture>
2829
<can_void>1</can_void>
2930
<can_accept_payment>1</can_accept_payment>

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,7 @@
206206
<arguments>
207207
<argument name="handlers" xsi:type="array">
208208
<item name="transaction_id" xsi:type="string">Magento\AuthorizenetAcceptjs\Gateway\Response\TransactionIdHandler</item>
209-
<item name="close_parent_transaction" xsi:type="string">Magento\AuthorizenetAcceptjs\Gateway\Response\CloseParentTransactionHandler</item>
210-
<item name="close_transaction" xsi:type="string">Magento\AuthorizenetAcceptjs\Gateway\Response\CloseTransactionHandler</item>
209+
<item name="close_transaction" xsi:type="string">Magento\AuthorizenetAcceptjs\Gateway\Response\ClosePartialTransactionHandler</item>
211210
</argument>
212211
</arguments>
213212
</virtualType>

app/code/Magento/AuthorizenetAcceptjs/i18n/en_US.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ Authorize.net,Authorize.net
1919
"ccLast4","Last 4 Digits of Card"
2020
"There was an error while trying to process the refund.","There was an error while trying to process the refund."
2121
"This transaction cannot be refunded with its current status.","This transaction cannot be refunded with its current status."
22+
"The transaction has not been settled, a partial refund is not yet available.","The transaction has not been settled, a partial refund is not yet available."

app/code/Magento/Braintree/Observer/AddPaypalShortcuts.php

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,27 @@
1515
class AddPaypalShortcuts implements ObserverInterface
1616
{
1717
/**
18-
* Block class
18+
* Alias for mini-cart block.
1919
*/
20-
const PAYPAL_SHORTCUT_BLOCK = \Magento\Braintree\Block\Paypal\Button::class;
20+
private const PAYPAL_MINICART_ALIAS = 'mini_cart';
21+
22+
/**
23+
* Alias for shopping cart page.
24+
*/
25+
private const PAYPAL_SHOPPINGCART_ALIAS = 'shopping_cart';
26+
27+
/**
28+
* @var string[]
29+
*/
30+
private $buttonBlocks;
31+
32+
/**
33+
* @param string[] $buttonBlocks
34+
*/
35+
public function __construct(array $buttonBlocks = [])
36+
{
37+
$this->buttonBlocks = $buttonBlocks;
38+
}
2139

2240
/**
2341
* Add Braintree PayPal shortcut buttons
@@ -35,7 +53,13 @@ public function execute(Observer $observer)
3553
/** @var ShortcutButtons $shortcutButtons */
3654
$shortcutButtons = $observer->getEvent()->getContainer();
3755

38-
$shortcut = $shortcutButtons->getLayout()->createBlock(self::PAYPAL_SHORTCUT_BLOCK);
56+
if ($observer->getData('is_shopping_cart')) {
57+
$shortcut = $shortcutButtons->getLayout()
58+
->createBlock($this->buttonBlocks[self::PAYPAL_SHOPPINGCART_ALIAS]);
59+
} else {
60+
$shortcut = $shortcutButtons->getLayout()
61+
->createBlock($this->buttonBlocks[self::PAYPAL_MINICART_ALIAS]);
62+
}
3963

4064
$shortcutButtons->addShortcut($shortcut);
4165
}

app/code/Magento/Braintree/Test/Unit/Observer/AddPaypalShortcutsTest.php

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,17 @@
1919
*/
2020
class AddPaypalShortcutsTest extends \PHPUnit\Framework\TestCase
2121
{
22+
/**
23+
* Tests PayPal shortcuts observer.
24+
*/
2225
public function testExecute()
2326
{
24-
$addPaypalShortcuts = new AddPaypalShortcuts();
27+
$addPaypalShortcuts = new AddPaypalShortcuts(
28+
[
29+
'mini_cart' => 'Minicart-block',
30+
'shopping_cart' => 'Shoppingcart-block'
31+
]
32+
);
2533

2634
/** @var Observer|\PHPUnit_Framework_MockObject_MockObject $observerMock */
2735
$observerMock = $this->getMockBuilder(Observer::class)
@@ -60,7 +68,7 @@ public function testExecute()
6068

6169
$layoutMock->expects(self::once())
6270
->method('createBlock')
63-
->with(AddPaypalShortcuts::PAYPAL_SHORTCUT_BLOCK)
71+
->with('Minicart-block')
6472
->willReturn($blockMock);
6573

6674
$shortcutButtonsMock->expects(self::once())

app/code/Magento/Braintree/etc/frontend/di.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,23 @@
5555
<argument name="payment" xsi:type="object">BraintreePayPalFacade</argument>
5656
</arguments>
5757
</type>
58+
<virtualType name="Magento\Braintree\Block\Paypal\ButtonShoppingCartVirtual" type="Magento\Braintree\Block\Paypal\Button">
59+
<arguments>
60+
<argument name="data" xsi:type="array">
61+
<item name="template" xsi:type="string">Magento_Braintree::paypal/button_shopping_cart.phtml</item>
62+
<item name="alias" xsi:type="string">braintree.paypal.mini-cart</item>
63+
<item name="button_id" xsi:type="string">braintree-paypal-mini-cart</item>
64+
</argument>
65+
</arguments>
66+
</virtualType>
67+
<type name="Magento\Braintree\Observer\AddPaypalShortcuts">
68+
<arguments>
69+
<argument name="buttonBlocks" xsi:type="array">
70+
<item name="mini_cart" xsi:type="string">Magento\Braintree\Block\Paypal\Button</item>
71+
<item name="shopping_cart" xsi:type="string">Magento\Braintree\Block\Paypal\ButtonShoppingCartVirtual</item>
72+
</argument>
73+
</arguments>
74+
</type>
5875

5976
<type name="Magento\Braintree\Model\Ui\PayPal\ConfigProvider">
6077
<arguments>

0 commit comments

Comments
 (0)