protected function setUp() { $this->objectManagerHelper = new ObjectManagerHelper($this); $this->mathDivision = $this->getMock('\\Magento\\Framework\\Math\\Division', ['getExactDivision'], [], '', false); $this->mathDivision->expects($this->any())->method('getExactDivision')->willReturn($this->qtyDivision); $this->localeFormat = $this->getMockForAbstractClass('\\Magento\\Framework\\Locale\\FormatInterface', ['getNumber']); $this->localeFormat->expects($this->any())->method('getNumber')->willReturn($this->qty); $this->object = $this->objectManagerHelper->getObject('Magento\\Framework\\Object'); $this->objectFactory = $this->getMock('\\Magento\\Framework\\Object\\Factory', ['create'], [], '', false); $this->objectFactory->expects($this->any())->method('create')->willReturn($this->object); $this->product = $this->getMock('Magento\\Catalog\\Model\\Product', ['load', 'isComposite', '__wakeup', 'isSaleable'], [], '', false); $this->productFactory = $this->getMock('Magento\\Catalog\\Model\\ProductFactory', ['create'], [], '', false); $this->productFactory->expects($this->any())->method('create')->willReturn($this->product); $this->stockStateProvider = $this->objectManagerHelper->getObject('Magento\\CatalogInventory\\Model\\StockStateProvider', ['mathDivision' => $this->mathDivision, 'localeFormat' => $this->localeFormat, 'objectFactory' => $this->objectFactory, 'productFactory' => $this->productFactory, 'qtyCheckApplicable' => $this->qtyCheckApplicable]); }
/** * @param bool $isChildItem * @param string $expectedMsg * @dataProvider checkQtyIncrementsMsgDataProvider */ public function testCheckQtyIncrementsMsg($isChildItem, $expectedMsg) { $qty = 1; $qtyIncrements = 5; $stockItem = $this->getMockBuilder('Magento\\CatalogInventory\\Api\\Data\\StockItemInterface')->disableOriginalConstructor()->setMethods($this->stockItemMethods)->getMockForAbstractClass(); $stockItem->expects($this->any())->method('getSuppressCheckQtyIncrements')->willReturn(false); $stockItem->expects($this->any())->method('getQtyIncrements')->willReturn($qtyIncrements); $stockItem->expects($this->any())->method('getIsChildItem')->willReturn($isChildItem); $stockItem->expects($this->any())->method('getProductName')->willReturn('Simple Product'); $this->mathDivision->expects($this->any())->method('getExactDivision')->willReturn(1); $result = $this->stockStateProvider->checkQtyIncrements($stockItem, $qty); $this->assertTrue($result->getHasError()); $this->assertEquals($expectedMsg, $result->getMessage()->render()); }
/** * @param StockItemInterface $stockItem * @param float|int $qty * @return \Magento\Framework\DataObject */ public function checkQtyIncrements(StockItemInterface $stockItem, $qty) { $result = new \Magento\Framework\DataObject(); if ($stockItem->getSuppressCheckQtyIncrements()) { return $result; } $qtyIncrements = $stockItem->getQtyIncrements() * 1; if ($qtyIncrements && $this->mathDivision->getExactDivision($qty, $qtyIncrements) != 0) { $result->setHasError(true)->setQuoteMessage(__('Please correct the quantity for some products.'))->setErrorCode('qty_increments')->setQuoteMessageIndex('qty'); if ($stockItem->getIsChildItem()) { $result->setMessage(__('You can buy %1 only in quantities of %2 at a time.', $stockItem->getProductName(), $qtyIncrements)); } else { $result->setMessage(__('You can buy this product only in quantities of %1 at a time.', $qtyIncrements)); } } return $result; }
/** * 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); }