diff --git a/app/code/Magento/Bundle/Helper/Data.php b/app/code/Magento/Bundle/Helper/Data.php index dbd4a6a039c27..3205ca94b35a0 100644 --- a/app/code/Magento/Bundle/Helper/Data.php +++ b/app/code/Magento/Bundle/Helper/Data.php @@ -26,6 +26,7 @@ public function __construct( \Magento\Catalog\Model\ProductTypes\ConfigInterface $config ) { $this->config = $config; + parent::__construct($context); } diff --git a/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php b/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php index 1c3cf33cbf73b..8f45f2133812a 100644 --- a/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Ui/DataProvider/Product/BundleDataProviderTest.php @@ -7,10 +7,10 @@ use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; use Magento\Bundle\Ui\DataProvider\Product\BundleDataProvider; -use Magento\Framework\App\RequestInterface; use Magento\Catalog\Model\ResourceModel\Product\Collection; use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; use Magento\Bundle\Helper\Data; +use Magento\CatalogInventory\Api\StockStateInterface; class BundleDataProviderTest extends \PHPUnit\Framework\TestCase { @@ -21,11 +21,6 @@ class BundleDataProviderTest extends \PHPUnit\Framework\TestCase */ protected $objectManager; - /** - * @var RequestInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - /** * @var CollectionFactory|\PHPUnit_Framework_MockObject_MockObject */ @@ -41,6 +36,11 @@ class BundleDataProviderTest extends \PHPUnit\Framework\TestCase */ protected $dataHelperMock; + /** + * @var StockStateInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $stockStateMock; + /** * @return void */ @@ -48,8 +48,9 @@ protected function setUp() { $this->objectManager = new ObjectManager($this); - $this->requestMock = $this->getMockBuilder(RequestInterface::class) + $this->stockStateMock = $this->getMockBuilder(StockStateInterface::class) ->getMockForAbstractClass(); + $this->collectionMock = $this->getMockBuilder(Collection::class) ->disableOriginalConstructor() ->setMethods( @@ -86,8 +87,8 @@ protected function getModel() 'primaryFieldName' => 'testPrimaryFieldName', 'requestFieldName' => 'testRequestFieldName', 'collectionFactory' => $this->collectionFactoryMock, - 'request' => $this->requestMock, 'dataHelper' => $this->dataHelperMock, + 'stockState' => $this->stockStateMock, 'addFieldStrategies' => [], 'addFilterStrategies' => [], 'meta' => [], @@ -95,6 +96,11 @@ protected function getModel() ]); } + /** + * Testing getData() method + * + * @return void + */ public function testGetData() { $items = ['testProduct1', 'testProduct2']; @@ -127,6 +133,11 @@ public function testGetData() $this->assertEquals($expectedData, $this->getModel()->getData()); } + /** + * Testing getCollection() method + * + * @return void + */ public function testGetCollection() { $this->assertInstanceOf(Collection::class, $this->getModel()->getCollection()); diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php index 5f1ffc3c26823..ac75535c80ad2 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/BundleDataProvider.php @@ -3,11 +3,14 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Bundle\Ui\DataProvider\Product; +use Magento\Bundle\Helper\Data; use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; use Magento\Catalog\Ui\DataProvider\Product\ProductDataProvider; -use Magento\Bundle\Helper\Data; +use Magento\CatalogInventory\Api\StockStateInterface; +use Magento\Framework\App\ObjectManager; class BundleDataProvider extends ProductDataProvider { @@ -16,6 +19,11 @@ class BundleDataProvider extends ProductDataProvider */ protected $dataHelper; + /** + * @var StockStateInterface + */ + private $stockState; + /** * Construct * @@ -24,10 +32,11 @@ class BundleDataProvider extends ProductDataProvider * @param string $requestFieldName * @param CollectionFactory $collectionFactory * @param Data $dataHelper - * @param \Magento\Ui\DataProvider\AddFieldToCollectionInterface[] $addFieldStrategies - * @param \Magento\Ui\DataProvider\AddFilterToCollectionInterface[] $addFilterStrategies * @param array $meta * @param array $data + * @param \Magento\Ui\DataProvider\AddFieldToCollectionInterface[] $addFieldStrategies + * @param \Magento\Ui\DataProvider\AddFilterToCollectionInterface[] $addFilterStrategies + * @param StockStateInterface $stockState */ public function __construct( $name, @@ -38,7 +47,8 @@ public function __construct( array $meta = [], array $data = [], array $addFieldStrategies = [], - array $addFilterStrategies = [] + array $addFilterStrategies = [], + StockStateInterface $stockState = null ) { parent::__construct( $name, @@ -52,6 +62,7 @@ public function __construct( ); $this->dataHelper = $dataHelper; + $this->stockState = $stockState ?: ObjectManager::getInstance()->get(StockStateInterface::class); } /** @@ -74,6 +85,13 @@ public function getData() } $items = $this->getCollection()->toArray(); + foreach ($items as $index => $item) { + if (!is_array($item) || !array_key_exists('entity_id', $item)) { + continue; + } + $items[$index]['selection_qty_is_integer'] = !$this->stockState->isStockQtyDecimal((int)$item['entity_id']); + } + return [ 'totalRecords' => $this->getCollection()->getSize(), 'items' => array_values($items), diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php index 98fd96c52ccd9..18e3169affaee 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePanel.php @@ -69,7 +69,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function modifyMeta(array $meta) @@ -220,7 +220,8 @@ private function removeFixedTierPrice(array $meta) } /** - * {@inheritdoc} + * @param array $data + * @return array */ public function modifyData(array $data) { @@ -377,6 +378,7 @@ protected function getBundleOptions() 'selection_price_type' => '', 'selection_price_value' => '', 'selection_qty' => '', + 'selection_qty_is_integer' => 'selection_qty_is_integer', ], 'links' => ['insertData' => '${ $.provider }:${ $.dataProvider }'], 'imports' => [ @@ -682,10 +684,11 @@ protected function getBundleSelections() 'validation' => [ 'required-entry' => true, 'validate-number' => true, + 'validate-digits' => true, 'validate-greater-than-zero' => true ], 'imports' => [ - 'isInteger' => '${ $.provider }:${ $.parentScope }.selection_qty_is_integer' + 'validateDigits' => '${ $.provider }:${ $.parentScope }.selection_qty_is_integer', ], ], ], diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePrice.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePrice.php index f431012dc3fa5..d4ea8c35d163d 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePrice.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundlePrice.php @@ -5,10 +5,10 @@ */ namespace Magento\Bundle\Ui\DataProvider\Product\Form\Modifier; -use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Catalog\Api\Data\ProductAttributeInterface; -use Magento\Framework\Stdlib\ArrayManager; use Magento\Catalog\Model\Locator\LocatorInterface; +use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; +use Magento\Framework\Stdlib\ArrayManager; /** * Customize Price field @@ -41,7 +41,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function modifyMeta(array $meta) { @@ -94,7 +94,8 @@ public function modifyMeta(array $meta) } /** - * {@inheritdoc} + * @param array $data + * @return array */ public function modifyData(array $data) { diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundleWeight.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundleWeight.php index 83e045d3562cf..eba5857868bc5 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundleWeight.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/BundleWeight.php @@ -5,8 +5,8 @@ */ namespace Magento\Bundle\Ui\DataProvider\Product\Form\Modifier; -use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Catalog\Api\Data\ProductAttributeInterface; +use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Framework\Stdlib\ArrayManager; /** @@ -30,7 +30,7 @@ public function __construct(ArrayManager $arrayManager) } /** - * {@inheritdoc} + * @inheritdoc */ public function modifyMeta(array $meta) { @@ -76,12 +76,13 @@ public function modifyMeta(array $meta) ] ] ); - + return $meta; } /** - * {@inheritdoc} + * @param array $data + * @return array */ public function modifyData(array $data) { diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/Composite.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/Composite.php index 4abc72f1f3f97..b70441efe5ebc 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/Composite.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/Composite.php @@ -5,13 +5,13 @@ */ namespace Magento\Bundle\Ui\DataProvider\Product\Form\Modifier; +use Magento\Bundle\Api\ProductOptionRepositoryInterface; +use Magento\Bundle\Model\Product\Type; +use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Locator\LocatorInterface; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Framework\ObjectManagerInterface; use Magento\Ui\DataProvider\Modifier\ModifierInterface; -use Magento\Bundle\Model\Product\Type; -use Magento\Bundle\Api\ProductOptionRepositoryInterface; -use Magento\Catalog\Api\ProductRepositoryInterface; /** * Class Bundle customizes Bundle product creation flow @@ -67,7 +67,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ public function modifyMeta(array $meta) { @@ -87,7 +87,8 @@ public function modifyMeta(array $meta) } /** - * {@inheritdoc} + * @param array $data + * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/StockData.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/StockData.php index 232807208047c..b368f9233acc0 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/StockData.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Form/Modifier/StockData.php @@ -5,9 +5,9 @@ */ namespace Magento\Bundle\Ui\DataProvider\Product\Form\Modifier; +use Magento\Bundle\Model\Product\Type; use Magento\Catalog\Model\Locator\LocatorInterface; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; -use Magento\Bundle\Model\Product\Type; /** * Class StockData hides unnecessary fields in Advanced Inventory Modal @@ -28,7 +28,8 @@ public function __construct(LocatorInterface $locator) } /** - * {@inheritdoc} + * @param array $data + * @return array */ public function modifyData(array $data) { @@ -36,7 +37,8 @@ public function modifyData(array $data) } /** - * {@inheritdoc} + * @param array $meta + * @return array */ public function modifyMeta(array $meta) { diff --git a/app/code/Magento/Bundle/Ui/DataProvider/Product/Listing/Collector/BundlePrice.php b/app/code/Magento/Bundle/Ui/DataProvider/Product/Listing/Collector/BundlePrice.php index 5870a59b594ea..117d1e075ea47 100644 --- a/app/code/Magento/Bundle/Ui/DataProvider/Product/Listing/Collector/BundlePrice.php +++ b/app/code/Magento/Bundle/Ui/DataProvider/Product/Listing/Collector/BundlePrice.php @@ -10,9 +10,9 @@ use Magento\Catalog\Api\Data\ProductRender\PriceInfoInterface; use Magento\Catalog\Api\Data\ProductRender\PriceInfoInterfaceFactory; use Magento\Catalog\Api\Data\ProductRenderInterface; +use Magento\Catalog\Model\ProductRender\FormattedPriceInfoBuilder; use Magento\Catalog\Ui\DataProvider\Product\ProductRenderCollectorInterface; use Magento\Framework\Pricing\PriceCurrencyInterface; -use Magento\Catalog\Model\ProductRender\FormattedPriceInfoBuilder; /** * Collect information about bundle price diff --git a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js index e61def6e962a4..dc546ef4e4362 100644 --- a/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js +++ b/app/code/Magento/Bundle/view/adminhtml/web/js/components/bundle-option-qty.js @@ -13,7 +13,8 @@ define([ valueUpdate: 'input', isInteger: true, validation: { - 'validate-number': true + 'validate-number': true, + 'validate-digits': true } }, @@ -32,6 +33,16 @@ define([ var notEqual = this.value() !== this.initialValue.toString(); return !this.visible() ? false : notEqual; + }, + + /** + * Update field validation rules + * + * @param {Boolean} value + */ + validateDigits: function (value) { + this.isInteger = value; + this.validation['validate-digits'] = this.isInteger; } }); diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php index 336aeffa10584..b4ca81efc0939 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/AdvancedPricing.php @@ -7,14 +7,16 @@ use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Model\Locator\LocatorInterface; -use Magento\Customer\Model\Customer\Source\GroupSourceInterface; -use Magento\Directory\Helper\Data; -use Magento\Framework\App\ObjectManager; -use Magento\Store\Model\StoreManagerInterface; +use Magento\CatalogInventory\Api\StockStateInterface; use Magento\Customer\Api\GroupManagementInterface; use Magento\Customer\Api\GroupRepositoryInterface; +use Magento\Customer\Model\Customer\Source\GroupSourceInterface; +use Magento\Directory\Helper\Data; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Module\Manager as ModuleManager; +use Magento\Framework\Stdlib\ArrayManager; +use Magento\Store\Model\StoreManagerInterface; use Magento\Ui\Component\Container; use Magento\Ui\Component\Form\Element\DataType\Number; use Magento\Ui\Component\Form\Element\DataType\Price; @@ -23,7 +25,6 @@ use Magento\Ui\Component\Form\Element\Select; use Magento\Ui\Component\Form\Field; use Magento\Ui\Component\Modal; -use Magento\Framework\Stdlib\ArrayManager; /** * Class AdvancedPricing @@ -100,6 +101,11 @@ class AdvancedPricing extends AbstractModifier */ private $customerGroupSource; + /** + * @var StockStateInterface + */ + private $stockState; + /** * @param LocatorInterface $locator * @param StoreManagerInterface $storeManager @@ -111,6 +117,7 @@ class AdvancedPricing extends AbstractModifier * @param ArrayManager $arrayManager * @param string $scopeName * @param GroupSourceInterface $customerGroupSource + * @param StockStateInterface $stockState * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -123,7 +130,8 @@ public function __construct( Data $directoryHelper, ArrayManager $arrayManager, $scopeName = '', - GroupSourceInterface $customerGroupSource = null + GroupSourceInterface $customerGroupSource = null, + StockStateInterface $stockState = null ) { $this->locator = $locator; $this->storeManager = $storeManager; @@ -136,10 +144,12 @@ public function __construct( $this->scopeName = $scopeName; $this->customerGroupSource = $customerGroupSource ?: ObjectManager::getInstance()->get(GroupSourceInterface::class); + $this->stockState = $stockState ?: ObjectManager::getInstance()->get(StockStateInterface::class); } /** - * {@inheritdoc} + * @param array $meta + * @return array * @since 101.0.0 */ public function modifyMeta(array $meta) @@ -158,7 +168,8 @@ public function modifyMeta(array $meta) } /** - * {@inheritdoc} + * @param array $data + * @return array * @since 101.0.0 */ public function modifyData(array $data) @@ -270,7 +281,7 @@ private function getWebsites() 'value' => 0, ] ]; - $product = $this->locator->getProduct(); + $product = $this->getProduct(); if (!$this->isScopeGlobal() && $product->getStoreId()) { /** @var \Magento\Store\Model\Website $website */ @@ -495,14 +506,21 @@ private function getTierPriceStructure($tierPricePath) 'formElement' => Input::NAME, 'componentType' => Field::NAME, 'dataType' => Number::NAME, + 'component' => 'Magento_CatalogInventory/js/components/qty-validator-changer', 'label' => __('Quantity'), 'dataScope' => 'price_qty', 'sortOrder' => 30, 'validation' => [ 'required-entry' => true, 'validate-greater-than-zero' => true, - 'validate-digits' => false, + 'validate-number' => false, 'validate-number' => true, + 'validate-digits' => $this->hasPriceQtyDigitsValidationPassed(), + ], + 'imports' => [ + 'handleChanges' => '${ $.provider }:data.product.stock_data.is_qty_decimal', + 'changeValueType' => + '${$.provider}:data.product.stock_data.enable_qty_increments' ], ], ], @@ -624,7 +642,7 @@ private function customizeAdvancedPricing() 'componentType' => Modal::NAME, 'dataScope' => '', 'provider' => 'product_form.product_form_data_source', - 'onCancel' => 'actionDone', + 'onCancel' => 'closeModal', 'options' => [ 'title' => __('Advanced Pricing'), 'buttons' => [ @@ -676,4 +694,29 @@ private function getStore() { return $this->locator->getStore(); } + + /** + * @since 102.0.2 + * + * @return \Magento\Catalog\Api\Data\ProductInterface + */ + private function getProduct() + { + return $this->locator->getProduct(); + } + + /** + * Get Price Qty digits validation + * @since 102.0.2 + * + * @return bool + */ + private function hasPriceQtyDigitsValidationPassed() + { + if (!$this->getProduct()->getId()) { + return false; + } + + return !$this->stockState->isStockQtyDecimal($this->getProduct()->getId()); + } } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php index 6ec1cc6c46d9d..62fe5b0cba193 100755 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php @@ -3,13 +3,16 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Catalog\Ui\DataProvider\Product\Form\Modifier; use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Model\Locator\LocatorInterface; +use Magento\CatalogInventory\Api\StockStateInterface; use Magento\Eav\Api\AttributeRepositoryInterface; -use Magento\Ui\Component\Form; +use Magento\Framework\App\ObjectManager; use Magento\Framework\Stdlib\ArrayManager; +use Magento\Ui\Component\Form; /** * Data provider for main panel of product page @@ -41,20 +44,28 @@ class General extends AbstractModifier */ private $attributeRepository; + /** + * @var StockStateInterface + */ + private $stockState; + /** * @param LocatorInterface $locator * @param ArrayManager $arrayManager * @param AttributeRepositoryInterface|null $attributeRepository + * @param StockStateInterface|null $stockState */ public function __construct( LocatorInterface $locator, ArrayManager $arrayManager, - AttributeRepositoryInterface $attributeRepository = null + AttributeRepositoryInterface $attributeRepository = null, + StockStateInterface $stockState = null ) { $this->locator = $locator; $this->arrayManager = $arrayManager; $this->attributeRepository = $attributeRepository - ?: \Magento\Framework\App\ObjectManager::getInstance()->get(AttributeRepositoryInterface::class); + ?: ObjectManager::getInstance()->get(AttributeRepositoryInterface::class); + $this->stockState = $stockState ?: ObjectManager::getInstance()->get(StockStateInterface::class);; } /** @@ -125,7 +136,7 @@ protected function customizeAdvancedPriceFormat(array $data) $value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE] = $this->formatPrice($value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE]); $value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE_QTY] = - (float) $value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE_QTY]; + $this->formatPriceQty($value[ProductAttributeInterface::CODE_TIER_PRICE_FIELD_PRICE_QTY]); } } @@ -393,12 +404,30 @@ protected function customizeNameListeners(array $meta) private function getLocaleCurrency() { if ($this->localeCurrency === null) { - $this->localeCurrency = \Magento\Framework\App\ObjectManager::getInstance() + $this->localeCurrency = ObjectManager::getInstance() ->get(\Magento\Framework\Locale\CurrencyInterface::class); } return $this->localeCurrency; } + /** + * Make price qty even int or decimal + * + * @param string|int|float $priceQty + * + * @return int + */ + private function formatPriceQty($priceQty) + { + $productId = $this->locator->getProduct()->getId(); + + if ($this->stockState->isStockQtyDecimal((int)$productId)) { + return $priceQty; + } + + return (int) $priceQty; + } + /** * Format price according to the locale of the currency * @@ -437,7 +466,7 @@ protected function formatNumber($value) $store = $this->locator->getStore(); $currency = $this->getLocaleCurrency()->getCurrency($store->getBaseCurrencyCode()); $value = $currency->toCurrency($value, ['display' => \Magento\Framework\Currency::NO_SYMBOL, - 'precision' => $precision]); + 'precision' => $precision]); return $value; } diff --git a/app/code/Magento/CatalogInventory/Api/StockQtyDecimalInterface.php b/app/code/Magento/CatalogInventory/Api/StockQtyDecimalInterface.php new file mode 100644 index 0000000000000..3c48a10f51e0c --- /dev/null +++ b/app/code/Magento/CatalogInventory/Api/StockQtyDecimalInterface.php @@ -0,0 +1,24 @@ +qtyIncrements = $this->stockConfiguration->getQtyIncrements($this->getStoreId()); } else { $this->qtyIncrements = $this->getData(static::QTY_INCREMENTS); - } - if ($this->getIsQtyDecimal()) { // Cast accordingly to decimal qty usage - $this->qtyIncrements = (float) $this->qtyIncrements; - } else { - $this->qtyIncrements = (int) $this->qtyIncrements; + // set qty_increment int type if is_qty_decimal is false + if (!$this->getIsQtyDecimal()) { + $this->qtyIncrements = (int) $this->qtyIncrements; + } } } if ($this->qtyIncrements <= 0) { diff --git a/app/code/Magento/CatalogInventory/Model/StockState.php b/app/code/Magento/CatalogInventory/Model/StockState.php index ac6dc16366798..01305b6edd9d7 100644 --- a/app/code/Magento/CatalogInventory/Model/StockState.php +++ b/app/code/Magento/CatalogInventory/Model/StockState.php @@ -5,15 +5,17 @@ */ namespace Magento\CatalogInventory\Model; +use Magento\CatalogInventory\Api\Data\StockItemInterface; use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\CatalogInventory\Api\StockStateInterface; +use Magento\CatalogInventory\Api\StockQtyDecimalInterface; use Magento\CatalogInventory\Model\Spi\StockRegistryProviderInterface; use Magento\CatalogInventory\Model\Spi\StockStateProviderInterface; /** * Interface StockState */ -class StockState implements StockStateInterface +class StockState implements StockStateInterface, StockQtyDecimalInterface { /** * @var StockStateProviderInterface @@ -156,4 +158,19 @@ public function checkQuoteItemQty($productId, $itemQty, $qtyToCheck, $origQty, $ $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); return $this->stockStateProvider->checkQuoteItemQty($stockItem, $itemQty, $qtyToCheck, $origQty); } + + /** + * @param int $productId + * @param string|int|null $scopeId + * + * @return bool + */ + public function isStockQtyDecimal(int $productId, $scopeId = null): bool + { + $scopeId = $scopeId ?? $this->stockConfiguration->getDefaultScopeId(); + /** @var StockItemInterface $stockItem */ + $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); + + return $stockItem->getIsQtyDecimal(); + } } diff --git a/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml b/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml index 0a7f0fdc32d40..fbbd6eb460fc4 100644 --- a/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml +++ b/app/code/Magento/CatalogInventory/view/adminhtml/ui_component/product_form.xml @@ -578,6 +578,7 @@ qty_increments ${$.provider}:data.product.stock_data.is_qty_decimal + ${$.provider}:data.product.stock_data.enable_qty_increments diff --git a/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/qty-validator-changer.js b/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/qty-validator-changer.js index 75d684137a28b..27a9f67bf6912 100644 --- a/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/qty-validator-changer.js +++ b/app/code/Magento/CatalogInventory/view/adminhtml/web/js/components/qty-validator-changer.js @@ -20,8 +20,24 @@ define([ var isDigits = value !== 1; this.validation['validate-integer'] = isDigits; + this.validation['validate-digits'] = isDigits; this.validation['less-than-equals-to'] = isDigits ? 99999999 : 99999999.9999; this.validate(); + }, + + /** + * Change input value type when "Enable Qty Increments" is "No" + * + * @param {Number|undefined} value + */ + changeValueType: function (value) { + var isEnableQtyIncrements = value === 1; + + if (!isEnableQtyIncrements && typeof this.value() !== 'undefined') { + if (this.value().length) { + this.value(parseInt(this.value(), 10)); + } + } } }); });