On the product page, I'm programmatically setting some custom options via additional_options. This is a calculated price and some hidden details.
I use checkout_cart_product_add_after and sales_convert_quote_item_to_order_item events to properly add the product to the cart with the calculated price and other custom options data.
And it works fine.
I'm able to load the product with those options again, when using the "edit" link in the cart.
The problem is that when I've made changes to the product and press "update cart", the cart loads without any of those options and only the base price (base price is just the product price i use to calculate the custom price).
So, all custom data gone.
I've googled and tried different things. For example tried using checkout_cart_update_item_complete event.
This code fails for checkout_cart_update_item_complete but works for checkout_cart_product_add_after:
$quoteItem = $observer->getQuoteItem();
$product = $quoteItem->getProduct();
This is the error I get:
Fatal error: Call to a member function getProduct() on a non-object
Why can't I get the quote item from checkout_cart_update_item_complete?
How can I get the updated quote item and make sure that my custom options are included?
UPDATE: Code examples - Simplified. Here I just try to set the calculated price and custom width and height fields.
/app/code/local/CoffeeMaker/CustomizeProduct/etc/config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<CoffeeMaker_CustomizeProduct>
<version>0.0.1</version>
</CoffeeMaker_CustomizeProduct>
</modules>
<frontend>
<events>
<catalog_product_load_after>
<observers>
<extra_options>
<type>model</type>
<class>CoffeeMaker_CustomizeProduct_Model_Observer</class>
<method>loadExtraOptions</method>
</extra_options>
</observers>
</catalog_product_load_after>
<checkout_cart_product_add_after>
<observers>
<custom_price>
<type>model</type>
<class>CoffeeMaker_CustomizeProduct_Model_Observer</class>
<method>customPrice</method>
</custom_price>
</observers>
</checkout_cart_product_add_after>
<checkout_cart_update_item_complete>
<observers>
<custom_price_update>
<type>model</type>
<class>CoffeeMaker_CustomizeProduct_Model_Observer</class>
<method>customPriceUpdate</method>
</custom_price_update>
</observers>
</checkout_cart_update_item_complete>
<sales_convert_quote_item_to_order_item>
<observers>
<extra_options>
<type>model</type>
<class>CoffeeMaker_CustomizeProduct_Model_Observer</class>
<method>salesConvertQuoteItemToOrderItem</method>
</extra_options>
</observers>
</sales_convert_quote_item_to_order_item>
</events>
</frontend>
</config>
/app/code/local/CoffeeMaker/CustomizeProduct/Model/Observer.php
<?php
class CoffeeMaker_CustomizeProduct_Model_Observer {
// I should be able to use customPrice() but it fails on line #2 as it doesn't seem to be able to get quoteitem for updated product
public function customPriceUpdate(Varien_Event_Observer $observer) {
$quoteItem = $observer->getQuoteItem();
$product = $quoteItem->getProduct();
/*
$basePrice = $product->getPrice();
$postData = Mage::app()->getFrontController()->getRequest()->getParams();
$width = $postData["customWidth"];
$height = $postData["customHeight"];
$m2 = ($width * $height) / 10000;
$totalPrice = (float) $m2 * $basePrice;
$totalPrice = ceil($totalPrice);
// Force minimum price (w/o tax)
if ($totalPrice < 400) {
$totalPrice = 400;
}
$quoteItem->setOriginalCustomPrice($totalPrice);
Mage::log("customPriceUpdate has run!");
*/
}
public function customPrice(Varien_Event_Observer $observer)
{
$quoteItem = $observer->getQuoteItem();
$product = $quoteItem->getProduct();
$basePrice = $product->getPrice();
$postData = Mage::app()->getFrontController()->getRequest()->getParams();
$width = $postData["customWidth"];
$height = $postData["customHeight"];
$m2 = ($width * $height) / 10000;
$totalPrice = (float) $m2 * $basePrice;
$totalPrice = ceil($totalPrice);
// Force minimum price (w/o tax)
if ($totalPrice < 400) {
$totalPrice = 400;
}
$quoteItem->setOriginalCustomPrice($totalPrice);
Mage::log("customPrice has run!");
}
public function loadExtraOptions(Varien_Event_Observer $observer) {
$action = Mage::app()->getFrontController()->getAction();
if ( $action->getFullActionName() == "checkout_cart_add" ) {
$data = $action->getRequest()->getParams();
$options = array(
"customWidth" => $data["customWidth"],
"customHeight" => $data["customHeight"]
);
$product = $observer->getProduct();
$additionalOptions = array();
if ( $additionalOption = $product->getCustomOption('additional_options') ) {
$additionalOptions = (array) unserialize($additionalOption->getValue());
}
foreach( $options as $key => $value ) {
$additionalOptions[] = array(
'label' => $key,
'value' => $value
);
}
$observer->getProduct()
->addCustomOption('additional_options', serialize($additionalOptions));
} else if ($action->getFullActionName() == "checkout_cart_configure") {
$id = $action->getRequest()->getParams()["id"];
$cart = Mage::getModel('checkout/cart')->getQuote();
$quoteItem = $cart->getItemById($id);
$options = array(
'customWidth' => "Boogie johnson",
'customHeight' => "Super Loogie"
);
$product = $observer->getProduct();
// Add to the additional options array
$additionalOptions = array();
if ( $additionalOption = $product->getCustomOption('additional_options') ) {
$additionalOptions = (array) unserialize($additionalOption->getValue());
}
foreach( $options as $key => $value ) {
$additionalOptions[] = array(
'label' => $key,
'value' => $value
);
}
$observer->getProduct()
->addCustomOption('additional_options', serialize($additionalOptions));
}
Mage::log("loadExtraOptions has run!");
}
public function salesConvertQuoteItemToOrderItem(Varien_Event_Observer $observer) {
$quoteItem = $observer->getItem();
if ($additionalOptions = $quoteItem->getOptionByCode('additional_options') ) {
$orderItem = $observer->getOrderItem();
$options = $orderItem->getProductOptions();
$options['additional_options'] = unserialize($additionalOptions->getValue());
$orderItem->setProductOptions($options);
}
}
}
my_template_path/catalog/product/view.phtml I've just added these inputs within the tag. And it works when putting the product in the basket.
Width: <input type="text" name="customWidth"><br>
Height: <input type="text" name="customHeight"><br>