From f990b5885a02db2eacda700e3438ceb3012bb627 Mon Sep 17 00:00:00 2001 From: Mohamed Azarudeen Date: Sun, 15 Dec 2024 10:50:14 +0530 Subject: [PATCH 1/6] 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 2/6] 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 3/6] 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 4/6] 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 5/6] 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 6/6] 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(
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.')) ?>