Oh snap! You are using an old version of browser. Update your browser to get new awesome features. Click for more details.

Magento Show ‘Out of stock’ simple products in the configurable product (in drop down menu)?

I need some help from advanced users with configurable products. By default Magento display on configurable product page (in drop down menu) only simple products which are “In stock”.

I want show all options, even when product is “out of stock”.

 Magento version 1.7

Relapse code in this file:  Your project/app/code/local/Mage/Catalog/Block/Product/View/Type/Configurable.php

<?php
/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magentocommerce.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magentocommerce.com for more information.
 *
 * @category    Mage
 * @package     Mage_Catalog
 * @copyright   Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
 * @license     http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */


/**
 * Catalog super product configurable part block
 *
 * @category   Mage
 * @package    Mage_Catalog
 * @author      Magento Core Team <core@magentocommerce.com>
 */
class Mage_Catalog_Block_Product_View_Type_Configurable extends Mage_Catalog_Block_Product_View_Abstract
{
    /**
     * Prices
     *
     * @var array
     */
    protected $_prices      = array();

    /**
     * Prepared prices
     *
     * @var array
     */
    protected $_resPrices   = array();

    /**
     * Get allowed attributes
     *
     * @return array
     */
    public function getAllowAttributes()
    {
        return $this->getProduct()->getTypeInstance(true)
            ->getConfigurableAttributes($this->getProduct());
    }

