Skip to content

Commit 6da65aa

Browse files
committed
Merge remote-tracking branch 'origin/imported-magento-magento2-32580' into 2.4-develop-pr137
2 parents b04f1d6 + 38d3756 commit 6da65aa

File tree

8 files changed

+323
-33
lines changed

8 files changed

+323
-33
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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\Quote\Observer;
9+
10+
use Magento\Framework\Event\Observer;
11+
use Magento\Framework\Event\ObserverInterface;
12+
use Magento\Quote\Model\Quote;
13+
use Magento\Sales\Model\Order;
14+
use Magento\Sales\Model\Order\Email\Container\InvoiceIdentity;
15+
use Magento\Sales\Model\Order\Email\Sender\InvoiceSender;
16+
use Psr\Log\LoggerInterface;
17+
18+
/**
19+
* Class responsive for sending invoice emails when order created through storefront.
20+
*/
21+
class SendInvoiceEmailObserver implements ObserverInterface
22+
{
23+
/**
24+
* @var LoggerInterface
25+
*/
26+
private $logger;
27+
28+
/**
29+
* @var InvoiceSender
30+
*/
31+
private $invoiceSender;
32+
33+
/**
34+
* @var InvoiceIdentity
35+
*/
36+
private $invoiceIdentity;
37+
38+
/**
39+
* @param LoggerInterface $logger
40+
* @param InvoiceSender $invoiceSender
41+
* @param InvoiceIdentity $invoiceIdentity
42+
*/
43+
public function __construct(
44+
LoggerInterface $logger,
45+
InvoiceSender $invoiceSender,
46+
InvoiceIdentity $invoiceIdentity
47+
) {
48+
$this->logger = $logger;
49+
$this->invoiceSender = $invoiceSender;
50+
$this->invoiceIdentity = $invoiceIdentity;
51+
}
52+
53+
/**
54+
* Send invoice email if allowed.
55+
*
56+
* @param Observer $observer
57+
*
58+
* @return void
59+
*/
60+
public function execute(Observer $observer)
61+
{
62+
if (!$this->isInvoiceEmailAllowed()) {
63+
return;
64+
}
65+
66+
/** @var Quote $quote */
67+
$quote = $observer->getEvent()->getQuote();
68+
/** @var Order $order */
69+
$order = $observer->getEvent()->getOrder();
70+
71+
/**
72+
* a flag to set that there will be redirect to third party after confirmation
73+
*/
74+
$redirectUrl = $quote->getPayment()->getOrderPlaceRedirectUrl();
75+
if (!$redirectUrl && $order->getCanSendNewEmailFlag()) {
76+
try {
77+
$invoice = current($order->getInvoiceCollection()->getItems());
78+
if ($invoice) {
79+
$this->invoiceSender->send($invoice);
80+
}
81+
} catch (\Throwable $e) {
82+
$this->logger->critical($e);
83+
}
84+
}
85+
}
86+
87+
/**
88+
* Is invoice email sending enabled
89+
*
90+
* @return bool
91+
*/
92+
private function isInvoiceEmailAllowed(): bool
93+
{
94+
return $this->invoiceIdentity->isEnabled();
95+
}
96+
}

app/code/Magento/Quote/Observer/SubmitObserver.php

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99
use Magento\Framework\Event\ObserverInterface;
1010
use Magento\Quote\Model\Quote;
1111
use Magento\Sales\Model\Order;
12-
use Magento\Sales\Model\Order\Email\Sender\InvoiceSender;
1312
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
1413
use Psr\Log\LoggerInterface;
1514

