diff --git a/CHANGELOG.md b/CHANGELOG.md index 089c31dd94..bef1b09cdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Release Notes for Craft Commerce +## Unreleased + +- Fixed a bug where draft purchasables would show up on the Inventory page. +- Fixed a PHP error that could occur when creating inventory transfers. +- Fixed a bug where the price was not formatted correctly according to the locale in the payment model on the Order Edit screens. ([#3789](https://github.com/craftcms/commerce/issues/3789)) + ## 5.2.7 - 2024-11 - Fixed an error that occurred on the Orders index page when running Craft CMS 5.5.4 or later. ([#3793](https://github.com/craftcms/commerce/issues/3793)) diff --git a/src/controllers/InventoryController.php b/src/controllers/InventoryController.php index 13e2653aea..7d083825f7 100644 --- a/src/controllers/InventoryController.php +++ b/src/controllers/InventoryController.php @@ -242,6 +242,8 @@ public function actionInventoryLevelsTableData(): Response $inventoryQuery->leftJoin(['purchasables' => Table::PURCHASABLES], '[[ii.purchasableId]] = [[purchasables.id]]'); $inventoryQuery->addGroupBy(['[[purchasables.description]]', '[[purchasables.sku]]']); + $inventoryQuery->andWhere(['not', ['elements.id' => null]]); + if ($search) { $inventoryQuery->andWhere(['or', ['like', 'purchasables.description', $search], ['like', 'purchasables.sku', $search]]); } diff --git a/src/controllers/OrdersController.php b/src/controllers/OrdersController.php index 52c382a06e..390a0b9b6a 100644 --- a/src/controllers/OrdersController.php +++ b/src/controllers/OrdersController.php @@ -1236,12 +1236,16 @@ public function actionPaymentAmountData(): Response $paymentCurrencies = Plugin::getInstance()->getPaymentCurrencies(); $paymentCurrency = $this->request->getRequiredParam('paymentCurrency'); $paymentAmount = $this->request->getRequiredParam('paymentAmount'); + $locale = $this->request->getRequiredParam('locale'); $orderId = $this->request->getRequiredParam('orderId'); /** @var Order $order */ $order = Order::find()->id($orderId)->one(); $baseCurrency = $order->currency; - $baseCurrencyPaymentAmount = $paymentCurrencies->convertCurrency($paymentAmount, $paymentCurrency, $baseCurrency); + $paymentAmount = MoneyHelper::toMoney(['value' => $paymentAmount, 'currency' => $baseCurrency, 'locale' => $locale]); + $paymentAmount = MoneyHelper::toDecimal($paymentAmount); + + $baseCurrencyPaymentAmount = $paymentCurrencies->convertCurrency((float)$paymentAmount, $paymentCurrency, $baseCurrency); $baseCurrencyPaymentAmountAsCurrency = Craft::t('commerce', 'Pay {amount} of {currency} on the order.', ['amount' => Currency::formatAsCurrency($baseCurrencyPaymentAmount, $baseCurrency), 'currency' => $baseCurrency]); $outstandingBalance = $order->outstandingBalance; diff --git a/src/elements/Product.php b/src/elements/Product.php index 20526d32c8..b8acf1a1e0 100644 --- a/src/elements/Product.php +++ b/src/elements/Product.php @@ -1065,6 +1065,18 @@ public function getVariants(bool $includeDisabled = false): VariantCollection return $this->_variants->filter(fn(Variant $variant) => $includeDisabled || ($variant->getStatus() === self::STATUS_ENABLED)); } + /** + * @return VariantCollection + * @throws InvalidConfigException + * @internal Do not use. Temporary method until we get a nested element manager provider in core. + * + * TODO: Remove this once we have a nested element manager provider interface in core. + */ + public function getAllVariants(): VariantCollection + { + return $this->getVariants(true); + } + /** * @inheritdoc */ @@ -1187,9 +1199,9 @@ public function getVariantManager(): NestedElementManager /** @phpstan-ignore-next-line */ fn(Product $product) => self::createVariantQuery($product), [ - 'attribute' => 'variants', + 'attribute' => 'allVariants', // TODO: can change this back to 'variants' once we have a nested element manager provider in core. 'propagationMethod' => $this->getType()->propagationMethod, - 'valueGetter' => fn(Product $product) => $product->getVariants(true), + 'valueSetter' => fn($variants) => $this->setVariants($variants), // TODO: can change this back to 'variants' once we have a nested element manager provider in core. ], ); } diff --git a/src/services/Inventory.php b/src/services/Inventory.php index 93107c4fba..0ffa7726d6 100644 --- a/src/services/Inventory.php +++ b/src/services/Inventory.php @@ -207,6 +207,7 @@ public function getInventoryLocationLevels(InventoryLocation $inventoryLocation, { $levels = $this->getInventoryLevelQuery(withTrashed: $withTrashed) ->andWhere(['inventoryLocationId' => $inventoryLocation->id]) + ->andWhere(['not', ['elements.id' => null]]) ->collect(); $inventoryItems = Plugin::getInstance()->getInventory()->getInventoryItemsByIds($levels->pluck('inventoryItemId')->unique()->toArray()); @@ -262,8 +263,12 @@ public function getInventoryLevelQuery(?int $limit = null, ?int $offset = null, ->limit($limit) ->offset($offset); + $query->leftJoin( + ['elements' => CraftTable::ELEMENTS], + '[[ii.purchasableId]] = [[elements.id]] AND [[elements.draftId]] IS NULL AND [[elements.revisionId]] IS NULL' + ); + if (!$withTrashed) { - $query->leftJoin(['elements' => CraftTable::ELEMENTS], '[[ii.purchasableId]] = [[elements.id]]'); $query->andWhere(['elements.dateDeleted' => null]); } diff --git a/src/services/InventoryLocations.php b/src/services/InventoryLocations.php index c92e806797..31ead4e14f 100644 --- a/src/services/InventoryLocations.php +++ b/src/services/InventoryLocations.php @@ -283,6 +283,7 @@ private function _createInventoryLocationsQuery(bool $withTrashed = false): Quer 'dateCreated', 'dateUpdated', ]) + ->orderBy(['name' => SORT_ASC]) ->from([Table::INVENTORYLOCATIONS]); if (!$withTrashed) { diff --git a/src/templates/_components/gateways/_modalWrapper.twig b/src/templates/_components/gateways/_modalWrapper.twig index 06ab826d5a..948ff011b4 100644 --- a/src/templates/_components/gateways/_modalWrapper.twig +++ b/src/templates/_components/gateways/_modalWrapper.twig @@ -20,9 +20,15 @@ {{ formHtml|raw }}