I'm looking to create a module that would invoke the rule to calculate the sell price of the line item using AJAX and then replace the sell price of the item on the page instead of making the customer add it to cart.
Here is my use case: I have different flavors that can be added to a product, and then dependent on the flavor the price is adjusted. The rules are working for adding to cart and thanks to the "custon ajax add to cart" module I have been able to get AJAX working there. Also, using this bit of code from #1300798: Show price in Add To Cart Form. I have been able to display the price on the add to cart form, and it also has a wrapper. So It would seem that all the pieces are aligned to have AJAX work for the radios and checkboxes on the line items, but I can't figure out a couple things:
1) How would I go about having the rule invoked? I know I have to use rules_invoke_event() with the calculate product price, but I am not sure what the second argument to pass to the rule is.
2) What would be the best means of having the price display replaced? Is this even possible with the framework?
3) Has anyone successfully done this before?
Best,
Tim
Comment | File | Size | Author |
---|---|---|---|
#57 | issue-example.gif | 174.27 KB | dtesenair |
#55 | switching-product.gif | 454.87 KB | dylf |
#52 | commerce_cart-incorporate-line-item-fields-ajax-price-recalculation-add-to-cart-1541886-51.patch | 5.66 KB | jsacksick |
| |||
#48 | flavours.gif | 120.28 KB | thejacer87 |
#30 | do_not_empty_field_080416.jpg | 327.19 KB | TheJoker |
Comments
Comment #1
OnkelTem CreditAttribution: OnkelTem commentedSame question.
I want to ajax-update sell price RIGHT on a product display node when a user changes option (which is commerce line item field).
How to do this?
Comment #2
NecroHill CreditAttribution: NecroHill commentedsame question
Comment #3
rszrama CreditAttribution: rszrama commentedHmm, you know, I hadn't considered this before, but here's how to do it. Warning: dev speak ahead.
Right now Drupal Commerce actually supports this behavior out of the box, it just only works through attribute fields, not line item fields added to the Add to Cart form. I never really considered adding AJAX support to the line item fields, but it could be done if you alter the Add to Cart form and add #ajax properties to the line item fields injected to the form you could probably make it happen. The only hitch is that the line item used to calculate sell prices on the Add to Cart form doesn't know anything about values coming in through the form state, and I'm not sure there's an appropriate place to alter this information on. You might get away with it by implementing some sort of preprocessor to the parameters passed in to the form - not sure.
Let's just go ahead and mark this as a feature request, but I doubt it'll go in before Commerce 2.x.
Comment #4
sacowan CreditAttribution: sacowan commentedHas anyone had any luck with this?
Comment #5
rszrama CreditAttribution: rszrama commentedThe issue would have been updated if so. Please don't change the issue status, as it's still a postponed feature request per my comment above.
Comment #6
MrPeanut CreditAttribution: MrPeanut commentedFor the sake of simplicity, is this a duplicate of #1692960: Refresh price field when a product is customized.?
Comment #7
rszrama CreditAttribution: rszrama commentedYep, let's close that one out.
Comment #8
mesch CreditAttribution: mesch commented+1 for having this functionality in core Commerce. Right now customers must add a product to the cart to see what effect their line item inputs have on the price, which is not ideal.
There seems to be two obstacles to making this happen. First, the field data is not actually added to the line item until the form is submitted. See the following in
commerce_cart_add_to_cart_form_submit()
:Second, I believe the
commerce_price
field uses thecommerce_product_calculate_sell_price
function to calculate the sell price. This function creates a generic, unpopulated line item. So even if a way is found to populate the line item in form state, the field will go on using an unpopulated line item.I really need this functionality for one line item field in particular, so for now my plan is to manually populate $form_state['line_item'], then invoke rule
commerce_product_calculate_sell_price
, and then manually refresh the price field by name. We'll see how it goes.Comment #9
griz CreditAttribution: griz commentedYes please.
This would solve the main problem with the granular nature of product pricing - if one has several product types with four or five options what is to be done when an additional service needs to be added?
Use case: print shop selling many different products with many options and an image field on the line item for the customer's design.
They then want to add an artwork checking service at a fixed fee per item, so naturally this would be another line item field and common sense might suggest a product reference. Using Rules it is easy enough to add the value of the referenced product onto the value of the referring product and this can be displayed in the cart and checkout through Views, but unfortunately using a product reference results in a dropdown with ugly "SKU - Title" options, no AJAX and not even a basic indication of price.
Comment #10
malberts CreditAttribution: malberts commentedI've started a module that lets you define a field option's price in one place (with a hook) which can then be used to display it on the Add to Cart form and for use in line item unit price calculation.
http://drupal.org/sandbox/malberts/1915570
It can calculate relative prices for options on single value fields and it can AJAX update the newly calculated custom product (line item) price.
Tomorrow I'm going to look at i18n and commerce_multicurrency support in there. Thereafter I have to get rid of any rough edges.
In the meantime, if anyone wants to look at it, go ahead. I'm currently testing it on Kickstart 2 with Entity Reference fields. I can see my prices with Select/Radio/Checkbox widgets and it updates my line item price, both on the product display node and in the cart.
Documentation is lacking, so if you want to test and don't know what's going on, ask me. Line item fields get some new settings (they should be self explanatory) and then 2 rules need to be enabled to test the bundled Entity Reference support.
Comment #11
marcus178 CreditAttribution: marcus178 commented@malberts Just having a look at your module and I'm a bit stuck on how to use it. I'm assuming I need to use hook_commerce_custom_product_pricing_calculate_option_price_alter to assign a price to the options but not sure what code to use within the hook to achieve this. Is there any chance of an example?
Comment #12
AnybodyI think this issue is related, but also states out, why commerce pricing attributes are not enough for cases where you absolutely require pricing rules power! The request has not lost any of its importance.
This screencast shows a good usage example: http://www.youtube.com/watch?v=j9KsyvQZaAY
So everybody may understand why this is important.
If someone has a working solution / workaround, please tell me!
PS: The module mentioned above does not work for me at all.
Comment #13
Problue SolutionsThis is essential for a dynamic product configurator type system, Commerce can do everything using custom line item fields and pricing rules, but whats missing is a dynamically updated price when the customer changes options, BEFORE they click add to cart.
I was almost thinking I could use Commerce for a project that requires this kind of thing, but unfortunately its back to a separate javascript solution now.
Comment #14
griz CreditAttribution: griz commentedI just managed to narrowly avoid bodging my way past this problem again by using malberts' module: http://drupal.org/sandbox/malberts/1915570
Despite supposedly being compatible only with option fields, it can be made to work with numeric fields (for multiplying a price by a float value) by adding an Ajax refresh button in a separate hook_form_alter:
I also had to stop commerce_vat from adding VAT twice, which I did by adding an ANDed group of two conditions: Not my_product_type AND Line item ID Not = 0.
It took me a while to get there, but thank you malberts!
Comment #15
Summit CreditAttribution: Summit commentedHi Griz, With what you made, is it now possible to handle quantum discounts and show the visitor real time that choosing a different quantity gives a different price?
Greetings, Martijn
Comment #16
griz CreditAttribution: griz commentedIn my use case this time the site owner is selling material by the meter, so we're not using the built-in quantity field. I've just tested it and changing the quantity field doesn't affect the price - the price is displayed based on your choice of formatter in the product type's view mode, and shows the unit price, not the line item total.
If you have Rules set up to alter the unit price based on quantity you may see the discount appear with the price if you've selected 'Formatted amount with components' and configured your Rule to add a 'Discount' price component, and you might be able to theme the output of that table or create your own formatter to show the line item's total as well as the unit price. I haven't tried either,
Or, perhaps preferably, you could show the price in the Add to Cart form using this https://www.drupal.org/node/1300798 which was linked in the OP, but take the quantity and unit price from the $form_state and multiply them.
Failing that, you could add an integer field to your line item to store the quantity, then in Rules you could use it's value to calculate your discount (which would definitely show up, I've tested that) and then populate the line item's built-in quantity field with it so that the discount is shown in the cart as expected.
Comment #17
griz CreditAttribution: griz commentedAlso, if you look at line 250 of malberts' module you'll see:
$form_state['values']['quantity'] has been commented out - not sure why, but you could try adding that back in.
I'd love to see this issue set to 'active' as given the code in malberts' sandbox there is definitely a viable way of integrating this functionality into commerce, but I've not even begun to look at commerce core and I have quite a lot left to do on my current project.
Comment #18
Andrew Gorokhovets CreditAttribution: Andrew Gorokhovets commentedsubscribe
Comment #19
fugazi CreditAttribution: fugazi commentedare already new opportunities were found to update the price on the product page. I have copied the video https://www.youtube.com/watch?hl=de&gl=DE&v=j9KsyvQZaAY , it all works just the price is not changed.
Comment #20
fugazi CreditAttribution: fugazi commentedany help appreciated
Comment #21
ryanfc78 CreditAttribution: ryanfc78 commentedI am looking for this as well. I hope this feature gets added soon.
Comment #22
trumanru CreditAttribution: trumanru commentedWaiting for the solution too. We need it so much!
Comment #23
mmtt CreditAttribution: mmtt commentedAre there any patches or goals for the next future to make this price changing by selecting attributes?
Comment #24
joep.hendrix CreditAttribution: joep.hendrix commentedI am afraid there will not be a solution before D8/Commerce2
Comment #25
diriy CreditAttribution: diriy commentedhope, we'll find it together...
I suggest to rebuild the "Quantity" widget with select box and the variants "1, 2, 3....". then, I think it is possible to work with Rules module... can it be considered as a solution? anyone tried?
Comment #26
diriy CreditAttribution: diriy commentedproposed suggestion above. needed to update issue
Comment #27
andyg5000Here's a patch to get us started here.
Comment #28
joshmillerTested Andy's patch. Not sure what the "foreach(element_child(" does for the fields on Andy's site, but I had to check for an empty array and just add it to the simple fields I was testing with.
Attached is the updated patch.
Below I've included an animated gif of this working. Please consider including this in the next version of Commerce, Ryan. Pretty please O:)
Comment #29
joshmillerComment #30
TheJoker CreditAttribution: TheJoker commentedjoshmiller, it works. Very cool!
But as always, is not without problems. I thought that the problem in the module "Conditional Fields" and wrote there https://www.drupal.org/node/2449311#comment-11053085. Now it seems that it is in a patch that is not working.
When switching between types of price is not set to zero, although given that it happened.
In molude malberts it works. But there can not be read text and numeric fields.
Please see what you can do.
Comment #31
wqmeng CreditAttribution: wqmeng commentedHello,
Have you considering to get this patch #28 also work with the field collection module https://www.drupal.org/project/field_collection?
Just testing this and I have a product which have a field collection field in the custom line item, and the field not work with this patch #28.
Thank you.
Comment #32
turbogeek CreditAttribution: turbogeek commentedThanks andyg5000 and joshmiller - patch #28 works well after testing. Hopefully this useful bit of code will make it in the next version of Commerce :)
Comment #33
sprucemoose CreditAttribution: sprucemoose commentedI have successfully applied this much needed patch, but the price in my product display is still not updating when selecting the line item (it is updated when I go to cart, so I think that is setup correctly). The ajax spinner appears briefly, but the price does not update.
Is there any additional setup I need to do after patching the cart module? Thanks
Comment #34
turbogeek CreditAttribution: turbogeek commentedHave you created a new Rule? If not, create one for the event "Calculating the sell price of a product" with your specific conditions and the action "Add an amount to the unit price".
Comment #35
sprucemoose CreditAttribution: sprucemoose commentedYes I had created the rule as described, and it is running and updating the price in the cart, but the ajax call does not update the price on the product display page. I have tried a fresh install with drupal 7.43, php 5.5 and the latest (patched as per 28) version of commerce and commerce custom product. I have formated line item total and product price to show as 'formatted price with components' etc, but am still not seeing the updated price in the product display. I feel I am probably missing some setting, but am banging my head against the wall trying to figure what it is!
Comment #36
turbogeek CreditAttribution: turbogeek commentedWhat about the ajax callback function, does it exist? It sounds like the callback "commerce_cart_add_to_cart_form_line_item_field_refresh" is being called but perhaps it doesn't exist or you need to clear cache. This function returns the product price.
Comment #37
sprucemoose CreditAttribution: sprucemoose commentedI found an error log message from when the "Calculating the sell price of a product" which was 'Unable to get the data value for the variable or parameter amount. Error: Unable to get the data property field_additional_price as the parent data structure is not set.'
I have since tried again with a fresh install. I and am no longer getting the error message, but am still not seeing the updated price on the product display page, but it is updated in the cart. I have flushd all caches, and checked the commerce_cart_add_to_cart_form_line_item_field_refresh function esicts. It exists just in the updated commerce_cart.module file. Is this the only place it needs to be?
Comment #38
turbogeek CreditAttribution: turbogeek commentedIt's difficult to determine what the issue might be so I made the patch into a simple module. It also includes a rules example that you can follow.
https://github.com/deckfifty/commerce-line-item-recalculate
Just enable, setup a rule and you should be good to go!
Comment #39
mglamanMarking for the D7 Sprint. Maybe we should promote this as a submodule, or get a patch in. Will want rszrama's feedback.
Comment #40
sprucemoose CreditAttribution: sprucemoose commentedI have discovered my issue was caused by having the 'number of values' field in the 'product reference' field of the product display set to 1. After changing this to unlimited everything is working perfectly now. Thank you andyg5000 for the patch, and to turbogeek for your assistance and the module version. Much appreciated!
Comment #41
mdupree CreditAttribution: mdupree as a volunteer and at Acro Commerce commentedTested via turbogeeks module based off JoshMillers patch. Works! thumbs up from me.
Thanks you guys!
Comment #42
mdupree CreditAttribution: mdupree as a volunteer and at Acro Commerce commentedShould we have a few more people test this? or should we update the status.
Comment #43
thejacer87 CreditAttribution: thejacer87 at Acro Commerce commentedtested the module by turbogeek. rule works for me
Comment #44
Alexandre360 CreditAttribution: Alexandre360 commented+1 for a commit. I think it should be added in core and not in a submodule. The core handle ajax price update for products attributes and it should provide the exact same feature for line items attributes to stay consistent.
Comment #45
AnybodyConfirming RTBC and +1 :)
Comment #46
turbogeek CreditAttribution: turbogeek commentedI agree Alexandre360, having the same callback for line items and attributes would be best. Hopefully it's in a future release.
Comment #47
joshmillerAs much as I want to see this in core Commerce, we need the RTBC to be on the actual patch and not a stand-alone module.
Comment #48
thejacer87 CreditAttribution: thejacer87 at Acro Commerce commentedTested the patch, NOT the module!
I sampled a use case similar to what @timodwhit was asking for in the original post. I added a Flavours field to the product line item type. Three choices, and made a rule for each. I think the patch should be committed, but maybe open an other issue to add some documentation to explain how to get this done.
Comment #49
mojiro CreditAttribution: mojiro commentedI tried to use this patch/module but I am facing a weird problem.
My price field's html is:
while the Ajax response is:
.. so my price-field's html is missing one div wrapper!
Do you have any idea why is this happening?
Comment #50
kopeboy CreditAttribution: kopeboy commentedWe have a working patch in #28 no?
Comment #51
rszrama CreditAttribution: rszrama at Centarro commentedComment #52
jsacksick CreditAttribution: jsacksick commentedI tested the patch, and wanted to test a usecase where you'd need to build a pricing calculation rule using license fields values... When you use the Commerce License module, an entity reference field is added from the line item to the license.
Using an Inline Entity Form widget, you could expose License fields from the add to cart form directly...
So with the patch from #28, license fields weren't triggering an ajax refresh, problem is, with the attached patch, an ajax request is correctly fired, but you can't actually react to the refresh using Rules because the license itself hasn't been created yet, thus, not accessible from the line item.
I cleaned up the huge loop and now relying on a recursive function for attaching the #ajax property.
Additionally, I added an alter hook (hook_commerce_cart_add_to_cart_form_line_item_field_refresh_alter(), similar to the hook fired when refreshing the attribute refresh one (hook_commerce_cart_attributes_refresh_alter()).
Since the form, $form_state & the line item is passed to the hook, you could use that to alter the price displayed....
Comment #53
mglamans/L/l
Two lines, should we just say "The array of AJAX commands." to keep it one line?
Should we add a matching field setting here that allows opting in for the cart settings?
So if they enable the cart settings field access, then the states API shows a checkbox "to include in pricing calculation."
Now we don't need to recurse. It goes on the top level, people alter in as needed.
Comment #54
lukasss CreditAttribution: lukasss commentedafter #52 I have fatal error:
call to undefined function commerce_product_pricing_invoke()
Comment #55
dylf CreditAttribution: dylf at Acro Commerce commentedDid some testing and the patch in #52 looks good to me. I would make the suggested edits in #53, but other than that RTBC +1 from me.
Comment #56
jsacksick CreditAttribution: jsacksick commented@lukasss you need to upgrade Commerce to the latest dev as well... (changes were introduced to the way we invoke pricing rules lately).
Comment #57
dtesenair CreditAttribution: dtesenair commentedFirst of all, thanks to all who have worked on and contributed to this functionality.
I'm using the module that turbogeek provided in #38 but am having an odd issue...
If my product display node only references a single product, everything works great... the rules fire when line item fields are updated and the price is calculated properly. However, if the display node references more than one product, the price calculation gets a little screwy:
- When selecting a different product the pricing rule that modified the price is not fired.
- When selecting the line item field, the pricing rule changes the display to the price of the first product.
My pricing rule is as follows:
Event:
- Calculating the sell price of a product
Conditions:
- Entity is of bundle = "Custom Print Line Item"
- Entity has field: field_add_frame
- Data comparison = field_add_frame=1
Actions
- Add an amount to the unit price = Amount: 500
Here's an animated GIF of the behavior:
I apologize in advance if I've missed some simple configuration but any help would be appreciated.
Comment #58
Frederic wbase CreditAttribution: Frederic wbase commentedHello
After testing this patch everything seems to work fine. But I have a use case where there are multiple inline entity forms in the add to cart form. See screenshort: https://www.dropbox.com/s/ysqc58er9tewk5r/Schermafdruk%202017-09-19%2017...
The issue is that the action buttons of those inline entity forms aren't working anymore. My guess is that this is because of the Ajax callback that is replaced, we now have 'commerce_cart_add_to_cart_form_line_item_field_refresh' instead of 'inline_entity_form_get_element' as a callback.
My first guess to solve this is by using the hook_commerce_cart_add_to_cart_form_line_item_field_refresh_alter but I am not 100% sure. Any thoughts?
grts
Comment #59
CProfessionals CreditAttribution: CProfessionals commentedApplied #28 patch to new install of commerce kickstart 2 with (7.x-1.x-dev updated 28 Aug 2017 at 19:14 UTC) release of Commerce module. Does not seem to query the pricing rules every refresh. Pricing stays the same. but when you go to checkout the correct value is on the order.
Comment #60
rszrama CreditAttribution: rszrama at Centarro commentedMoving this back to needs work after testing and removing from the 1.14 release plan.
I duplicated the issue in comment #57 - I'm not sure there's a great way to support line item fields in the attribute related refresh, because you don't have the opportunity to pass in a line item or form state information during the rendering of the price field that is replaced into the page. I suppose we'd simply have to calculate the price a second time in the event we detect line item fields on the form and swap it in directly.
That said, I'm not sure it's a great idea to be recursively setting the Ajax callback like this patch does as of #52. There could be line item fields that legitimately need to set their own, even if it's something as simple as adding additional values to an unlimited multi-value field.
I think for this patch to be successful, we'll need to introduce constraints and not attempt to support line item field based price calculation in every instance. I'd be fine with just admitting it won't work for inline entity forms or fields that have their own Ajax callbacks, for example. I'd even be fine with restricting it to products without attributes, but I think that issue is more easily solved than the latter.