1615
/**
17-
* Class responsive for sending order and invoice emails when it's created through storefront.
16+
* Class responsive for sending order emails when it's created through storefront.
1817
*/
1918
class SubmitObserver implements ObserverInterface
2019
{
@@ -28,28 +27,20 @@ class SubmitObserver implements ObserverInterface
2827
*/
2928
private $orderSender;
3029

31-
/**
32-
* @var InvoiceSender
33-
*/
34-
private $invoiceSender;
35-
3630
/**
3731
* @param LoggerInterface $logger
3832
* @param OrderSender $orderSender
39-
* @param InvoiceSender $invoiceSender
4033
*/
4134
public function __construct(
4235
LoggerInterface $logger,
43-
OrderSender $orderSender,
44-
InvoiceSender $invoiceSender
36+
OrderSender $orderSender
4537
) {
4638
$this->logger = $logger;
4739
$this->orderSender = $orderSender;
48-
$this->invoiceSender = $invoiceSender;
4940
}
5041

5142
/**
52-
* Send order and invoice email.
43+
* Send order email.
5344
*
5445
* @param Observer $observer
5546
*
@@ -69,11 +60,7 @@ public function execute(Observer $observer)
6960
if (!$redirectUrl && $order->getCanSendNewEmailFlag()) {
7061
try {
7162
$this->orderSender->send($order);
72-
$invoice = current($order->getInvoiceCollection()->getItems());
73-
if ($invoice) {
74-
$this->invoiceSender->send($invoice);
75-
}
76-
} catch (\Exception $e) {
63+
} catch (\Throwable $e) {
7764
$this->logger->critical($e);
7865
}
7966
}
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
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\Quote\Test\Unit\Observer;
9+
10+
use Magento\Framework\Event;
11+
use Magento\Framework\Event\Observer;
12+
use Magento\Quote\Model\Quote;
13+
use Magento\Quote\Model\Quote\Payment;
14+
use Magento\Quote\Observer\SubmitObserver;
15+
use Magento\Sales\Model\Order;
16+
use Magento\Sales\Model\Order\Email\Sender\InvoiceSender;
17+
use Magento\Sales\Model\Order\Email\Sender\OrderSender;
18+
use Magento\Sales\Model\Order\Invoice;
19+
use Magento\Sales\Model\ResourceModel\Order\Invoice\Collection;
20+
use PHPUnit\Framework\MockObject\MockObject;
21+
use PHPUnit\Framework\TestCase;
22+
use Psr\Log\LoggerInterface;
23+
use Magento\Sales\Model\Order\Email\Container\InvoiceIdentity;
24+
use Magento\Quote\Observer\SendInvoiceEmailObserver;
25+
26+
/**
27+
* Test for sending invoice email during order place on frontend
28+
*
29+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
30+
*/
31+
class SendInvoiceEmailObserverTest extends TestCase
32+
{
33+
/**
34+
* @var SendInvoiceEmailObserver
35+
*/
36+
private $model;
37+
38+
/**
39+
* @var LoggerInterface|MockObject
40+
*/
41+
private $loggerMock;
42+
43+
/**
44+
* @var InvoiceSender|MockObject
45+
*/
46+
private $invoiceSenderMock;
47+
48+
/**
49+
* @var InvoiceIdentity|MockObject
50+
*/
51+
private $invoiceIdentityMock;
52+
53+
/**
54+
* @var Observer|MockObject
55+
*/
56+
private $observerMock;
57+
58+
/**
59+
* @var Quote|MockObject
60+
*/
61+
private $quoteMock;
62+
63+
/**
64+
* @var Order|MockObject
65+
*/
66+
private $orderMock;
67+
68+
/**
69+
* @var Payment|MockObject
70+
*/
71+
private $paymentMock;
72+
73+
/**
74+
* @inheirtDoc
75+
*/
76+
protected function setUp(): void
77+
{
78+
$this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
79+
$this->quoteMock = $this->createMock(Quote::class);
80+
$this->orderMock = $this->createMock(Order::class);
81+
$this->paymentMock = $this->createMock(Payment::class);
82+
$this->invoiceSenderMock = $this->createMock(InvoiceSender::class);
83+
$this->invoiceIdentityMock = $this->getMockBuilder(InvoiceIdentity::class)
84+
->disableOriginalConstructor()
85+
->setMethods(['isEnabled'])
86+
->getMock();
87+
$eventMock = $this->getMockBuilder(Event::class)
88+
->disableOriginalConstructor()
89+
->setMethods(['getQuote', 'getOrder'])
90+
->getMock();
91+
$this->observerMock = $this->createPartialMock(Observer::class, ['getEvent']);
92+
$this->observerMock->expects($this->any())->method('getEvent')->willReturn($eventMock);
93+
$eventMock->expects($this->any())->method('getQuote')->willReturn($this->quoteMock);
94+
$eventMock->expects($this->any())->method('getOrder')->willReturn($this->orderMock);
95+
$this->quoteMock->expects($this->any())->method('getPayment')->willReturn($this->paymentMock);
96+
$this->model = new SendInvoiceEmailObserver(
97+
$this->loggerMock,
98+
$this->invoiceSenderMock,
99+
$this->invoiceIdentityMock
100+
);
101+
}
102+
103+
/**
104+
* Tests successful email sending.
105+
*/
106+
public function testSendEmail()
107+
{
108+
$this->invoiceIdentityMock
109+
->expects($this->once())
110+
->method('isEnabled')
111+
->willReturn(true);
112+
113+
$this->paymentMock->method('getOrderPlaceRedirectUrl')->willReturn('');
114+
115+
$invoice = $this->createMock(Invoice::class);
116+
$invoiceCollection = $this->createMock(Collection::class);
117+
$invoiceCollection->method('getItems')
118+
->willReturn([$invoice]);
119+
$this->orderMock->method('getInvoiceCollection')
120+
->willReturn($invoiceCollection);
121+
$this->quoteMock
122+
->expects($this->any())
123+
->method('getPayment')
124+
->willReturn($this->paymentMock);
125+
126+
$this->orderMock->method('getCanSendNewEmailFlag')->willReturn(true);
127+
$this->invoiceSenderMock->expects($this->once())
128+
->method('send')
129+
->with($invoice)
130+
->willReturn(true);
131+
$this->loggerMock->expects($this->never())
132+
->method('critical');
133+
134+
$this->model->execute($this->observerMock);
135+
}
136+
137+
/**
138+
* Tests email sending disabled by configuration.
139+
*/
140+
public function testSendEmailDisabled()
141+
{
142+
$this->invoiceIdentityMock
143+
->expects($this->once())
144+
->method('isEnabled')
145+
->willReturn(false);
146+
147+
$this->paymentMock
148+
->expects($this->never())
149+
->method('getOrderPlaceRedirectUrl');
150+
$this->orderMock
151+
->expects($this->never())
152+
->method('getInvoiceCollection');
153+
154+
$this->quoteMock
155+
->expects($this->never())
156+
->method('getPayment');
157+
158+
$this->orderMock
159+
->expects($this->never())
160+
->method('getCanSendNewEmailFlag');
161+
$this->loggerMock->expects($this->never())
162+
->method('critical');
163+
164+
$this->model->execute($this->observerMock);
165+
}
166+
167+
/**
168+
* Tests failing email sending.
169+
*/
170+
public function testFailToSendEmail()
171+
{
172+
$this->invoiceIdentityMock
173+
->expects($this->once())
174+
->method('isEnabled')
175+
->willReturn(true);
176+
$this->paymentMock->expects($this->once())->method('getOrderPlaceRedirectUrl')->willReturn('');
177+
178+
$invoice = $this->createMock(Invoice::class);
179+
$invoiceCollection = $this->createMock(Collection::class);
180+
$invoiceCollection->method('getItems')
181+
->willReturn([$invoice]);
182+
$this->orderMock->method('getInvoiceCollection')
183+
->willReturn($invoiceCollection);
184+
185+
$this->orderMock->expects($this->once())->method('getCanSendNewEmailFlag')->willReturn(true);
186+
$this->invoiceSenderMock->expects($this->once())->method('send')->willThrowException(
187+
new \Exception('Some email sending Error')
188+
);
189+
$this->loggerMock->expects($this->once())->method('critical');
190+
$this->model->execute($this->observerMock);
191+
}
192+
193+
/**
194+
* Tests send email when redirect.
195+
*/
196+
public function testSendEmailWhenRedirectUrlExists()
197+
{
198+
$this->invoiceIdentityMock
199+
->expects($this->once())
200+
->method('isEnabled')
201+
->willReturn(true);
202+
203+
$this->paymentMock->expects($this->once())->method('getOrderPlaceRedirectUrl')->willReturn(false);
204+
$this->orderMock->expects($this->once())->method('getCanSendNewEmailFlag');
205+
$this->invoiceSenderMock->expects($this->never())->method('send');
206+
$this->loggerMock->expects($this->never())->method('critical');
207+
$this->model->execute($this->observerMock);
208+
}
209+
}

0 commit comments

Comments
 (0)