Custom attribute/field in Magento Checkout

INTRODUCTION:

This wiki shows sample setup to move a checkout field or customer attribute from its EAV structure to sales level.

Specifically this example shows moving an attribute on customer/address to order.The example is more influenced by how magento move the field shipping_method,shipping_description and slightly by how TM/checkoutfield is implemented.
The concept is then adapted to just be any kind of checkout field or already existing attribute.

Obviously during the pre dispatch one has access to the entire post from checkout incase one just needs to work on a field in the checkout.

DEFINE SALES ATTRIBUTES (SAME AS IN EAV) – SETUP:

Assume there is an attribute custom_attribute on customer address:

$setup = new Mage_Sales_Model_Resource_Setup('sales_setup');
$setup->addAttribute('order', 'custom_attribute', array('type' => Varien_Db_Ddl_Table::TYPE_VARCHAR));$setup->addAttribute('quote_address', 'custom_attribute', array('type' => Varien_Db_Ddl_Table::TYPE_VARCHAR));

ADD THE FIELD ONCE FROM CUSTOMER ADDRESS TO QUOTE ADDRESS (OBSERVER):

Define events during checkout, in this case is a standard magenta one page but no difference if this was onestepcheckout or firecheckout.It will work the same especially that part of saveBilling.

<frontend><events><controller_action_predispatch_checkout_onepage_savebilling><observers><orderexport_save_quote_billing_checkout><class>CUSTOM_MODULE/observer</class><method>
                    setCheckoutDataField</method></orderexport_save_quote_billing_checkout></observers></controller_action_predispatch_checkout_onepage_savebilling><controller_action_predispatch_checkout_onepage_saveshipping><observers><orderexport_save_quote_shipping_checkout><class>CUSTOM_MODULE/observer</class><method>setCheckoutDataField</method></orderexport_save_quote_shipping_checkout>                
            </observers>            
        </controller_action_predispatch_checkout_onepage_saveshipping>        
    </events></frontend>

IMPLIMENT THE OBSERVER DEFINED BY THE ABOVE LISTENERS:

Move the data from customer address to quote address:

    public function setCheckoutDataField(Varien_Event_Observer $observer)
    {
        $quote = Mage::getSingleton('checkout/session')->getQuote();
        $quote->getBillingAddress()->setData('custom_attribute', $quote->getCustomer()->getDefaultBillingAddress()->getData('custom_attribute'));
        $quote->getShippingAddress()->setData('custom_attribute', $quote->getCustomer()->getDefaultShippingAddress()->getData('custom_attribute'));
        return $this;
    }

COPY FIELD SET:

Some definition to tell magenta to migrate or move our custom_attribute to other parts during the checkout – look under Sales/Model/Convert one could also use observers here:

 
<global><fieldsets><!-- move custom_attribute to quote/address--><sales_convert_order><custom_attribute><to_quote_address_shipping>*</to_quote_address_shipping><to_quote_address_billing>*</to_quote_address_billing></custom_attribute></sales_convert_order><!-- move custom_attribute from quote/address to order--><sales_convert_quote_address><custom_attribute><to_order>*</to_order></custom_attribute>
        </sales_convert_quote_address>
    </fieldsets>
</global>

REFENCE:
core/sales
TM/checkoutfield

Written by O.Z.Muhsin (Dev @Madia BV)

Pragmatic refunds in Magento

Creditmemo or Refund in Magento:

Row based based on row
Shipping Amount i.e refunded amount equals shipping_amount
Full i.e grand_total equals refunded amount
Positive i.e grand_total + refunded amount
Negative i.e grand_total – refunded amount

1.ROW BASED REFUND:

Assume you have $orderItem that needs to be refunded by $qty

$qtys['qtys'][$orderItem->getId()] = $qty;$this->createCreditmemo($order, $qtys);

2. SHIPPING AMOUNT REFUND:

$qtys = array(‘shipping_amount’ => $amount);$this->createCreditmemo($order, $qtys);

3.FULL REFUND

$qtys = array();
$this->createCreditmemo($order, $qtys);

4.POSITIVE REFUND:

