Custom Sized Products

Last modified by Mark_Kimsal on Fri, February 15, 2008 15:03
Source|Old Revisions  |  Back To Group

This is an old revision of the document!


Purposed: Sell more products than you have room for in the database by taking customer input and attaching it to the customer’s order.

Skill level: Intermediate to Advanced developer.

Target Audience: Any organization that creates “Made-to-Order” products.

Tested with Magento versions:

  • 0.6.14100 (BETA)

This article will detail an approach to taking custom sized orders from customers and attaching the specific information to an order invoice.

The steps involved are:

  • Create a product attribute in an attribute_set for your products that need a custom size. We will call this attribute “custom_size’ for the remainder of this article.
  • Alter the product info page to show specific form controls to the user for entering their size information.
  • Alter the cart procedure to attach the customer’s information to the product
  • Alter the order processing procedure to pass the product information into the order (sales_quote_item in Magento speak)

Product Attributes

You will need to create a product attribute called “custom_size” and attach this to any attribute set required for each product that can accept a custom size. This attribute will not be shown to the front end. It will act as a container and pass messages through-out the Magento system.

User Input

Altering the product info page to include specific size form controls is different for each organization’s needs. For this article we will create 2 input fields, one to ask for width information as whole inches, and one to get fractional width information down to the 1/8th of an inch.

Cart Procedure

As the first step, we will hard code in a valid of 23 & 1/8” into the custom field for testing purposes.

in app/code/core/Mage/Checkout/controllers/CartController.php around line: 89

$product→setData(’custom_size’, ‘32 1/8”‘);

Add the above line just above the line:

$cart→addProduct($product, $qty);

We need to modify one more part of the cart, otherwise, if someone orders another product with a different custom size, it will overwrite this first product. Technically, this is part of the Sales Quote, but, I feel, it mainly affects the behavior of the cart, so we will discuss it here.

Edit app/code/core/Mage/Sales/Model/Quote.php

    /**
     * Retrieve quote item by product id
     *
     * @param   int $productId
     * @return  Mage_Sales_Model_Quote_Item || false
     */
    public function getItemByProduct(Mage_Catalog_Model_Product $product)
    {
        foreach ($this->getAllItems() as $item) {
            if ($item->getSuperProductId()) {
                if ($product->getSuperProduct() && $item->getSuperProductId() == $product->getSuperProduct()->getId()) {
                    if ($item->getProductId() == $product->getId()) {
                        return $item;
                    }
                }
            }
            else {
                // CUSTOMIZED
                if ($item->getProductId() == $product->getId() && ( $item->getCustomSize() === $product->getCustomSize()) ) {
                    return $item;
                }
            }
        }
        return false;
    }

We need to alter the last if statement in this function and add our own comparison of custom sizes between the new product being added to the cart and the existing product in our cart (sales quote $item).

Alter the Sales Quote

Now we have to modify the definition of the Sales Quote in order for it to read and store this new, non-standard information from a product. Normally, in Magento, all unique characteristics are described by one SKU and one Product ID. Having a 1-to-1 mapping of features to unique SKU is necessary, we are trying to target the organizations that have too many products to turn into unique products in the database.

The definition of a “Sales Quote” is made up of attributes much like the definition of a product. But, there is no user interface to alter it (yet). Therefore, we need to run a few commands in SQL:

select @entity_type_id:=entity_type_id from eav_entity_type
where entity_type_code='quote_item';

insert into eav_attribute
    (entity_type_id, attribute_code, backend_type, frontend_input)
values (@entity_type_id, 'custom_size', 'text', 'text');

What we’ve done, basically, is ask the system for the entity ID of quote items, and inserted a new attribute for quote items in the attribute system (eav_attribute). We’ve said that it is text (frontend_input), and it should be stored in a MySQL text column (backend_type).

Lastly, the code does not (yet) automatically process all defined attributes for a quote, so we will have to add that ourselves.

