From f990b5885a02db2eacda700e3438ceb3012bb627 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Sun, 15 Dec 2024 10:50:14 +0530 Subject: [PATCH 01/14] Grouped product frontend quantity validation added and code refactor --- .../Block/Plugin/ProductView.php | 36 +++++------- .../Model/Product/QuantityValidator.php | 53 +++++++++++++++++ .../ViewModel/ValidateQuantity.php | 58 +++++++++++++++++++ .../catalog_product_view_type_grouped.xml | 14 +++-- .../templates/product/view/type/grouped.phtml | 17 +++--- .../wishlist_index_configure_type_grouped.xml | 10 +++- 6 files changed, 151 insertions(+), 37 deletions(-) create mode 100644 app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php create mode 100644 app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index c8245a53c147c..eff32dd4c600e 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -1,26 +1,26 @@ stockRegistry = $stockRegistry; + $this->productQuantityValidator = $productQuantityValidator; } /** @@ -34,20 +34,12 @@ public function afterGetQuantityValidators( \Magento\Catalog\Block\Product\View $block, array $validators ) { - $stockItem = $this->stockRegistry->getStockItem( - $block->getProduct()->getId(), - $block->getProduct()->getStore()->getWebsiteId() + return array_merge( + $validators, + $this->productQuantityValidator->getData( + $block->getProduct()->getId(), + $block->getProduct()->getStore()->getWebsiteId() + ) ); - - $params = []; - if ($stockItem->getMaxSaleQty()) { - $params['maxAllowed'] = (float)$stockItem->getMaxSaleQty(); - } - if ($stockItem->getQtyIncrements() > 0) { - $params['qtyIncrements'] = (float)$stockItem->getQtyIncrements(); - } - $validators['validate-item-quantity'] = $params; - - return $validators; } } diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php new file mode 100644 index 0000000000000..526d8d9d21a0e --- /dev/null +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -0,0 +1,53 @@ +stockRegistry = $stockRegistry; + } + + /** + * To get quantity validators + * + * @param int $productId + * @param int $websiteId + * + * @return array + */ + public function getData($productId, $websiteId): array + { + $stockItem = $this->stockRegistry->getStockItem($productId, $websiteId); + + $params = []; + $validators = []; + $params['minAllowed'] = (float)$stockItem->getMinSaleQty(); + if ($stockItem->getMaxSaleQty()) { + $params['maxAllowed'] = (float)$stockItem->getMaxSaleQty(); + } + if ($stockItem->getQtyIncrements() > 0) { + $params['qtyIncrements'] = (float)$stockItem->getQtyIncrements(); + } + $validators['validate-item-quantity'] = $params; + + return $validators; + } +} diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php new file mode 100644 index 0000000000000..df2a9d8bb394b --- /dev/null +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -0,0 +1,58 @@ +serializer = $serializer; + $this->productQuantityValidator = $productQuantityValidator; + } + + /** + * To get the quantity validators + * + * @param int $productId + * @param int $websiteId + * + * @return string + */ + public function getQuantityValidators($productId, $websiteId): string + { + return $this->serializer->serialize( + array_merge( + ['validate-grouped-qty' => '#super-product-table'], + $this->productQuantityValidator->getData($productId, $websiteId) + ) + ); + } +} diff --git a/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml b/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml index a774f384d947a..7f99e022227ac 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml +++ b/app/code/Magento/GroupedProduct/view/frontend/layout/catalog_product_view_type_grouped.xml @@ -1,15 +1,19 @@ - + + + Magento\GroupedProduct\ViewModel\ValidateQuantity + + diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 996c61571563a..7d5cab6dabba8 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -1,7 +1,7 @@ -setPreconfiguredValue(); ?> -getProduct(); ?> -getAssociatedProducts(); ?> - 0; ?> +setPreconfiguredValue(); + $_product = $block->getProduct(); + $_associatedProducts = $block->getAssociatedProducts(); + $_hasAssociatedProducts = count($_associatedProducts) > 0; + $viewModel = $block->getData('validateQuantityViewModel'); +?>
diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml index 92bb55ebd0ee1..0ac7e88196246 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml @@ -1,15 +1,19 @@ - + + + Magento\GroupedProduct\ViewModel\ValidateQuantity + + From 94fadc842e83e1217082c3317829a7c49de3e299 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Fri, 20 Dec 2024 11:30:24 +0530 Subject: [PATCH 02/14] Ignore item qty validation if zero qty entered in grouped product --- .../view/frontend/templates/product/view/type/grouped.phtml | 1 + lib/web/mage/validation.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 7d5cab6dabba8..71a5426600a0c 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -56,6 +56,7 @@ title="escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" data-validate="escapeHtmlAttr($viewModel->getQuantityValidators($_item->getId(), $_item->getWebsiteId())) ?>" + data-no-validation-for-zero-qty="true" data-errors-message-box="#validation-message-box"/> diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 72baf69740c9b..6fdd221f26226 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1643,6 +1643,9 @@ define([ isQtyIncrementsValid = typeof params.qtyIncrements === 'undefined' || resolveModulo(qty, $.mage.parseNumber(params.qtyIncrements)) === 0.0; + if ($(element).data('no-validation-for-zero-qty') === true && qty === 0) { + return true; + } result = qty > 0; if (result === false) { From a1923771627e2cd1c40b5fd556ff633d8c8bfd4b Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Mon, 30 Dec 2024 11:23:52 +0530 Subject: [PATCH 03/14] Unit test & static test cases issues fixed --- .../Block/Plugin/ProductView.php | 2 +- .../Model/Product/QuantityValidator.php | 2 +- .../Unit/Block/Plugin/ProductViewTest.php | 23 ++++++++++--- .../ViewModel/ValidateQuantity.php | 2 +- .../catalog_product_view_type_grouped.xml | 2 +- .../templates/product/view/type/grouped.phtml | 32 +++++++++---------- .../wishlist_index_configure_type_grouped.xml | 2 +- 7 files changed, 40 insertions(+), 25 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index eff32dd4c600e..bcd9a00be937c 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -1,6 +1,6 @@ stockRegistry = $this->getMockBuilder(StockRegistryInterface::class) ->getMock(); + + $this->productQuantityValidator = $objectManager->getObject( + QuantityValidator::class, + [ + 'stockRegistry' => $this->stockRegistry + ] + ); + $this->block = $objectManager->getObject( ProductView::class, [ - 'stockRegistry' => $this->stockRegistry + 'productQuantityValidator' => $this->productQuantityValidator ] ); } @@ -59,6 +73,7 @@ public function testAfterGetQuantityValidators() { $result = [ 'validate-item-quantity' => [ + 'minAllowed' => 1.0, 'maxAllowed' => 5.0, 'qtyIncrements' => 3.0 ] @@ -86,9 +101,9 @@ public function testAfterGetQuantityValidators() ->method('getStockItem') ->with('productId', 'websiteId') ->willReturn($this->stockItem); + $this->stockItem->expects($this->any())->method('getMinSaleQty')->willReturn(1); $this->stockItem->expects($this->any())->method('getMaxSaleQty')->willReturn(5); $this->stockItem->expects($this->any())->method('getQtyIncrements')->willReturn(3); - $this->assertEquals($result, $this->block->afterGetQuantityValidators($productViewBlock, $validators)); } } diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php index df2a9d8bb394b..c7367539770c0 100644 --- a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -1,6 +1,6 @@ diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 71a5426600a0c..417d9012f98ee 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -1,14 +1,14 @@ - + - + isSaleable()): ?> - + @@ -37,8 +37,8 @@ - isSaleable()): ?> - @@ -89,7 +89,7 @@ diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml index 0ac7e88196246..27d63bad57c08 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_grouped.xml @@ -1,7 +1,7 @@ From ceb85978679800380f66bde6bc08285c0b24201b Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Mon, 30 Dec 2024 18:27:43 +0530 Subject: [PATCH 04/14] Static test fixed --- .../Test/Unit/Block/Plugin/ProductViewTest.php | 1 - .../view/frontend/templates/product/view/type/grouped.phtml | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php index 48ba80121a829..94d08027362e5 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php @@ -53,7 +53,6 @@ protected function setUp(): void $this->stockRegistry = $this->getMockBuilder(StockRegistryInterface::class) ->getMock(); - $this->productQuantityValidator = $objectManager->getObject( QuantityValidator::class, [ diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 417d9012f98ee..3662149d75211 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -55,7 +55,10 @@ value="escapeHtmlAttr($_item->getQty() * 1) ?>" title="escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" - data-validate="escapeHtmlAttr($viewModel->getQuantityValidators($_item->getId(), $_item->getWebsiteId())) ?>" + data-validate="escapeHtmlAttr($viewModel->getQuantityValidators( + $_item->getId(), + $_item->getWebsiteId() + )) ?>" data-no-validation-for-zero-qty="true" data-errors-message-box="#validation-message-box"/> From 3e0c5a76337e42bfdfd58f9777305ae48748e983 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Tue, 31 Dec 2024 15:02:33 +0530 Subject: [PATCH 05/14] Indent issue fixed --- lib/web/mage/validation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/web/mage/validation.js b/lib/web/mage/validation.js index 6fdd221f26226..3f1df78dcfdee 100644 --- a/lib/web/mage/validation.js +++ b/lib/web/mage/validation.js @@ -1644,7 +1644,7 @@ define([ resolveModulo(qty, $.mage.parseNumber(params.qtyIncrements)) === 0.0; if ($(element).data('no-validation-for-zero-qty') === true && qty === 0) { - return true; + return true; } result = qty > 0; From 1ca6c6d8be284561ec999cde64cca934237f81c8 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Thu, 23 Jan 2025 21:52:04 +0530 Subject: [PATCH 06/14] Code review changes --- .../Block/Plugin/ProductView.php | 9 ++++++--- .../Model/Product/QuantityValidator.php | 18 ++++++----------- .../ViewModel/ValidateQuantity.php | 20 ++++--------------- 3 files changed, 16 insertions(+), 31 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index bcd9a00be937c..7f809e07b4018 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -6,6 +6,7 @@ namespace Magento\CatalogInventory\Block\Plugin; use Magento\CatalogInventory\Model\Product\QuantityValidator; +use Magento\Framework\App\ObjectManager; class ProductView { @@ -15,12 +16,14 @@ class ProductView private $productQuantityValidator; /** - * @param QuantityValidator $productQuantityValidator + * @param QuantityValidator|null $productQuantityValidator */ public function __construct( - QuantityValidator $productQuantityValidator + QuantityValidator $productQuantityValidator = null ) { - $this->productQuantityValidator = $productQuantityValidator; + $this->productQuantityValidator = $productQuantityValidator ?: ObjectManager::getInstance()->get( + QuantityValidator::class + ); } /** diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php index 16e6d8d98b70d..1ad6d938d73d6 100644 --- a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -11,40 +11,34 @@ class QuantityValidator { - /** - * @var StockRegistryInterface - */ - private $stockRegistry; - /** * @param StockRegistryInterface $stockRegistry */ public function __construct( - StockRegistryInterface $stockRegistry + private readonly StockRegistryInterface $stockRegistry ) { - $this->stockRegistry = $stockRegistry; } /** * To get quantity validators * * @param int $productId - * @param int $websiteId + * @param int|null $websiteId * * @return array */ - public function getData($productId, $websiteId): array + public function getData(int $productId, int|null $websiteId): array { $stockItem = $this->stockRegistry->getStockItem($productId, $websiteId); $params = []; $validators = []; - $params['minAllowed'] = (float)$stockItem->getMinSaleQty(); + $params['minAllowed'] = $stockItem->getMinSaleQty(); if ($stockItem->getMaxSaleQty()) { - $params['maxAllowed'] = (float)$stockItem->getMaxSaleQty(); + $params['maxAllowed'] = $stockItem->getMaxSaleQty(); } if ($stockItem->getQtyIncrements() > 0) { - $params['qtyIncrements'] = (float)$stockItem->getQtyIncrements(); + $params['qtyIncrements'] = (float) $stockItem->getQtyIncrements(); } $validators['validate-item-quantity'] = $params; diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php index c7367539770c0..b8bf9bd6faad8 100644 --- a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -16,37 +16,25 @@ */ class ValidateQuantity implements ArgumentInterface { - /** - * @var Json - */ - private $serializer; - - /** - * @var QuantityValidator - */ - private $productQuantityValidator; - /** * @param Json $serializer * @param QuantityValidator $productQuantityValidator */ public function __construct( - Json $serializer, - QuantityValidator $productQuantityValidator, + private readonly Json $serializer, + private readonly QuantityValidator $productQuantityValidator, ) { - $this->serializer = $serializer; - $this->productQuantityValidator = $productQuantityValidator; } /** * To get the quantity validators * * @param int $productId - * @param int $websiteId + * @param int|null $websiteId * * @return string */ - public function getQuantityValidators($productId, $websiteId): string + public function getQuantityValidators(int $productId, int|null $websiteId): string { return $this->serializer->serialize( array_merge( From baeb177a3bdf99a46a8744ee943f6146c291df9b Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Fri, 7 Mar 2025 15:49:59 +0530 Subject: [PATCH 07/14] Removed deprecated methods, get data using MSI and unit test added --- .../Block/Plugin/ProductView.php | 2 +- .../Model/Product/QuantityValidator.php | 68 ++++++++--- .../Unit/Block/Plugin/ProductViewTest.php | 108 ------------------ .../Model/Product/QuantityValidatorTest.php | 100 ++++++++++++++++ .../Magento/CatalogInventory/composer.json | 2 + .../Magento/CatalogInventory/etc/module.xml | 6 +- .../ViewModel/ValidateQuantity.php | 6 +- .../templates/product/view/type/grouped.phtml | 2 +- 8 files changed, 164 insertions(+), 130 deletions(-) delete mode 100644 app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php create mode 100644 app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index 7f809e07b4018..38add312c2b4a 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -40,7 +40,7 @@ public function afterGetQuantityValidators( return array_merge( $validators, $this->productQuantityValidator->getData( - $block->getProduct()->getId(), + $block->getProduct()->getSku(), $block->getProduct()->getStore()->getWebsiteId() ) ); diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php index 1ad6d938d73d6..6c88da96e7431 100644 --- a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -7,41 +7,79 @@ namespace Magento\CatalogInventory\Model\Product; -use Magento\CatalogInventory\Api\StockRegistryInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface; +use Magento\InventorySalesApi\Api\StockResolverInterface; +use Magento\InventorySalesApi\Api\Data\SalesChannelInterface; +use Magento\Store\Model\StoreManagerInterface; class QuantityValidator { /** - * @param StockRegistryInterface $stockRegistry + * @param GetStockItemConfigurationInterface $getStockItemConfiguration + * @param StoreManagerInterface $storeManager + * @param StockResolverInterface $stockResolver */ public function __construct( - private readonly StockRegistryInterface $stockRegistry + private readonly GetStockItemConfigurationInterface $getStockItemConfiguration, + private readonly StoreManagerInterface $storeManager, + private readonly StockResolverInterface $stockResolver ) { } /** * To get quantity validators * - * @param int $productId + * @param string $sku * @param int|null $websiteId * * @return array */ - public function getData(int $productId, int|null $websiteId): array + public function getData(string $sku, int|null $websiteId): array { - $stockItem = $this->stockRegistry->getStockItem($productId, $websiteId); + try { + $stockItemConfig = $this->getStockItemConfiguration->execute( + $sku, + $this->getStockId($websiteId) + ); - $params = []; - $validators = []; - $params['minAllowed'] = $stockItem->getMinSaleQty(); - if ($stockItem->getMaxSaleQty()) { - $params['maxAllowed'] = $stockItem->getMaxSaleQty(); + $params = []; + $validators = []; + $params['minAllowed'] = $stockItemConfig->getMinSaleQty(); + + if ($stockItemConfig->getMaxSaleQty()) { + $params['maxAllowed'] = $stockItemConfig->getMaxSaleQty(); + } + if ($stockItemConfig->getQtyIncrements() > 0) { + $params['qtyIncrements'] = $stockItemConfig->getQtyIncrements(); + } + $validators['validate-item-quantity'] = $params; + + return $validators; + } catch (\Exception $e) { + return []; } - if ($stockItem->getQtyIncrements() > 0) { - $params['qtyIncrements'] = (float) $stockItem->getQtyIncrements(); + } + + /** + * Get Stock ID by Website ID + * + * @param int|null $websiteId + * @return int + * @throws LocalizedException + */ + private function getStockId(?int $websiteId): int + { + if ($websiteId === null) { + $websiteId = $this->storeManager->getWebsite()->getId(); } - $validators['validate-item-quantity'] = $params; - return $validators; + $websiteCode = $this->storeManager->getWebsite($websiteId)->getCode(); + $stock = $this->stockResolver->execute( + SalesChannelInterface::TYPE_WEBSITE, + $websiteCode + ); + + return (int) $stock->getStockId(); } } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php deleted file mode 100644 index 94d08027362e5..0000000000000 --- a/app/code/Magento/CatalogInventory/Test/Unit/Block/Plugin/ProductViewTest.php +++ /dev/null @@ -1,108 +0,0 @@ -stockItem = $this->getMockBuilder(Item::class) - ->disableOriginalConstructor() - ->onlyMethods(['getMinSaleQty', 'getMaxSaleQty', 'getQtyIncrements']) - ->getMock(); - - $this->stockRegistry = $this->getMockBuilder(StockRegistryInterface::class) - ->getMock(); - - $this->productQuantityValidator = $objectManager->getObject( - QuantityValidator::class, - [ - 'stockRegistry' => $this->stockRegistry - ] - ); - - $this->block = $objectManager->getObject( - ProductView::class, - [ - 'productQuantityValidator' => $this->productQuantityValidator - ] - ); - } - - public function testAfterGetQuantityValidators() - { - $result = [ - 'validate-item-quantity' => [ - 'minAllowed' => 1.0, - 'maxAllowed' => 5.0, - 'qtyIncrements' => 3.0 - ] - ]; - $validators = []; - $productViewBlock = $this->getMockBuilder(View::class) - ->disableOriginalConstructor() - ->getMock(); - $productMock = $this->getMockBuilder(Product::class) - ->disableOriginalConstructor() - ->addMethods(['_wakeup']) - ->onlyMethods(['getId', 'getStore']) - ->getMock(); - $storeMock = $this->getMockBuilder(Store::class) - ->disableOriginalConstructor() - ->addMethods(['_wakeup']) - ->onlyMethods(['getWebsiteId']) - ->getMock(); - - $productViewBlock->expects($this->any())->method('getProduct')->willReturn($productMock); - $productMock->expects($this->once())->method('getId')->willReturn('productId'); - $productMock->expects($this->once())->method('getStore')->willReturn($storeMock); - $storeMock->expects($this->once())->method('getWebsiteId')->willReturn('websiteId'); - $this->stockRegistry->expects($this->once()) - ->method('getStockItem') - ->with('productId', 'websiteId') - ->willReturn($this->stockItem); - $this->stockItem->expects($this->any())->method('getMinSaleQty')->willReturn(1); - $this->stockItem->expects($this->any())->method('getMaxSaleQty')->willReturn(5); - $this->stockItem->expects($this->any())->method('getQtyIncrements')->willReturn(3); - $this->assertEquals($result, $this->block->afterGetQuantityValidators($productViewBlock, $validators)); - } -} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php new file mode 100644 index 0000000000000..6589f442ed3c8 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php @@ -0,0 +1,100 @@ +getStockItemConfiguration = $this->createMock(GetStockItemConfigurationInterface::class); + $this->storeManager = $this->createMock(StoreManagerInterface::class); + $this->stockResolver = $this->createMock(StockResolverInterface::class); + + $this->quantityValidator = new QuantityValidator( + $this->getStockItemConfiguration, + $this->storeManager, + $this->stockResolver + ); + } + + public function testGetDataWithValidators(): void + { + $website = $this->createMock(WebsiteInterface::class); + $website->method('getCode')->willReturn(self::WEBSITE_CODE); + + $stock = $this->createMock(StockInterface::class); + $stock->method('getStockId')->willReturn(self::STOCK_ID); + + $stockItemConfiguration = $this->createMock(StockItemConfigurationInterface::class); + $stockItemConfiguration->method('getMinSaleQty')->willReturn(2.0); + $stockItemConfiguration->method('getMaxSaleQty')->willReturn(10.0); + $stockItemConfiguration->method('getQtyIncrements')->willReturn(2.0); + + // Set expectations + $this->storeManager->expects($this->once()) + ->method('getWebsite') + ->with(self::WEBSITE_ID) + ->willReturn($website); + + $this->stockResolver->expects($this->once()) + ->method('execute') + ->with(SalesChannelInterface::TYPE_WEBSITE, self::WEBSITE_CODE) + ->willReturn($stock); + + $this->getStockItemConfiguration->expects($this->once()) + ->method('execute') + ->with(self::TEST_SKU, self::STOCK_ID) + ->willReturn($stockItemConfiguration); + + $expected = [ + 'validate-item-quantity' => [ + 'minAllowed' => 2, + 'maxAllowed' => 10, + 'qtyIncrements' => 2.0 + ] + ]; + + $result = $this->quantityValidator->getData(self::TEST_SKU, self::WEBSITE_ID); + $this->assertEquals($expected, $result); + } +} diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json index d78c97d97eed6..c452c042d5f45 100644 --- a/app/code/Magento/CatalogInventory/composer.json +++ b/app/code/Magento/CatalogInventory/composer.json @@ -8,6 +8,8 @@ "php": "~8.2.0||~8.3.0||~8.4.0", "magento/framework": "*", "magento/module-catalog": "*", + "magento/module-inventory-configuration-api": "*", + "magento/module-inventory-sales-api": "*", "magento/module-config": "*", "magento/module-customer": "*", "magento/module-eav": "*", diff --git a/app/code/Magento/CatalogInventory/etc/module.xml b/app/code/Magento/CatalogInventory/etc/module.xml index d643c5015130f..775d4f94139e9 100644 --- a/app/code/Magento/CatalogInventory/etc/module.xml +++ b/app/code/Magento/CatalogInventory/etc/module.xml @@ -1,14 +1,16 @@ + + diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php index b8bf9bd6faad8..d987c89e0ad9a 100644 --- a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -29,17 +29,17 @@ public function __construct( /** * To get the quantity validators * - * @param int $productId + * @param string $sku * @param int|null $websiteId * * @return string */ - public function getQuantityValidators(int $productId, int|null $websiteId): string + public function getQuantityValidators(string $sku, int|null $websiteId): string { return $this->serializer->serialize( array_merge( ['validate-grouped-qty' => '#super-product-table'], - $this->productQuantityValidator->getData($productId, $websiteId) + $this->productQuantityValidator->getData($sku, $websiteId) ) ); } diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 3662149d75211..05b973bd94b8f 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -56,7 +56,7 @@ title="escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" data-validate="escapeHtmlAttr($viewModel->getQuantityValidators( - $_item->getId(), + $_item->getSku(), $_item->getWebsiteId() )) ?>" data-no-validation-for-zero-qty="true" From 9a46f52f04d5a88673f4c4463abcb9b8c83b8b25 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Mon, 10 Mar 2025 14:07:02 +0530 Subject: [PATCH 08/14] Static test case fix --- .../Test/Unit/Model/Product/QuantityValidatorTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php index 6589f442ed3c8..483d610db972b 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php @@ -1,4 +1,8 @@ Date: Thu, 3 Apr 2025 17:51:17 +0530 Subject: [PATCH 09/14] Test case failures fix --- .../CatalogInventory/Block/Plugin/ProductView.php | 14 ++++++-------- app/code/Magento/CatalogInventory/composer.json | 2 -- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index 38add312c2b4a..46c94c617ae5e 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -5,8 +5,8 @@ */ namespace Magento\CatalogInventory\Block\Plugin; +use Magento\Catalog\Block\Product\View; use Magento\CatalogInventory\Model\Product\QuantityValidator; -use Magento\Framework\App\ObjectManager; class ProductView { @@ -16,25 +16,23 @@ class ProductView private $productQuantityValidator; /** - * @param QuantityValidator|null $productQuantityValidator + * @param QuantityValidator $productQuantityValidator */ public function __construct( - QuantityValidator $productQuantityValidator = null + QuantityValidator $productQuantityValidator ) { - $this->productQuantityValidator = $productQuantityValidator ?: ObjectManager::getInstance()->get( - QuantityValidator::class - ); + $this->productQuantityValidator = $productQuantityValidator; } /** * Adds quantities validator. * - * @param \Magento\Catalog\Block\Product\View $block + * @param View $block * @param array $validators * @return array */ public function afterGetQuantityValidators( - \Magento\Catalog\Block\Product\View $block, + View $block, array $validators ) { return array_merge( diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json index c452c042d5f45..d78c97d97eed6 100644 --- a/app/code/Magento/CatalogInventory/composer.json +++ b/app/code/Magento/CatalogInventory/composer.json @@ -8,8 +8,6 @@ "php": "~8.2.0||~8.3.0||~8.4.0", "magento/framework": "*", "magento/module-catalog": "*", - "magento/module-inventory-configuration-api": "*", - "magento/module-inventory-sales-api": "*", "magento/module-config": "*", "magento/module-customer": "*", "magento/module-eav": "*", From 92c7ad3ef40ddab5471d52c43f824e3fe2b580b2 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Mon, 7 Apr 2025 21:36:05 +0530 Subject: [PATCH 10/14] Composer dependency added --- app/code/Magento/CatalogInventory/composer.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json index d78c97d97eed6..133b2264e320e 100644 --- a/app/code/Magento/CatalogInventory/composer.json +++ b/app/code/Magento/CatalogInventory/composer.json @@ -11,6 +11,8 @@ "magento/module-config": "*", "magento/module-customer": "*", "magento/module-eav": "*", + "magento/module-inventory-configuration-api": "*", + "magento/module-inventory-sales-api": "*", "magento/module-quote": "*", "magento/module-store": "*", "magento/module-ui": "*" From 0a8daf166c0f721b1bfb7dd069c3b32bb4981785 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Wed, 9 Apr 2025 12:52:29 +0530 Subject: [PATCH 11/14] Mftf test case fix for min qty validation --- .../Test/AdminAddInStockProductToTheCartTest.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml index 4f2dd66e4d4ff..fbb65d41b6db2 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminAddInStockProductToTheCartTest.xml @@ -1,8 +1,8 @@ @@ -48,7 +48,7 @@ - + @@ -111,17 +111,17 @@ - + - + - + From 203ba70b8d5cdf7daad39ec410c75632860193ed Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Wed, 16 Apr 2025 12:53:57 +0530 Subject: [PATCH 12/14] Reverted the msi modules approach --- .../Block/Plugin/ProductView.php | 2 +- .../Model/Product/QuantityValidator.php | 68 ++++------------- .../Model/Product/QuantityValidatorTest.php | 76 ++++++------------- .../Magento/CatalogInventory/composer.json | 2 - .../Magento/CatalogInventory/etc/module.xml | 2 - .../ViewModel/ValidateQuantity.php | 6 +- .../templates/product/view/type/grouped.phtml | 2 +- 7 files changed, 42 insertions(+), 116 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index 46c94c617ae5e..4ec714a53ac10 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -38,7 +38,7 @@ public function afterGetQuantityValidators( return array_merge( $validators, $this->productQuantityValidator->getData( - $block->getProduct()->getSku(), + $block->getProduct()->getId(), $block->getProduct()->getStore()->getWebsiteId() ) ); diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php index 6c88da96e7431..1ad6d938d73d6 100644 --- a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -7,79 +7,41 @@ namespace Magento\CatalogInventory\Model\Product; -use Magento\Framework\Exception\LocalizedException; -use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface; -use Magento\InventorySalesApi\Api\StockResolverInterface; -use Magento\InventorySalesApi\Api\Data\SalesChannelInterface; -use Magento\Store\Model\StoreManagerInterface; +use Magento\CatalogInventory\Api\StockRegistryInterface; class QuantityValidator { /** - * @param GetStockItemConfigurationInterface $getStockItemConfiguration - * @param StoreManagerInterface $storeManager - * @param StockResolverInterface $stockResolver + * @param StockRegistryInterface $stockRegistry */ public function __construct( - private readonly GetStockItemConfigurationInterface $getStockItemConfiguration, - private readonly StoreManagerInterface $storeManager, - private readonly StockResolverInterface $stockResolver + private readonly StockRegistryInterface $stockRegistry ) { } /** * To get quantity validators * - * @param string $sku + * @param int $productId * @param int|null $websiteId * * @return array */ - public function getData(string $sku, int|null $websiteId): array + public function getData(int $productId, int|null $websiteId): array { - try { - $stockItemConfig = $this->getStockItemConfiguration->execute( - $sku, - $this->getStockId($websiteId) - ); + $stockItem = $this->stockRegistry->getStockItem($productId, $websiteId); - $params = []; - $validators = []; - $params['minAllowed'] = $stockItemConfig->getMinSaleQty(); - - if ($stockItemConfig->getMaxSaleQty()) { - $params['maxAllowed'] = $stockItemConfig->getMaxSaleQty(); - } - if ($stockItemConfig->getQtyIncrements() > 0) { - $params['qtyIncrements'] = $stockItemConfig->getQtyIncrements(); - } - $validators['validate-item-quantity'] = $params; - - return $validators; - } catch (\Exception $e) { - return []; + $params = []; + $validators = []; + $params['minAllowed'] = $stockItem->getMinSaleQty(); + if ($stockItem->getMaxSaleQty()) { + $params['maxAllowed'] = $stockItem->getMaxSaleQty(); } - } - - /** - * Get Stock ID by Website ID - * - * @param int|null $websiteId - * @return int - * @throws LocalizedException - */ - private function getStockId(?int $websiteId): int - { - if ($websiteId === null) { - $websiteId = $this->storeManager->getWebsite()->getId(); + if ($stockItem->getQtyIncrements() > 0) { + $params['qtyIncrements'] = (float) $stockItem->getQtyIncrements(); } + $validators['validate-item-quantity'] = $params; - $websiteCode = $this->storeManager->getWebsite($websiteId)->getCode(); - $stock = $this->stockResolver->execute( - SalesChannelInterface::TYPE_WEBSITE, - $websiteCode - ); - - return (int) $stock->getStockId(); + return $validators; } } diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php index 483d610db972b..407042f3edc4f 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php @@ -7,14 +7,9 @@ namespace Magento\CatalogInventory\Test\Unit\Model\Product; +use Magento\CatalogInventory\Api\StockRegistryInterface; use Magento\CatalogInventory\Model\Product\QuantityValidator; -use Magento\InventoryConfigurationApi\Api\GetStockItemConfigurationInterface; -use Magento\InventoryConfigurationApi\Api\Data\StockItemConfigurationInterface; -use Magento\InventorySalesApi\Api\Data\SalesChannelInterface; -use Magento\InventoryApi\Api\Data\StockInterface; -use Magento\InventorySalesApi\Api\StockResolverInterface; -use Magento\Store\Api\Data\WebsiteInterface; -use Magento\Store\Model\StoreManagerInterface; +use Magento\CatalogInventory\Api\Data\StockItemInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -23,10 +18,8 @@ */ class QuantityValidatorTest extends TestCase { + private const PRODUCT_ID = 42; private const WEBSITE_ID = 1; - private const WEBSITE_CODE = 'base'; - private const STOCK_ID = 1; - private const TEST_SKU = 'TEST-SKU'; /** * @var QuantityValidator @@ -34,71 +27,46 @@ class QuantityValidatorTest extends TestCase private $quantityValidator; /** - * @var GetStockItemConfigurationInterface|MockObject + * @var StockRegistryInterface|MockObject */ - private $getStockItemConfiguration; - - /** - * @var StoreManagerInterface|MockObject - */ - private $storeManager; - - /** - * @var StockResolverInterface|MockObject - */ - private $stockResolver; + private $stockRegistry; protected function setUp(): void { - $this->getStockItemConfiguration = $this->createMock(GetStockItemConfigurationInterface::class); - $this->storeManager = $this->createMock(StoreManagerInterface::class); - $this->stockResolver = $this->createMock(StockResolverInterface::class); + $this->stockRegistry = $this->createMock(StockRegistryInterface::class); $this->quantityValidator = new QuantityValidator( - $this->getStockItemConfiguration, - $this->storeManager, - $this->stockResolver + $this->stockRegistry ); } - public function testGetDataWithValidators(): void + public function testGetDataWithMinMaxAndIncrements(): void { - $website = $this->createMock(WebsiteInterface::class); - $website->method('getCode')->willReturn(self::WEBSITE_CODE); - - $stock = $this->createMock(StockInterface::class); - $stock->method('getStockId')->willReturn(self::STOCK_ID); + $stockItem = $this->createMock(StockItemInterface::class); - $stockItemConfiguration = $this->createMock(StockItemConfigurationInterface::class); - $stockItemConfiguration->method('getMinSaleQty')->willReturn(2.0); - $stockItemConfiguration->method('getMaxSaleQty')->willReturn(10.0); - $stockItemConfiguration->method('getQtyIncrements')->willReturn(2.0); + $stockItem->method('getMinSaleQty') + ->willReturn(2.0); - // Set expectations - $this->storeManager->expects($this->once()) - ->method('getWebsite') - ->with(self::WEBSITE_ID) - ->willReturn($website); + $stockItem->method('getMaxSaleQty') + ->willReturn(10.0); - $this->stockResolver->expects($this->once()) - ->method('execute') - ->with(SalesChannelInterface::TYPE_WEBSITE, self::WEBSITE_CODE) - ->willReturn($stock); + $stockItem->method('getQtyIncrements') + ->willReturn(2.0); - $this->getStockItemConfiguration->expects($this->once()) - ->method('execute') - ->with(self::TEST_SKU, self::STOCK_ID) - ->willReturn($stockItemConfiguration); + $this->stockRegistry->expects($this->once()) + ->method('getStockItem') + ->with(self::PRODUCT_ID, self::WEBSITE_ID) + ->willReturn($stockItem); $expected = [ 'validate-item-quantity' => [ - 'minAllowed' => 2, - 'maxAllowed' => 10, + 'minAllowed' => 2.0, + 'maxAllowed' => 10.0, 'qtyIncrements' => 2.0 ] ]; - $result = $this->quantityValidator->getData(self::TEST_SKU, self::WEBSITE_ID); + $result = $this->quantityValidator->getData(self::PRODUCT_ID, self::WEBSITE_ID); $this->assertEquals($expected, $result); } } diff --git a/app/code/Magento/CatalogInventory/composer.json b/app/code/Magento/CatalogInventory/composer.json index 133b2264e320e..d78c97d97eed6 100644 --- a/app/code/Magento/CatalogInventory/composer.json +++ b/app/code/Magento/CatalogInventory/composer.json @@ -11,8 +11,6 @@ "magento/module-config": "*", "magento/module-customer": "*", "magento/module-eav": "*", - "magento/module-inventory-configuration-api": "*", - "magento/module-inventory-sales-api": "*", "magento/module-quote": "*", "magento/module-store": "*", "magento/module-ui": "*" diff --git a/app/code/Magento/CatalogInventory/etc/module.xml b/app/code/Magento/CatalogInventory/etc/module.xml index 775d4f94139e9..9acc30b86c656 100644 --- a/app/code/Magento/CatalogInventory/etc/module.xml +++ b/app/code/Magento/CatalogInventory/etc/module.xml @@ -9,8 +9,6 @@ - - diff --git a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php index d987c89e0ad9a..b8bf9bd6faad8 100644 --- a/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php +++ b/app/code/Magento/GroupedProduct/ViewModel/ValidateQuantity.php @@ -29,17 +29,17 @@ public function __construct( /** * To get the quantity validators * - * @param string $sku + * @param int $productId * @param int|null $websiteId * * @return string */ - public function getQuantityValidators(string $sku, int|null $websiteId): string + public function getQuantityValidators(int $productId, int|null $websiteId): string { return $this->serializer->serialize( array_merge( ['validate-grouped-qty' => '#super-product-table'], - $this->productQuantityValidator->getData($sku, $websiteId) + $this->productQuantityValidator->getData($productId, $websiteId) ) ); } diff --git a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml index 05b973bd94b8f..3662149d75211 100644 --- a/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml +++ b/app/code/Magento/GroupedProduct/view/frontend/templates/product/view/type/grouped.phtml @@ -56,7 +56,7 @@ title="escapeHtmlAttr(__('Qty')) ?>" class="input-text qty" data-validate="escapeHtmlAttr($viewModel->getQuantityValidators( - $_item->getSku(), + $_item->getId(), $_item->getWebsiteId() )) ?>" data-no-validation-for-zero-qty="true" From 42d9406d83243ab8b21519fd5a7f0080e6616ebc Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Fri, 23 May 2025 16:09:28 +0530 Subject: [PATCH 13/14] Code review changes --- .../Block/Plugin/ProductView.php | 9 ++- .../Model/Product/QuantityValidator.php | 4 ++ .../Model/Product/QuantityValidatorTest.php | 60 +++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index 4ec714a53ac10..8c00dc5725239 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -7,6 +7,7 @@ use Magento\Catalog\Block\Product\View; use Magento\CatalogInventory\Model\Product\QuantityValidator; +use Magento\Framework\App\ObjectManager; class ProductView { @@ -16,12 +17,14 @@ class ProductView private $productQuantityValidator; /** - * @param QuantityValidator $productQuantityValidator + * @param QuantityValidator|null $productQuantityValidator */ public function __construct( - QuantityValidator $productQuantityValidator + QuantityValidator $productQuantityValidator = null ) { - $this->productQuantityValidator = $productQuantityValidator; + $this->productQuantityValidator = $productQuantityValidator ?? ObjectManager::getInstance()->get( + QuantityValidator::class + ); } /** diff --git a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php index 1ad6d938d73d6..6cbef082e00f0 100644 --- a/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php +++ b/app/code/Magento/CatalogInventory/Model/Product/QuantityValidator.php @@ -31,6 +31,10 @@ public function getData(int $productId, int|null $websiteId): array { $stockItem = $this->stockRegistry->getStockItem($productId, $websiteId); + if (!$stockItem) { + return []; + } + $params = []; $validators = []; $params['minAllowed'] = $stockItem->getMinSaleQty(); diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php index 407042f3edc4f..ee9227ae366db 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/Product/QuantityValidatorTest.php @@ -69,4 +69,64 @@ public function testGetDataWithMinMaxAndIncrements(): void $result = $this->quantityValidator->getData(self::PRODUCT_ID, self::WEBSITE_ID); $this->assertEquals($expected, $result); } + + public function testReturnsEmptyArrayForNonExistentProductOrWebsite(): void + { + $this->stockRegistry->expects($this->once()) + ->method('getStockItem') + ->with(self::PRODUCT_ID, self::WEBSITE_ID) + ->willReturn(null); + + $result = $this->quantityValidator->getData(self::PRODUCT_ID, self::WEBSITE_ID); + $this->assertSame([], $result, 'Should return empty array when StockItem is not found'); + } + + public function testHandlesNullValuesFromStockItem(): void + { + $stockItem = $this->createMock(StockItemInterface::class); + $stockItem->method('getMinSaleQty') + ->willReturn(null); + $stockItem->method('getMaxSaleQty') + ->willReturn(null); + $stockItem->method('getQtyIncrements') + ->willReturn(null); + + $this->stockRegistry->expects($this->once()) + ->method('getStockItem') + ->with(self::PRODUCT_ID, self::WEBSITE_ID) + ->willReturn($stockItem); + + $expected = [ + 'validate-item-quantity' => [ + 'minAllowed' => null + ], + ]; + $result = $this->quantityValidator->getData(self::PRODUCT_ID, self::WEBSITE_ID); + $this->assertEquals($expected, $result); + } + + public function testHandlesInvalidValuesFromStockItem(): void + { + $stockItem = $this->createMock(StockItemInterface::class); + $stockItem->method('getMinSaleQty') + ->willReturn('not-a-number'); + $stockItem->method('getMaxSaleQty') + ->willReturn(-5); + $stockItem->method('getQtyIncrements') + ->willReturn(false); + + $this->stockRegistry->expects($this->once()) + ->method('getStockItem') + ->with(self::PRODUCT_ID, self::WEBSITE_ID) + ->willReturn($stockItem); + + $expected = [ + 'validate-item-quantity' => [ + 'minAllowed' => 'not-a-number', + 'maxAllowed' => -5 + ], + ]; + $result = $this->quantityValidator->getData(self::PRODUCT_ID, self::WEBSITE_ID); + $this->assertEquals($expected, $result); + } } From ddcfdec42a0277f2de4ef537c4b355c4b43240c9 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Fri, 23 May 2025 21:01:10 +0530 Subject: [PATCH 14/14] Null assigment removed --- .../CatalogInventory/Block/Plugin/ProductView.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php index 8c00dc5725239..4ec714a53ac10 100644 --- a/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php +++ b/app/code/Magento/CatalogInventory/Block/Plugin/ProductView.php @@ -7,7 +7,6 @@ use Magento\Catalog\Block\Product\View; use Magento\CatalogInventory\Model\Product\QuantityValidator; -use Magento\Framework\App\ObjectManager; class ProductView { @@ -17,14 +16,12 @@ class ProductView private $productQuantityValidator; /** - * @param QuantityValidator|null $productQuantityValidator + * @param QuantityValidator $productQuantityValidator */ public function __construct( - QuantityValidator $productQuantityValidator = null + QuantityValidator $productQuantityValidator ) { - $this->productQuantityValidator = $productQuantityValidator ?? ObjectManager::getInstance()->get( - QuantityValidator::class - ); + $this->productQuantityValidator = $productQuantityValidator; } /**
escapeHtml(__('Grouped product items')) ?>escapeHtml(__('Grouped product items')) ?>
escapeHtml(__('Product Name')) ?>escapeHtml(__('Product Name')) ?> escapeHtml(__('Qty')) ?>escapeHtml(__('Qty')) ?>
- escapeHtml($_item->getName()) ?> + + escapeHtml($_item->getName()) ?> getCanShowProductPrice($_product)): ?> getCanShowProductPrice($_item)): ?> getProductPrice($_item) ?> @@ -46,22 +46,22 @@ + isSaleable()): ?>
-
- escapeHtml(__('Out of stock')) ?> +
+ escapeHtml(__('Out of stock')) ?>
- escapeHtml(__('No options of this product are available.')) ?> + escapeHtml(__('No options of this product are available.')) ?>