$qtys = array('adjustment_positive’ => $amount);
$this->createCreditmemo($order, $qtys);

5.NEGATIVE REFUND

$qtys = array('adjustment_negative' => $amount);$this->createCreditmemo($order, $qtys);

API CALL:

 
    public function createCreditmemo(Mage_Sales_Model_Order $order, $qtys = array())
    {
    try {/** @var Mage_Sales_Model_Service_Order $service */
        $service = Mage::getModel('sales/service_order', $order);$creditmemo = $service->prepareCreditmemo($qtys);
        $creditmemo->getOrder()->setIsInProcess(true);//set refund data on the order
        Mage::getModel('core/resource_transaction')->addObject($creditmemo)
            ->addObject($creditmemo->getOrder())
            ->save();//refund
        $creditmemo->refund();
        $transactionSave = Mage::getModel('core/resource_transaction')
                        ->addObject($creditmemo)
                        ->addObject($creditmemo->getOrder());if ($creditmemo->getInvoice()) {
            $transactionSave->addObject($creditmemo->getInvoice());
        }
        $transactionSave->save();
        $creditmemo->getOrder()->setCustomerNoteNotify(true);
        $creditmemo->sendEmail();
        } catch (Exception $e) {
            Mage::logException($e);
        }
        return true;
    }

Changing product listing default direction by layout

By looking at this class I noticed that magento does expect default_direction – indicating it can be modified via layout:

Mage_Catalog_Block_Product_List:_beforeToHtml

Layout.xml:

<catalog_category_default translate="label">
    <reference name="product_list">
        <action method="setDefaultDirection"><value>desc</value></action>
    </reference>
</catalog_category_default>
 
<catalog_category_layered>
    <reference name="product_list">
        <action method="setDefaultDirection"><value>desc</value></action>
    </reference>
</catalog_category_layered>

Cdokus reviewed on 1.9.0.1v magento

Well obviously this weekend my wife and daughter are all out for swimming and I thought you know what ? Lets review the cdokus v0007 (latest) and see what all users will experience from Magento connect all the way to creating product and add some bunch pdf’s.

The extension works pretty fine as advertised 😀

cdokus-1

As it can be seen that on latest magento the download links on product page as expected.

cdokus-2

And the file user is downloading get stored on the correct location on the server.

Any hows its all good news so far! Enjoy the ride and have a nice weekend !

Notice:Major server maintainance

Unfortunately this has to happen, as this blog is running under my machine which was built a while ago with x86 architecture.Finally starting on sunday till today I quite busy executing this make over to x86_64 😀

My appologies for the invonience.So far so good most of the things are in place just minors here and there which needs couple reboot every kernel compile 😀

ERROR 1449 (HY000) at line 16982: The user specified as a definer (‘user’@’localhost’) does not exist

/*!50013 DEFINER=`some_user`@`some_host` SQL SECURITY DEFINER */

As far as I know, there is not yet a flag for mysqldump to avoid DEFINER export. So, a solution is to replace

DEFINER=`some_user`@`some_host`

with

DEFINER=CURRENT_USER

How to retrieve eav attribute’s database tables dynamically in Magento

This is a sample or example code where attributes database tables are being retrieved dynamically.In the end of the loop there is an example code where by some storeview level of the attributes are being removed as maintanance procedure or whatever someones wants to do.

P:S
**Notice the DELETE SQL statement is commented out to be careful from copy paste and run!

< ?php
 
ini_set('display_errors', 1);
require '../app/Mage.php';
 
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
Mage::setIsDeveloperMode(true);
 
/**
 * @desc Tested for Catalog Only
 */
$attributeCodes = array('name', 'description', 'short_description');
foreach ($attributeCodes as $attributeCode) {
    $attribute = Mage::getModel('eav/config')->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
    //table name
    $table = $attribute->getBackend()->getTable();
    //attribute_id
    $attributeId = $attribute->getId();    
    /**
     * @desc Example usage Remove some values
     */
    $db = Mage::getSingleton('core/resource')->getConnection('core_write');
    $where[] = $db->quoteInto('attribute_id = ?', $attributeId);
    $where[] = $db->quoteInto('store_id IN(?)', array(1, 2));
//    $db->delete($table, $where);
}