13

I have an observer that is adding dynamic custom options to the product detail page, which is called on the catalog_controller_product_view event. This allows the customer to select from a dropdown of their existing license codes.

public function addLicenseOptions(Varien_Event_Observer $observer) {
    $product = $observer->getEvent()->getProduct();
    if ($product->isSubscriptionProduct()) {
        $optionModel = Mage::getModel('catalog/product_option')
            ->setTitle('License Code')
            ->setProductId($product->getId())
            ->setStoreId($product->getStoreId())
            ->setId('license_code')
            ->setType('drop_down')
            ->setPrice(null)
            ->setPriceType(null)
            ->setIsRequire(true);

        $customer = Mage::getSingleton('customer/session')->getCustomer();
        if ($customer->getId()) {
            $linksPurchased = Mage::getResourceModel('downloadable/link_purchased_collection')
                        ->addFieldToFilter('customer_id', $customer->getId());

            if ($linksPurchased->count() > 0) {
                foreach ($linksPurchased as $linkPurchased) {
                    $valueModel = Mage::getModel('catalog/product_option_value')
                        ->setTitle($linkPurchased->getData('key_code'))
                        ->setProduct($product)
                        ->setOption($optionModel)
                        ->setId($linkPurchased->getData('license_code'))
                        ->setPrice(null)
                        ->setPriceType('fixed')
                        ->setSku(null);
                    $optionModel->addValue($valueModel);
                }
                $product->setHasOptions(1);
                $product->addOption($optionModel);
            }
        }
    }
}

But, when I place the order, the selected options are only saved in the info_buyRequest. Is there a way to get it to save as if it were a product option created in the admin?

0

2 Answers 2

6

I've done something similar but not quite. Maybe it helps.
my task was to have a checkbox on each product page called gift wrap. If checked then, the sales team would know to wrap the product (they only had a single wrapping option).
So I did this in order to be able to port the wrap checkbox value from product to quote to order. (I could have used a custom option but it's ugly to add one option to a few thousand products).

I had an observer for the event sales_convert_quote_item_to_order_item.

public function checkGiftWrap($observer)
{
    $orderItem = $observer->getEvent()->getOrderItem();
    $item = $observer->getEvent()->getItem();
    $wrap = $item->getOptionByCode('wrap');
    if ($wrap){
        $options = $orderItem->getProductOptions();
        $options['wrap'] = unserialize($wrap->getValue());
        $orderItem->setProductOptions($options);
    }
    return $this;
}

I've rewritten the Mage_Catalog_Helper_Product_Configuration::getCustomOptions helper in order to tell Magento that my option is important and should treat it separately

<?php
class [Namespace]_[Module]_Helper_Product_Configuration extends Mage_Catalog_Helper_Product_Configuration
{
    public function getCustomOptions(Mage_Catalog_Model_Product_Configuration_Item_Interface $item){
        $options = parent::getCustomOptions($item);
        $wrap = $item->getOptionByCode('wrap');
        if ($wrap){
            $options = array_merge($options, array(unserialize($wrap->getValue())));
        }
        return $options;
    }
}

For the same reason I've rewritten Mage_Sales_Block_Order_Item_Renderer_Default::getItemOptions so my option will be displayed in the cart

<?php
class [Namespace]_[Module]_Block_Sales_Order_Item_Renderer_Default extends Mage_Sales_Block_Order_Item_Renderer_Default
{
    public function getItemOptions(){
        $result = parent::getItemOptions();
        $options = $this->getOrderItem()->getProductOptions();
        if (isset($options['wrap'])){
            $result = array_merge($result, array($options['wrap']));
        }
        return $result;
    }
}

and the admin name column for the order items grid:

<?php
class [Namespace]_[Module]_Block_Adminhtml_Sales_Items_Column_Name extends Mage_Adminhtml_Block_Sales_Items_Column_Name
{
    public function getOrderOptions(){
        $result = parent::getOrderOptions();
        if ($options = $this->getItem()->getProductOptions()) {
            if (isset($options['wrap'])) {
                $result = array_merge($result, array($options['wrap']));
            }
        }
        return $result;
    }
}

[EDIT]
It seams I missed something. I only implemented the option to add a giftwrap once the product is in the cart.
But I think you can use the same code in an event prior or after adding the item to the cart.

$data = array();
$data['label'] = Mage::helper('helper_alias')->__('Giftwrapping');
$data['value'] = Mage::helper('helper_alias')->__('Yes');
$product->addCustomOption('wrap', serialize($data));
$item->addOption($product->getCustomOption('wrap'));
$item->save(); //this line should be called only if it's not called by default after your event is dispatched.

That's it. I hope you can get something useful out of it.

6
  • Where I'm having trouble is getting the option. When I call $item->getOptionByCode('license_code') I'm getting a null. My options don't even show up when I call the following: $helper = Mage::helper('catalog/product_configuration'); $options = $helper->getCustomOptions($quoteItem); How are you setting the 'wrap' option?
    – Laura
    Commented May 27, 2015 at 21:22
  • @Laura. I'll check if I missed something and get back to you.
    – Marius
    Commented May 28, 2015 at 6:26
  • @Laura. I double checked and it seams I missed something. For me, the option to add giftwrapping is shows only in the cart. I forgot I changed this because the client requested it. I updated the answer with the code I used in a custom action. Maybe you can add it in a cart event observer.
    – Marius
    Commented May 28, 2015 at 7:01
  • I ended up parsing the buy request after all. The problem is that the options I'm setting in my original code block were not getting transferred to the quote item at all outside of the buy request.
    – Laura
    Commented Jun 1, 2015 at 18:37
  • @Marius I want to add product in cart with on the fly generate option without add in product option in admin side how it possible Commented Oct 1, 2016 at 11:48
4

Tying on to Marius' answer, here's something I've come up with:

I have a custom controller that handles the configuration of a custom product type. This controller adds additional_options during add to cart.

// My_Module_CartController::addToCartAction
// Get your product model
$product = $this->getProduct();

// Create options
$options = array();
$options['my_option'] = array(
    'label' => 'My Label',
    'value' => 'my_value'
);

$cartRequest = array(
    'product' => $product->getId(),
    'qty' => '1'
);

$cart = Mage::getModel('checkout/cart');
$cart->init();

// Add options
$product->addCustomOption('additional_options', serialize($options));

// Add to cart
$cart->addProduct($product, $cartRequest);
$cart->save();

In an observer on the event sales_convert_quote_item_to_order_item, I then grab the additional_options and set as options on the order item:

// My_Module_Model_Order_Observer::convertQuoteToOrder(Varien_Event_Observer $o)
// Get quote and order items
$orderItem = $o->getEvent()->getOrderItem();
$quoteItem = $o->getEvent()->getItem();

// Get serialized options set on product earlier
$myOptions = $item->getProduct()->getCustomOption('additional_options')->getValue();

// Add these options into the order item's options
$options = $orderItem->getProductOptions();
$options['additional_options'] = unserialize($myOptions);
$orderItem->setProductOptions($options);

return $this;

By using additional_options you shouldn't have to worry about various blocks/templates rendering the options (although you may prefer an altered format) as these blocks will call $options['additional_options']See Here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.