Skip to content

Issue-33519. Added logic for grouping alerts by store #35996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
312b288
Issue-33519. Added logic for grouping alerts by store
topanok Aug 22, 2022
d5fca9f
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Aug 22, 2022
4856232
Issue-33519. Remove Cyclomatic Complexity
topanok Aug 29, 2022
e06aa7c
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Aug 29, 2022
f56b742
Issue-33519. Remove Cyclomatic Complexity(v2)
topanok Aug 29, 2022
e668165
Issue-35789. Static test fixes
topanok Aug 29, 2022
32f86c2
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Sep 18, 2022
83f0a95
Issue-35789. Added @SuppressWarnings(PHPMD.CouplingBetweenObjects) cl…
topanok Sep 18, 2022
b80184f
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Sep 21, 2022
e1c5714
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Nov 9, 2022
98bdc54
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Dec 6, 2022
f96039a
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Dec 11, 2022
b31aba5
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Dec 13, 2022
de36fec
Merge remote-tracking branch 'origin/2.4-develop' into fix-for-issue-…
topanok Jan 12, 2023
53ec371
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Jan 20, 2023
381bca3
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Jan 24, 2023
310e085
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Jan 31, 2023
567b794
Merge remote-tracking branch 'origin/2.4-develop' into fix-for-issue-…
topanok Feb 9, 2023
0a71fd7
Issue-33519 Fix user soumah's long line
topanok Feb 10, 2023
c7217f6
Issue-33519 Move argument to next line
topanok Feb 14, 2023
fc61c9a
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Feb 14, 2023
c2db279
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Feb 25, 2023
de8ce8f
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Mar 15, 2023
11afdf1
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Mar 20, 2023
6a925b6
Merge branch '2.4-develop' into fix-for-issue-33519
engcom-Hotel May 15, 2023
feedd13
Merge branch '2.4-develop' into fix-for-issue-33519
engcom-Hotel Jun 28, 2023
80acc6c
Issue-33519 Automatic tests
topanok Jul 3, 2023
9693ac3
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Jul 3, 2023
2692fa5
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Oct 21, 2023
0e0598d
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Dec 11, 2023
fb21999
Merge branch '2.4-develop' into fix-for-issue-33519
andrewbess Dec 26, 2023
86b5e61
Merge branch '2.4-develop' into fix-for-issue-33519
engcom-Hotel Feb 6, 2024
5288548
Added return type to function
engcom-Echo Feb 13, 2024
8d1dc5b
Merge branch '2.4-develop' into fix-for-issue-33519
engcom-Hotel Feb 14, 2024
2aa445e
Merge branch '2.4-develop' into fix-for-issue-33519
topanok Mar 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 86 additions & 35 deletions app/code/Magento/ProductAlert/Model/Mailing/AlertProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,44 +165,45 @@ private function processAlerts(string $alertType, array $customerIds, int $websi
$defaultStoreId = $website->getDefaultStore()->getId();
$products = [];

/** @var Price|Stock $alert */
foreach ($collection as $alert) {
try {
if ($alert->getStoreId()) {
$email->setStoreId($alert->getStoreId());
$groupedByStore = $this->groupAlertsByStore($collection, (int)$defaultStoreId);

foreach ($groupedByStore as $storeId => $alerts) {
$email->setStoreId($storeId);

/** @var Price|Stock $alert */
foreach ($alerts as $alert) {
try {
if ($customer === null) {
$customer = $this->customerRepository->getById($alert->getCustomerId());
} elseif ((int)$customer->getId() !== (int)$alert->getCustomerId()) {
$this->sendEmail($customer, $email);
$customer = $this->customerRepository->getById($alert->getCustomerId());
}

if (!isset($products[$alert->getProductId()])) {
$product = $this->productRepository->getById(
$alert->getProductId(),
false,
$defaultStoreId,
true
);
$products[$alert->getProductId()] = $product;
} else {
$product = $products[$alert->getProductId()];
}

$this->saveAlert($alertType, $alert, $product, $website, $customer, $email);
} catch (\Exception $e) {
$errors[] = $e->getMessage();
}
if ($customer === null) {
$customer = $this->customerRepository->getById($alert->getCustomerId());
} elseif ((int)$customer->getId() !== (int)$alert->getCustomerId()) {
$this->sendEmail($customer, $email);
$customer = $this->customerRepository->getById($alert->getCustomerId());
}

if (!isset($products[$alert->getProductId()])) {
$product = $this->productRepository->getById($alert->getProductId(), false, $defaultStoreId, true);
$products[$alert->getProductId()] = $product;
} else {
$product = $products[$alert->getProductId()];
}

switch ($alertType) {
case self::ALERT_TYPE_STOCK:
$this->saveStockAlert($alert, $product, $website, $email);
break;
case self::ALERT_TYPE_PRICE:
$this->savePriceAlert($alert, $product, $customer, $email);
break;
}
} catch (\Exception $e) {
$errors[] = $e->getMessage();
}
}

if ($customer !== null) {
try {
$this->sendEmail($customer, $email);
} catch (\Exception $e) {
$errors[] = $e->getMessage();
if ($customer !== null) {
try {
$this->sendEmail($customer, $email);
} catch (\Exception $e) {
$errors[] = $e->getMessage();
}
}
}

Expand Down Expand Up @@ -256,6 +257,56 @@ private function getAlertCollection(string $alertType, array $customerIds, int $
return $collection;
}

/**
* Prepare an array of alerts grouped by store ID
*
* @param AbstractCollection $collection
* @param int $defaultStoreId
* @return array
*/
private function groupAlertsByStore(AbstractCollection $collection, int $defaultStoreId): array
{
$groupedByStore = [];
foreach ($collection as $item) {
if ($storeId = $item->getStoreId()) {
$groupedByStore[$storeId][] = $item;
} else {
$groupedByStore[$defaultStoreId][] = $item;
}
}

return $groupedByStore;
}

/**
* Save alert by type
*
* @param string $alertType
* @param Stock|Price $alert
* @param ProductInterface $product
* @param WebsiteInterface $website
* @param CustomerInterface $customer
* @param Email $email
* @throws \Exception
*/
private function saveAlert(
string $alertType,
$alert,
ProductInterface $product,
WebsiteInterface $website,
CustomerInterface $customer,
Email $email
): void {
switch ($alertType) {
case self::ALERT_TYPE_STOCK:
$this->saveStockAlert($alert, $product, $website, $email);
break;
case self::ALERT_TYPE_PRICE:
$this->savePriceAlert($alert, $product, $customer, $email);
break;
}
}

/**
* Save Price Alert
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ class TransportInterfaceMock implements \Magento\Framework\Mail\TransportInterfa
*/
private $message;

/**
* @var int
*/
private static $sentMsgCount = 0;

/**
* TransportInterfaceMock constructor.
*
Expand All @@ -35,6 +40,7 @@ public function __construct($message = null)
*/
public function sendMessage()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can have a return type here as void maybe

Suggested change
public function sendMessage()
public function sendMessage() : void

{
self::$sentMsgCount++;
//phpcs:ignore Squiz.PHP.NonExecutableCode.ReturnNotRequired
return;
}
Expand All @@ -48,4 +54,25 @@ public function getMessage()
{
return $this->message;
}

/**
* Returns count of sent messages
*
* @return int
*/
public function getSentMsgCount(): int
{
return self::$sentMsgCount;
}

/**
* Reset amount of sent message
*
* @param int $count
* @return void
*/
public function resetSentMsgCount($count = 0): void
{
self::$sentMsgCount = $count;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
use Magento\Customer\Test\Fixture\Customer as CustomerFixture;
use Magento\Framework\Mail\EmailMessage;
use Magento\ProductAlert\Model\ResourceModel\Stock\CollectionFactory as StockCollectionFactory;
use Magento\ProductAlert\Test\Fixture\PriceAlert as PriceAlertFixture;
use Magento\ProductAlert\Test\Fixture\StockAlert as StockAlertFixture;
use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\Store;
use Magento\Store\Test\Fixture\Group as StoreGroupFixture;
Expand All @@ -26,6 +28,7 @@
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\Helper\Xpath;
use Magento\TestFramework\Mail\Template\TransportBuilderMock;
use Magento\TestFramework\Mail\TransportInterfaceMock;
use Magento\TestFramework\ObjectManager;
use Magento\Translation\Test\Fixture\Translation as TranslationFixture;
use PHPUnit\Framework\TestCase;
Expand All @@ -44,20 +47,25 @@ class AlertProcessorTest extends TestCase
private $objectManager;

/**
* @var Publisher
* @var AlertProcessor
*/
private $publisher;
private $alertProcessor;

/**
* @var AlertProcessor
* @var StockCollectionFactory
*/
private $alertProcessor;
private $stockCollectionFactory;

/**
* @var TransportBuilderMock
*/
private $transportBuilder;

/**
* @var TransportInterfaceMock
*/
private $transportInterface;

/**
* @var DataFixtureStorage
*/
Expand All @@ -69,8 +77,11 @@ class AlertProcessorTest extends TestCase
protected function setUp(): void
{
$this->objectManager = Bootstrap::getObjectManager();
$this->publisher = $this->objectManager->get(Publisher::class);
$this->alertProcessor = $this->objectManager->get(AlertProcessor::class);
$this->stockCollectionFactory = $this->objectManager->get(StockCollectionFactory::class);

$this->transportInterface = $this->objectManager->get(TransportInterfaceMock::class);
$this->transportInterface->resetSentMsgCount();

$this->transportBuilder = $this->objectManager->get(TransportBuilderMock::class);
$this->fixtures = DataFixtureStorageManager::getStorage();
Expand Down Expand Up @@ -243,6 +254,38 @@ public function testValidateCurrentTheme()
);
}

#[
DbIsolation(false),
Config('catalog/productalert/allow_stock', 1),
DataFixture(CustomerFixture::class, as: 'customer'),
DataFixture(ProductFixture::class, as: 'product'),
DataFixture(StoreFixture::class, ['store_group_id' => 1, 'code' => 'pt_br_store'], 'store2'),
DataFixture(
StockAlertFixture::class,
[
'customer_id' => '$customer.id$',
'product_id' => '$product.id$',
'website_id' => 1,
'store_id' => 1,
]
),
DataFixture(
StockAlertFixture::class,
[
'customer_id' => '$customer.id$',
'product_id' => '$product.id$',
'website_id' => 1,
'store_id' => '$store2.id$',
]
),
]
public function testCustomerShouldGetEmailForEveryStoreView()
{
$customerId = (int) $this->fixtures->get('customer')->getId();
$this->processAlerts($customerId, 1, AlertProcessor::ALERT_TYPE_STOCK);
$this->assertEquals(2, $this->transportInterface->getSentMsgCount());
}

/**
* @param int $customerId
* @param int $websiteId
Expand Down