LemonStand Forum: Product Customization Issue - LemonStand Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Product Customization Issue

#1 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 09 August 2010 - 12:50 PM

I'm beginning to implement a custom module for one of our clients that allows a user to customize a product before it gets added to the cart.

* 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?
0

#2 User is online   Aleksey 

  • Co-Founder
  • Group: +Administrators
  • Posts: 3,633
  • Joined: 31-October 09

Posted 09 August 2010 - 02:20 PM

Hi!

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 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 10 August 2010 - 06:28 AM

I saw that events page after I posted and thought it might be the way I'd have to go - I'm wondering if there's a way to create a single field to a serialized array that i can just pass all the options from this into -- There's several fields and they change depending on selection. Also, how would i display that information then in the orders screen in the admin once it's serialized in the DB?

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

0

#4 User is offline   Phil 

  • Lemonholic
  • PipPipPip
  • Group: Members
  • Posts: 195
  • Joined: 13-January 10
  • LocationCumberland, BC, Canada

Posted 10 August 2010 - 11:29 AM

When you extend the model to add the custom fields, just do something like the following:
$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

0

#5 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 10 August 2010 - 11:34 AM

Yeah, I'd need to unserialize the data first and have some sort of html to layout the data once i had it, that's the part i'm having trouble pinning down, I've got the new column defined and saving and all that stuff...
0

#6 User is online   Aleksey 

  • Co-Founder
  • Group: +Administrators
  • Posts: 3,633
  • Joined: 31-October 09

Posted 10 August 2010 - 02:52 PM

Hi!

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 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 10 August 2010 - 04:19 PM

Here's the basic premise including files (i'm just running this free in a separate vhost so if you want to see it you'll want to do the same, or just take a look at the code).

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
0

#8 User is online   Aleksey 

  • Co-Founder
  • Group: +Administrators
  • Posts: 3,633
  • Joined: 31-October 09

Posted 10 August 2010 - 06:35 PM

Hi!

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 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 10 August 2010 - 07:18 PM

How will i go about displaying the information in the admin? I really just want to display some html formatted information from the array, I don't think it makes much sense to put them into text fields or anything.

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!
0

#10 User is online   Aleksey 

  • Co-Founder
  • Group: +Administrators
  • Posts: 3,633
  • Joined: 31-October 09

Posted 10 August 2010 - 07:32 PM

Quote

How will i go about displaying the information in the admin? I really just want to display some html formatted information from the array, I don't think it makes much sense to put them into text fields or anything.


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 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 11 August 2010 - 10:47 AM

Aleksey,
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

0

#12 User is online   Aleksey 

  • Co-Founder
  • Group: +Administrators
  • Posts: 3,633
  • Joined: 31-October 09

Posted 11 August 2010 - 06:14 PM

Hi!

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 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 13 August 2010 - 08:22 AM

Aleksey,
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?
0

#14 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 13 August 2010 - 08:53 AM

Actually, I've just run into another snag... my $custom_data doesn't seem to be making it when i'm logged in a registered user, works fine when i'm not logged in though?

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

0

#15 User is online   Aleksey 

  • Co-Founder
  • Group: +Administrators
  • Posts: 3,633
  • Joined: 31-October 09

Posted 13 August 2010 - 07:55 PM

Hi!

Quote

Actually, I've just run into another snag... my $custom_data doesn't seem to be making it when i'm logged in a registered user, works fine when i'm not logged in though?

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

I'm not sure how to get the product information in the onBeforeSetCartQuantity event handler to check my custom data,


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 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 16 August 2010 - 07:04 AM

Aleksey thanks - i was under the impression that since there was no event for extending the shop:onExtendCartItem that i didn't nee d to do anything, and missed the table when i was looking through them earlier but that seems to have fixed it.

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!
0

#17 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 16 August 2010 - 09:25 AM

Ok, one last time, and then i think we're done with this... Your example above worked fine when setting the data to static values, but It appears that my $order_item->x_epnewsletters_options is empty even though the data is there in the db and all the prices are being calculated correctly on the front... any thoughts why that variable is empty in the admin? I've tried doing a define_columns on that hoping it just "didn't know" what data i was talking about but that didn't seem to make any difference. I've also tried traceLogging the serialized "$order_item->x_epnewsletters_options" but according to LS it's empty (again, even though there is def. a serialized array saved in the db for the order item id.


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

0

#18 User is online   Aleksey 

  • Co-Founder
  • Group: +Administrators
  • Posts: 3,633
  • Joined: 31-October 09

Posted 16 August 2010 - 02:39 PM

Hi, Mitch!

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 User is online   Aleksey 

  • Co-Founder
  • Group: +Administrators
  • Posts: 3,633
  • Joined: 31-October 09

Posted 16 August 2010 - 04:10 PM

Mitch,

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 User is offline   mitchkramez 

  • Member
  • PipPipPip
  • Group: Members
  • Posts: 84
  • Joined: 26-February 10

Posted 16 August 2010 - 05:15 PM

Aleksey, I had already extended that table under an assumption, and there is in fact data in the table for my x_epnewsletters_options field in the format of a serialized array:

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
0

Share this topic:


Page 1 of 1

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users