Thursday, 22 February 2018

How to create custom attribute same as Group Price / Tier Price for product in magento admin panel / Backend

Create extension for this. We have add "jobber price (jobber_price)" in attribute.


Step 1.
Create module xml file : app/etc/modules/Jaydip_Kansagra.xml


<?xml version="1.0"?>
<config>
    <modules>
        <Jaydip_Kansagra>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Core />
             </depends>
        </Jaydip_Kansagra>
    </modules>
</config>

Step 2 :
Create config file : app/code/local/Jaydip/Kansagra/etc/config.xml


<?xml version="1.0"?>
<config>
    <modules>
        <Jaydip_Kansagra>
            <version>1.0.0</version>
        </Jaydip_Kansagra>
    </modules>
    <global>
        <resources>
            <jaydip_kansagra_setup>
                <setup>
                    <module>Jaydip_Kansagra</module>
                    <class>Jaydip_Kansagra_Model_Resource_Setup</class>
                </setup>
            </jaydip_kansagra_setup>
        </resources>
        <models>
            <jaydip_kansagra>
                <class>Jaydip_Kansagra_Model</class>
                <resourceModel>jaydip_kansagra_resource</resourceModel>
            </jaydip_kansagra>
            <jaydip_kansagra_resource>
                <class>Jaydip_Kansagra_Model_Resource</class>
                <entities>
                    <jobber_price>
                        <table>catalog_product_entity_jobber_price</table>
                    </jobber_price>
                </entities>
            </jaydip_kansagra_resource>
        </models>
    </global>
    <adminhtml>
        <events>
            <adminhtml_catalog_product_edit_prepare_form>
                <observers>
                    <jobberelement>
                        <class>Jaydip_Kansagra_Model_Observer</class>
                        <method>addJobberelement</method>
                    </jobberelement>
                </observers>
            </adminhtml_catalog_product_edit_prepare_form>
        </events>
    </adminhtml>
</config>  

Step 3 : Create block file : app/code/local/Jaydip/Kansagra/Block/Adminhtml/Catalog/Product/Edit/Tab/Price/Jobber.php

class Jaydip_Kansagra_Block_Adminhtml_Catalog_Product_Edit_Tab_Price_jobber
    extends Jaydip_Kansagra_Block_Adminhtml_Catalog_Product_Edit_Tab_Price_Jobber_Abstract
{
    /**
     * Initialize block
     */
    public function __construct()
    {
        $this->setTemplate('catalog/product/edit/price/jobber.phtml');
    }
    /**
     * Sort values
     *
     * @param array $data
     * @return array
     */
    protected function _sortValues($data)
    {
        usort($data, array($this, '_sortGroupPrices'));
        return $data;
    }
    /**
     * Sort jobber price values callback method
     *
     * @param array $a
     * @param array $b
     * @return int
     */
    protected function _sortGroupPrices($a, $b)
    {
        if ($a['website_id'] != $b['website_id']) {
            return $a['website_id'] < $b['website_id'] ? -1 : 1;
        }
        if ($a['cust_group'] != $b['cust_group']) {
            return $this->getCustomerGroups($a['cust_group']) < $this->getCustomerGroups($b['cust_group']) ? -1 : 1;
        }
        return 0;
    }
    /**
     * Prepare global layout
     *
     * Add "Add Jobber Price" button to layout
     *
     * @return Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Price_Group
     */
    protected function _prepareLayout()
    {
        $button = $this->getLayout()->createBlock('adminhtml/widget_button')
            ->setData(array(
                'label' => Mage::helper('catalog')->__('Add Jobber Price'),
                'onclick' => 'return jobberPriceControl.addItem()',
                'class' => 'add'
            ));
        $button->setName('add_jobber_price_item_button');
        $this->setChild('add_button', $button);
        return parent::_prepareLayout();
    }
}

Step 4 :
Create Abstract.php file in : app/code/local/Jaydip/Kansagra/Block/Adminhtml/Catalog/Product/Edit/Tab/Price/Jobber/Abstract.php

