I have managed to create a new Rule condition called "Total product of type quantity comparison"

This condition is the same as the "Total product quantity comparison" but also takes a product type, and only counts items of that type.

Below are the condition declaration for hook_rules_condition_info() and the call back. It would be cool if they could be included as I think being able to get the quantity of a product type is particularly useful for things like shipping calculations and discounts.

  $conditions['commerce_order_compare_total_product_type_quantity'] = array(
    'label' => t('Total product of type quantity comparison'),
    'parameter' => array(
      'commerce_order' => array(
        'type' => 'commerce_order',
        'label' => t('Order'),
        'description' => t('The order whose product line item quantities should be totalled. If the specified order does not exist, the comparison will act as if it is against a quantity of 0.'),
      ),
      'product_type' => array(
        'type' => 'text',
        'label' => t('Product Type'),
        'description' => t('The type of the product to look for on the order.'),
        'options list' => 'commerce_product_type_options_list',
        'restriction' => 'input',
      ),
      'operator' => array(
        'type' => 'text',
        'label' => t('Operator'),
        'description' => t('The comparison operator to use against the total number of products on the order.'),
        'default value' => '>=',
        'options list' => 'commerce_numeric_comparison_operator_options_list',
        'restriction' => 'input',
      ),
      'value' => array(
        'type' => 'text',
        'label' => t('Quantity'),
        'default value' => 1,
        'description' => t('The value to compare against the total quantity of products on the order.'),
      ),
    ),
    'group' => t('Commerce Order'),
    'callbacks' => array(
      'execute' => 'commerce_order_rules_compare_total_product_type_quantity',
    ),
  );
/**
 * Condition callback: compares the total quantity of products of a specific type
 * against the specified quantity.
 */
function commerce_order_rules_compare_total_product_type_quantity($order, $product_type, $operator, $value) {
  $products = array($product_type => 0);

  // If we received an order, get the total quantity of products on it.
  if (!empty($order)) {
    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  
    // Populate the array of the quantities of the products on the order.
    foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
      if (in_array($line_item_wrapper->type->value(), commerce_product_line_item_types())) {
      	// Get the product
      	$product_wrapper = entity_metadata_wrapper('commerce_product', $line_item_wrapper->commerce_product->product_id->value());
        // Extract a product type and quantity from the line item.
        $line_item_product_type = $product_wrapper->type->value();
        $quantity = $line_item_wrapper->quantity->value();

        // Update the product's quantity value.
        if (empty($products[$line_item_product_type])) {
          $products[$line_item_product_type] = $quantity;
        }
        else {
          $products[$line_item_product_type] += $quantity;
        }
      }
    }
  }

  // Make a quantity comparison based on the operator.
  switch ($operator) {
    case '<':
      return $products[$product_type] < $value;
    case '<=':
      return $products[$product_type] <= $value;
    case '=':
      return $products[$product_type] == $value;
    case '>=':
      return $products[$product_type] >= $value;
    case '>':
      return $products[$product_type] > $value;
  }

  return FALSE;
}

Cheers,
Sam

Comments

PrinceManfred’s picture

Looks good at first glance. I'll test it out either tonight or tomorrow and hopefully get it committed ASAP.

Thanks for submitting it : )

PrinceManfred’s picture

The code you submitted works well. I'm making a few changes to make the code more consistent with how the other conditions are structured. I'm also adding a checkbox to the condition to allow the user to specify if they want to do the comparison to the quantity of all products excluding that of the type specified.

I need to make sure there aren't any issues with using this condition with modules that add custom line types (like Commerce Shipping). I should have the changes committed tonight. Let me know if you have any input on the changes I'm making.

Thanks

essbee’s picture

Good thinking, I only needed the qty of specific type so didnt add in the frills. Good work.

Shouldn't have an issue with additional line item types as it uses the built in routine to check the line type is a product before making comparisons.

On a side note, do you think my rules will carry over over if, once you have made the commit, I enable your module and disable mine?
I'd hate to have to recreate the 20 shipping rules I have :)

PrinceManfred’s picture

Status: Needs review » Fixed

It's committed. I'm not sure how frequently the dev package updates but it's availible from git immediately. commerce_product_line_item_types is a niffty little function. I'm going to update the other conditions to use it for line item checks.

Your current rules won't carry over to commerce_conditions. The name of the rule was changed to bring it in line with the naming pattern used in the module. Your best bet, if you want to switch over to the commerce_conditions version, is to keep both modules installed, change the conditions out for each rule, and then get rid of your original module. That'll at least keep you from having to select all of the options for the rules, and it'll be harder to forget to add one back.

Thanks again for for contribution.

Status: Fixed » Closed (fixed)

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