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?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Poieo’s picture

Title: shipping cost calculation based on product type » Check 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.

Poieo’s picture

Title: Check an order's product class » Missing Rule to "Check an order's product class"
bwynants’s picture

FileSize
2.34 KB

thanks for the tip, this adds the Rule

bwynants’s picture

Status: Active » Needs review

Status: Needs review » Needs work

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

longwave’s picture

TR’s picture

Component: Shipping » Code
Status: Needs work » Needs review
FileSize
3.3 KB

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.

softprmaodmca’s picture

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

Dan Z’s picture

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.

TR’s picture

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.

Poieo’s picture

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

Dan Z’s picture

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

longwave’s picture

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.

bwynants’s picture

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

Dan Z’s picture

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....

TR’s picture

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.

longwave’s picture

$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.

DanZ’s picture

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.

DanZ’s picture

Status: Needs work » Needs review
FileSize
4.98 KB

Here's the patch.

stefank’s picture

longwave’s picture

@stefank: Have you tried this patch yourself?

stefank’s picture

yeah i tried it. can confirm that it works

DanZ’s picture

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.

longwave’s picture

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.

DanZ’s picture

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).

longwave’s picture

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.