/** * Test if the item needs to have its quantity checked for available * inventory. * @param Mage_Sales_Model_Quote_Item $item The item to check * @return bool True if inventory is managed, false if not */ public function isItemInventoried(Mage_Sales_Model_Quote_Item $item) { // never consider a child product as inventoried, allow the parent deal // with inventory and let the child not need to worry about it as the parent // will be the item to keep track of qty being ordered. // Both checks needed as child items will not have a parent item id prior // to being saved and a parent item prior to being added to the parent (e.g. // immediately after being loaded from the DB). if ($item->getParentItemId() || $item->getParentItem()) { return false; } // when dealing with parent items, if any child of the product is managed // stock, consider the entire item as managed stock - allows for the parent // config product in the quote to deal with inventory while allowing child // products to not care individually if ($item->getHasChildren()) { foreach ($item->getChildren() as $childItem) { $childStock = $childItem->getProduct()->getStockItem(); if ($this->isManagedStock($childStock)) { // This Parent is inventoried. Child's ROM setting is 'No backorders', and Manage Stock check hasn't been manually overridden return true; } } // if none of the children were managed stock, the parent is not inventoried return false; } return $this->isManagedStock($item->getProduct()->getStockItem()); }
/** * Check Quote item qty. If qty is not enougth for order, error flag and message added to $quote item * * @param Mage_Sales_Model_Quote_Item $quoteItem */ protected function checkQuoteItemQty($quoteItem) { $qty = $quoteItem->getQty(); if (($options = $quoteItem->getQtyOptions()) && $qty > 0) { $qty = $quoteItem->getProduct()->getTypeInstance(true)->prepareQuoteItemQty($qty, $quoteItem->getProduct()); $quoteItem->setData('qty', $qty); foreach ($options as $option) { $optionQty = $qty * $option->getValue(); $increaseOptionQty = ($quoteItem->getQtyToAdd() ? $quoteItem->getQtyToAdd() : $qty) * $option->getValue(); $stockItem = $option->getProduct()->getStockItem(); /* @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ if (!$stockItem instanceof Mage_CatalogInventory_Model_Stock_Item) { $quoteItem->setHasError(true)->setMessage('Stock item for Product in option is not valid'); return; } $result = $stockItem->checkQuoteItemQty($optionQty, $optionQty, $option->getValue()); if ($result->getHasError()) { $quoteItem->setHasError(true)->setMessage($result->getQuoteMessage()); } } } else { $stockItem = $quoteItem->getProduct()->getStockItem(); /* @var $stockItem Mage_CatalogInventory_Model_Stock_Item */ if (!$stockItem instanceof Mage_CatalogInventory_Model_Stock_Item) { Mage::throwException(Mage::helper('cataloginventory')->__('Stock item for Product is not valid')); } /** * When we work with subitem (as subproduct of bundle or configurable product) */ if ($quoteItem->getParentItem()) { $rowQty = $quoteItem->getParentItem()->getQty() * $qty; /** * we are using 0 because original qty was processed */ $qtyForCheck = 0; } else { $increaseQty = $quoteItem->getQtyToAdd() ? $quoteItem->getQtyToAdd() : $qty; $rowQty = $qty; $qtyForCheck = $qty; } $result = $stockItem->checkQuoteItemQty($rowQty, $qtyForCheck, $qty); if ($result->getHasError()) { $quoteItem->setHasError(true)->setMessage($result->getQuoteMessage()); } } }
/** * Add error info to the item and quote the item belongs to with the * provided error code and messages. * * @param Mage_Sales_Model_Quote_Item * @param int * @param string * @param string * @return self */ protected function _addErrorInfoForItem(Mage_Sales_Model_Quote_Item $item, $errorCode, $itemMessage, $quoteMessage) { $item->addErrorInfo(self::ERROR_INFO_SOURCE, $errorCode, $itemMessage); $parentItem = $item->getParentItem(); if ($parentItem) { $parentItem->addErrorInfo(self::ERROR_INFO_SOURCE, $errorCode, $itemMessage); } $item->getQuote()->addErrorInfo(self::ERROR_INFO_TYPE, self::ERROR_INFO_SOURCE, $errorCode, $quoteMessage); return $this; }
/** * Add error info to the item and quote the item belongs to with the * provided error code and messages. * * @param Mage_Sales_Model_Quote_Item * @param int * @param string * @param string * @return self */ protected function _addErrorInfoForItem(Mage_Sales_Model_Quote_Item $item, $errorCode, $itemMessage, $quoteMessage) { $item->addErrorInfo(EbayEnterprise_Inventory_Model_Quantity_Service::ERROR_INFO_SOURCE, $errorCode, $itemMessage); $parentItem = $item->getParentItem(); if ($parentItem) { $parentItem->addErrorInfo(EbayEnterprise_Inventory_Model_Quantity_Service::ERROR_INFO_SOURCE, $errorCode, $itemMessage); } $item->getQuote()->addErrorInfo(EbayEnterprise_Inventory_Model_Quantity_Service::ERROR_INFO_TYPE, EbayEnterprise_Inventory_Model_Quantity_Service::ERROR_INFO_SOURCE, $errorCode, $quoteMessage); return $this; }
/** * override for changing the current stock qty based on the quote_item * (this is a bad design from Magento, checkQuoteItemQty should receive the quoteItem in the original code too) * * @param mixed $qty * @param mixed $summaryQty * @param int $origQty * @param Mage_Sales_Model_Quote_Item $quoteItem * * @return Varien_Object */ public function checkQuoteItemQty($qty, $summaryQty, $origQty = 0, $quoteItem = null, $product = null) { if ($quoteItem && ITwebexperts_Payperrentals_Helper_Data::isReservationOnly($product) && (!$quoteItem->getChildren() || Mage::app()->getStore()->isAdmin())) { $qtyOption = 1; if ($quoteItem->getParentProductQty()) { $qty = $quoteItem->getParentProductQty(); $qtyOption = $quoteItem->getParentProductQtyOption(); } $quoteItemId = $quoteItem->getId(); if ($quoteItem->getParentItem() && $quoteItem->getParentItem()->getProduct()) { if ($quoteItem->getParentItem()->getProduct()->getTypeId() == ITwebexperts_Payperrentals_Helper_Data::PRODUCT_TYPE_BUNDLE) { $quoteItemId = $quoteItem->getParentItem()->getItemId(); } } $turnoverArr = ITwebexperts_Payperrentals_Helper_Data::getTurnoverFromQuoteItemOrBuyRequest($product, $quoteItem); list($startDate, $endDate) = array($turnoverArr['before'], $turnoverArr['after']); $result = new Varien_Object(); $result->setHasError(false); if (!is_numeric($qty)) { $qty = Mage::app()->getLocale()->getNumber($qty); } /** * Check quantity type */ $result->setItemIsQtyDecimal($this->getIsQtyDecimal()); if (!$this->getIsQtyDecimal()) { $result->setHasQtyOptionUpdate(true); $qty = intval($qty); /** * Adding stock data to quote item */ $result->setItemQty($qty); if (!is_numeric($qty)) { $qty = Mage::app()->getLocale()->getNumber($qty); } $origQty = intval($origQty); $result->setOrigQty($origQty); } if ($qty < ITwebexperts_Payperrentals_Helper_Inventory::getMinSaleQuantity($product)) { $result->setHasError(true)->setMessage(Mage::helper('cataloginventory')->__('The minimum quantity allowed for purchase is %s.', ITwebexperts_Payperrentals_Helper_Inventory::getMinSaleQuantity($product)))->setErrorCode('qty_min')->setQuoteMessage(Mage::helper('cataloginventory')->__('Some of the products cannot be ordered in requested quantity.'))->setQuoteMessageIndex('qty'); return $result; } if ($qty > ITwebexperts_Payperrentals_Helper_Inventory::getMaxSaleQuantity($product)) { $result->setHasError(true)->setMessage(Mage::helper('cataloginventory')->__('The maximum quantity allowed for purchase is %s.', ITwebexperts_Payperrentals_Helper_Inventory::getMaxSaleQuantity($product)))->setErrorCode('qty_max')->setQuoteMessage(Mage::helper('cataloginventory')->__('Some of the products cannot be ordered in requested quantity.'))->setQuoteMessageIndex('qty'); return $result; } $result->addData($this->checkQtyIncrements($qty)->getData()); if ($result->getHasError()) { return $result; } $option = $quoteItem->getOptionByCode('info_buyRequest'); $buyRequest = $option ? unserialize($option->getValue()) : null; if (Mage::app()->getStore()->isAdmin() && Mage::getSingleton('adminhtml/session_quote')->getOrderId()) { $editedOrderId = Mage::getSingleton('adminhtml/session_quote')->getOrderId(); $order = Mage::getModel('sales/order')->load($editedOrderId); $buyRequestArray = (array) $buyRequest; foreach ($order->getAllItems() as $oItem) { if ($oItem->getProduct()->getId() != $product->getId()) { continue; } if (is_object($oItem->getOrderItem())) { $item = $oItem->getOrderItem(); } else { $item = $oItem; } if ($item->getParentItem()) { continue; } //check for bundles if (count($item->getChildrenItems()) > 0) { foreach ($item->getChildrenItems() as $child) { $turnoverArr = ITwebexperts_Payperrentals_Helper_Data::getTurnoverFromQuoteItemOrBuyRequest($child->getProductId(), $child); $buyRequestArray['excluded_qty'][] = array('product_id' => $child->getProductId(), 'start_date' => $turnoverArr['before'], 'end_date' => $turnoverArr['after'], 'qty' => $item->getQtyOrdered()); } } else { $turnoverArr = ITwebexperts_Payperrentals_Helper_Data::getTurnoverFromQuoteItemOrBuyRequest($item->getProductId(), $item); $buyRequestArray['excluded_qty'][] = array('product_id' => $item->getProductId(), 'start_date' => $turnoverArr['before'], 'end_date' => $turnoverArr['after'], 'qty' => $item->getQtyOrdered()); } } $buyRequest = new Varien_Object($buyRequestArray); } if (isset($buyRequest['start_date']) && isset($buyRequest['end_date'])) { if (strtotime($buyRequest['start_date']) > strtotime($buyRequest['end_date'])) { $message = Mage::helper('payperrentals')->__('Start Date is bigger then End Date. Please change!'); $result->setHasError(true)->setMessage($message)->setQuoteMessage($message); return $result; } } $isAvailable = false; if (ITwebexperts_Payperrentals_Helper_Inventory::isAllowedOverbook($product->getId())) { $isAvailable = true; } if (ITwebexperts_Payperrentals_Helper_Data::isBuyout($buyRequest)) { if (!$isAvailable) { Mage::register('quote_item_id', $quoteItemId); $maxQty = ITwebexperts_Payperrentals_Helper_Inventory::getQuantity($product, null, null, $buyRequest); Mage::unregister('quote_item_id'); if ($maxQty >= $qty) { $isAvailable = true; } } if ($isAvailable) { return $result; } else { $message = Mage::helper('payperrentals')->__('There is not enough quantity for buy this product'); $result->setHasError(true)->setMessage($message)->setQuoteMessage($message); return $result; } } if (!Mage::app()->getStore()->isAdmin() && !Mage::getSingleton('checkout/session')->getIsExtendedQuote() && isset($buyRequest['start_date']) && isset($buyRequest['end_date']) && ITwebexperts_Payperrentals_Helper_Inventory::isExcludedDay($product->getId(), $buyRequest['start_date'], $buyRequest['end_date'])) { $message = Mage::helper('payperrentals')->__('There are blocked dates or excluded days on your selected dates!'); $result->setHasError(true)->setMessage($message)->setQuoteMessage($message); return $result; } else { if (!$isAvailable && isset($buyRequest['start_date']) && isset($buyRequest['end_date'])) { Mage::register('quote_item_id', $quoteItemId); $maxQty = ITwebexperts_Payperrentals_Helper_Inventory::getQuantity($product, $startDate, $endDate, $buyRequest); Mage::unregister('quote_item_id'); if ($maxQty >= $qty) { $isAvailable = true; } } } if (ITwebexperts_Payperrentals_Helper_Data::isUsingGlobalDatesShoppingCart($product) && !$buyRequest['start_date']) { $message = Mage::helper('payperrentals')->__('Please select Global Dates!'); $result->setHasError(true)->setMessage($message)->setQuoteMessage($message); return $result; } if (!Mage::app()->getStore()->isAdmin() && !ITwebexperts_Payperrentals_Helper_Data::isBuyout($buyRequest) && (isset($buyRequest['start_date']) && strtotime($buyRequest['start_date']) < strtotime(date('Y-m-d')) || isset($buyRequest['end_date']) && strtotime($buyRequest['end_date']) < strtotime(date('Y-m-d')))) { $message = Mage::helper('payperrentals')->__('The selected Dates are in the past. Please select new dates!'); $result->setHasError(true)->setMessage($message)->setQuoteMessage($message); return $result; } if (Mage::app()->getStore()->isAdmin() && ITwebexperts_Payperrentals_Helper_Inventory::isAllowedOverbook($product->getId()) && ITwebexperts_Payperrentals_Helper_Inventory::showAdminOverbookWarning()) { Mage::register('quote_item_id', $quoteItemId); $maxQty = ITwebexperts_Payperrentals_Helper_Inventory::getQuantity($product, $startDate, $endDate, $buyRequest, true); Mage::unregister('quote_item_id'); if ($maxQty < $qty) { $message = Mage::helper('cataloginventory')->__('Product is not available for the selected dates'); $result->setHasError(false)->setMessage($message)->setQuoteMessage($message)->setQuoteMessageIndex('qtyppr'); return $result; } } Mage::dispatchEvent('before_stock_check', array('buyrequest' => $buyRequest, 'isavailable' => &$isAvailable)); if (!$isAvailable) { if (isset($buyRequest['start_date']) && isset($buyRequest['end_date'])) { //Mage::register('no_quote', 1); Mage::register('quote_item_id', $quoteItemId); $maxQty = ITwebexperts_Payperrentals_Helper_Inventory::getQuantity($product, $startDate, $endDate, $buyRequest); Mage::unregister('quote_item_id'); $maxQty = intval($maxQty / $qtyOption); //Mage::unregister('no_quote', 1); if ($maxQty > 0) { $message = Mage::helper('payperrentals')->__('Max quantity available for these dates is: ' . $maxQty . ', your quantity has been adjusted.'); // Mage::getSingleton('checkout/session')->addError($message); $result->setHasQtyOptionUpdate(true); //$result->setOrigQty($maxQty); $result->setQty($maxQty); $result->setItemQty($maxQty); $result->setMessage($message)->setQuoteMessage($message); return $result; } $message = Mage::helper('cataloginventory')->__('The requested quantity for "%s" is not available.', $this->getProductName()); } else { $message = Mage::helper('cataloginventory')->__('Please select Start and End Dates'); } $result->setHasError(true)->setMessage($message)->setQuoteMessage($message)->setQuoteMessageIndex('qtyppr'); return $result; } return $result; } $return = parent::checkQuoteItemQty($qty, $summaryQty, $origQty); return $return; }
/** * @param Mage_Sales_Model_Quote_Item $item * @param int $index * * @return Bronto_Common_Model_Email_Template_Filter */ protected function _filterQuoteItem($item, $index = null) { if ($item->getParentItem()) { return $this; } if (Mage::helper('bronto_common')->displayPriceIncTax($item->getStore())) { $checkout = Mage::helper('checkout'); $this->setField("productPrice_{$index}", $this->formatPrice($checkout->getPriceInclTax($item))); $this->setField("productTotal_{$index}", $this->formatPrice($checkout->getSubtotalInclTax($item))); } else { $this->setField("productPrice_{$index}", $this->formatPrice($item->getPrice())); $this->setField("productTotal_{$index}", $this->formatPrice($item->getRowTotal())); } $this->setField("productName_{$index}", $item->getName()); $this->setField("productSku_{$index}", $item->getSku()); $this->setField("productQty_{$index}", $item->getQty()); $this->setField("productUrl_{$index}", $this->_getQuoteItemUrl($item)); /* @var $product Mage_Catalog_Model_Product */ $product = $item->getProduct(); if (!$product) { $product = Mage::helper('bronto_common/product')->getProduct($item->getProductId(), $this->getStoreId()); } $this->_filterProduct($product, $index); return $this; }
/** * Add active parent product from item. * * @param Mage_Sales_Model_Quote_Item $item * @return $this */ public function addActiveItemParentProduct($item) { if ($item && $item->getId() && $item->getParentItemId()) { if ($item->getParentItem()->getProduct()->getTypeId() == 'configurable') { // for price calculations to become accurate we need to reload the product, // otherwise things like tier pricing won't be loaded on it and the calculations // will ne dup being incorrect. $this->_activeItemParentProducts[$item->getProduct()->getId()] = Mage::getModel('catalog/product')->load($item->getParentItem()->getProductId()); } } return $this; }
/** * Retrieves the fixed weight set on the parent item * * @param Mage_Sales_Model_Quote_Item $item * @param bool $cartFreeShipping is the cart marked as free shipping * @param Webshopapps_Wsacommon_Model_Totals $finalTotals the final totals model instance * @param bool $isParent is the $item the parent item or a child * @return bool success */ private function setBundleParentWeight($item, $cartFreeShipping, &$finalTotals, $isParent = true) { $parentItem = $isParent ? $item : $item->getParentItem(); if ($parentItem->getProduct()->getWeightType()) { $itemWeight = $parentItem->getProduct()->getWeight(); $rowWeight = $itemWeight * $parentItem->getQty(); if ($cartFreeShipping || $item->getFreeShipping() === true) { $rowWeight = 0; } elseif (is_numeric($item->getFreeShipping())) { $freeQty = $item->getFreeShipping(); if ($item->getQty() > $freeQty) { $rowWeight = $itemWeight * ($item->getQty() - $freeQty); } else { $rowWeight = 0; } } $finalTotals->setWeight($rowWeight); $finalTotals->setFreeMethodWeight($rowWeight); return true; } else { return false; } }
/** * Retenders the item's redemption rules and final row total and returns it. * @param Mage_Sales_Model_Quote_Item $item * @return array a map of the new item redemption data: * array('redemptions_data'=>{...}, 'row_total'=>float) */ protected function getUpdatedRedemptionData($item, $do_incl_tax = true) { // Step 1: Create a map of usability for all applied redemptions //echo "$item->getRedeemedPointsHash()"; $redeemed_points = Mage::helper('rewards')->unhashIt($item->getRedeemedPointsHash()); // Prepare data from item and initalize counters if ($item->getQuote()) { $store_currency = round($item->getQuote()->getStoreToQuoteRate(), 4); } if ($item->getOrder()) { $store_currency = round($item->getOrder()->getStoreToQuoteRate(), 4); } if ($item->hasCustomPrice()) { $product_price = (double) $item->getCustomPrice() * $store_currency; } else { //@nelkaake -a 17/02/11: We need to use our own calculation because the one that was set by the // rest of the Magento system is rounded. if (Mage::helper('tax')->priceIncludesTax() && $item->getPriceInclTax()) { $product_price = $item->getPriceInclTax() / (1 + $item->getTaxPercent() / 100); } else { $product_price = (double) $item->getPrice() * $store_currency; } } if ($item->getParentItem() || sizeof($redeemed_points) == 0) { return array('redemptions_data' => array(), 'row_total_incl_tax' => $item->getRowTotalInclTax(), 'row_total' => $item->getRowTotal()); } $total_qty = $item->getQty(); $total_qty_redeemed = 0.0; $row_total = 0.0; $new_redeemed_points = array(); $ret = array(); // Loop through and apply all our rules. foreach ($redeemed_points as $key => &$redemption_instance) { $redemption_instance = (array) $redemption_instance; $applic_qty = $redemption_instance[self::POINTS_APPLICABLE_QTY]; $rule_id = $redemption_instance[self::POINTS_RULE_ID]; $effect = $redemption_instance[self::POINTS_EFFECT]; $uses = isset($redemption_instance[self::POINTS_USES]) ? (int) $redemption_instance[self::POINTS_USES] : 1; $rule = Mage::helper('rewards/rule')->getCatalogRule($rule_id); // If a rule was turned off at some point in the back-end it should be removed and not calculated in the cart anymore. if (!$rule->getIsActive()) { $this->removeCatalogRedemptionsFromItem($item, array($rule_id)); $effect = ""; } $total_qty_remain = $total_qty - $total_qty_redeemed; if ($total_qty_remain > 0) { if ($total_qty_remain < $applic_qty) { $applic_qty = $total_qty_remain; $redemption_instance[TBT_Rewards_Model_Redeem::POINTS_APPLICABLE_QTY] = $applic_qty; } $price_after_redem = $this->getPriceAfterEffect($product_price, $effect, $item); $row_total += $applic_qty * (double) $price_after_redem; $total_qty_redeemed += $applic_qty; $new_redeemed_points[] = $redemption_instance; } else { $redemption_instance[TBT_Rewards_Model_Catalogrule_Rule::POINTS_APPLICABLE_QTY] = 0; $redemption_instance[TBT_Rewards_Model_Catalogrule_Rule::POINTS_USES] = 1; // used once by default unset($redeemed_points[$key]); } } $ret['redemptions_data'] = $new_redeemed_points; // Add in the left over products that perhaps weren't affected by qty adjustment. $total_qty_remain = $total_qty - $total_qty_redeemed; if ($total_qty_remain < 0) { $total_qty_remain = 0; $total_qty_redeemed = $total_qty; //throw new Exception("Redemption rules may be overlapping. Please notify the store administrator of this error."); } $row_total += $total_qty_remain * (double) $product_price; $ret['row_total'] = $row_total; $ret['row_total_incl_tax'] = $row_total * (1 + $item->getTaxPercent() / 100); return $ret; }