Product Customization Issue
#1
Posted 09 August 2010 - 12:50 PM
* These are newsletters, they are priced at $0.29 a piece - base price
* You can order any quantity of them for each issue date (the twelve months of the year)
** Each month you select should multiply them qty times the number of months you've selected for a product total price
** You can then select some customization options that affect the price by $50/month selected etc...
There are several other issues that will affect the price based on the number of issues, but I think the above will get me the information I need on how, if it's possible, to adjust the price of the product before adding it to the cart, depending on the selected options... Any thoughts?
#2
Posted 09 August 2010 - 02:20 PM
Well, I cannot say that I completely understood the task, but I think I got the point. You need to define a set of parameters the product cost depends on. If these parameters cannot be presented as standard LemonStand product features (options and extras), you will need to extend your product as it is described in this article: http://lemonstandapp...omize_products/
You can calculate the product cost dynamically on the Product page, using JavaScript. You will need to develop a script for it, of course. When the product is added to the cart you can override the cart item cost by handling the shop:onGetCartItemPrice event (please find a description on this page: http://lemonstandapp...onstand_events/). Inside the event hander you can access the Shop_CartItem object and load the product information and custom fields (using the get_data_field() method of the Shop_CartItem object) in order to calculate the item price.
I hope this helps. Let me know if you need any additional information.
Thank you
#3
Posted 10 August 2010 - 06:28 AM
I see that I can access my custom fields pretty easily in the event handler by referencing the $custom_data var, so I guess my only question is how to be able to pull that serialized array and simply display it (no editing) on the admin side in a new tab... Or am I unable to create my own tab?
This post has been edited by mitchkramez: 10 August 2010 - 11:02 AM
#4
Posted 10 August 2010 - 11:29 AM
$model->add_form_field('field_name')->tab('Name of custom tab');Edit: I see you need to unserialize the data first. In that case I'm not totally sure.
This post has been edited by pnomolos: 10 August 2010 - 11:32 AM
#5
Posted 10 August 2010 - 11:34 AM
#6
Posted 10 August 2010 - 02:52 PM
In order to add custom data field to the order item model, you need to extend it using using the shop:onExtendOrderItemModel and shop:onExtendOrderItemForm events (you can find the description on this page: http://lemonstandapp...c_information/)
In order to save serialized data, you need to extend the cart item and order item models with at least 1 text field (x_newspaper_raw_data, for example). On the shop:onExtendOrderItemModel and shop:onExtendOrderItemForm event handlers you don't need to add the new field to the model and to the order item form. Instead, you can create another visual field which will display the unserialized custom data. For example:
public function subscribeEvents()
{
Backend::$events->addEvent('shop:onExtendOrderItemModel', $this, 'extend_order_item');
Backend::$events->addEvent('shop:onExtendOrderItemForm', $this, 'extend_order_item_model');
}
public function extend_order_item($order_item)
{
// Define a new custom column. It is a virtual column, and it does not exist in the database
$order_item->custom_columns['x_some_data'] = db_text;
// Unserialize your data. You can do $order_item->x_some_data = unserialize($order_item->x_newspaper_raw_data);
$order_item->x_some_data = 'Some text';
// Add the virtual field to the model
$order_item->define_column('x_some_data', 'Some data');
}
public function extend_order_item_model($order_item)
{
// Add the virtual field to the form, to the Custom Data tab
$order_item->add_form_field('x_some_data')->tab('Custom Data')->renderAs(frm_text);
}(please find the screenshot attached)
But do you really need to use serialized data? You will need to prepare the serialized value when the product is added to the cart. There is no way to do that in LemonStand. You cannot override custom data values in the event handlers. But we can extend the API with a corresponding event if you need that.
Another option is to create separate field (extend the cart item and order item models) for each product customization field. Then you will not need to work with serialized data. But you still can use a virtual field for displaying the customization data in a single text field, if you want.
Please let me know what do you think. It is not difficult for us to extend the API.
Thank you
#7
Posted 10 August 2010 - 04:19 PM
As you can see in the files the dependencies are really kind of ridiculous, but this client has worked this way and we don't really have any options on another way to do it -- Let me know if you see a better way. The client chooses the quantity, and the number of issues they'd like to receive and any personalization on them.
Here's a screenshot if that will suffice:
http://cl.ly/7c9a52098b8affb6cf0c
Thanks in advance for the advice/help
#8
Posted 10 August 2010 - 06:35 PM
I looked into the screenshot (sorry, have no time for analyzing code). Should the months in the Issues section be dynamic? Also, it seems the checkboxes in the Personalization section depend on months selected in the Issues, so you cannot use fixed fields in the database for maintaining these checkboxes. It looks like only the Home Mailing feature is fixed.
Well, I suggest you to use custom code for generating controls on the product page and then save all data into a single filed in the order items table. It matches your original idea. We will extend the API in order to allow you to serialize data before saving it into the database. The code on the Product page should generate required controls and dynamically display checkboxes in the Personalization section (you can use JavaScript for that). Please use the following format for product field names: "item_data[x_field_name]", as it is described in this article: http://lemonstandapp...omize_products/ There will be no actual fields in the database (x_issue_august, for example). Instead you will use these fields for generating serialized data and calculating the product price.
You can begin implementing the product page. We will add the required API event when you are ready.
Thank you
#9
Posted 10 August 2010 - 07:18 PM
As soon as you can get it in the API that'd be ideal, I'm in the middle of implementing this functionality so the sooner the better! :)
FWIW, i'm naming my fields as such:
item_data[x_epnewsletters_options][personalization][<?= $month['month_abbrev'] ?>][]
they're all starting with x_epnewsletters_options and then continuing the array so it's easy to serialize.
Thanks again - you guys are incredible!
#10
Posted 10 August 2010 - 07:32 PM
Quote
As I mentioned above, you can create a custom (virtual) text field in the order item model and populate it with unserialized data. So in the Administration Area you will have a big text field with all information provided by the customer.
Thank you!
#11
Posted 11 August 2010 - 10:47 AM
After i serialize my array in my shop:onBeforeAddToCart event handler, it just keeps giving me an alert that says: "Array to string conversion" is this the extending of the API you were talking about or am I missing something? Here's my event handler for that piece:
public function before_add($cart_name, $product, $quantity, $options, $extra_options, $custom_data)
{
//if we're a newsletter... let's do some qty requirement checks
if ($product->x_epnewsletters_is_customizable_newsletter == 1)
{
// ===========================================================================
// = let's do some checking in here to make sure they have the right quanity =
// ===========================================================================
if(!empty($custom_data['x_epnewsletters_options']['personalization']) && ($quantity < 100)) {
throw new Phpr_ApplicationException('Personalization requires a minimum order of 100');
}
if(!empty($custom_data['x_epnewsletters_options']['mailing']) && ($quantity < 200)) {
throw new Phpr_ApplicationException('Home mailing requires a minimum order of 200');
}
//serialize it
$custom_data['x_epnewsletters_options'] = serialize($custom_data['x_epnewsletters_options']);
}
}
I'll attach my module in case that's helpful to anyone.
EDIT:
I think this is happening because my x_epnewsletters_options[personalization] doesn't always exist... should i be checking it differently in there -- it's fine when i have one of those front/back cover options checked?
This post has been edited by mitchkramez: 11 August 2010 - 11:33 AM
#12
Posted 11 August 2010 - 06:14 PM
I just added the shop:onPreProcessProductCustomData event to the API. You need to use it instead of the shop:onBeforeAddToCart, because it allows to modify the custom data before products are added to the cart. I will add documentation to the Wiki later. The event handler has the same parameters as the shop:onBeforeAddToCart handler, so you can just replace the event name in the addEvent call in your subscribeEvents() method.
To update the custom data the handler should return an array of updated data fields:
public function preprocess_custom_data($cart_name, $product, $quantity, $options, $extra_options, $custom_data)
{
$result = array();
$result['x_epnewsletters_options'] = 'some value';
return $result;
}Regarding the error you get - try looking to the logs/errors.txt file. This file contains a list of detailed error descriptions with script names and line numbers. Also you can use the traceLog() function to send tracing information to the logs/info.txt file. For example you can save the $custom_data value to the trace log in the beginning of the event hanlder:
traceLog($custom_data)
It will help you to troubleshoot the problem. BTW, non-checked checkboxes do not appear in the POST result and in the custom data array.
EDIT: I updated the documentation: http://lemonstandapp...onstand_events/
Thank you
This post has been edited by Aleksey: 11 August 2010 - 08:41 PM
#13
Posted 13 August 2010 - 08:22 AM
Thanks! that's worked perfectly and took care of the array message I was getting. I have one other question now: I'd like to prevent them from changing the quantity in the cart if certain parameters are set, but I'm not sure how to get the product information in the onBeforeSetCartQuantity event handler to check my custom data, and see if it's a custom newsletter product... It'd be nice if it just passed the $cart_item object along with it... Any thoughts or examples?
#14
Posted 13 August 2010 - 08:53 AM
EDIT:
$cart_item->get_data_field('x_epnewsletters_options') returns blank when i'm logged in, returns as expected when i'm not logged in on the front.
This post has been edited by mitchkramez: 13 August 2010 - 09:03 AM
#15
Posted 13 August 2010 - 07:55 PM
Quote
EDIT:
$cart_item->get_data_field('x_epnewsletters_options') returns blank when i'm logged in, returns as expected when i'm not logged in on the front.
Have you extended the customer cart item table? This article (http://lemonstandapp...ic_information/) has a link to the module template which contains an example of database updates which add new fields to the customer cart items table. Basically, you need the customer cart table (shop_customer_cart_items) has the x_epnewsletters_options field. Please check it.
Quote
In the onBeforeSetCartQuantity event handler you can use the cart item key to load the cart item:
public function cart_quantity($cart_name, $key, $value)
{
$item = Shop_Cart::find_item($key, $cart_name);
// Now you can load any data from the cart item (Shop_CartItem class)
}Thanks
#16
Posted 16 August 2010 - 07:04 AM
Regarding the Shop_Cart::find_item is there a reason that's not in the documentation for Shop_Cart? It seems pretty useful.
Thanks for helping me through my ignorance, We're very impressed with the flexibility of Lemonstand and your team!
#17
Posted 16 August 2010 - 09:25 AM
public function extend_order_item_model($order_item)
{
// Define a new custom column. It is a virtual column, and it does not exist in the database
$order_item->custom_columns['x_epnewsletters_unserialized_data'] = db_text;
$order_item->define_column('x_epnewsletters_options', 'Serialized Data');
//works:
$order_item->x_epnewsletters_unserialized_data = 'HAMBURGERS';
//doesn't work:
$order_item->x_epnewsletters_unserialized_data = unserialize($order_item->x_epnewsletters_options);
//$order_item->x_epnewsletters_options is empty, though i can see the data in the shop_order_items db table..
// Add the virtual field to the model
$order_item->define_column('x_epnewsletters_unserialized_data', 'Customization Data');
}
public function extend_order_item_form($order_item)
{
$order_item->add_form_field('x_epnewsletters_unserialized_data')->tab('Custom Data')->renderAs(frm_text);
}
This post has been edited by mitchkramez: 16 August 2010 - 09:28 AM
#18
Posted 16 August 2010 - 02:39 PM
The code looks right. I added you to Skype. Please let me know when you are online, we will troubleshoot this problem together.
Thank you
#19
Posted 16 August 2010 - 04:10 PM
I think I forgot to tell you that you need to extend the order items table as well. Sorry for misleading you. Please add the x_epnewsletters_options field to the shop_order_items table. You can do that with an update SQL file, as it is shown in the module template on this page: http://lemonstandapp...ic_information/
Thank you
#20
Posted 16 August 2010 - 05:15 PM
http://img.skitch.co...ctmqdekg9s4.jpg
so i must be missing something yet that the order preview in the admin isn't pulling in the data unless i set it to some static string, or some other variable set within that method

Help