    /**
     * Check if allowed attributes have options
     *
     * @return bool
     */
    public function hasOptions()
    {
        $attributes = $this->getAllowAttributes();
        if (count($attributes)) {
            foreach ($attributes as $attribute) {
                /** @var Mage_Catalog_Model_Product_Type_Configurable_Attribute $attribute */
                if ($attribute->getData('prices')) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Get Allowed Products
     *
     * @return array
     */
    // Original code to modify
    /*public function getAllowProducts()
    {
        if (!$this->hasAllowProducts()) {
            $products = array();
            $skipSaleableCheck = Mage::helper('catalog/product')->getSkipSaleableCheck();
            $allProducts = $this->getProduct()->getTypeInstance(true)
                ->getUsedProducts(null, $this->getProduct());
            foreach ($allProducts as $product) {
                if ($product->isSaleable() || $skipSaleableCheck) {
                    $products[] = $product;
                }
            }
            $this->setAllowProducts($products);
        }
        return $this->getData('allow_products');
    }*/
    public function getAllowProducts() {
        $allProducts = $this->getProduct()->getTypeInstance()->getUsedProducts();
        $this->setAllowProducts($allProducts);
        return $this->getData('allow_products');
    }

    /**
     * retrieve current store
     *
     * @return Mage_Core_Model_Store
     */
    public function getCurrentStore()
    {
        return Mage::app()->getStore();
    }

    /**
     * Returns additional values for js config, con be overriden by descedants
     *
     * @return array
     */
    protected function _getAdditionalConfig()
    {
        return array();
    }

    /**
     * Composes configuration for js
     *
     * @return string
     */
    // Original code to modify
//    public function getJsonConfig()
//    {
//        $attributes = array();
//        $options    = array();
//        $store      = $this->getCurrentStore();
//        $taxHelper  = Mage::helper('tax');
//        $currentProduct = $this->getProduct();

//        $preconfiguredFlag = $currentProduct->hasPreconfiguredValues();
//        if ($preconfiguredFlag) {
//            $preconfiguredValues = $currentProduct->getPreconfiguredValues();
//            $defaultValues       = array();
//        }

//        foreach ($this->getAllowProducts() as $product) {
//            $productId  = $product->getId();

//            foreach ($this->getAllowAttributes() as $attribute) {
//                $productAttribute   = $attribute->getProductAttribute();
//                $productAttributeId = $productAttribute->getId();
//                $attributeValue     = $product->getData($productAttribute->getAttributeCode());
//                if (!isset($options[$productAttributeId])) {
//                    $options[$productAttributeId] = array();
//                }

//                if (!isset($options[$productAttributeId][$attributeValue])) {
//                    $options[$productAttributeId][$attributeValue] = array();
//                }
//                $options[$productAttributeId][$attributeValue][] = $productId;
//            }
//        }

//        $this->_resPrices = array(
//            $this->_preparePrice($currentProduct->getFinalPrice())
//        );

//        foreach ($this->getAllowAttributes() as $attribute) {
 //           $productAttribute = $attribute->getProductAttribute();
//            $attributeId = $productAttribute->getId();
//            $info = array(
//                'id'        => $productAttribute->getId(),
//                'code'      => $productAttribute->getAttributeCode(),
 //               'label'     => $attribute->getLabel(),
//                'options'   => array()
 //           );

//            $optionPrices = array();
//            $prices = $attribute->getPrices();
//            if (is_array($prices)) {
//                foreach ($prices as $value) {
//                    if(!$this->_validateAttributeValue($attributeId, $value, $options)) {
//                        continue;
//                    }
//                    $currentProduct->setConfigurablePrice(
//                        $this->_preparePrice($value['pricing_value'], $value['is_percent'])
//                    );
//                    $currentProduct->setParentId(true);
//                    Mage::dispatchEvent(
//                        'catalog_product_type_configurable_price',
//                        array('product' => $currentProduct)
//                    );
  //                  $configurablePrice = $currentProduct->getConfigurablePrice();

//                    if (isset($options[$attributeId][$value['value_index']])) {
//                        $productsIndex = $options[$attributeId][$value['value_index']];
//                    } else {
//                        $productsIndex = array();
//                    }

//                    $info['options'][] = array(
//                        'id'        => $value['value_index'],
//                        'label'     => $value['label'],
//                        'price'     => $configurablePrice,
//                        'oldPrice'  => $this->_prepareOldPrice($value['pricing_value'], $value['is_percent']),
//                        'products'  => $productsIndex,
//                    );
  //                  $optionPrices[] = $configurablePrice;
//                }
//            }
            /**
             * Prepare formated values for options choose
             */
//            foreach ($optionPrices as $optionPrice) {
//                foreach ($optionPrices as $additional) {
//                    $this->_preparePrice(abs($additional-$optionPrice));
//                }
//            }
//            if($this->_validateAttributeInfo($info)) {
//                $attributes[$attributeId] = $info;
  //          }

            // Add attribute default value (if set)
//            if ($preconfiguredFlag) {
  //              $configValue = $preconfiguredValues->getData('super_attribute/' . $attributeId);
//                if ($configValue) {
//                    $defaultValues[$attributeId] = $configValue;
//                }
//            }
//        }

//        $taxCalculation = Mage::getSingleton('tax/calculation');
//        if (!$taxCalculation->getCustomer() && Mage::registry('current_customer')) {
//            $taxCalculation->setCustomer(Mage::registry('current_customer'));
//        }

//        $_request = $taxCalculation->getRateRequest(false, false, false);
//        $_request->setProductClassId($currentProduct->getTaxClassId());
//        $defaultTax = $taxCalculation->getRate($_request);

//        $_request = $taxCalculation->getRateRequest();
//        $_request->setProductClassId($currentProduct->getTaxClassId());
//        $currentTax = $taxCalculation->getRate($_request);

//        $taxConfig = array(
//            'includeTax'        => $taxHelper->priceIncludesTax(),
//            'showIncludeTax'    => $taxHelper->displayPriceIncludingTax(),
//            'showBothPrices'    => $taxHelper->displayBothPrices(),
//            'defaultTax'        => $defaultTax,
//            'currentTax'        => $currentTax,
//            'inclTaxTitle'      => Mage::helper('catalog')->__('Incl. Tax')
//        );

//        $config = array(
//            'attributes'        => $attributes,
//            'template'          => str_replace('%s', '#{price}', $store->getCurrentCurrency()->getOutputFormat()),
//            'basePrice'         => $this->_registerJsPrice($this->_convertPrice($currentProduct->getFinalPrice())),
//            'oldPrice'          => $this->_registerJsPrice($this->_convertPrice($currentProduct->getPrice())),
//            'productId'         => $currentProduct->getId(),
//            'chooseText'        => Mage::helper('catalog')->__('Choose an Option...'),
//            'taxConfig'         => $taxConfig
//        );

//        if ($preconfiguredFlag && !empty($defaultValues)) {
//            $config['defaultValues'] = $defaultValues;
//        }

    //    $config = array_merge($config, $this->_getAdditionalConfig());

    //   return Mage::helper('core')->jsonEncode($config);
    //}
    public function getJsonConfig()
    {
        $attributes = array();
        $options = array();
        $store = Mage::app()->getStore();
        foreach ($this->getAllowProducts() as $product) {
            $productId  = $product->getId();
            //var_dump(    'testo' . floor($product->getStockItem()->getQty())  );



            foreach ($this->getAllowAttributes() as $attribute) {
                $productAttribute = $attribute->getProductAttribute();
                $attributeValue = $product->getData($productAttribute->getAttributeCode());

                $options['qty'][$product -> getAttributeText($productAttribute->getName())] = floor($product->getStockItem()->getQty());


                if (!isset($options[$productAttribute->getId()])) {
                    $options[$productAttribute->getId()] = array();
                }

                if (!isset($options[$productAttribute->getId()][$attributeValue])) {
                    $options[$productAttribute->getId()][$attributeValue] = array();
                }
                $options[$productAttribute->getId()][$attributeValue][] = $productId;
            }
        }

        $this->_resPrices = array(
            $this->_preparePrice($this->getProduct()->getFinalPrice())
        );

        foreach ($this->getAllowAttributes() as $attribute) {
            $productAttribute = $attribute->getProductAttribute();
            $attributeId = $productAttribute->getId();
            $info = array(
                'id'        => $productAttribute->getId(),
                'code'      => $productAttribute->getAttributeCode(),
                'label'     => $attribute->getLabel(),
                'options'   => array()
            );

            $optionPrices = array();
            $prices = $attribute->getPrices();
            if (is_array($prices)) {
                foreach ($prices as $value) {
                    if(!$this->_validateAttributeValue($attributeId, $value, $options)) {
                        continue;
                    }

                    $info['options'][] = array(
                        'id'    => $value['value_index'],
                        'label' => ($options['qty'][$value['label']] <= 0) ? $value['label'] . ' * out of stock' : $value['label'] . "",
                        'price' => $this->_preparePrice($value['pricing_value'], $value['is_percent']),
                        'products'   => isset($options[$attributeId][$value['value_index']]) ? $options[$attributeId][$value['value_index']] : array(),
                    );
                    $optionPrices[] = $this->_preparePrice($value['pricing_value'], $value['is_percent']);
                    //$this->_registerAdditionalJsPrice($value['pricing_value'], $value['is_percent']);
                }
            }
            /**
             * Prepare formated values for options choose
             */
            foreach ($optionPrices as $optionPrice) {
                foreach ($optionPrices as $additional) {
                    $this->_preparePrice(abs($additional-$optionPrice));
                }
            }
            if($this->_validateAttributeInfo($info)) {
                $attributes[$attributeId] = $info;
            }
        }
        /*echo '<pre>';
        print_r($this->_prices);
        echo '</pre>';die();*/

        $_request = Mage::getSingleton('tax/calculation')->getRateRequest(false, false, false);
        $_request->setProductClassId($this->getProduct()->getTaxClassId());
        $defaultTax = Mage::getSingleton('tax/calculation')->getRate($_request);

        $_request = Mage::getSingleton('tax/calculation')->getRateRequest();
        $_request->setProductClassId($this->getProduct()->getTaxClassId());
        $currentTax = Mage::getSingleton('tax/calculation')->getRate($_request);

        $taxConfig = array(
            'includeTax'        => Mage::helper('tax')->priceIncludesTax(),
            'showIncludeTax'    => Mage::helper('tax')->displayPriceIncludingTax(),
            'showBothPrices'    => Mage::helper('tax')->displayBothPrices(),
            'defaultTax'        => $defaultTax,
            'currentTax'        => $currentTax,
            'inclTaxTitle'      => Mage::helper('catalog')->__('Incl. Tax'),
        );

        $config = array(
            'attributes'        => $attributes,
            'template'          => str_replace('%s', '#{price}', $store->getCurrentCurrency()->getOutputFormat()),
//            'prices'          => $this->_prices,
            'basePrice'         => $this->_registerJsPrice($this->_convertPrice($this->getProduct()->getFinalPrice())),
            'oldPrice'          => $this->_registerJsPrice($this->_convertPrice($this->getProduct()->getPrice())),
            'productId'         => $this->getProduct()->getId(),
            'chooseText'        => Mage::helper('catalog')->__('Choose option...'),
            'taxConfig'         => $taxConfig,
        );

        return Zend_Json::encode($config);
    }

    /**
     * Validating of super product option value
     *
     * @param array $attributeId
     * @param array $value
     * @param array $options
     * @return boolean
     */
    protected function _validateAttributeValue($attributeId, &$value, &$options)
    {
        if(isset($options[$attributeId][$value['value_index']])) {
            return true;
        }

        return false;
    }

    /**
     * Validation of super product option
     *
     * @param array $info
     * @return boolean
     */
    protected function _validateAttributeInfo(&$info)
    {
        if(count($info['options']) > 0) {
            return true;
        }
        return false;
    }

    /**
     * Calculation real price
     *
     * @param float $price
     * @param bool $isPercent
     * @return mixed
     */
    protected function _preparePrice($price, $isPercent = false)
    {
        if ($isPercent && !empty($price)) {
            $price = $this->getProduct()->getFinalPrice() * $price / 100;
        }

        return $this->_registerJsPrice($this->_convertPrice($price, true));
    }

    /**
     * Calculation price before special price
     *
     * @param float $price
     * @param bool $isPercent
     * @return mixed
     */
    protected function _prepareOldPrice($price, $isPercent = false)
    {
        if ($isPercent && !empty($price)) {
            $price = $this->getProduct()->getPrice() * $price / 100;
        }

        return $this->_registerJsPrice($this->_convertPrice($price, true));
    }

    /**
     * Replace ',' on '.' for js
     *
     * @param float $price
     * @return string
     */
    protected function _registerJsPrice($price)
    {
        return str_replace(',', '.', $price);
    }

    /**
     * Convert price from default currency to current currency
     *
     * @param float $price
     * @param boolean $round
     * @return float
     */
    protected function _convertPrice($price, $round = false)
    {
        if (empty($price)) {
            return 0;
        }

        $price = $this->getCurrentStore()->convertPrice($price);
        if ($round) {
            $price = $this->getCurrentStore()->roundPrice($price);
        }

        return $price;
    }
}

(0) comments