/**
  * 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);
     }
 }
예제 #2
0
 /**
  * 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;
 }
예제 #4
0
 /**
  * {@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;
 }
예제 #5
0
 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));
 }
예제 #6
0
 /**
  * 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;
 }
예제 #7
0
 /**
  * @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));
 }
예제 #8
0
 /**
  * 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);
 }
예제 #9
0
 /**
  * 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;
 }
예제 #10
0
 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);
 }
예제 #11
0
 /**
  * @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);
 }
예제 #13
0
 /**
  * @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());
 }
예제 #14
0
 /**
  * @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());
 }
예제 #15
0
 /**
  * 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;
 }
예제 #16
0
 /**
  * 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));
     }
 }
예제 #17
0
 /**
  * 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;
 }
예제 #18
0
 /**
  * @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([]));
 }
예제 #20
0
 /**
  * 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;
 }
예제 #22
0
 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();
 }
예제 #23
0
 /**
  * @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));
     }
 }
예제 #25
0
 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);
 }
예제 #27
0
 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);
 }
예제 #28
0
 /**
  * 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;
 }
예제 #30
0
 /**
  * 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();
 }