How can I make it so that shipping cost depends on the type of products purchased.

As long as products of type A are in the cart the shipping will cost a fixed amount (e.g. 5 EUR)

As soon as one of the products is of type B (even is some products are of type A) the shipping cost must become another fixed amount (e.g. 10 EUR)

can somebody give me some pointers on how this can be set up?

Files: 
CommentFileSizeAuthor
#19 order_product_class_condition-1243988-18.patch4.98 KBDanZ
PASSED: [[SimpleTest]]: [MySQL] 2,802 pass(es).
[ View ]
#7 1243988.patch3.3 KBTR
PASSED: [[SimpleTest]]: [MySQL] 2,411 pass(es).
[ View ]
#3 patch.patch2.34 KBbwynants
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch patch_112.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.
[ View ]

Comments

Title:shipping cost calculation based on product typeCheck an order's product class
Category:support» feature

The 6.x version had a method to check and order's product class to provide shipping methods. The 7.x version seems to be missing this condition, unless it's hiding under a different name.

Title:Check an order's product classMissing Rule to "Check an order's product class"

StatusFileSize
new2.34 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch patch_112.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.
[ View ]

thanks for the tip, this adds the Rule

Status:Active» Needs review

Status:Needs review» Needs work

The last submitted patch, patch.patch, failed testing.

Component:Shipping» Code
Status:Needs work» Needs review
StatusFileSize
new3.3 KB
PASSED: [[SimpleTest]]: [MySQL] 2,411 pass(es).
[ View ]

Re-rolled patch against head with correct patch format, then fixed coding standards problems. I haven't tested this on a site yet - let's see what the testbot has to say first.

#7: 1243988.patch queued for re-testing.

Closed #1751894: Add "cart contains product class" test as a duplicate.

Any updates on whether that patch works? That feature would sure be better than adding every single product in a class.

If anyone has tested it, they haven't told us here ... I would rather not commit something that hasn't been tested by the people who need that feature.

So if you would like to try it out and report back, that would be very helpful in moving this along.

I've been using the patch in #3 for almost a year now with no issues. I'll switch to #7 and post back.

I guess I can be a tester. I'll give it a try in a week or two after I finish my current project.

Status:Needs review» Needs work

If I add this condition to the "Order status gets updated" event, then I get the following notice:

Notice: Undefined property: stdClass::$type in uc_order_condition_has_productclass()

$product->type is not guaranteed to be set for ordered products.

mmm, I only use it to calculate shipping costs based on product type...

Is $product->nid (node ID) is guaranteed to exist for ordered products? If so, it could be used to look up the product node, which should be guaranteed to have a type (although, in theory, that could have been modified).

So, if $product->type doesn't exist, look up the $node->type?

Why isn't the type guaranteed to exist in ordered products, anyway? It seems easy enough to get when creating that record....

The $product object that's stored in the cart doesn't contain all the product information, nor should it. Think of the cart more like a DB table functioning as a relationship - all it really needs is the nid and a few other things, everything else can be and should looked up. That's how Drupal enables node types to be extensible by other modules. A simple fix would be to throw in a node_load($nid) right at the beginning. This is an efficient function - if the node has already been loaded (which it almost certainly will be) this will give you immediate access to all the product data from the cache.

$product->nid is guaranteed to be set, although node_load() may return FALSE - if the order is historic and the product node has since been deleted, or if the product was added using the "blank line" option in the admin order edit page. The comparison should probably ignore both these cases, as we have no way of telling what the actual product class was.

Updated #7.

Added check for empty $product->type, and attempted to get it from the node.

Added help text and improved the label to explain what the "Required" option does, because it was completely confusing. Clarified it for the product check, too, while I was there.

Commented the callback function parameters.

Changed assorted names to meet Drupal coding conventions.

I considered using 'restriction' => 'input' on the boolean options (to get rid of the data selection and only have the checkboxes), but it's just barely conceivable that someone might want to flip those switches based on some data selection. Not likely, though.

This will fail gracefully if someone changes a node type ID (product type ID). It would be better to implement hook_uc_product_class() and/or hook_node_type_update() and hook_node_type_delete() to update the rule conditions and all the saved ordered products when someone changes the node/product type.

A remaining condition that should be implemented is checking the order products against a taxonomy. That's a different request, though.

My apologies: This "new" functionality really wants a test case, but I don't know how to add one.

Status:Needs work» Needs review
StatusFileSize
new4.98 KB
PASSED: [[SimpleTest]]: [MySQL] 2,802 pass(es).
[ View ]

Here's the patch.

@stefank: Have you tried this patch yourself?

yeah i tried it. can confirm that it works

A more general version of this would be "Order contains at least X products of the following classes."

An even more general version would allow the admin to select a numerical comparison operator.

Not too difficult. Is it worth doing before committing this? Once this condition goes in, it can't easily be changed.

Extending a condition with existing settings is possible, it's just changing existing settings that is hard. In your example you could just extend the existing condition by defaulting X to 1 for sites that are already using it. I also don't want to make the condition overly complicated, if nobody really needs that feature.

I think a better solution for Rules would be an order condition that somehow lets you specify any existing node/product conditions, e.g. "Order contains [operator] [number] products that match [condition]" but I am not sure how feasible this is, and is outside the scope of this issue.

Also why did you change the quoting style in unrelated functions in this patch? It's not really necessary, if we are to do that everywhere it should be a separate issue.

The quoting style was changed in #7. I just left it alone because it was (very slightly) better that way.

Having a single order condition that allows checking of multiple ordered product conditions is an interesting thought. Would that be better than having multiple conditions that each check different things? Probably.

Eventually, it will probably be a good idea to attach conditions to other items. Right now, it's all about the orders. It might be reasonable to attach conditions to packages or products, for instance, to see if they work with a given shipping method (or whatever).

Status:Needs review» Fixed

Committed #19. Further feature requests to extend this condition, or create a general "order contains products that match this condition" condition, should be separate issues.

Status:Fixed» Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.