abstract class Jaydip_Kansagra_Block_Adminhtml_Catalog_Product_Edit_Tab_Price_Jobber_Abstract
    extends Mage_Adminhtml_Block_Widget
    implements Varien_Data_Form_Element_Renderer_Interface
{
    /**
     * Form element instance
     *
     * @var Varien_Data_Form_Element_Abstract
     */
    protected $_element;
    /**
     * Customer groups cache
     *
     * @var array
     */
    protected $_customerGroups;
    /**
     * Websites cache
     *
     * @var array
     */
    protected $_websites;
    /**
     * Retrieve current product instance
     *
     * @return Mage_Catalog_Model_Product
     */
    public function getProduct()
    {
        return Mage::registry('product');
    }
    /**
     * Render HTML
     *
     * @param Varien_Data_Form_Element_Abstract $element
     * @return string
     */
    public function render(Varien_Data_Form_Element_Abstract $element)
    {
        $this->setElement($element);
        return $this->toHtml();
    }
    /**
     * Set form element instance
     *
     * @param Varien_Data_Form_Element_Abstract $element
     * @return Mage_Adminhtml_Block_Catalog_Product_Edit_Tab_Price_Group_Abstract
     */
    public function setElement(Varien_Data_Form_Element_Abstract $element)
    {
        $this->_element = $element;
        return $this;
    }
    /**
     * Retrieve form element instance
     *
     * @return Varien_Data_Form_Element_Abstract
     */
    public function getElement()
    {
        return $this->_element;
    }
    /**
     * Prepare group price values
     *
     * @return array
     */
    public function getValues()
    {
        $values = array();
        $data = $this->getElement()->getValue();
        if (is_array($data)) {
            $values = $this->_sortValues($data);
        }
        foreach ($values as &$value) {
            $value['readonly'] = ($value['website_id'] == 0)
                && $this->isShowWebsiteColumn()
                && !$this->isAllowChangeWebsite();
        }
        return $values;
    }
    /**
     * Sort values
     *
     * @param array $data
     * @return array
     */
    protected function _sortValues($data)
    {
        return $data;
    }
    /**
     * Retrieve allowed customer groups
     *
     * @param int|null $groupId  return name by customer group id
     * @return array|string
     */
    public function getCustomerGroups($groupId = null)
    {
        if ($this->_customerGroups === null) {
            if (!Mage::helper('catalog')->isModuleEnabled('Mage_Customer')) {
                return array();
            }
            $collection = Mage::getModel('customer/group')->getCollection();
            $this->_customerGroups = $this->_getInitialCustomerGroups();
            foreach ($collection as $item) {
                /** @var $item Mage_Customer_Model_Group */
                $this->_customerGroups[$item->getId()] = $item->getCustomerGroupCode();
            }
        }
        if ($groupId !== null) {
            return isset($this->_customerGroups[$groupId]) ? $this->_customerGroups[$groupId] : array();
        }
        return $this->_customerGroups;
    }
    /**
     * Retrieve list of initial customer groups
     *
     * @return array
     */
    protected function _getInitialCustomerGroups()
    {
        return array();
    }
    /**
     * Retrieve number of websites
     *
     * @return int
     */
    public function getWebsiteCount()
    {
        return count($this->getWebsites());
    }
    /**
     * Show website column and switcher for group price table
     *
     * @return bool
     */
    public function isMultiWebsites()
    {
        return !Mage::app()->isSingleStoreMode();
    }
    /**
     * Retrieve allowed for edit websites
     *
     * @return array
     */
    public function getWebsites()
    {
        if (!is_null($this->_websites)) {
            return $this->_websites;
        }
        $this->_websites = array(
            0 => array(
                'name' => Mage::helper('catalog')->__('All Websites'),
                'currency' => Mage::app()->getBaseCurrencyCode()
            )
        );
        if (!$this->isScopeGlobal() && $this->getProduct()->getStoreId()) {
            /** @var $website Mage_Core_Model_Website */
            $website = Mage::app()->getStore($this->getProduct()->getStoreId())->getWebsite();
            $this->_websites[$website->getId()] = array(
                'name' => $website->getName(),
                'currency' => $website->getBaseCurrencyCode()
            );
        } elseif (!$this->isScopeGlobal()) {
            $websites = Mage::app()->getWebsites(false);
            $productWebsiteIds  = $this->getProduct()->getWebsiteIds();
            foreach ($websites as $website) {
                /** @var $website Mage_Core_Model_Website */
                if (!in_array($website->getId(), $productWebsiteIds)) {
                    continue;
                }
                $this->_websites[$website->getId()] = array(
                    'name' => $website->getName(),
                    'currency' => $website->getBaseCurrencyCode()
                );
            }
        }
        return $this->_websites;
    }
    /**
     * Retrieve default value for customer group
     *
     * @return int
     */
    public function getDefaultCustomerGroup()
    {
        return Mage_Customer_Model_Group::CUST_GROUP_ALL;
    }
    /**
     * Retrieve default value for website
     *
     * @return int
     */
    public function getDefaultWebsite()
    {
        if ($this->isShowWebsiteColumn() && !$this->isAllowChangeWebsite()) {
            return Mage::app()->getStore($this->getProduct()->getStoreId())->getWebsiteId();
        }
        return 0;
    }
    /**
     * Retrieve 'add group price item' button HTML
     *
     * @return string
     */
    public function getAddButtonHtml()
    {
        return $this->getChildHtml('add_button');
    }
    /**
     * Retrieve customized price column header
     *
     * @param string $default
     * @return string
     */
    public function getPriceColumnHeader($default)
    {
        if ($this->hasData('price_column_header')) {
            return $this->getData('price_column_header');
        } else {
            return $default;
        }
    }
    /**
     * Retrieve customized price column header
     *
     * @param string $default
     * @return string
     */
    public function getPriceValidation($default)
    {
        if ($this->hasData('price_validation')) {
            return $this->getData('price_validation');
        } else {
            return $default;
        }
    }
    /**
     * Retrieve Group Price entity attribute
     *
     * @return Mage_Catalog_Model_Resource_Eav_Attribute
     */
    public function getAttribute()
    {
        return $this->getElement()->getEntityAttribute();
    }
    /**
     * Check group price attribute scope is global
     *
     * @return bool
     */
    public function isScopeGlobal()
    {
        return $this->getAttribute()->isScopeGlobal();
    }
    /**
     * Show group prices grid website column
     *
     * @return bool
     */
    public function isShowWebsiteColumn()
    {
        if ($this->isScopeGlobal() || Mage::app()->isSingleStoreMode()) {
            return false;
        }
        return true;
    }
    /**
     * Check is allow change website value for combination
     *
     * @return bool
     */
    public function isAllowChangeWebsite()
    {
        if (!$this->isShowWebsiteColumn() || $this->getProduct()->getStoreId()) {
            return false;
        }
        return true;
    }

Step 5 :
Create Model file : app/code/local/Jaydip/Kansagra/Model/Jobberprice.php


class Jaydip_Kansagra_Model_Jobberprice
    extends Jaydip_Kansagra_Model_Jobberprice_Abstract
{
    /**
     * Retrieve resource instance
     *
     * @return Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Attribute_Backend_Tierprice
     */
    protected function _getResource()
    {
        return Mage::getResourceSingleton('jaydip_kansagra/jobberprice');
    }
    /**
     * Error message when duplicates
     *
     * @return string
     */
    protected function _getDuplicateErrorMessage()
    {
        return Mage::helper('catalog')->__('Duplicate website group price customer group.');
    }
}


Step 6 :
Create model Abstract : app/code/local/Jaydip/Kansagra/Model/Jobberprice/Abstract.php 


abstract class Jaydip_Kansagra_Model_Jobberprice_Abstract
    extends Mage_Catalog_Model_Product_Attribute_Backend_Price
{
    /**
     * Website currency codes and rates
     *
     * @var array
     */
    protected $_rates;
    /**
     * Error message when duplicates
     *
     * @abstract
     * @return string
     */
    abstract protected function _getDuplicateErrorMessage();
    /**
     * Retrieve websites currency rates and base currency codes
     *
     * @return array
     */
    protected function _getWebsiteCurrencyRates()
    {
        if (is_null($this->_rates)) {
            $this->_rates = array();
            $baseCurrency = Mage::app()->getBaseCurrencyCode();
            foreach (Mage::app()->getWebsites() as $website) {
                /* @var $website Mage_Core_Model_Website */
                if ($website->getBaseCurrencyCode() != $baseCurrency) {
                    $rate = Mage::getModel('directory/currency')
                        ->load($baseCurrency)
                        ->getRate($website->getBaseCurrencyCode());
                    if (!$rate) {
                        $rate = 1;
                    }
                    $this->_rates[$website->getId()] = array(
                        'code' => $website->getBaseCurrencyCode(),
                        'rate' => $rate
                    );
                } else {
                    $this->_rates[$website->getId()] = array(
                        'code' => $baseCurrency,
                        'rate' => 1
                    );
                }
            }
        }
        return $this->_rates;
    }
    /**
     * Get additional unique fields
     *
     * @param array $objectArray
     * @return array
     */
    protected function _getAdditionalUniqueFields($objectArray)
    {
        return array();
    }
    /**
     * Whether group price value fixed or percent of original price
     *
     * @param Mage_Catalog_Model_Product_Type_Price $priceObject
     * @return bool
     */
    protected function _isPriceFixed($priceObject)
    {
        return $priceObject->isGroupPriceFixed();
    }
    /**
     * Validate group price data
     *
     * @param Mage_Catalog_Model_Product $object
     * @throws Mage_Core_Exception
     * @return bool
     */
    public function validate($object)
    {
        $attribute = $this->getAttribute();
        $priceRows = $object->getData($attribute->getName());
        if (empty($priceRows)) {
            return true;
        }
        // validate per website
        $duplicates = array();
        foreach ($priceRows as $priceRow) {
            if (!empty($priceRow['delete'])) {
                continue;
            }
            $compare = join('-', array_merge(
                array($priceRow['website_id'], $priceRow['cust_group']),
                $this->_getAdditionalUniqueFields($priceRow)
            ));
            if (isset($duplicates[$compare])) {
                Mage::throwException($this->_getDuplicateErrorMessage());
            }
            $duplicates[$compare] = true;
        }
        // if attribute scope is website and edit in store view scope
        // add global group prices for duplicates find
        if (!$attribute->isScopeGlobal() && $object->getStoreId()) {
            $origGroupPrices = $object->getOrigData($attribute->getName());
            foreach ($origGroupPrices as $price) {
                if ($price['website_id'] == 0) {
                    $compare = join('-', array_merge(
                        array($price['website_id'], $price['cust_group']),
                        $this->_getAdditionalUniqueFields($price)
                    ));
                    $duplicates[$compare] = true;
                }
            }
        }
        // validate currency
        $baseCurrency = Mage::app()->getBaseCurrencyCode();
        $rates = $this->_getWebsiteCurrencyRates();
        foreach ($priceRows as $priceRow) {
            if (!empty($priceRow['delete'])) {
                continue;
            }
            if ($priceRow['website_id'] == 0) {
                continue;
            }
            $globalCompare = join('-', array_merge(
                array(0, $priceRow['cust_group']),
                $this->_getAdditionalUniqueFields($priceRow)
            ));
            $websiteCurrency = $rates[$priceRow['website_id']]['code'];
            if ($baseCurrency == $websiteCurrency && isset($duplicates[$globalCompare])) {
                Mage::throwException($this->_getDuplicateErrorMessage());
            }
        }
        return true;
    }
    /**
     * Prepare group prices data for website
     *
     * @param array $priceData
     * @param string $productTypeId
     * @param int $websiteId
     * @return array
     */
    public function preparePriceData(array $priceData, $productTypeId, $websiteId)
    {
        $rates  = $this->_getWebsiteCurrencyRates();
        $data   = array();
        $price  = Mage::getSingleton('catalog/product_type')->priceFactory($productTypeId);
        foreach ($priceData as $v) {
            $key = join('-', array_merge(array($v['cust_group']), $this->_getAdditionalUniqueFields($v)));
            if ($v['website_id'] == $websiteId) {
                $data[$key] = $v;
                $data[$key]['website_price'] = $v['price'];
            } else if ($v['website_id'] == 0 && !isset($data[$key])) {
                $data[$key] = $v;
                $data[$key]['website_id'] = $websiteId;
                if ($this->_isPriceFixed($price)) {
                    $data[$key]['price'] = $v['price'] * $rates[$websiteId]['rate'];
                    $data[$key]['website_price'] = $v['price'] * $rates[$websiteId]['rate'];
                }
            }
        }
        return $data;
    }
    /**
     * Assign group prices to product data
     *
     * @param Mage_Catalog_Model_Product $object
     * @return Mage_Catalog_Model_Product_Attribute_Backend_Groupprice_Abstract
     */
    public function afterLoad($object)
    {
        $storeId   = $object->getStoreId();
        $websiteId = null;
        if ($this->getAttribute()->isScopeGlobal()) {
            $websiteId = 0;
        } else if ($storeId) {
            $websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
        }
        $data = $this->_getResource()->loadPriceData($object->getId(), $websiteId);
        foreach ($data as $k => $v) {
            $data[$k]['website_price'] = $v['price'];
            if ($v['all_groups']) {
                $data[$k]['cust_group'] = Mage_Customer_Model_Group::CUST_GROUP_ALL;
            }
        }
        if (!$object->getData('_edit_mode') && $websiteId) {
            $data = $this->preparePriceData($data, $object->getTypeId(), $websiteId);
        }
        $object->setData($this->getAttribute()->getName(), $data);
        $object->setOrigData($this->getAttribute()->getName(), $data);
        $valueChangedKey = $this->getAttribute()->getName() . '_changed';
        $object->setOrigData($valueChangedKey, 0);
        $object->setData($valueChangedKey, 0);
//pre($object->getData());exit;
        return $this;
    }
    /**
     * After Save Attribute manipulation
     *
     * @param Mage_Catalog_Model_Product $object
     * @return Mage_Catalog_Model_Product_Attribute_Backend_Groupprice_Abstract
     */
    public function afterSave($object)
    {
        $websiteId  = Mage::app()->getStore($object->getStoreId())->getWebsiteId();
        $isGlobal   = $this->getAttribute()->isScopeGlobal() || $websiteId == 0;
        $priceRows = $object->getData($this->getAttribute()->getName());
     
        if (empty($priceRows)) {
            if ($isGlobal) {
                $this->_getResource()->deletePriceData($object->getId());
            } else {
                $this->_getResource()->deletePriceData($object->getId(), $websiteId);
            }
            return $this;
        }
        $old = array();
        $new = array();
        // prepare original data for compare
        $origGroupPrices = $object->getOrigData($this->getAttribute()->getName());
        if (!is_array($origGroupPrices)) {
            $origGroupPrices = array();
        }
        foreach ($origGroupPrices as $data) {
            if ($data['website_id'] > 0 || ($data['website_id'] == '0' && $isGlobal)) {
                $key = join('-', array_merge(
                    array($data['website_id'], $data['cust_group']),
                    $this->_getAdditionalUniqueFields($data)
                ));
                $old[$key] = $data;
            }
        }
        // prepare data for save
        foreach ($priceRows as $data) {
            $hasEmptyData = false;
            foreach ($this->_getAdditionalUniqueFields($data) as $field) {
                if (empty($field)) {
                    $hasEmptyData = true;
                    break;
                }
            }
            if ($hasEmptyData || !isset($data['cust_group']) || !empty($data['delete'])) {
                continue;
            }
            if ($this->getAttribute()->isScopeGlobal() && $data['website_id'] > 0) {
                continue;
            }
            if (!$isGlobal && (int)$data['website_id'] == 0) {
                continue;
            }
            $key = join('-', array_merge(
                array($data['website_id'], $data['cust_group']),
                $this->_getAdditionalUniqueFields($data)
            ));
            $useForAllGroups = $data['cust_group'] == Mage_Customer_Model_Group::CUST_GROUP_ALL;
            $customerGroupId = !$useForAllGroups ? $data['cust_group'] : 0;
            $new[$key] = array_merge(array(
                'website_id'        => $data['website_id'],
                'all_groups'        => $useForAllGroups ? 1 : 0,
                'customer_group_id' => $customerGroupId,
                'value'             => $data['price'],
            ), $this->_getAdditionalUniqueFields($data));
        }
        $delete = array_diff_key($old, $new);
        $insert = array_diff_key($new, $old);
        $update = array_intersect_key($new, $old);
        $isChanged  = false;
        $productId  = $object->getId();
        if (!empty($delete)) {
            foreach ($delete as $data) {
                $this->_getResource()->deletePriceData($productId, null, $data['price_id']);
                $isChanged = true;
            }
        }
        if (!empty($insert)) {
            foreach ($insert as $data) {
                $price = new Varien_Object($data);
                $price->setEntityId($productId);
                $this->_getResource()->savePriceData($price);
                $isChanged = true;
            }
        }
        if (!empty($update)) {
            foreach ($update as $k => $v) {
                if ($old[$k]['price'] != $v['value']) {
                    $price = new Varien_Object(array(
                        'value_id'  => $old[$k]['price_id'],
                        'value'     => $v['value']
                    ));
                    $this->_getResource()->savePriceData($price);
                    $isChanged = true;
                }
            }
        }
        if ($isChanged) {
            $valueChangedKey = $this->getAttribute()->getName() . '_changed';
            $object->setData($valueChangedKey, 1);
        }
        return $this;
    }
}


Step 7 :
Create Resource file : app/code/local/Jaydip/Kansagra/Model/Resource/Jobberprice.php


class Jaydip_Kansagra_Model_Resource_Jobberprice
    extends Jaydip_Kansagra_Model_Resource_Jobberprice_Abstract
{
    /**
     * Initialize connection and define main table
     *
     */
    protected function _construct()
    {
        $this->_init('jaydip_kansagra/jobber_price', 'value_id');
    }
}


Step 8 :
Create Resource Abstract file : /app/code/local/Jaydip/Kansagra/Model/Resource/Jobberprice/Abstract.php


abstract class Jaydip_Kansagra_Model_Resource_Jobberprice_Abstract
    extends Mage_Core_Model_Resource_Db_Abstract
{
    /**
     * Load Tier Prices for product
     *
     * @param int $productId
     * @param int $websiteId
     * @return Mage_Catalog_Model_Resource_Product_Attribute_Backend_Tierprice
     */
    public function loadPriceData($productId, $websiteId = null)
    {
        $adapter = $this->_getReadAdapter();
        $columns = array(
            'price_id'      => $this->getIdFieldName(),
            'website_id'    => 'website_id',
            'all_groups'    => 'all_groups',
            'cust_group'    => 'customer_group_id',
            'price'         => 'value',
        );
        $columns = $this->_loadPriceDataColumns($columns);
        $select  = $adapter->select()
            ->from($this->getMainTable(), $columns)
            ->where('entity_id=?', $productId);
        $this->_loadPriceDataSelect($select);
        if (!is_null($websiteId)) {
            if ($websiteId == '0') {
                $select->where('website_id = ?', $websiteId);
            } else {
                $select->where('website_id IN(?)', array(0, $websiteId));
            }
        }
        return $adapter->fetchAll($select);
    }
    /**
     * Load specific sql columns
     *
     * @param array $columns
     * @return array
     */
    protected function _loadPriceDataColumns($columns)
    {
        return $columns;
    }
    /**
     * Load specific db-select data
     *
     * @param Varien_Db_Select $select
     * @return Varien_Db_Select
     */
    protected function _loadPriceDataSelect($select)
    {
        return $select;
    }
    /**
     * Delete Tier Prices for product
     *
     * @param int $productId
     * @param int $websiteId
     * @param int $priceId
     * @return int The number of affected rows
     */
    public function deletePriceData($productId, $websiteId = null, $priceId = null)
    {
        $adapter = $this->_getWriteAdapter();
        $conds   = array(
            $adapter->quoteInto('entity_id = ?', $productId)
        );
        if (!is_null($websiteId)) {
            $conds[] = $adapter->quoteInto('website_id = ?', $websiteId);
        }
        if (!is_null($priceId)) {
            $conds[] = $adapter->quoteInto($this->getIdFieldName() . ' = ?', $priceId);
        }
        $where = implode(' AND ', $conds);
        return $adapter->delete($this->getMainTable(), $where);
    }
    /**
     * Save tier price object
     *
     * @param Varien_Object $priceObject
     * @return Mage_Catalog_Model_Resource_Product_Attribute_Backend_Tierprice
     */
    public function savePriceData(Varien_Object $priceObject)
    {
        $adapter = $this->_getWriteAdapter();
        $data    = $this->_prepareDataForTable($priceObject, $this->getMainTable());
        if (!empty($data[$this->getIdFieldName()])) {
            $where = $adapter->quoteInto($this->getIdFieldName() . ' = ?', $data[$this->getIdFieldName()]);
            unset($data[$this->getIdFieldName()]);
            $adapter->update($this->getMainTable(), $data, $where);
        } else {
            $adapter->insert($this->getMainTable(), $data);
        }
        return $this;
    }
}


Step 9:
Create Observer file : app/code/local/Jaydip/Kansagra/Model/Observer.php


class Jaydip_Kansagra_Model_Observer extends Mage_Core_Model_Abstract
{
 
    /**
     * get default values
     *
     * @access public
     * @return block
     */
    public function addJobberelement($observer)
    {
        $form = $observer->getEvent()->getForm();
        $jobberPrice = $form->getElement('jobber_price');
        if ($jobberPrice) {
            $jobberPrice->setRenderer(
                Mage::app()->getLayout()->createBlock('jaydip_kansagra/adminhtml_catalog_product_edit_tab_price_jobber')
            );
        }
    }
}


Step 10:
Create phtml file : app/design/adminhtml/default/admintheme/template/catalog/product/edit/price/jobber.phtml


<?php
$_htmlId = $this->getElement()->getHtmlId();
$_htmlClass = $this->getElement()->getClass();
$_htmlName = $this->getElement()->getName();
$_readonly = $this->getElement()->getReadonly();
$_priceValueValidation = $this->getPriceValidation('validate-zero-or-greater');
$_showWebsite= $this->isMultiWebsites();
?>
<tr>
    <td class="label"><?php echo $this->getElement()->getLabel(); ?></td>
    <td colspan="10" class="grid tier">
        <table cellspacing="0" class="data border" id="jobber_prices_table">
            <?php if ($_showWebsite) : ?>
            <col width="135" />
            <?php endif; ?>
            <col width="120" />
            <col />
            <col width="1" />
            <thead>
            <tr class="headings">
                <th <?php if (!$_showWebsite): ?>style="display: none;"<?php endif; ?>><?php echo Mage::helper('catalog')->__('Website'); ?></th>
                <th><?php echo Mage::helper('catalog')->__('Customer Group'); ?></th>
                <th><?php echo $this->getPriceColumnHeader(Mage::helper('catalog')->__('Price')); ?></th>
                <th class="last"><?php echo Mage::helper('catalog')->__('Action'); ?></th>
            </tr>
            </thead>
            <tbody id="<?php echo $_htmlId; ?>_container"></tbody>
            <tfoot>
            <tr>
                <td <?php if (!$_showWebsite): ?>style="display: none;"<?php endif; ?>></td>
                <td colspan="4" class="a-right"><?php echo $this->getAddButtonHtml(); ?></td>
            </tr>
            </tfoot>
        </table>
        <script type="text/javascript">
            //<![CDATA[
            var jobberPriceRowTemplate = '<tr>'
                + '<td<?php if (!$_showWebsite): ?> style="display:none"<?php endif; ?>>'
                + '<select class="<?php echo $_htmlClass; ?> required-entry" name="<?php echo $_htmlName; ?>[{{index}}][website_id]" id="jobber_price_row_{{index}}_website">'
            <?php foreach ($this->getWebsites() as $_websiteId => $_info) : ?>
                + '<option value="<?php echo $_websiteId; ?>"><?php echo $this->jsQuoteEscape($this->escapeHtml($_info['name'])); ?><?php if (!empty($_info['currency'])) : ?> [<?php echo $this->escapeHtml($_info['currency']); ?>]<?php endif; ?></option>'
                <?php endforeach; ?>
                + '</select></td>'
                + '<td><select class="<?php echo $_htmlClass; ?> custgroup required-entry" name="<?php echo $_htmlName; ?>[{{index}}][cust_group]" id="jobber_price_row_{{index}}_cust_group">'
            <?php foreach ($this->getCustomerGroups() as $_groupId => $_groupName): ?>
                + '<option value="<?php echo $_groupId; ?>"><?php echo $this->jsQuoteEscape($this->escapeHtml($_groupName)); ?></option>'
                <?php endforeach; ?>
                + '</select></td>'
                + '<td><input class="<?php echo $_htmlClass; ?> required-entry <?php echo $_priceValueValidation; ?>" type="text" name="<?php echo $_htmlName; ?>[{{index}}][price]" value="{{price}}" id="jobber_price_row_{{index}}_price" /></td>'
                + '<td class="last"><input type="hidden" name="<?php echo $_htmlName; ?>[{{index}}][delete]" class="delete" value="" id="jobber_price_row_{{index}}_delete" />'
                + '<button title="<?php echo Mage::helper('catalog')->__('Delete Group Price'); ?>" type="button" class="scalable delete icon-btn delete-product-option" id="jobber_price_row_{{index}}_delete_button" onclick="return jobberPriceControl.deleteItem(event);">'
                + '<span><span><span><?php echo Mage::helper('catalog')->__('Delete'); ?></span></span></span></button></td>'
                + '</tr>';
            var jobberPriceControl = {
                template: new Template(jobberPriceRowTemplate, new RegExp('(^|.|\\r|\\n)({{\\s*(\\w+)\\s*}})', '')),
                itemsCount: 0,
                addItem : function () {
                <?php if ($_readonly): ?>
                    if (arguments.length < 3) {
                        return;
                    }
                    <?php endif; ?>
                    var data = {
                        website_id: '<?php echo $this->getDefaultWebsite(); ?>',
                        group: '<?php echo $this->getDefaultCustomerGroup(); ?>',
                        price: '',
                        readOnly: false,
                        index: this.itemsCount++
                    };
                    if(arguments.length >= 3) {
                        data.website_id = arguments[0];
                        data.group = arguments[1];
                        data.price = arguments[2];
                    }
                    if (arguments.length == 4) {
                        data.readOnly = arguments[3];
                    }
                    Element.insert($('<?php echo $_htmlId; ?>_container'), {
                        bottom : this.template.evaluate(data)
                    });
                    $('jobber_price_row_' + data.index + '_cust_group').value = data.group;
                    $('jobber_price_row_' + data.index + '_website').value    = data.website_id;
                <?php if ($this->isShowWebsiteColumn() && !$this->isAllowChangeWebsite()): ?>
                    var websiteElement = $('jobber_price_row_' + data.index + '_website');
                    var websiteCaption = websiteElement.options[websiteElement.selectedIndex].text;
                    websiteElement.insert({after:'<span class="website-name">' + websiteCaption + '</span>'});
                    websiteElement.hide();
                    <?php endif;?>
                    if (data.readOnly == '1') {
                        ['website', 'cust_group', 'price', 'delete'].each(function(element_suffix) {
                            $('jobber_price_row_' + data.index + '_' + element_suffix).disabled = true;
                        });
                        $('jobber_price_row_' + data.index + '_delete_button').hide();
                    }
                <?php if ($_readonly): ?>
                    $('<?php echo $_htmlId; ?>_container').select('input', 'select').each(this.disableElement);
                    $('<?php echo $_htmlId; ?>_container').up('table').select('button').each(this.disableElement);
                    <?php else: ?>
                    $('<?php echo $_htmlId; ?>_container').select('input', 'select').each(function(element) {
                        Event.observe(element, 'change', element.setHasChanges.bind(element));
                    });
                    <?php endif; ?>
                },
                disableElement: function(element) {
                    element.disabled = true;
                    element.addClassName('disabled');
                },
                deleteItem: function(event) {
                    var tr = Event.findElement(event, 'tr');
                    if (tr) {
                        Element.select(tr, '.delete').each(function(element) {
                            element.value='1';
                        });
                        Element.select(tr, ['input', 'select']).each(function(element) {
                            element.hide();
                        });
                        Element.hide(tr);
                        Element.addClassName(tr, 'no-display template');
                    }
                    return false;
                }
            };
            <?php foreach ($this->getValues() as $_item) : ?>
            jobberPriceControl.addItem('<?php echo $_item['website_id']; ?>', '<?php echo $_item['cust_group']; ?>', '<?php echo sprintf('%.2f', $_item['price']); ?>', <?php echo (int)!empty($_item['readonly']); ?>);
                <?php endforeach; ?>
            <?php if ($_readonly) : ?>
            $('<?php echo $_htmlId; ?>_container').up('table').select('button')
                .each(jobberPriceControl.disableElement);
                <?php endif; ?>
            //]]>
        </script>
    </td></tr>

Step 11:
Create SQL file : app/code/local/Jaydip/Kansagra/sql/jaydip_kansagra_setup/install-1.0.0.php


$installer = new Mage_Eav_Model_Entity_Setup('core_setup');
$installer->addAttribute(Mage_Catalog_Model_Product::ENTITY, 'jobber_price', array(
    'type'                       => 'decimal',
    'label'                      => 'Jobber Price',
    'input'                      => 'text',
    'backend'                    => 'jaydip_kansagra/jobberprice',
    'required'                   => false,
    'sort_order'                 => 6,
    'global'                     => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_WEBSITE,
    'apply_to'                   => 'simple,configurable,virtual',
    'group'                      => 'Prices',
));
$table = $installer->getConnection()
    ->newTable($installer->getTable('jaydip_kansagra/jobber_price'))
    ->addColumn('value_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'identity'  => true,
        'nullable'  => false,
        'primary'   => true,
        ), 'Value ID')
    ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned'  => true,
        'nullable'  => false,
        'default'   => '0',
        ), 'Entity ID')
    ->addColumn('all_groups', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned'  => true,
        'nullable'  => false,
        'default'   => '1',
        ), 'Is Applicable To All Customer Groups')
    ->addColumn('customer_group_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned'  => true,
        'nullable'  => false,
        'default'   => '0',
        ), 'Customer Group ID')
    ->addColumn('value', Varien_Db_Ddl_Table::TYPE_DECIMAL, '12,4', array(
        'nullable'  => false,
        'default'   => '0.0000',
        ), 'Value')
    ->addColumn('website_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
        'unsigned'  => true,
        'nullable'  => false,
        ), 'Website ID')
    ->addIndex(
        $installer->getIdxName(
            'jaydip_kansagra/jobber_price',
            array('entity_id', 'all_groups', 'customer_group_id', 'website_id'),
            Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
        ),
        array('entity_id', 'all_groups', 'customer_group_id', 'website_id'),
        array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE))
    ->addIndex($installer->getIdxName('jaydip_kansagra/jobber_price', array('entity_id')),
        array('entity_id'))
    ->addIndex($installer->getIdxName('jaydip_kansagra/jobber_price', array('customer_group_id')),
        array('customer_group_id'))
    ->addIndex($installer->getIdxName('jaydip_kansagra/jobber_price', array('website_id')),
        array('website_id'))
    ->addForeignKey(
        $installer->getFkName(
            'jaydip_kansagra/jobber_price',
            'customer_group_id',
            'customer/customer_group',
            'customer_group_id'
        ),
        'customer_group_id', $installer->getTable('customer/customer_group'), 'customer_group_id',
         Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey(
        $installer->getFkName(
            'jaydip_kansagra/jobber_price',
            'entity_id',
            'catalog/product',
            'entity_id'
        ),
        'entity_id', $installer->getTable('catalog/product'), 'entity_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey(
        $installer->getFkName(
            'jaydip_kansagra/jobber_price',
            'website_id',
            'core/website',
            'website_id'
        ),
        'website_id', $installer->getTable('core/website'), 'website_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->setComment('Catalog Product Jobber Price Attribute Backend Table');
$installer->getConnection()->createTable($table);
$installer->endSetup();

Friday, 9 February 2018

How to add / create grid Tab in custom module in magento admin panel

Step1 :
open : /app/code/local/Namespace/Modulename/Block/Adminhtml/Employee/Edit/Tabs.php
Add following lines

protected function _beforeToHtml()
{
.........
.........
.........
$this->addTab(
    'form_advancepayment',
    array(
'label'   => Mage::helper('namespace_modulename')->__('Advance Payment'),
'title'   => Mage::helper('namespace_modulename')->__('Advance Payment'),
'content' => $this->getLayout()->createBlock(
    'namespace_modulename/adminhtml_employee_edit_tab_advancepayment'
)
->toHtml(),
    )
);
return parent::_beforeToHtml();
}
Step2 :
Create new file (Advancepayment.php) : /app/code/local/Namespace/Modulename/Block/Adminhtml/Employee/Edit/Tab/Advancepayment.php
<?php
class Namespace_Modulename_Block_Adminhtml_Employee_Edit_Tab_Advancepayment extends Mage_Adminhtml_Block_Widget_Grid
{
    public function __construct()
    {
        parent::__construct();
        $this->setId('advancepymt_grid');
        $this->setDefaultSort('entity_id');
        $this->setDefaultDir('DESC');
        $this->setSaveParametersInSession(true);
        $this->setUseAjax(true);
        //$this->setFilterVisibility(false);
    }
   
    protected function _prepareCollection()
    {
        $id = $this->getRequest()->getParam('id');
        $collection = Mage::getModel('namespace_modulename/advancepymt')
            ->getCollection()
            ->addFieldToFilter('employee_id', $id);
       
        $this->setCollection($collection);
        return parent::_prepareCollection();
    }
   
    protected function _prepareColumns()
    {
        $this->addColumn(
            'entity_id',
            array(
                'header' => Mage::helper('namespace_modulename')->__('Id'),
                'index'  => 'entity_id',
                'filter' => false,
                'type'   => 'number'
            )
        );
        $this->addColumn(
            'payment',
            array(
                'header'    => Mage::helper('namespace_modulename')->__('Payment'),
                'align'     => 'left',
                'type'   => 'number',
                'index'     => 'payment',
            )
        );
       
        $this->addColumn(
            'created_at',
            array(
                'header' => Mage::helper('namespace_modulename')->__('Created at'),
                'index'  => 'created_at',
                'width'  => '120px',
                'type'   => 'datetime',
            )
        );
        return parent::_prepareColumns();
    }
   
    public function getGridUrl()
    {
        return $this->getUrl('*/*/advancepymt', array('_current'=>true));
    }
   
    public function getRowUrl($row)
    {
        return $this->getUrl('*/*/edit', array('id' => $row->getId()));
    }
Step3 :
Create function in current controller : /app/code/local/Namespace/Modulename/controllers/Adminhtml/Payroll/EmployeeController.php
class Namespace_Modulename_Adminhtml_Payroll_EmployeeController extends Namespace_Modulename_Controller_Adminhtml_Payroll
{
.............
.............
.............
public function advancepymtAction() {
        $this->loadLayout();
        $this->getLayout()->getBlock('edit.tab.advancepayment');
        $this->renderLayout(); 
    }
Step4 :
Add view in admin layout xml file : /app/design/adminhtml/default/default/layout/namespace_modulename.xml
Add following code into file

...........
...........
<adminhtml_modulename_employee_advancepymt>
<block type="core/text_list" name="root" output="toHtml">
    <block type="namespace_modulename/adminhtml_employee_edit_tab_advancepayment" name="edit.tab.advancepayment"/>
</block>
</adminhtml_modulename_employee_advancepymt>
...........
........... 

Thursday, 1 February 2018

Half hours / 15 Minutes time loop in Javascript / jQuery

        var x = 30; //minutes interval
        var timesarr = []; // time array
        var tt = 0; // start time
        var ap = ['AM', 'PM']; // AM-PM
        //Loop to increment the time and push results in times array
        for (var i=0;tt<24*60; i++) {
          var hh = Math.floor(tt/60); // getting hours of day in 0-24 format
          var mm = (tt%60); // getting minutes of the hour in 0-55 format
          timesarr[i] = ("0" + (hh % 12)).slice(-2) + ':' + ("0" + mm).slice(-2) + ' ' + ap[Math.floor(hh/12)]; // pushing data in array in [00:00 - 12:00 AM/PM format]
          tt = tt + x;
        }
        console.log(timesarr);

Thursday, 25 January 2018

How to keep multiple values selected dropdown in magento addField (multiselect)



$filterData = $this->helper('adminhtml')->prepareFilterString($this->getRequest()->getParam('filter', false));
$fieldset->addField('warehouse', 'multiselect', array(
            'label' => Mage::helper('namespace_reports')->__('Warehouse'),
            'title' => Mage::helper('namespace_reports')->__('Select multiple warehouse'),
            'name' => 'warehouse',
            'values' => $this->_getWarehouseArr(),
            'value' => isset($filterData['warehouse'][0]) ? explode(',', $filterData['warehouse'][0]) : array(),
            'style' => 'height:43px'
        ));

Tuesday, 23 January 2018

How to set background color into transparent image Imagick PHP

ini_set('display_errors',1);
header('Content-type: image/png');
$strInputFile = 'front.png'; // transparent image
$im = new Imagick($strInputFile);
$im->setImageBackgroundColor('green');
$im = $im->flattenImages();
echo $im;exit;

Saturday, 13 January 2018

How to install custom or subdomain SSL certificate in AWS.

How to install custom or subdomain SSL certificate in AWS.

1. sudo dpkg –s openssl

2. sudo a2enmod ssl

3. sudo service apache2 restart

4. openssl req -nodes -newkey rsa:2048 -keyout myserver.key -out server.csr
1. Country Name (2 letter code) [AU]: GB
2. State or Province Name (full name) [Some-State]: Surrey
3. Locality Name (eg, city) []: London
4. Organization Name (eg, company) [Internet Widgits Pty Ltd]: Company Name Pvt Ltd
5. Organizational Unit Name (eg, section) []: IT Department
6. Common Name (eg, YOUR name) []: yourdomain.com
7. Email Address []:webmaster@yourdomain.com
8. A challenge password []:
9. An optional company name []:

5. GET Certificate files and upload to "/var/www/html/cert/" :
1. private.key - Which you have generate using step 4
2. c00d2e98b15a0818.crt - Which you get certificate 3rd party
3. gd_bundle-g2-g1.crt - Which you get chain 3rd party

6. sudo nano /etc/apache2/sites-available/default-ssl.conf
**************
**************
DocumentRoot /var/www/html
<Directory /var/www/html/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
allow from all
</Directory>
*******
*******
*******
SSLCertificateFile "/var/www/html/cert/c00d2e98b15a0818.crt"
SSLCertificateKeyFile "/var/www/html/cert/private.key"
SSLCertificateChainFile "/var/www/html/cert/gd_bundle-g2-g1.crt"
*******
*******
*******

7. sudo a2ensite default-ssl.conf
8. sudo service apache2 restart
9. Check your ssl : https://www.sslshopper.com/ssl-checker.html

Tuesday, 9 January 2018

Clear configurable Swatches, Images, Flush Magento ALL Cache and cache files

ini_set('display_errors', 1);
require_once('../app/Mage.php');
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
/* Clear Cache */
try {
    $allTypes = Mage::app()->useCache();
    foreach($allTypes as $type => $cache) {
        Mage::app()->getCacheInstance()->cleanType($type);
    }
   
    /**
     * Flush cache storage
     */
    Mage::dispatchEvent('adminhtml_cache_flush_all');
    Mage::app()->getCacheInstance()->flush();
   
    /**
     * Flush all magento cache
     */
    Mage::app()->cleanCache();
    Mage::dispatchEvent('adminhtml_cache_flush_system');
   
   
} catch (Exception $e) {
    Mage::logException($e->getMessage());
}
try {
    /* cleanImages */
    Mage::getModel('catalog/product_image')->clearCache();
    Mage::dispatchEvent('clean_catalog_images_cache_after');
   
    /* cleanSwatches */
    Mage::helper('configurableswatches/productimg')->clearSwatchesCache();
    Mage::dispatchEvent('clean_configurable_swatches_cache_after');
   
    clearCstoreCacheDir('../var/cache');
   
    echo 'Success';
   
} catch (Mage_Core_Exception $e) {
    echo $e->getMessage();
} catch (Exception $e) {
    echo Mage::helper('adminhtml')->__('An error occurred while clearing the configurable swatches image cache.');
}
function clearCstoreCacheDir($dirPath) {
    if (!is_dir($dirPath)) {
        throw new InvalidArgumentException("$dirPath must be a directory");
    }
    if (substr($dirPath, strlen($dirPath) - 1, 1) != '/') {
        $dirPath .= '/';
    }
    $files = glob($dirPath . '*', GLOB_MARK);
    foreach ($files as $file) {
        if (is_dir($file)) {
            self::deleteDir($file);
        } else {
            unlink($file);
        }
    }
    rmdir($dirPath);
}