Skip to content

Commit 50c9ca8

Browse files
committed
Fix #4054 catalog price generation when saving a product
1 parent 49f157b commit 50c9ca8

5 files changed

Lines changed: 59 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
- Fixed a PHP error that could occur when viewing variant indexes and using Craft CMS 5.6.17 or earlier. ([#4060](https://github.com/craftcms/commerce/issues/4060))
77
- Fixed a bug where currency based order condition rules incorrectly showed up as custom fields.
88
- Fixed a bug where Subscription and Transfer elements’ field layouts were not deleted when Commerce was uninstalled.
9+
- Fixed a bug where catalog prices weren’t getting generated when saving a product. ([#4054](https://github.com/craftcms/commerce/issues/4054))
10+
- Added `craft\commerce\services\CatalogPricing::afterRequestHandler()`.
11+
- Added `craft\commerce\services\CatalogPricing::requestPurchasablePriceGeneration()`.
912

1013
## 5.4.0 - 2025-06-23
1114

src/Plugin.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,6 +854,8 @@ function(DefineBehaviorsEvent $event) {
854854
Event::on(Elements::class, Elements::EVENT_AUTHORIZE_VIEW, [$this->getInventoryLocations(), 'authorizeInventoryLocationAddressView']);
855855
Event::on(Elements::class, Elements::EVENT_AUTHORIZE_SAVE, [$this->getInventoryLocations(), 'authorizeInventoryLocationAddressEdit']);
856856
Event::on(Elements::class, Elements::EVENT_AUTHORIZE_CREATE_DRAFTS, [$this->getInventoryLocations(), 'authorizeInventoryLocationAddressEdit']);
857+
858+
Event::on(Craft::$app::class, Craft::$app::EVENT_AFTER_REQUEST, [$this->getCatalogPricing(), 'afterRequestHandler']);
857859
}
858860

859861
/**

src/base/Purchasable.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,10 +1213,7 @@ public function afterPropagate(bool $isNew): void
12131213
{
12141214
parent::afterPropagate($isNew);
12151215

1216-
Plugin::getInstance()->getCatalogPricing()->createCatalogPricingJob([
1217-
'purchasableIds' => [$this->getCanonicalId()],
1218-
'storeId' => $this->getStoreId(),
1219-
]);
1216+
Plugin::getInstance()->getCatalogPricing()->requestPurchasablePriceGeneration($this);
12201217
}
12211218

12221219
/**

src/elements/Product.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,9 @@ public function afterPropagate(bool $isNew): void
20182018
$this->getVariantManager()->maintainNestedElements($this, $isNew);
20192019
parent::afterPropagate($isNew);
20202020

2021+
// Add variants to the queue for price generation
2022+
$this->getVariants()->each(fn(Variant $v) => Plugin::getInstance()->getCatalogPricing()->requestPurchasablePriceGeneration($v));
2023+
20212024
// Save a new revision?
20222025
if ($this->_shouldSaveRevision()) {
20232026
Craft::$app->getRevisions()->createRevision($this, notes: $this->revisionNotes);

src/services/CatalogPricing.php

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,55 @@ class CatalogPricing extends Component
4545
*/
4646
private ?array $_allCatalogPrices = null;
4747

48+
/**
49+
* @var array Purchasable IDs collected during the request phase, indexed by Store ID.
50+
*/
51+
private array $_requestedPurchasableIds = [];
52+
53+
/**
54+
* @param Purchasable $purchasable
55+
* @return void
56+
* @throws InvalidConfigException
57+
* @since 5.4.1
58+
*/
59+
public function requestPurchasablePriceGeneration(Purchasable $purchasable): void
60+
{
61+
$storeId = $purchasable->getStoreId();
62+
$id = $purchasable->getCanonicalId();
63+
64+
if (!isset($this->_requestedPurchasableIds[$storeId])) {
65+
$this->_requestedPurchasableIds[$storeId] = [];
66+
}
67+
68+
$this->_requestedPurchasableIds[$storeId][] = $id;
69+
}
70+
71+
/**
72+
* @return void
73+
* @throws InvalidConfigException
74+
* @since 5.4.1
75+
*/
76+
public function afterRequestHandler(): void
77+
{
78+
if (empty($this->_requestedPurchasableIds)) {
79+
return;
80+
}
81+
82+
foreach ($this->_requestedPurchasableIds as $storeId => $purchasableIds) {
83+
$purchasableIds = array_unique($purchasableIds);
84+
if (empty($purchasableIds)) {
85+
continue;
86+
}
87+
88+
$this->createCatalogPricingJob([
89+
'purchasableIds' => $purchasableIds,
90+
'storeId' => $storeId,
91+
]);
92+
}
93+
94+
$this->_requestedPurchasableIds = [];
95+
}
96+
4897
/**
4998
* @param Queue|QueueInterface|null $queue
5099
* @param float $progress
@@ -484,7 +533,7 @@ public function afterSavePurchasableHandler(ModelEvent $event): void
484533
return;
485534
}
486535

487-
$this->createCatalogPricingJob(['purchasableIds' => [$event->sender->id]]);
536+
$this->requestPurchasablePriceGeneration($event->sender);
488537
}
489538

490539
/**

0 commit comments

Comments
 (0)