app/code/core/Mage/Sales/Model/Quote/Item/Abstract.php

    /**
     * Import item data from product model object
     *
     * @param   Mage_Catalog_Model_Product $product
     * @return  Mage_Sales_Model_Quote_Item
     */
    public function importCatalogProduct(Mage_Catalog_Model_Product $product)
    {
        $this->setProductId($product->getId())
            ->setSku($product->getSku())
            ->setName($product->getName())
            ->setWeight($product->getWeight())
            ->setTaxClassId($product->getTaxClassId())
            ->setCost($product->getCost());

//this is our new code
        if (strlen($product->getCustomSize())) {
                $this->setCustomSize($product->getCustomSize());
        }
//done with our new code

        if($product->getSuperProduct()) {
                $this->setSuperProductId($product->getSuperProduct()->getId());
        }
        $this->setProduct($product);

        return $this;
    }

The if(strlen()) check is required for an obscure reason. If you don’t check for empty values, your sales quote will be refreshed upon checkout with default values from the product. Remember that we’re bucking the trend here. Our product has a blank attribute by default to act as containers for all parts of Magento. This is one of those areas where our idea of using an attribute as a message container wasn’t the intended purpose of product attributes.

Note: You should be able to add a product to your cart and see your new custom_size variable in the database in the table sales_quote_entity_text. If not, fix the problem before proceeding any further.

Alter Sales Order

This method is no longer recommended

We’re almost done. We just have to tell the sales order that it should behave just like the sales quote. Firstly, add the attribute to the system just like for the quotes.

select @entity_type_id:=entity_type_id from eav_entity_type
where entity_type_code='order_item';

insert into eav_attribute
    (entity_type_id, attribute_code, backend_type, frontend_input)
values (@entity_type_id, 'custom_size', 'text', 'text');

The only thing that changed was quote_item into order_item.

Now, we need to make a similar code change:


    public function importQuoteItem(Mage_Sales_Model_Quote_Item $item)
    {

        $this->setQuoteItemId($item->getId())
            ->setStoreId($item->getQuote()->getStoreId())
            ->setProductId($item->getProductId())
            ->setSku($item->getSku())
            ->setImage($item->getImage())
            ->setName($item->getName())
            ->setDescription($item->getDescription())
            ->setQtyOrdered($item->getQty())
            ->setPrice($item->getCalculationPrice())
            ->setRowTotal($item->getRowTotal())
            ;
            // TODO - all others

        if ( strlen($item->getCustomSize()) ) {
               $this->setCustomSize( $item->getCustomSize() );
        }

        Mage::dispatchEvent('sales_order_item_import_qoute_item', array('quote_item'=>$item, 'order_item'=>$this));
        return $this;
    }

Make sure you don’t just copy and paste, the variable is called $item here, not $product.

You should be able to place an entire order here and see the variables in your database. If not, stop before proceeding any further.

Alter Sales Order 2

The sales order is created from the sales quote in a different way in 0.7 and 0.8. You can now use Magento’s event system to safely add your custom attributes to the final order.

Make a new Helper class, and give it 1 method that will listen for order creation events:

class CompXYZ_MadeToOrder_Helper_Event extends Mage_Core_Helper_Abstract
{
      static function attachSpecialOrderAttribs($observer) {
        $event = $observer->getEvent();
        $orderItem = $event->getOrderItem();
        $quoteItem = $event->getItem();

        $orderItem->setLineItemDetails( $quoteItem->getLineItemDetails() );
        $orderItem->setConfigId( $quoteItem->getConfigId() );

      }
}

Save this file as app/code/local/CompXYZ/YourModule/Helper/Event.php.

Now we will make this code listen to order events. Edit your app/code/local/CompXYZ/YourModule/etc/config.xml

Add this block of code somewhere in the frontend tags. If you don’t have frontend tags, just add them around this code:


        <events>
          <sales_convert_quote_item_to_order_item>
            <observers>
              <my_cart_checker>
                <type>helper</type>
                <class>Metrof_MadeToOrder_Helper_Event</class>
                <method>attachSpecialOrderAttribs</method>
              </my_cart_checker>
            </observers>
          </sales_convert_quote_item_to_order_item>
        </events>

Show New Info with an Order

Use your PHP skills to change this file:

Adminhtml/Block/Sales/Order/View/Items.php


        $this->addColumn('custom_size', array(
            'header' => __('Details'),
            'getter' =>  'getCustomSize',
            'store'     => Mage::registry('sales_order')->getStoreId()
        ));




 

Magento 2 GitHub Repository

Magento Job Board - Some sort of tag line goes here

Latest Posts| View all Jobs