Documentation

Why can't I access my custom fields in Rules?

Update: The Discounts and Product Pricing Rules tutorial has a screencast with a complete demonstration of the techniques required here

When configuring Rules conditions and actions using the data selector, you may have encountered a scenario where you can't see any of the custom fields on entities passed as parameters for the rule's event. This is due to the fact that Rules only knows about the default fields that we tell it should function in a manner similar to entity properties. In order to access additional fields, you have to do one of two things in your conditions:

  1. Use the Entity has field condition to ensure the field you want to access exists on the variable you want to use it for, or
  2. Use the Data comparison condition to check the type of the entity (i.e. product type) to gain access to every field on the entity.

This example Rule can be imported into your site to demonstrate this aspect of Rules. It will apply a 10% discount to any product whose SKU is PROD-01:

{ "rules_discount_product_one" : {
    "LABEL" : "Discount Product One",
    "PLUGIN" : "reaction rule",
    "REQUIRES" : [ "rules", "commerce_line_item", "commerce_product_reference" ],
    "ON" : [ "commerce_product_calculate_sell_price" ],
    "IF" : [
      { "data_is" : { "data" : [ "line-item:type" ], "value" : "product" } },
      { "data_is" : { "data" : [ "line-item:commerce-product:sku" ], "value" : "PROD-01" } }
    ],
    "DO" : [
      { "commerce_line_item_unit_price_multiply" : { "line_item" : [ "line_item" ], "amount" : ".9" } }
    ]
  }
}

Unfortunately, there's also a bug in Rules that may account for the lack of fields in your data selector. In instances where you're looking for fields on an entity referenced by another entity (e.g. fields on the product reference by a line item in a product pricing rule), Rules will not acknowledge the existence of fields on the referenced entity. The workaround to this is to use Rules components to access field data on the referenced entities, but this method is really only feasible for advanced Rules users with a programming background. Your best bet will be to follow along in the issue waiting for it to be solved in Rules:

http://drupal.org/node/1053850

If you need to apply a workaround and don't have time to wait, you might glean some advice from this comment by EndEd in an issue pertaining to tax rules. Additionally, you could just write a custom condition / action or use a PHP condition / action through the Rules UI to access the field data directly.

Comments

amirtaiar on January 2, 2012

I am trying to do the follow:
I have a "website" content type which have a size vocabulary (big, medium..).
I am using the same terms as atribute in the product type field and created several products each with different term.
I create a rule that create a "website" for each lime item that have been purchase.
What I need to do is that the "website" that just created will get the term from the product(line item) that just purchase.

I have tried tons of way to get the line item term / product term in a rule action with no success. With "entity has field, data comparetion, set data value and much more...
Any idea how to accomplish this?

Thank you..

robertfoleyjr on May 3, 2012

This post is really important, especially for anyone trying to write rules to impact taxes, shipping, product prices, etc. What would be great to list in a table would be all of the unique fields each entity depends on (especially all of the line item types).

That way developers can understand how to properly scope the entities that they want to manipulate.
For those watching at home, I'm talking about:

In order for you to even target a commerce entity you must make sure the event is appropriate to the objects you want to manipulate.

Rule - Conditions Section

Add a condition of type "Entity has field"

target the "base" entity type that is in scope.

Select the field that is the unique or required for the entity. For example targeting line items where it contains the "commerce_product" field means the line item is a product entry, verses a line item that contains a "commerce_customer_address" as this would be a customer profile item.

I think it would be helpful to have this listed in one place for easy reference.

dannymacom on June 5, 2012

Due to the fact that Commerce Shipping doesn't allow these comparisons on the event "Calculating a shipping rate", those data values do not exist to be compared. At least that is why I think that doesn't work. :)

Fonant on September 7, 2012

See my comment "Two-stage process from line-item to product custom field" - you can do something similar to access the product SKU.

Fonant on September 7, 2012

Just to say I've worked around this for a product type with a "points to add field" that is used to add that number of userpoints to the person ordering when the payment is completed. It needed two components called in sequence:

1) Rule
Event: on payment completed
Action: loop through the order line-items. Each line-item has an action to call the next component with parameters of order and the line-item.
2) Component
Parameters: order, line-item
Condition: data comparison line-item:type is Product (to expose line-item:commerce-product)
Action: call next component with parameters of order and line-item:commerce-product
3) Component
Parameters: order, product
Condition: data comparison product:type is Product (to expose the product:field-points-to-add)
Action: add userpoints, number to add being product:field-points-to-add

