/** * Return creditmemo items qty to stock * * @param EventObserver $observer * @return void */ public function execute(EventObserver $observer) { /* @var $creditmemo \Magento\Sales\Model\Order\Creditmemo */ $creditmemo = $observer->getEvent()->getCreditmemo(); $itemsToUpdate = []; foreach ($creditmemo->getAllItems() as $item) { $qty = $item->getQty(); if ($item->getBackToStock() && $qty || $this->stockConfiguration->isAutoReturnEnabled()) { $productId = $item->getProductId(); $parentItemId = $item->getOrderItem()->getParentItemId(); /* @var $parentItem \Magento\Sales\Model\Order\Creditmemo\Item */ $parentItem = $parentItemId ? $creditmemo->getItemByOrderId($parentItemId) : false; $qty = $parentItem ? $parentItem->getQty() * $qty : $qty; if (isset($itemsToUpdate[$productId])) { $itemsToUpdate[$productId] += $qty; } else { $itemsToUpdate[$productId] = $qty; } } } if (!empty($itemsToUpdate)) { $this->stockManagement->revertProductsSale($itemsToUpdate, $creditmemo->getStore()->getWebsiteId()); $updatedItemIds = array_keys($itemsToUpdate); $this->stockIndexerProcessor->reindexList($updatedItemIds); $this->priceIndexer->reindexList($updatedItemIds); } }
/** * Load inventory data for a list of product ids and a given store. * * @param integer $storeId Store id. * @param array $productIds Product ids list. * * @return array */ public function loadInventoryData($storeId, $productIds) { $websiteId = $this->getWebsiteId($storeId); $stockId = $this->getStockId($websiteId); $select = $this->getConnection()->select()->from(['ciss' => $this->getTable('cataloginventory_stock_status')], ['product_id', 'stock_status', 'qty'])->where('ciss.stock_id = ?', $stockId)->where('ciss.website_id = ?', $this->stockConfiguration->getDefaultScopeId())->where('ciss.product_id IN(?)', $productIds); return $this->getConnection()->fetchAll($select); }
/** * Update stock item on the stock and distribute qty by lots. * * @param \Magento\CatalogInventory\Model\StockManagement $subject * @param \Closure $proceed * @param array $items * @param int $websiteId is not used * @throws \Magento\Framework\Exception\LocalizedException * @return null */ public function aroundRegisterProductsSale(\Magento\CatalogInventory\Model\StockManagement $subject, \Closure $proceed, array $items, $websiteId) { /* This code is moved from original 'registerProductsSale' method. */ /* replace websiteId by stockId */ $stockId = $this->_manStock->getCurrentStockId(); $def = $this->_manTrans->begin(); $lockedItems = $this->_resourceStock->lockProductsStock(array_keys($items), $stockId); $fullSaveItems = $registeredItems = []; foreach ($lockedItems as $lockedItemRecord) { $productId = $lockedItemRecord['product_id']; $orderedQty = $items[$productId]; /** @var \Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem */ $stockItem = $this->_providerStockRegistry->getStockItem($productId, $stockId); $stockItemId = $stockItem->getItemId(); $canSubtractQty = $stockItemId && $this->_canSubtractQty($stockItem); if (!$canSubtractQty || !$this->_configStock->isQty($lockedItemRecord['type_id'])) { continue; } if (!$stockItem->hasAdminArea() && !$this->_stockState->checkQty($productId, $orderedQty)) { $this->_manTrans->rollback($def); throw new \Magento\Framework\Exception\LocalizedException(__('Not all of your products are available in the requested quantity.')); } if ($this->_canSubtractQty($stockItem)) { $stockItem->setQty($stockItem->getQty() - $orderedQty); } $registeredItems[$productId] = $orderedQty; if (!$this->_stockState->verifyStock($productId) || $this->_stockState->verifyNotification($productId)) { $fullSaveItems[] = $stockItem; } } $this->_resourceStock->correctItemsQty($registeredItems, $stockId, '-'); $this->_manTrans->commit($def); return $fullSaveItems; }
/** * {@inheritdoc} */ public function modifyData(array $data) { $fieldCode = 'quantity_and_stock_status'; $model = $this->locator->getProduct(); $modelId = $model->getId(); /** @var StockItemInterface $stockItem */ $stockItem = $this->stockRegistry->getStockItem($modelId, $model->getStore()->getWebsiteId()); $stockData = $modelId ? $this->getData($stockItem) : []; if (!empty($stockData)) { $data[$modelId][self::DATA_SOURCE_DEFAULT][self::STOCK_DATA_FIELDS] = $stockData; } if (isset($stockData['is_in_stock'])) { $data[$modelId][self::DATA_SOURCE_DEFAULT][$fieldCode]['is_in_stock'] = (int) $stockData['is_in_stock']; } if (!empty($this->stockConfiguration->getDefaultConfigValue(StockItemInterface::MIN_SALE_QTY))) { $minSaleQtyData = null; $defaultConfigValue = $this->stockConfiguration->getDefaultConfigValue(StockItemInterface::MIN_SALE_QTY); if (strpos($defaultConfigValue, 'a:') === 0) { // Set data source for dynamicRows Minimum Qty Allowed in Shopping Cart $minSaleQtyValue = unserialize($defaultConfigValue); foreach ($minSaleQtyValue as $group => $qty) { $minSaleQtyData[] = [StockItemInterface::CUSTOMER_GROUP_ID => $group, StockItemInterface::MIN_SALE_QTY => $qty]; } } else { $minSaleQtyData = $defaultConfigValue; } $path = $modelId . '/' . self::DATA_SOURCE_DEFAULT . '/stock_data/min_qty_allowed_in_shopping_cart'; $data = $this->arrayManager->set($path, $data, $minSaleQtyData); } return $data; }
public function testAssignStatusToProduct() { $websiteId = 1; $status = 'test'; $stockStatusMock = $this->getMockBuilder('Magento\\CatalogInventory\\Api\\Data\\StockStatusInterface')->disableOriginalConstructor()->getMock(); $stockStatusMock->expects($this->any())->method('getStockStatus')->willReturn($status); $this->stockRegistryProviderMock->expects($this->any())->method('getStockStatus')->willReturn($stockStatusMock); $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn($websiteId); $productMock = $this->getMockBuilder('Magento\\Catalog\\Model\\Product')->disableOriginalConstructor()->setMethods(['setIsSalable', 'getId'])->getMock(); $productMock->expects($this->once())->method('setIsSalable')->with($status); $this->assertNull($this->stock->assignStatusToProduct($productMock)); }
/** * Add products to items and item options * * @return $this */ protected function _assignProducts() { \Magento\Framework\Profiler::start('WISHLIST:' . __METHOD__, ['group' => 'WISHLIST', 'method' => __METHOD__]); $productIds = []; $this->_productIds = array_merge($this->_productIds, array_keys($productIds)); /** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection */ $productCollection = $this->_productCollectionFactory->create(); if ($this->_productVisible) { $productCollection->setVisibility($this->_productVisibility->getVisibleInSiteIds()); } $productCollection->addPriceData()->addTaxPercents()->addIdFilter($this->_productIds)->addAttributeToSelect('*')->addOptionsToResult()->addUrlRewrite(); if ($this->_productSalable) { $productCollection = $this->_adminhtmlSales->applySalableProductTypesFilter($productCollection); } $this->_eventManager->dispatch('wishlist_item_collection_products_after_load', ['product_collection' => $productCollection]); $checkInStock = $this->_productInStock && !$this->stockConfiguration->isShowOutOfStock(); foreach ($this as $item) { $product = $productCollection->getItemById($item->getProductId()); if ($product) { if ($checkInStock && !$product->isInStock()) { $this->removeItemByKey($item->getId()); } else { $product->setCustomOptions([]); $item->setProduct($product); $item->setProductName($product->getName()); $item->setName($product->getName()); $item->setPrice($product->getPrice()); } } else { $item->isDeleted(true); } } \Magento\Framework\Profiler::stop('WISHLIST:' . __METHOD__); return $this; }
/** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function testGenerateSimpleProducts() { $productsData = [6 => ['image' => 'image.jpg', 'name' => 'config-red', 'configurable_attribute' => '{"new_attr":"6"}', 'sku' => 'config-red', 'quantity_and_stock_status' => ['qty' => ''], 'weight' => '333']]; $stockData = ['manage_stock' => '0', 'use_config_enable_qty_increments' => '1', 'use_config_qty_increments' => '1', 'use_config_manage_stock' => 0, 'is_decimal_divided' => 0]; $parentProductMock = $this->getMockBuilder('\\Magento\\Catalog\\Model\\Product')->setMethods(['__wakeup', 'getNewVariationsAttributeSetId', 'getStockData', 'getQuantityAndStockStatus', 'getWebsiteIds'])->disableOriginalConstructor()->getMock(); $newSimpleProductMock = $this->getMockBuilder('\\Magento\\Catalog\\Model\\Product')->setMethods(['__wakeup', 'save', 'getId', 'setStoreId', 'setTypeId', 'setAttributeSetId', 'getTypeInstance', 'getStoreId', 'addData', 'setWebsiteIds', 'setStatus', 'setVisibility'])->disableOriginalConstructor()->getMock(); $productTypeMock = $this->getMockBuilder('Magento\\Catalog\\Model\\Product\\Type')->setMethods(['getSetAttributes'])->disableOriginalConstructor()->getMock(); $editableAttributeMock = $this->getMockBuilder('Magento\\Eav\\Model\\Entity\\Attribute')->setMethods(['getIsUnique', 'getAttributeCode', 'getFrontend', 'getIsVisible'])->disableOriginalConstructor()->getMock(); $frontendAttributeMock = $this->getMockBuilder('Magento\\Eav\\Model\\Entity\\Attribute\\Frontend')->setMethods(['getInputType'])->disableOriginalConstructor()->getMock(); $parentProductMock->expects($this->once())->method('getNewVariationsAttributeSetId')->willReturn('new_attr_set_id'); $this->productFactoryMock->expects($this->once())->method('create')->willReturn($newSimpleProductMock); $newSimpleProductMock->expects($this->once())->method('setStoreId')->with(0)->willReturnSelf(); $newSimpleProductMock->expects($this->once())->method('setTypeId')->with('simple')->willReturnSelf(); $newSimpleProductMock->expects($this->once())->method('setAttributeSetId')->with('new_attr_set_id')->willReturnSelf(); $newSimpleProductMock->expects($this->once())->method('getTypeInstance')->willReturn($productTypeMock); $productTypeMock->expects($this->once())->method('getSetAttributes')->with($newSimpleProductMock)->willReturn([$editableAttributeMock]); $editableAttributeMock->expects($this->once())->method('getIsUnique')->willReturn(false); $editableAttributeMock->expects($this->once())->method('getAttributeCode')->willReturn('some_code'); $editableAttributeMock->expects($this->any())->method('getFrontend')->willReturn($frontendAttributeMock); $frontendAttributeMock->expects($this->any())->method('getInputType')->willReturn('input_type'); $editableAttributeMock->expects($this->any())->method('getIsVisible')->willReturn(false); $parentProductMock->expects($this->once())->method('getStockData')->willReturn($stockData); $parentProductMock->expects($this->once())->method('getQuantityAndStockStatus')->willReturn(['is_in_stock' => 1]); $newSimpleProductMock->expects($this->once())->method('getStoreId')->willReturn('store_id'); $this->stockConfiguration->expects($this->once())->method('getManageStock')->with('store_id')->willReturn(1); $newSimpleProductMock->expects($this->once())->method('addData')->willReturnSelf(); $parentProductMock->expects($this->once())->method('getWebsiteIds')->willReturn('website_id'); $newSimpleProductMock->expects($this->once())->method('setWebsiteIds')->with('website_id')->willReturnSelf(); $newSimpleProductMock->expects($this->once())->method('setVisibility')->with(1)->willReturnSelf(); $newSimpleProductMock->expects($this->once())->method('save')->willReturnSelf(); $newSimpleProductMock->expects($this->once())->method('getId')->willReturn('product_id'); $this->assertEquals(['product_id'], $this->model->generateSimpleProducts($parentProductMock, $productsData)); }
/** * Run test getDefaultConfigValue method * * @return void */ public function testGetDefaultConfigValue() { $field = 'filed-name'; $this->stockConfigurationMock->expects($this->once())->method('getDefaultConfigValue')->will($this->returnValue('return-value')); $result = $this->inventory->getDefaultConfigValue($field); $this->assertEquals('return-value', $result); }
/** * Add Notify Stock Qty Condition to collection * * @param null|int $storeId * @return $this */ public function useNotifyStockQtyFilter($storeId = null) { $this->joinInventoryItem(['qty']); $notifyStockExpr = $this->getConnection()->getCheckSql($this->_getInventoryItemField('use_config_notify_stock_qty') . ' = 1', (int) $this->stockConfiguration->getNotifyStockQty($storeId), $this->_getInventoryItemField('notify_stock_qty')); $this->getSelect()->where($this->_getInventoryItemField('qty') . ' < ?', $notifyStockExpr); return $this; }
public function testRefundOrderInventory() { $websiteId = 0; $ids = ['1', '14']; $items = []; $isAutoReturnEnabled = true; $itemsToUpdate = []; foreach ($ids as $id) { $item = $this->getCreditMemoItem($id); $items[] = $item; $itemsToUpdate[$item->getProductId()] = $item->getQty(); } $creditMemo = $this->getMock('Magento\\Sales\\Model\\Order\\Creditmemo', [], [], '', false); $creditMemo->expects($this->once())->method('getAllItems')->will($this->returnValue($items)); $store = $this->getMock('Magento\\Store\\Model\\Store', ['getWebsiteId', '__wakeup'], [], '', false); $store->expects($this->once())->method('getWebsiteId')->will($this->returnValue($websiteId)); $creditMemo->expects($this->once())->method('getStore')->will($this->returnValue($store)); $this->stockConfiguration->expects($this->any())->method('isAutoReturnEnabled')->will($this->returnValue($isAutoReturnEnabled)); $this->stockManagement->expects($this->once())->method('revertProductsSale')->with($itemsToUpdate, $websiteId); $this->stockIndexerProcessor->expects($this->once())->method('reindexList')->with($ids); $this->priceIndexer->expects($this->once())->method('reindexList')->with($ids); $this->event->expects($this->once())->method('getCreditmemo')->will($this->returnValue($creditMemo)); $this->eventObserver->expects($this->atLeastOnce())->method('getEvent')->will($this->returnValue($this->event)); $this->observer->refundOrderInventory($this->eventObserver); }
/** * @param string $productSku * @param null $websiteId * @return int * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function getProductStockStatusBySku($productSku, $websiteId = null) { //if (!$websiteId) { $websiteId = $this->stockConfiguration->getDefaultWebsiteId(); //} $productId = $this->resolveProductId($productSku); return $this->getProductStockStatus($productId, $websiteId); }
/** * @param int $productId * @param float $itemQty * @param float $qtyToCheck * @param float $origQty * @param int $scopeId * @return int */ public function checkQuoteItemQty($productId, $itemQty, $qtyToCheck, $origQty, $scopeId = null) { if ($scopeId === null) { $scopeId = $this->stockConfiguration->getDefaultScopeId(); } $stockItem = $this->stockRegistryProvider->getStockItem($productId, $scopeId); return $this->stockStateProvider->checkQuoteItemQty($stockItem, $itemQty, $qtyToCheck, $origQty); }
/** * @magentoDataFixture Magento/Store/_files/website.php * @magentoDataFixture Magento/Catalog/_files/product_simple.php * * @throws \Magento\Framework\Exception\NoSuchEntityException */ public function testReindexEntity() { /** @var \Magento\Catalog\Model\ProductRepository $productRepository */ $productRepository = $this->getObject(\Magento\Catalog\Model\ProductRepository::class); /** @var \Magento\Store\Api\WebsiteRepositoryInterface $websiteRepository */ $websiteRepository = $this->getObject(\Magento\Store\Api\WebsiteRepositoryInterface::class); $product = $productRepository->get('simple'); $testWebsite = $websiteRepository->get('test'); $product->setWebsiteIds([1, $testWebsite->getId()])->save(); /** @var \Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory $criteriaFactory */ $criteriaFactory = $this->getObject(\Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory::class); /** @var \Magento\CatalogInventory\Api\StockStatusRepositoryInterface $stockStatusRepository */ $stockStatusRepository = $this->getObject(\Magento\CatalogInventory\Api\StockStatusRepositoryInterface::class); $criteria = $criteriaFactory->create(); $criteria->setProductsFilter([$product->getId()]); $criteria->addFilter('website', 'website_id', $this->stockConfiguration->getDefaultScopeId()); $items = $stockStatusRepository->getList($criteria)->getItems(); $this->assertEquals($product->getId(), $items[$product->getId()]->getProductId()); }
/** * @param bool $useConfigMinQty * @param float $minQty * @dataProvider setMinQtyDataProvider */ public function testSetMinQty($useConfigMinQty, $minQty) { $this->setDataArrayValue('use_config_min_qty', $useConfigMinQty); if ($useConfigMinQty) { $this->stockConfiguration->expects($this->any())->method('getMinQty')->will($this->returnValue($minQty)); } else { $this->setDataArrayValue('min_qty', $minQty); } $this->assertSame($minQty, $this->item->getMinQty()); }
/** * Filter stock data * * @param array $stockData * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function filter(array $stockData) { if (!isset($stockData['use_config_manage_stock'])) { $stockData['use_config_manage_stock'] = 0; } if ($stockData['use_config_manage_stock'] == 1 && !isset($stockData['manage_stock'])) { $stockData['manage_stock'] = $this->stockConfiguration->getManageStock(); } if (isset($stockData['qty']) && (double) $stockData['qty'] > self::MAX_QTY_VALUE) { $stockData['qty'] = self::MAX_QTY_VALUE; } if (isset($stockData['min_qty']) && (int) $stockData['min_qty'] < 0) { $stockData['min_qty'] = 0; } if (!isset($stockData['is_decimal_divided']) || $stockData['is_qty_decimal'] == 0) { $stockData['is_decimal_divided'] = 0; } return $stockData; }
/** * Load some inventory configuration settings * * @return void */ protected function _initConfig() { if (!$this->_isConfig) { $configMap = ['_isConfigManageStock' => \Magento\CatalogInventory\Model\Configuration::XML_PATH_MANAGE_STOCK, '_isConfigBackorders' => \Magento\CatalogInventory\Model\Configuration::XML_PATH_BACKORDERS, '_configMinQty' => \Magento\CatalogInventory\Model\Configuration::XML_PATH_MIN_QTY, '_configNotifyStockQty' => \Magento\CatalogInventory\Model\Configuration::XML_PATH_NOTIFY_STOCK_QTY]; foreach ($configMap as $field => $const) { $this->{$field} = (int) $this->_scopeConfig->getValue($const, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); } $this->_isConfig = true; $this->_configTypeIds = array_keys($this->stockConfiguration->getIsQtyTypeIds(true)); } }
/** * Initialize creditmemo model instance * * @return \Magento\Sales\Model\Order\Creditmemo|false * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function load() { $creditmemo = false; $creditmemoId = $this->getCreditmemoId(); $orderId = $this->getOrderId(); if ($creditmemoId) { $creditmemo = $this->creditmemoFactory->create()->load($creditmemoId); } elseif ($orderId) { $data = $this->getCreditmemo(); $order = $this->orderFactory->create()->load($orderId); $invoice = $this->_initInvoice($order); if (!$this->_canCreditmemo($order)) { return false; } $savedData = $this->_getItemData(); $qtys = []; $backToStock = []; foreach ($savedData as $orderItemId => $itemData) { if (isset($itemData['qty'])) { $qtys[$orderItemId] = $itemData['qty']; } if (isset($itemData['back_to_stock'])) { $backToStock[$orderItemId] = true; } } $data['qtys'] = $qtys; $service = $this->orderServiceFactory->create(['order' => $order]); if ($invoice) { $creditmemo = $service->prepareInvoiceCreditmemo($invoice, $data); } else { $creditmemo = $service->prepareCreditmemo($data); } /** * Process back to stock flags */ foreach ($creditmemo->getAllItems() as $creditmemoItem) { $orderItem = $creditmemoItem->getOrderItem(); $parentId = $orderItem->getParentItemId(); if (isset($backToStock[$orderItem->getId()])) { $creditmemoItem->setBackToStock(true); } elseif ($orderItem->getParentItem() && isset($backToStock[$parentId]) && $backToStock[$parentId]) { $creditmemoItem->setBackToStock(true); } elseif (empty($savedData)) { $creditmemoItem->setBackToStock($this->stockConfiguration->isAutoReturnEnabled()); } else { $creditmemoItem->setBackToStock(false); } } } $this->eventManager->dispatch('adminhtml_sales_order_creditmemo_register_before', ['creditmemo' => $creditmemo, 'input' => $this->getCreditmemo()]); $this->registry->register('current_creditmemo', $creditmemo); return $creditmemo; }
/** * @param array $config * @param mixed $expected * @dataProvider getQtyIncrementsDataProvider( */ public function testGetQtyIncrements($config, $expected) { $this->setDataArrayValue('qty_increments', $config['qty_increments']); $this->setDataArrayValue('enable_qty_increments', $config['enable_qty_increments']); $this->setDataArrayValue('use_config_qty_increments', $config['use_config_qty_increments']); if ($config['use_config_qty_increments']) { $this->stockConfiguration->expects($this->once())->method('getQtyIncrements')->with($this->storeId)->willReturn($config['qty_increments']); } else { $this->setDataArrayValue('qty_increments', $config['qty_increments']); } $this->assertEquals($expected, $this->item->getQtyIncrements()); }
public function testModifyData() { $modelId = 1; $someData = 1; $this->productMock->expects($this->any())->method('getId')->willReturn($modelId); $this->stockConfigurationMock->expects($this->any())->method('getDefaultConfigValue')->willReturn("a:0:{}"); $this->stockItemMock->expects($this->once())->method('getData')->willReturn(['someData']); $this->stockItemMock->expects($this->once())->method('getManageStock')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getQty')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getMinQty')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getMinSaleQty')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getMaxSaleQty')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getIsQtyDecimal')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getIsDecimalDivided')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getBackorders')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getNotifyStockQty')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getEnableQtyIncrements')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getQtyIncrements')->willReturn($someData); $this->stockItemMock->expects($this->once())->method('getIsInStock')->willReturn($someData); $this->arrayManagerMock->expects($this->once())->method('set')->with('1/product/stock_data/min_qty_allowed_in_shopping_cart')->willReturnArgument(1); $this->assertArrayHasKey($modelId, $this->getModel()->modifyData([])); }
/** * Update items low stock date basing on their quantities and config settings * * @param int|string $website * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @return void */ public function updateLowStockDate($website) { $websiteId = $this->stockConfiguration->getDefaultScopeId(); $this->_initConfig(); $connection = $this->getConnection(); $condition = $connection->quoteInto('(use_config_notify_stock_qty = 1 AND qty < ?)', $this->_configNotifyStockQty) . ' OR (use_config_notify_stock_qty = 0 AND qty < notify_stock_qty)'; $currentDbTime = $connection->quoteInto('?', $this->dateTime->gmtDate()); $conditionalDate = $connection->getCheckSql($condition, $currentDbTime, 'NULL'); $value = ['low_stock_date' => new \Zend_Db_Expr($conditionalDate)]; $select = $connection->select()->from($this->getTable('catalog_product_entity'), 'entity_id')->where('type_id IN(?)', $this->_configTypeIds); $where = sprintf('website_id = %1$d' . ' AND ((use_config_manage_stock = 1 AND 1 = %2$d) OR (use_config_manage_stock = 0 AND manage_stock = 1))' . ' AND product_id IN (%3$s)', $websiteId, $this->_isConfigManageStock, $select->assemble()); $connection->update($this->getTable('cataloginventory_stock_item'), $value, $where); }
/** * Prepare stock item data for save * * @param \Magento\Catalog\Model\Product $product * @return $this */ protected function saveStockItemData($product) { $stockItemData = $product->getStockData(); $stockItemData['product_id'] = $product->getId(); if (!isset($stockItemData['website_id'])) { $stockItemData['website_id'] = $this->stockConfiguration->getDefaultScopeId(); } $stockItemData['stock_id'] = $this->stockRegistry->getStock($stockItemData['website_id'])->getStockId(); foreach ($this->paramListToCheck as $dataKey => $configPath) { if (null !== $product->getData($configPath['item']) && null === $product->getData($configPath['config'])) { $stockItemData[$dataKey] = false; } } $originalQty = $product->getData('stock_data/original_inventory_qty'); if (strlen($originalQty) > 0) { $stockItemData['qty_correction'] = (isset($stockItemData['qty']) ? $stockItemData['qty'] : 0) - $originalQty; } // todo resolve issue with builder and identity field name $stockItem = $this->stockRegistry->getStockItem($stockItemData['product_id'], $stockItemData['website_id']); $stockItem->addData($stockItemData); $this->stockItemRepository->save($stockItem); return $this; }
public function testExecuteThatProductIdsAreObtainedFromAttributeHelper() { $this->attributeHelper->expects($this->any())->method('getProductIds')->will($this->returnValue([5])); $this->attributeHelper->expects($this->any())->method('getSelectedStoreId')->will($this->returnValue([1])); $this->attributeHelper->expects($this->any())->method('getStoreWebsiteId')->will($this->returnValue(1)); $this->stockConfig->expects($this->any())->method('getConfigItemOptions')->will($this->returnValue([])); $this->dataObjectHelperMock->expects($this->any())->method('populateWithArray')->with($this->stockItem, $this->anything(), '\\Magento\\CatalogInventory\\Api\\Data\\StockItemInterface')->willReturnSelf(); $this->product->expects($this->any())->method('isProductsHasSku')->with([5])->will($this->returnValue(true)); $this->stockItemService->expects($this->any())->method('getStockItem')->with(5, 1)->will($this->returnValue($this->stockItem)); $this->stockIndexerProcessor->expects($this->any())->method('reindexList')->with([5]); $this->request->expects($this->any())->method('getParam')->will($this->returnValueMap([['inventory', [], [7]]])); $this->messageManager->expects($this->never())->method('addError'); $this->messageManager->expects($this->never())->method('addException'); $this->object->execute(); }
/** * @expectedException \Magento\Framework\Exception\CouldNotSaveException */ public function testSaveException() { $productId = 1; $this->stockItemMock->expects($this->any())->method('getProductId')->willReturn($productId); $this->productMock->expects($this->once())->method('load')->with($productId)->willReturnSelf(); $this->productMock->expects($this->once())->method('getId')->willReturn($productId); $this->productMock->expects($this->once())->method('getTypeId')->willReturn('typeId'); $this->stockConfigurationMock->expects($this->once())->method('isQty')->with('typeId')->willReturn(false); $this->stockItemMock->expects($this->once())->method('setQty')->with(0)->willReturnSelf(); $this->stockItemMock->expects($this->once())->method('getWebsiteId')->willReturn(1); $this->stockItemMock->expects($this->once())->method('setWebsiteId')->with(1)->willReturnSelf(); $this->stockItemMock->expects($this->once())->method('getStockId')->willReturn(1); $this->stockItemMock->expects($this->once())->method('setStockId')->with(1)->willReturnSelf(); $this->stockItemResourceMock->expects($this->once())->method('save')->with($this->stockItemMock)->willThrowException(new \Exception()); $this->model->save($this->stockItemMock); }
/** * @param ProductInterface $product * @param StockItemInterface $stockItem * @throws LocalizedException * @return void */ private function validateStockItem(ProductInterface $product, StockItemInterface $stockItem) { $defaultScopeId = $this->stockConfiguration->getDefaultScopeId(); $defaultStockId = $this->stockRegistry->getStock($defaultScopeId)->getStockId(); $stockId = $stockItem->getStockId(); if ($stockId !== null && $stockId != $defaultStockId) { throw new LocalizedException(__('Invalid stock id: %1. Only default stock with id %2 allowed', $stockId, $defaultStockId)); } $stockItemId = $stockItem->getItemId(); if ($stockItemId !== null && (!is_numeric($stockItemId) || $stockItemId <= 0)) { throw new LocalizedException(__('Invalid stock item id: %1. Should be null or numeric value greater than 0', $stockItemId)); } $defaultStockItemId = $this->stockRegistry->getStockItem($product->getId())->getItemId(); if ($defaultStockItemId && $stockItemId !== null && $defaultStockItemId != $stockItemId) { throw new LocalizedException(__('Invalid stock item id: %1. Assigned stock item id is %2', $stockItemId, $defaultStockItemId)); } }
public function testExecuteThatProductIdsAreObtainedFromAttributeHelper() { $this->attributeHelper->expects($this->any())->method('getProductIds')->will($this->returnValue([5])); $this->attributeHelper->expects($this->any())->method('getSelectedStoreId')->will($this->returnValue([1])); $this->attributeHelper->expects($this->any())->method('getStoreWebsiteId')->will($this->returnValue(1)); $this->stockConfig->expects($this->any())->method('getConfigItemOptions')->will($this->returnValue([])); $itemToSave = $this->getMockBuilder('Magento\\CatalogInventory\\Api\\Data\\StockItemInterface')->disableOriginalConstructor()->setMethods(['setItemId', 'save'])->getMockForAbstractClass(); $this->stockItemBuilder->expects($this->any())->method('mergeDataObjectWithArray')->withAnyParameters()->willReturnSelf(); $this->stockItemBuilder->expects($this->any())->method('create')->willReturn($itemToSave); $this->product->expects($this->any())->method('isProductsHasSku')->with([5])->will($this->returnValue(true)); $this->stockItemService->expects($this->any())->method('getStockItem')->with(5, 1)->will($this->returnValue($this->stockItem)); $this->stockIndexerProcessor->expects($this->any())->method('reindexList')->with([5]); $this->request->expects($this->any())->method('getParam')->will($this->returnValueMap([['inventory', [], [7]]])); $this->messageManager->expects($this->never())->method('addError'); $this->messageManager->expects($this->never())->method('addException'); $this->object->execute(); }
/** * @expectedException \Magento\Framework\Exception\LocalizedException * @expectedExceptionMessage Invalid stock item id: 35. Assigned stock item id is 40 */ public function testAroundSaveWithNotAssignedStockItemId() { $stockId = 80; $stockItemId = 35; $defaultScopeId = 100; $defaultStockId = 80; $storedStockitemId = 40; $this->stockItem->expects($this->once())->method('getStockId')->willReturn($stockId); $this->stockRegistry->expects($this->once())->method('getStock')->with($defaultScopeId)->willReturn($this->defaultStock); $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn($defaultScopeId); $this->defaultStock->expects($this->once())->method('getStockId')->willReturn($defaultStockId); $this->product->expects($this->once())->method('getExtensionAttributes')->willReturn($this->productExtension); $this->productExtension->expects($this->once())->method('getStockItem')->willReturn($this->stockItem); $this->stockItem->expects($this->once())->method('getItemId')->willReturn($stockItemId); $storedStockItem = $this->getMockBuilder(StockItemInterface::class)->setMethods(['getItemId'])->getMockForAbstractClass(); $storedStockItem->expects($this->once())->method('getItemId')->willReturn($storedStockitemId); $this->stockRegistry->expects($this->once())->method('getStockItem')->willReturn($storedStockItem); $this->plugin->aroundSave($this->productRepository, $this->closure, $this->product); }
public function testBuildWithoutOutOfStock() { $scopeId = '113'; $tableSuffix = 'scope113_someNamesomeValue'; $index = 'test_index_name'; $dimensions = [$this->createDimension('scope', $scopeId), $this->createDimension('someName', 'someValue')]; $this->request->expects($this->exactly(2))->method('getDimensions')->willReturn($dimensions); $this->dimensionScopeResolver->expects($this->once())->method('getScope')->willReturn($this->scopeInterface); $this->scopeInterface->expects($this->once())->method('getId')->willReturn('someValue'); $this->mockBuild($index, $tableSuffix, false); $this->stockConfiguration->expects($this->once())->method('getDefaultScopeId')->willReturn(1); $this->config->expects($this->once())->method('isSetFlag')->with('cataloginventory/options/show_out_of_stock')->will($this->returnValue(false)); $this->connection->expects($this->once())->method('quoteInto')->with(' AND stock_index.website_id = ?', 1)->willReturn(' AND stock_index.website_id = 1'); $this->select->expects($this->at(2))->method('where')->with('(someName=someValue)')->willReturnSelf(); $this->select->expects($this->at(3))->method('joinLeft')->with(['stock_index' => 'cataloginventory_stock_status'], 'search_index.entity_id = stock_index.product_id' . ' AND stock_index.website_id = 1', [])->willReturnSelf(); $this->select->expects($this->at(4))->method('where')->with('stock_index.stock_status = ?', 1)->will($this->returnSelf()); $result = $this->target->build($this->request); $this->assertSame($this->select, $result); }
/** * Fill simple product data during generation * * @param \Magento\Catalog\Model\Product $product * @param \Magento\Catalog\Model\Product $parentProduct * @param array $postData * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * * @return void */ protected function fillSimpleProductData(\Magento\Catalog\Model\Product $product, \Magento\Catalog\Model\Product $parentProduct, $postData) { $product->setStoreId(\Magento\Store\Model\Store::DEFAULT_STORE_ID)->setTypeId($postData['weight'] ? ProductType::TYPE_SIMPLE : ProductType::TYPE_VIRTUAL)->setAttributeSetId($parentProduct->getNewVariationsAttributeSetId()); foreach ($product->getTypeInstance()->getEditableAttributes($product) as $attribute) { if ($attribute->getIsUnique() || $attribute->getAttributeCode() == 'url_key' || $attribute->getFrontend()->getInputType() == 'gallery' || $attribute->getFrontend()->getInputType() == 'media_image' || !$attribute->getIsVisible()) { continue; } $product->setData($attribute->getAttributeCode(), $parentProduct->getData($attribute->getAttributeCode())); } $postData['stock_data'] = $parentProduct->getStockData(); $postData['stock_data']['manage_stock'] = $postData['quantity_and_stock_status']['qty'] === '' ? 0 : 1; if (!isset($postData['stock_data']['is_in_stock'])) { $stockStatus = $parentProduct->getQuantityAndStockStatus(); $postData['stock_data']['is_in_stock'] = $stockStatus['is_in_stock']; } $configDefaultValue = $this->stockConfiguration->getManageStock($product->getStoreId()); $postData['stock_data']['use_config_manage_stock'] = $postData['stock_data']['manage_stock'] == $configDefaultValue ? 1 : 0; $postData = $this->processMediaGallery($product, $postData); $postData['status'] = isset($postData['status']) ? $postData['status'] : \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; $product->addData($postData)->setWebsiteIds($parentProduct->getWebsiteIds())->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_NOT_VISIBLE); }
/** * @inheritdoc */ public function save(\Magento\CatalogInventory\Api\Data\StockItemInterface $stockItem) { try { /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productFactory->create(); $product->load($stockItem->getProductId()); if (!$product->getId()) { return $stockItem; } $typeId = $product->getTypeId() ?: $product->getTypeInstance()->getTypeId(); $isQty = $this->stockConfiguration->isQty($typeId); if ($isQty) { $isInStock = $this->stockStateProvider->verifyStock($stockItem); if ($stockItem->getManageStock() && !$isInStock) { $stockItem->setIsInStock(false)->setStockStatusChangedAutomaticallyFlag(true); } // if qty is below notify qty, update the low stock date to today date otherwise set null $stockItem->setLowStockDate(null); if ($this->stockStateProvider->verifyNotification($stockItem)) { $stockItem->setLowStockDate((new \DateTime())->format('Y-m-d H:i:s')); } $stockItem->setStockStatusChangedAuto(0); if ($stockItem->hasStockStatusChangedAutomaticallyFlag()) { $stockItem->setStockStatusChangedAuto((int) $stockItem->getStockStatusChangedAutomaticallyFlag()); } } else { $stockItem->setQty(0); } $stockItem->setWebsiteId($stockItem->getWebsiteId()); $stockItem->setStockId($stockItem->getStockId()); $this->resource->save($stockItem); $this->indexProcessor->reindexRow($stockItem->getProductId()); } catch (\Exception $exception) { throw new CouldNotSaveException(__($exception->getMessage())); } return $stockItem; }
/** * Check if is possible subtract value from item qty * * @param StockItemInterface $stockItem * @return bool */ protected function canSubtractQty(StockItemInterface $stockItem) { return $stockItem->getManageStock() && $this->stockConfiguration->canSubtractQty(); }