Skip to content

Commit 6bf3dfc

Browse files
#29549: Scheduled price rule time zone correction - refactoring.
1 parent d9a0f6f commit 6bf3dfc

File tree

1 file changed

+124
-5
lines changed

1 file changed

+124
-5
lines changed

app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php

Lines changed: 124 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use Magento\Catalog\Model\Product;
1010
use Magento\Catalog\Model\ProductFactory;
1111
use Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher;
12+
use Magento\CatalogRule\Model\Indexer\IndexBuilder\ProductLoader;
13+
use Magento\CatalogRule\Model\Indexer\IndexerTableSwapperInterface as TableSwapper;
1214
use Magento\CatalogRule\Model\ResourceModel\Rule\Collection as RuleCollection;
1315
use Magento\CatalogRule\Model\ResourceModel\Rule\CollectionFactory as RuleCollectionFactory;
1416
use Magento\CatalogRule\Model\Rule;
@@ -17,9 +19,9 @@
1719
use Magento\Framework\App\ResourceConnection;
1820
use Magento\Framework\Exception\LocalizedException;
1921
use Magento\Framework\Pricing\PriceCurrencyInterface;
20-
use Magento\CatalogRule\Model\Indexer\IndexBuilder\ProductLoader;
21-
use Magento\CatalogRule\Model\Indexer\IndexerTableSwapperInterface as TableSwapper;
2222
use Magento\Framework\Stdlib\DateTime;
23+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
24+
use Magento\Store\Model\ScopeInterface;
2325
use Magento\Store\Model\StoreManagerInterface;
2426
use Psr\Log\LoggerInterface;
2527

@@ -143,11 +145,26 @@ class IndexBuilder
143145
*/
144146
private $pricesPersistor;
145147

148+
/**
149+
* @var TimezoneInterface|mixed
150+
*/
151+
private $localeDate;
152+
153+
/**
154+
* @var ActiveTableSwitcher|mixed
155+
*/
156+
private $activeTableSwitcher;
157+
146158
/**
147159
* @var TableSwapper
148160
*/
149161
private $tableSwapper;
150162

