/** * Set inventory data to custom attribute * * @param Product $object * @return $this */ public function afterLoad($object) { $stockItemDo = $this->stockItemService->getStockItem($object->getId()); $object->setData($this->getAttribute()->getAttributeCode(), array('is_in_stock' => $stockItemDo->getIsInStock(), 'qty' => $stockItemDo->getQty())); return parent::afterLoad($object); }
/** * Copy product inventory data (used for product duplicate functionality) * * @param \Magento\Catalog\Model\Product $product * @param \Magento\Catalog\Model\Product $duplicate * @return void */ public function build(\Magento\Catalog\Model\Product $product, \Magento\Catalog\Model\Product $duplicate) { $stockData = ['use_config_min_qty' => 1, 'use_config_min_sale_qty' => 1, 'use_config_max_sale_qty' => 1, 'use_config_backorders' => 1, 'use_config_notify_stock_qty' => 1]; /** @var \Magento\CatalogInventory\Service\V1\Data\StockItem $currentStockItemDo */ $currentStockItemDo = $this->stockItemService->getStockItem($product->getId()); if ($currentStockItemDo->getStockId()) { $stockData += ['use_config_enable_qty_inc' => $currentStockItemDo->isUseConfigEnableQtyInc(), 'enable_qty_increments' => $currentStockItemDo->isEnableQtyIncrements(), 'use_config_qty_increments' => $currentStockItemDo->isUseConfigQtyIncrements(), 'qty_increments' => $currentStockItemDo->getQtyIncrements()]; } $duplicate->setStockData($stockData); }
public function testGetStockItem() { $productId = 123; $stockItemData = ['some_key' => 'someValue']; $stockItemModel = $this->getMockBuilder('Magento\\CatalogInventory\\Model\\Stock\\Item')->disableOriginalConstructor()->getMock(); $stockItemModel->expects($this->once())->method('getData')->will($this->returnValue($stockItemData)); $this->stockItemRegistry->expects($this->once())->method('retrieve')->with($productId)->will($this->returnValue($stockItemModel)); $this->stockItemBuilder->expects($this->once())->method('populateWithArray')->with($stockItemData); $stockItemDo = $this->getMockBuilder('Magento\\CatalogInventory\\Service\\V1\\Data\\StockItem')->disableOriginalConstructor()->getMock(); $this->stockItemBuilder->expects($this->once())->method('create')->will($this->returnValue($stockItemDo)); $this->assertEquals($stockItemDo, $this->model->getStockItem($productId)); }
/** * @param \Magento\Sales\Model\Quote $quote * @param \Magento\Catalog\Model\Product $product * @param \Magento\Framework\Object $config * @return \Magento\Sales\Model\Quote\Item|string */ public function init(\Magento\Sales\Model\Quote $quote, \Magento\Catalog\Model\Product $product, \Magento\Framework\Object $config) { /** @var \Magento\CatalogInventory\Service\V1\Data\StockItem $stockItemDo */ $stockItemDo = $this->stockItemService->getStockItem($product->getId()); if ($stockItemDo->getStockId() && $stockItemDo->getIsQtyDecimal()) { $product->setIsQtyDecimal(1); } else { $config->setQty((int) $config->getQty()); } $product->setCartQty($config->getQty()); $item = $quote->addProduct($product, $config, \Magento\Catalog\Model\Product\Type\AbstractType::PROCESS_MODE_FULL); return $item; }
/** * Prepare items to pieces * * @return array */ protected function _getAllItems() { $allItems = $this->_request->getAllItems(); $fullItems = array(); foreach ($allItems as $item) { if ($item->getProductType() == Type::TYPE_BUNDLE && $item->getProduct()->getShipmentType()) { continue; } $qty = $item->getQty(); $changeQty = true; $checkWeight = true; $decimalItems = array(); if ($item->getParentItem()) { if (!$item->getParentItem()->getProduct()->getShipmentType()) { continue; } if ($item->getIsQtyDecimal()) { $qty = $item->getParentItem()->getQty(); } else { $qty = $item->getParentItem()->getQty() * $item->getQty(); } } $itemWeight = $item->getWeight(); if ($item->getIsQtyDecimal() && $item->getProductType() != Type::TYPE_BUNDLE) { $productId = $item->getProduct()->getId(); $isDecimalDivided = $this->stockItemService->getStockItem($productId)->getIsDecimalDivided(); if ($isDecimalDivided) { if ($this->stockItemService->getEnableQtyIncrements($productId) && $this->stockItemService->getQtyIncrements($productId)) { $itemWeight = $itemWeight * $this->stockItemService->getQtyIncrements($productId); $qty = round($item->getWeight() / $itemWeight * $qty); $changeQty = false; } else { $itemWeight = $this->_getWeight($itemWeight * $item->getQty()); $maxWeight = $this->_getWeight($this->_maxWeight, true); if ($itemWeight > $maxWeight) { $qtyItem = floor($itemWeight / $maxWeight); $decimalItems[] = array('weight' => $maxWeight, 'qty' => $qtyItem); $weightItem = $this->mathDivision->getExactDivision($itemWeight, $maxWeight); if ($weightItem) { $decimalItems[] = array('weight' => $weightItem, 'qty' => 1); } $checkWeight = false; } } } else { $itemWeight = $itemWeight * $item->getQty(); } } if ($checkWeight && $this->_getWeight($itemWeight) > $this->_getWeight($this->_maxWeight, true)) { return array(); } if ($changeQty && !$item->getParentItem() && $item->getIsQtyDecimal() && $item->getProductType() != Type::TYPE_BUNDLE) { $qty = 1; } if (!empty($decimalItems)) { foreach ($decimalItems as $decimalItem) { $fullItems = array_merge($fullItems, array_fill(0, $decimalItem['qty'] * $qty, $decimalItem['weight'])); } } else { $fullItems = array_merge($fullItems, array_fill(0, $qty, $this->_getWeight($itemWeight))); } } sort($fullItems); return $fullItems; }
/** * Compose Packages For Carrier. * Divides order into items and items into parts if it's necessary * * @param \Magento\Shipping\Model\Carrier\AbstractCarrier $carrier * @param \Magento\Sales\Model\Quote\Address\RateRequest $request * @return array [int, float] */ public function composePackagesForCarrier($carrier, $request) { $allItems = $request->getAllItems(); $fullItems = array(); $maxWeight = (double) $carrier->getConfigData('max_package_weight'); /** @var $item \Magento\Sales\Model\Quote\Item */ foreach ($allItems as $item) { if ($item->getProductType() == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE && $item->getProduct()->getShipmentType()) { continue; } $qty = $item->getQty(); $changeQty = true; $checkWeight = true; $decimalItems = array(); if ($item->getParentItem()) { if (!$item->getParentItem()->getProduct()->getShipmentType()) { continue; } $qty = $item->getIsQtyDecimal() ? $item->getParentItem()->getQty() : $item->getParentItem()->getQty() * $item->getQty(); } $itemWeight = $item->getWeight(); if ($item->getIsQtyDecimal() && $item->getProductType() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { $productId = $item->getProduct()->getId(); if ($this->stockItemService->getStockItem($productId)->getIsDecimalDivided()) { if ($this->stockItemService->getEnableQtyIncrements($productId) && $this->stockItemService->getQtyIncrements($productId)) { $itemWeight = $itemWeight * $this->stockItemService->getQtyIncrements($productId); $qty = round($item->getWeight() / $itemWeight * $qty); $changeQty = false; } else { $itemWeight = $itemWeight * $item->getQty(); if ($itemWeight > $maxWeight) { $qtyItem = floor($itemWeight / $maxWeight); $decimalItems[] = array('weight' => $maxWeight, 'qty' => $qtyItem); $weightItem = $this->mathDivision->getExactDivision($itemWeight, $maxWeight); if ($weightItem) { $decimalItems[] = array('weight' => $weightItem, 'qty' => 1); } $checkWeight = false; } else { $itemWeight = $itemWeight * $item->getQty(); } } } else { $itemWeight = $itemWeight * $item->getQty(); } } if ($checkWeight && $maxWeight && $itemWeight > $maxWeight) { return array(); } if ($changeQty && !$item->getParentItem() && $item->getIsQtyDecimal() && $item->getProductType() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) { $qty = 1; } if (!empty($decimalItems)) { foreach ($decimalItems as $decimalItem) { $fullItems = array_merge($fullItems, array_fill(0, $decimalItem['qty'] * $qty, $decimalItem['weight'])); } } else { $fullItems = array_merge($fullItems, array_fill(0, $qty, $itemWeight)); } } sort($fullItems); return $this->_makePieces($fullItems, $maxWeight); }
/** * Checking availability of items with decimal qty * * @return bool */ public function hasItemsWithDecimalQty() { foreach ($this->getAllItems() as $item) { /** @var \Magento\CatalogInventory\Service\V1\Data\StockItem $stockItemDo */ $stockItemDo = $this->stockItemService->getStockItem($item->getProduct()->getId()); if ($stockItemDo->getStockId() && $stockItemDo->getIsQtyDecimal()) { return true; } } return false; }
/** * Stock item saving. * * @return $this */ protected function _saveStockItem() { /** @var $stockResource \Magento\CatalogInventory\Model\Resource\Stock\Item */ $stockResource = $this->_stockResItemFac->create(); $entityTable = $stockResource->getMainTable(); while ($bunch = $this->_dataSourceModel->getNextBunch()) { $stockData = array(); $productIdsToReindex = array(); // Format bunch to stock data rows foreach ($bunch as $rowNum => $rowData) { if (!$this->isRowAllowedToImport($rowData, $rowNum)) { continue; } // only SCOPE_DEFAULT can contain stock data if (self::SCOPE_DEFAULT != $this->getRowScope($rowData)) { continue; } $row = array(); $row['product_id'] = $this->_newSku[$rowData[self::COL_SKU]]['entity_id']; $productIdsToReindex[] = $row['product_id']; $row['stock_id'] = \Magento\CatalogInventory\Model\Stock\Item::DEFAULT_STOCK_ID; $stockItemDo = $this->stockItemService->getStockItem($row['product_id']); $existStockData = $stockItemDo->__toArray(); $row = array_merge($this->defaultStockData, array_intersect_key($existStockData, $this->defaultStockData), array_intersect_key($rowData, $this->defaultStockData), $row); $row = $this->stockItemService->processIsInStock($row); if ($this->stockItemService->isQty($this->_newSku[$rowData[self::COL_SKU]]['type_id'])) { if ($this->stockItemService->verifyNotification($row['product_id'])) { $row['low_stock_date'] = $this->_localeDate->date(null, null, null, false)->toString(\Magento\Framework\Stdlib\DateTime::DATETIME_INTERNAL_FORMAT); } $row['stock_status_changed_auto'] = (int) (!$this->stockItemService->verifyStock($row['product_id'])); } else { $row['qty'] = 0; } $stockData[] = $row; } // Insert rows if (!empty($stockData)) { $this->_connection->insertOnDuplicate($entityTable, $stockData); } if ($productIdsToReindex) { $this->newIndexer->load('catalog_product_category')->reindexList($productIdsToReindex); } } return $this; }
/** * Retrieve Catalog Inventory Stock Item Model * * @return \Magento\CatalogInventory\Service\V1\Data\StockItem */ public function getStockItemDo() { return $this->stockItemService->getStockItem($this->getProduct()->getId()); }
/** * 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(); /** * @todo Should be refactored together with \Magento\CatalogInventory\Model\Stock\Item::getStockId */ $stockItemData['stock_id'] = \Magento\CatalogInventory\Model\Stock\Item::DEFAULT_STOCK_ID; 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'] = $stockItemData['qty'] - $originalQty; } $stockItemDo = $this->stockItemService->getStockItem($product->getId()); $this->stockItemService->saveStockItem($this->stockItemBuilder->mergeDataObjectWithArray($stockItemDo, $stockItemData)); return $this; }
/** * Setup product for quote item * * @param \Magento\Catalog\Model\Product $product * @return $this */ public function setProduct($product) { if ($this->getQuote()) { $product->setStoreId($this->getQuote()->getStoreId()); $product->setCustomerGroupId($this->getQuote()->getCustomerGroupId()); } $this->setData('product', $product)->setProductId($product->getId())->setProductType($product->getTypeId())->setSku($this->getProduct()->getSku())->setName($product->getName())->setWeight($this->getProduct()->getWeight())->setTaxClassId($product->getTaxClassId())->setBaseCost($product->getCost()); /** @var \Magento\CatalogInventory\Service\V1\Data\StockItem $stockItemDo */ $stockItemDo = $this->stockItemService->getStockItem($product->getId()); if ($stockItemDo->getStockId()) { $this->setIsQtyDecimal($stockItemDo->getIsQtyDecimal()); } $this->_eventManager->dispatch('sales_quote_item_set_product', array('product' => $product, 'quote_item' => $this)); return $this; }
/** * Processing additional validation to check if carrier applicable. * * @param RateRequest $request * @return $this|bool|Error */ public function proccessAdditionalValidation(RateRequest $request) { //Skip by item validation if there is no items in request if (!count($this->getAllItems($request))) { return $this; } $maxAllowedWeight = (double) $this->getConfigData('max_package_weight'); $errorMsg = ''; $configErrorMsg = $this->getConfigData('specificerrmsg'); $defaultErrorMsg = __('The shipping module is not available.'); $showMethod = $this->getConfigData('showmethod'); /** @var $item \Magento\Sales\Model\Quote\Item */ foreach ($this->getAllItems($request) as $item) { $product = $item->getProduct(); if ($product && $product->getId()) { $weight = $product->getWeight(); $stockItemData = $this->stockItemService->getStockItem($product->getId()); $doValidation = true; if ($stockItemData->getIsQtyDecimal() && $stockItemData->getIsDecimalDivided()) { if ($this->stockItemService->getEnableQtyIncrements($product->getId()) && $this->stockItemService->getQtyIncrements($product->getId())) { $weight = $weight * $this->stockItemService->getQtyIncrements($product->getId()); } else { $doValidation = false; } } elseif ($stockItemData->getIsQtyDecimal() && !$stockItemData->getIsDecimalDivided()) { $weight = $weight * $item->getQty(); } if ($doValidation && $weight > $maxAllowedWeight) { $errorMsg = $configErrorMsg ? $configErrorMsg : $defaultErrorMsg; break; } } } if (!$errorMsg && !$request->getDestPostcode() && $this->isZipCodeRequired($request->getDestCountryId())) { $errorMsg = __('This shipping method is not available. Please specify the zip code.'); } if ($errorMsg && $showMethod) { $error = $this->_rateErrorFactory->create(); $error->setCarrier($this->_code); $error->setCarrierTitle($this->getConfigData('title')); $error->setErrorMessage($errorMsg); return $error; } elseif ($errorMsg) { return false; } return $this; }