From e8a4ae451a7efd027f187f1baabb03220309d927 Mon Sep 17 00:00:00 2001 From: KrasnoshchokBohdan Date: Thu, 8 May 2025 15:32:50 +0300 Subject: [PATCH 1/4] magento/magento2#39861: Shipment email not sent when submitted from Admin Order view despite being enabled in store configuration - adding storeId to canSendNewShipmentEmail method --- .../Shipping/Controller/Adminhtml/Order/Shipment/Save.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php index 122ae505498ae..04757e22abfae 100644 --- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php +++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php @@ -167,7 +167,8 @@ public function execute() $this->_saveShipment($shipment); - if (!empty($data['send_email']) && $this->salesData->canSendNewShipmentEmail()) { + if (!empty($data['send_email']) + && $this->salesData->canSendNewShipmentEmail($shipment->getOrder()->getStoreId())) { $this->shipmentSender->send($shipment); } From 97239feccdf2066d81ff173384addf6536646089 Mon Sep 17 00:00:00 2001 From: KrasnoshchokBohdan Date: Thu, 8 May 2025 19:11:54 +0300 Subject: [PATCH 2/4] magento/magento2#39861: Shipment email not sent when submitted from Admin Order view despite being enabled in store configuration - copyright --- .../Shipping/Controller/Adminhtml/Order/Shipment/Save.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php index 04757e22abfae..0d871ac86ae79 100644 --- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php +++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php @@ -1,7 +1,7 @@ Date: Mon, 26 May 2025 12:03:39 +0300 Subject: [PATCH 3/4] Update Save.php add comment --- .../Shipping/Controller/Adminhtml/Order/Shipment/Save.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php index 0d871ac86ae79..4e279aaf04939 100644 --- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php +++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/Shipment/Save.php @@ -167,6 +167,7 @@ public function execute() $this->_saveShipment($shipment); + // Pass the specific store ID from the order to check if shipment emails are enabled for that store if (!empty($data['send_email']) && $this->salesData->canSendNewShipmentEmail($shipment->getOrder()->getStoreId())) { $this->shipmentSender->send($shipment); From cbfe66a5a076028e33e98a79dfe113358b5a1c51 Mon Sep 17 00:00:00 2001 From: KrasnoshchokBohdan Date: Sat, 5 Jul 2025 09:57:02 +0300 Subject: [PATCH 4/4] magento/magento2#39861: Shipment email not sent when submitted from Admin Order view despite being enabled in store configuration - Add unit tests for shipment email sending with store-specific logic --- .../Adminhtml/Order/Shipment/SaveTest.php | 182 +++++++++++++++++- 1 file changed, 174 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/Shipment/SaveTest.php b/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/Shipment/SaveTest.php index 7830a4e989848..6f00e88b177f2 100644 --- a/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/Shipment/SaveTest.php +++ b/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/Shipment/SaveTest.php @@ -1,7 +1,7 @@ formKeyValidator->expects($this->once()) + ->method('validate') + ->willReturn(true); + + $this->request->expects($this->once()) + ->method('isPost') + ->willReturn(true); + + $shipmentId = 1000012; + $orderId = 10003; + $shipmentData = ['items' => [], 'send_email' => $sendEmailRequested ? 'on' : '']; + + $this->request->expects($this->any()) + ->method('getParam') + ->willReturnMap([ + ['order_id', null, $orderId], + ['shipment_id', null, $shipmentId], + ['shipment', null, $shipmentData], + ['tracking', null, []] + ]); + + $order = $this->createPartialMock(Order::class, ['setCustomerNoteNotify', 'getStoreId', '__wakeup']); + $order->expects($this->any()) + ->method('getStoreId') + ->willReturn($storeId); + + $shipment = $this->createPartialMock( + Shipment::class, + ['load', 'save', 'register', 'getOrder', 'getOrderId', '__wakeup'] + ); + $shipment->expects($this->any()) + ->method('getOrder') + ->willReturn($order); + $shipment->expects($this->any()) + ->method('getOrderId') + ->willReturn($orderId); + + if ($sendEmailRequested) { + $this->salesData->expects($this->once()) + ->method('canSendNewShipmentEmail') + ->with($storeId) + ->willReturn($emailEnabledForStore); + } else { + $this->salesData->expects($this->never()) + ->method('canSendNewShipmentEmail'); + } + + if ($shouldSendEmail) { + $this->shipmentSender->expects($this->once()) + ->method('send') + ->with($shipment); + } else { + $this->shipmentSender->expects($this->never()) + ->method('send'); + } + + $this->shipmentLoader->expects($this->once()) + ->method('load') + ->willReturn($shipment); + + $this->setupCommonMocks($shipment, $order, $orderId); + + $this->saveAction->execute(); + } + + /** + * Test that email is not sent when disabled for specific store but enabled globally + */ + public function testEmailNotSentWhenDisabledForSpecificStore(): void + { + $storeId = 2; + $this->testCanSendNewShipmentEmailWithStoreId( + $storeId, + true, + false, + false + ); + } + + /** + * Test that email is sent when enabled for specific store even if disabled globally + */ + public function testEmailSentWhenEnabledForSpecificStore(): void + { + $storeId = 2; + $this->testCanSendNewShipmentEmailWithStoreId( + $storeId, + true, + true, + true + ); + } + + /** + * @return array + */ + public static function storeIdDataProvider(): array + { + return [ + 'default_store_email_requested_enabled' => [1, true, true, true], + 'default_store_email_requested_disabled' => [1, true, false, false], + 'custom_store_email_requested_enabled' => [2, true, true, true], + 'custom_store_email_requested_disabled' => [2, true, false, false], + 'custom_store_email_not_requested' => [2, false, true, false], + 'multistore_environment_store_3' => [3, true, true, true], + 'multistore_environment_store_5_disabled' => [5, true, false, false], + ]; + } + /** * @return array */ public static function executeDataProvider(): array { /** - * bool $formKeyIsValid - * bool $isPost - * string $sendEmail - * bool $emailEnabled - * bool $shouldEmailBeSent - */ + * bool $formKeyIsValid + * bool $isPost + * string $sendEmail + * bool $emailEnabled + * bool $shouldEmailBeSent + */ return [ [false, false, '', false, false], [true, false, '', false, false], @@ -409,6 +529,52 @@ public static function executeDataProvider(): array ]; } + /** + * Setup common mocks needed for successful execution + */ + private function setupCommonMocks(MockObject $shipment, MockObject $order, int $orderId): void + { + $shipment->expects($this->once()) + ->method('register') + ->willReturnSelf(); + + $order->expects($this->once()) + ->method('setCustomerNoteNotify'); + + $this->labelGenerator->expects($this->any()) + ->method('create') + ->willReturn(true); + + $saveTransaction = $this->getMockBuilder(Transaction::class) + ->disableOriginalConstructor() + ->getMock(); + $saveTransaction->method('addObject')->willReturnSelf(); + + $this->objectManager->expects($this->once()) + ->method('create') + ->with(Transaction::class) + ->willReturn($saveTransaction); + + $this->objectManager->expects($this->once()) + ->method('get') + ->with(Session::class) + ->willReturn($this->session); + + $this->session->expects($this->once()) + ->method('getCommentText') + ->with(true); + + $this->shipmentValidatorMock->expects($this->once()) + ->method('validate') + ->willReturn($this->validationResult); + + $this->validationResult->expects($this->once()) + ->method('hasMessages') + ->willReturn(false); + + $this->prepareRedirect(['order_id' => $orderId]); + } + /** * @param array $arguments *