163+
/**
164+
* @var ProductLoader|mixed
165+
*/
166+
private $productLoader;
167+
151168
/**
152169
* @param RuleCollectionFactory $ruleCollectionFactory
153170
* @param PriceCurrencyInterface $priceCurrency
@@ -168,6 +185,7 @@ class IndexBuilder
168185
* @param ActiveTableSwitcher|null $activeTableSwitcher
169186
* @param ProductLoader|null $productLoader
170187
* @param TableSwapper|null $tableSwapper
188+
* @param TimezoneInterface|null $localeDate
171189
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
172190
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
173191
*/
@@ -190,7 +208,8 @@ public function __construct(
190208
RuleProductPricesPersistor $pricesPersistor = null,
191209
ActiveTableSwitcher $activeTableSwitcher = null,
192210
ProductLoader $productLoader = null,
193-
TableSwapper $tableSwapper = null
211+
TableSwapper $tableSwapper = null,
212+
TimezoneInterface $localeDate = null
194213
) {
195214
$this->resource = $resource;
196215
$this->connection = $resource->getConnection();
@@ -222,8 +241,16 @@ public function __construct(
222241
$this->pricesPersistor = $pricesPersistor ?? ObjectManager::getInstance()->get(
223242
RuleProductPricesPersistor::class
224243
);
244+
$this->activeTableSwitcher = $activeTableSwitcher ?? ObjectManager::getInstance()->get(
245+
ActiveTableSwitcher::class
246+
);
247+
$this->productLoader = $productLoader ?? ObjectManager::getInstance()->get(
248+
ProductLoader::class
249+
);
225250
$this->tableSwapper = $tableSwapper ??
226251
ObjectManager::getInstance()->get(TableSwapper::class);
252+
$this->localeDate = $localeDate ??
253+
ObjectManager::getInstance()->get(TimezoneInterface::class);
227254
}
228255

229256
/**
@@ -237,11 +264,19 @@ public function __construct(
237264
public function reindexById($id)
238265
{
239266
try {
240-
$this->doReindexByIds([$id]);
267+
$this->cleanProductIndex([$id]);
268+
269+
$products = $this->productLoader->getProducts([$id]);
270+
$activeRules = $this->getActiveRules();
271+
foreach ($products as $product) {
272+
$this->applyRules($activeRules, $product);
273+
}
274+
275+
$this->reindexRuleGroupWebsite->execute();
241276
} catch (\Exception $e) {
242277
$this->critical($e);
243278
throw new LocalizedException(
244-
__("Catalog rule indexing failed. See details in exception log.")
279+
__('Catalog rule indexing failed. See details in exception log.')
245280
);
246281
}
247282
}
@@ -369,6 +404,68 @@ protected function cleanByIds($productIds)
369404
$this->cleanProductPriceIndex($productIds);
370405
}
371406

407+
/**
408+
* Assign product to rule
409+
*
410+
* @param Rule $rule
411+
* @param int $productEntityId
412+
* @param array $websiteIds
413+
* @return void
414+
*/
415+
private function assignProductToRule(Rule $rule, int $productEntityId, array $websiteIds): void
416+
{
417+
$ruleId = (int) $rule->getId();
418+
$ruleProductTable = $this->getTable('catalogrule_product');
419+
$this->connection->delete(
420+
$ruleProductTable,
421+
[
422+
'rule_id = ?' => $ruleId,
423+
'product_id = ?' => $productEntityId,
424+
]
425+
);
426+
427+
$customerGroupIds = $rule->getCustomerGroupIds();
428+
$sortOrder = (int)$rule->getSortOrder();
429+
$actionOperator = $rule->getSimpleAction();
430+
$actionAmount = $rule->getDiscountAmount();
431+
$actionStop = $rule->getStopRulesProcessing();
432+
433+
$rows = [];
434+
foreach ($websiteIds as $websiteId) {
435+
$scopeTz = new \DateTimeZone(
436+
$this->localeDate->getConfigTimezone(ScopeInterface::SCOPE_WEBSITE, $websiteId)
437+
);
438+
$fromTime = $rule->getFromDate()
439+
? (new \DateTime($rule->getFromDate(), $scopeTz))->getTimestamp()
440+
: 0;
441+
$toTime = $rule->getToDate()
442+
? (new \DateTime($rule->getToDate(), $scopeTz))->getTimestamp() + IndexBuilder::SECONDS_IN_DAY - 1
443+
: 0;
444+
foreach ($customerGroupIds as $customerGroupId) {
445+
$rows[] = [
446+
'rule_id' => $ruleId,
447+
'from_time' => $fromTime,
448+
'to_time' => $toTime,
449+
'website_id' => $websiteId,
450+
'customer_group_id' => $customerGroupId,
451+
'product_id' => $productEntityId,
452+
'action_operator' => $actionOperator,
453+
'action_amount' => $actionAmount,
454+
'action_stop' => $actionStop,
455+
'sort_order' => $sortOrder,
456+
];
457+
458+
if (count($rows) == $this->batchCount) {
459+
$this->connection->insertMultiple($ruleProductTable, $rows);
460+
$rows = [];
461+
}
462+
}
463+
}
464+
if ($rows) {
465+
$this->connection->insertMultiple($ruleProductTable, $rows);
466+
}
467+
}
468+
372469
/**
373470
* Apply rule
374471
*
@@ -392,6 +489,28 @@ protected function applyRule(Rule $rule, $product)
392489
return $this;
393490
}
394491

492+
/**
493+
* Apply rules
494+
*
495+
* @param RuleCollection $ruleCollection
496+
* @param Product $product
497+
* @return void
498+
*/
499+
private function applyRules(RuleCollection $ruleCollection, Product $product): void
500+
{
501+
foreach ($ruleCollection as $rule) {
502+
if (!$rule->validate($product)) {
503+
continue;
504+
}
505+
506+
$websiteIds = array_intersect($product->getWebsiteIds(), $rule->getWebsiteIds());
507+
$this->assignProductToRule($rule, $product->getId(), $websiteIds);
508+
}
509+
510+
$this->cleanProductPriceIndex([$product->getId()]);
511+
$this->reindexRuleProductPrice->execute($this->batchCount, $product->getId());
512+
}
513+
395514
/**
396515
* Retrieve table name
397516
*

0 commit comments

Comments
 (0)