Skip to content

Commit 1c3e953

Browse files
committed
MC-38717: Sales emails asynchronous sending sends out old emails
1 parent 26acabe commit 1c3e953

File tree

2 files changed

+105
-11
lines changed

2 files changed

+105
-11
lines changed

app/code/Magento/Sales/Model/EmailSenderHandler.php

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55
*/
66
namespace Magento\Sales\Model;
77

8+
use Magento\Framework\App\Config\ValueFactory;
9+
use Magento\Framework\App\Config\ValueInterface;
10+
use Magento\Framework\App\ObjectManager;
11+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
812
use Magento\Sales\Model\Order\Email\Container\IdentityInterface;
913

1014
/**
@@ -53,32 +57,50 @@ class EmailSenderHandler
5357
*/
5458
private $storeManager;
5559

60+
/**
61+
* Config data factory
62+
*
63+
* @var ValueFactory
64+
*/
65+
private $configValueFactory;
66+
67+
/**
68+
* @var TimezoneInterface
69+
*/
70+
private $localeDate;
71+
5672
/**
5773
* @param \Magento\Sales\Model\Order\Email\Sender $emailSender
5874
* @param \Magento\Sales\Model\ResourceModel\EntityAbstract $entityResource
5975
* @param \Magento\Sales\Model\ResourceModel\Collection\AbstractCollection $entityCollection
6076
* @param \Magento\Framework\App\Config\ScopeConfigInterface $globalConfig
6177
* @param IdentityInterface|null $identityContainer
62-
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
63-
* @throws \InvalidArgumentException
78+
* @param \Magento\Store\Model\StoreManagerInterface|null $storeManager
79+
* @param ValueFactory|null $configValueFactory
80+
* @param TimezoneInterface|null $localeDate
6481
*/
6582
public function __construct(
6683
\Magento\Sales\Model\Order\Email\Sender $emailSender,
6784
\Magento\Sales\Model\ResourceModel\EntityAbstract $entityResource,
6885
\Magento\Sales\Model\ResourceModel\Collection\AbstractCollection $entityCollection,
6986
\Magento\Framework\App\Config\ScopeConfigInterface $globalConfig,
7087
IdentityInterface $identityContainer = null,
71-
\Magento\Store\Model\StoreManagerInterface $storeManager = null
88+
\Magento\Store\Model\StoreManagerInterface $storeManager = null,
89+
?ValueFactory $configValueFactory = null,
90+
?TimezoneInterface $localeDate = null
7291
) {
7392
$this->emailSender = $emailSender;
7493
$this->entityResource = $entityResource;
7594
$this->entityCollection = $entityCollection;
7695
$this->globalConfig = $globalConfig;
7796

78-
$this->identityContainer = $identityContainer ?: \Magento\Framework\App\ObjectManager::getInstance()
97+
$this->identityContainer = $identityContainer ?: ObjectManager::getInstance()
7998
->get(\Magento\Sales\Model\Order\Email\Container\NullIdentity::class);
80-
$this->storeManager = $storeManager ?: \Magento\Framework\App\ObjectManager::getInstance()
99+
$this->storeManager = $storeManager ?: ObjectManager::getInstance()
81100
->get(\Magento\Store\Model\StoreManagerInterface::class);
101+
102+
$this->configValueFactory = $configValueFactory ?: ObjectManager::getInstance()->get(ValueFactory::class);
103+
$this->localeDate = $localeDate ?: ObjectManager::getInstance()->get(TimezoneInterface::class);
82104
}
83105

84106
/**
@@ -90,6 +112,8 @@ public function sendEmails()
90112
if ($this->globalConfig->getValue('sales_email/general/async_sending')) {
91113
$this->entityCollection->addFieldToFilter('send_email', ['eq' => 1]);
92114
$this->entityCollection->addFieldToFilter('email_sent', ['null' => true]);
115+
$startFromDate = $this->getStartFromDate();
116+
$this->entityCollection->addFieldToFilter('created_at', ['from' => $startFromDate]);
93117
$this->entityCollection->setPageSize(
94118
$this->globalConfig->getValue('sales_email/general/sending_limit')
95119
);
@@ -140,4 +164,24 @@ private function getStores(
140164

141165
return $stores;
142166
}
167+
168+
/**
169+
* Get start from date for collection filter
170+
*
171+
* @return string
172+
*/
173+
private function getStartFromDate(): string
174+
{
175+
$fromDate = $this->localeDate->date()->format('Y-m-d H:i:s');
176+
/** @var $configValue ValueInterface */
177+
$configValue = $this->configValueFactory->create();
178+
$configValue->load('sales_email/general/async_sending', 'path');
179+
180+
if ($configValue->getId()) {
181+
$fromDate = $this->localeDate->date($configValue->getUpdatedAt())
182+
->modify('-1 day')->format('Y-m-d H:i:s');
183+
}
184+
185+
return $fromDate;
186+
}
143187
}