Phew!

vimal on June 6, 2013

You sir, saved my life. I cannot thank you enough. I saved huge amount of server resources, content redundancy and all kinds of stuff. Thank you.

Summit on December 13, 2013

Hi @Fonant, can you place your rule in code here? I do not get it if this is only one rule or different onces, and when I see it in code, it is more clear.
Thanks for this in advance, greetings, Martijn

jameswoods on February 1, 2013

I hope this is the proper place to ask a question.

Question: How can I get fields from 2-deep referenced entities into scope for "Product pricing rules"?

Background / Setup:

I am attempting to use rules to modify the price of a product based on the value of a field in a referenced entity. I cannot get the field to show up in the rules conditions.

I'm using Drupal 7, commerce, registration, and commerce_registration.

I have a Content type "Event" that has a Product reference field "Register".
My Product reference field references a product type "Event Registration".
My "Event Registration" Product type has a Registration field "Event registration".
To collect registrant data, I have put fields on my Registration type, and these fields show up when proceeding to "Checkout", allowing users to provide their registration information.
These fields also show up on the Commerce review pane, allowing customers to review their registration information (very nice).

I run into trouble with the client requirement "Allow for different price points for types of tickets". E.g. General tickets cost $15, Student tickets cost $10, etc... I cannot seem to figure out how to get the fields into scope so I can use rules' conditions and actions to modify the price.

It *seems* like I need to implement hook_entity_property_info_alter() to tell rules "Hey! I've got these fields, and here's where they are in the database.". I created a mini-module that will dpm() the properties provided by hook_entity_property_info_alter(), but I'm not really sure where to go next. Am I able to update the entity metadata here so that rules will know about it? Ugh.

I've read:
http://drupal.org/node/1053850 (which has more subscribers than our local newspaper!)
http://www.trellon.com/content/blog/creating-own-entities-entity-api (um...just out of my reach without a bit of help)
http://drupal.org/node/1081800#comment-4240420 and followed the steps (#13 - I've tried to follow along, but I simply can't get the referenced fields into scope)

alinouman92 on March 13, 2013

I have written this code in rule(it was select available payment method) condition may be it helps some one

<?php
$line_items
= $commerce_order->commerce_line_items['und'];
foreach(
$line_items as $lid) {
 
$line_item = commerce_line_item_load($lid['line_item_id']);
  
$pid = $line_item->data['context']['product_ids'][0];
 
$product commerce_product_load($pid);
  
$field_part = $product->field_minimum_participants['und'][0]['value'];

 if(
$field_part == 1) {

    return
TRUE
 
  }
}
return
FALSE;
?>

sambaynham on June 13, 2013

One crucial bit of info the solutions on this page miss: The rules issue is now solved, but if your field is a custom one, defined in-module, you may still have the problems getting at its data.

In order to do this, you need to make sure your hook_field_info implements the property_type element, at the very least.

Check out this page for more info:
http://www.thecarneyeffect.co.uk/describe-field-properties-make-custom-f...

Paul Driver on July 25, 2013

I read that the rules issue is fixed, but still I am unable to 'scope in' my custom fields. What is the secret?

When I employ the method of creating a separate component, I am prompted for a product specific data selector, which I can't provide.

It would be great if somebody could find time to answer this here or even make a screencast. I am sure that I am not alone in being really stuck with this.

As with the questioners below, my need is to trigger a shipping rule based on the value of a custom (boolean) field.

http://www.drupalcommerce.org/questions/7879/make-flat-rate-shipping-ser...

http://www.drupalcommerce.org/questions/8388/flat-rate-shipping-service-...

Paul Driver on July 25, 2013

I read that the rules issue is fixed, but still I am unable to 'scope in' my custom fields. What is the secret?

When I employ the method of creating a separate component, I am prompted for a product specific data selector, which I can't provide.

It would be great if somebody could find time to answer this here or even make a screencast. I am sure that I am not alone in being really stuck with this.

As with the questioners below, my need is to trigger a shipping rule based on the value of a custom (boolean) field.

http://www.drupalcommerce.org/questions/7879/make-flat-rate-shipping-ser...

http://www.drupalcommerce.org/questions/8388/flat-rate-shipping-service-...

nicodv on September 2, 2013

@Fonant, I'm really amazed with your workaround. Not only because it was smart, but because it gave me a brand new angle to look at rules construction: I've been 1 year dealing with this fun module and I never thought of chaining components like that. Also... you solved my problem. Thanks. Nico :)