app/code/Magento/Sales/Test/Unit/Model/EmailSenderHandlerTest.php

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77

88
namespace Magento\Sales\Test\Unit\Model;
99

10+
use Magento\Config\Model\Config\Backend\Encrypted;
1011
use Magento\Framework\App\Config;
12+
use Magento\Framework\App\Config\Value;
13+
use Magento\Framework\App\Config\ValueFactory;
1114
use Magento\Framework\DB\Select;
15+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
1216
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1317
use Magento\Sales\Model\AbstractModel;
1418
use Magento\Sales\Model\EmailSenderHandler;
@@ -71,6 +75,16 @@ class EmailSenderHandlerTest extends TestCase
7175
*/
7276
private $storeManagerMock;
7377

78+
/**
79+
* @var ValueFactory|MockObject
80+
*/
81+
private $configValueFactory;
82+
83+
/**
84+
* @var TimezoneInterface|MockObject
85+
*/
86+
private $localeDate;
87+
7488
protected function setUp(): void
7589
{
7690
$objectManager = new ObjectManager($this);
@@ -110,15 +124,25 @@ protected function setUp(): void
110124
StoreManagerInterface::class
111125
);
112126

127+
$this->configValueFactory = $this->createMock(
128+
ValueFactory::class
129+
);
130+
131+
$this->localeDate = $this->createMock(
132+
TimezoneInterface::class
133+
);
134+
113135
$this->object = $objectManager->getObject(
114136
EmailSenderHandler::class,
115137
[
116-
'emailSender' => $this->emailSender,
117-
'entityResource' => $this->entityResource,
118-
'entityCollection' => $this->entityCollection,
119-
'globalConfig' => $this->globalConfig,
120-
'identityContainer' => $this->identityContainerMock,
121-
'storeManager' => $this->storeManagerMock,
138+
'emailSender' => $this->emailSender,
139+
'entityResource' => $this->entityResource,
140+
'entityCollection' => $this->entityCollection,
141+
'globalConfig' => $this->globalConfig,
142+
'identityContainer' => $this->identityContainerMock,
143+
'storeManager' => $this->storeManagerMock,
144+
'configValueFactory' => $this->configValueFactory,
145+
'localeDate' => $this->localeDate,
122146
]
123147
);
124148
}
@@ -151,6 +175,14 @@ public function testExecute($configValue, $collectionItems, $emailSendingResult)
151175
->method('addFieldToFilter')
152176
->with('email_sent', ['null' => true]);
153177

178+
$dateTime = new \DateTime();
179+
$nowDate = $dateTime->format('Y-m-d H:i:s');
180+
$fromDate = $dateTime->modify('-1 day')->format('Y-m-d H:i:s');
181+
$this->entityCollection
182+
->expects($this->at(2))
183+
->method('addFieldToFilter')
184+
->with('created_at', ['from' => $fromDate]);
185+
154186
$this->entityCollection
155187
->expects($this->any())
156188
->method('addAttributeToSelect')
@@ -175,6 +207,24 @@ public function testExecute($configValue, $collectionItems, $emailSendingResult)
175207
->method('getItems')
176208
->willReturn($collectionItems);
177209

210+
/** @var Value|Encrypted|MockObject $valueMock */
211+
$backendModelMock = $this->getMockBuilder(Value::class)
212+
->disableOriginalConstructor()
213+
->onlyMethods(['load', 'getId'])
214+
->addMethods(['getUpdatedAt'])
215+
->getMock();
216+
$backendModelMock->expects($this->once())->method('load')->willReturnSelf();
217+
$backendModelMock->expects($this->once())->method('getId')->willReturn(1);
218+
$backendModelMock->expects($this->once())->method('getUpdatedAt')->willReturn($nowDate);
219+
220+
$this->configValueFactory->expects($this->once())
221+
->method('create')
222+
->willReturn($backendModelMock);
223+
224+
$this->localeDate->expects($this->exactly(2))
225+
->method('date')
226+
->willReturn(new \DateTime($nowDate));
227+
178228
if ($collectionItems) {
179229

180230
/** @var AbstractModel|MockObject $collectionItem */

0 commit comments

Comments
 (0)