1

I have to types of a same product (used a select list field):

1|Physical
2|Digital
(key|label)

Physical items needs shipping calculated. Digital doesn't.

Problem appears when you add physical and digital item to cart, rules calculate the flat rate shipping to both items. Which is wrong, it should calculate rate to physical and ignore digital product.

I'm thinking it has something to do with data comparison? Am I on the right path? I tried various options/sorting.

enter image description here

Update

My exported rule looks like this now (as per the recommendation in the 1st answer to also use the Conditional Rules module):

{ "rules__1_extra" : {
    "LABEL" : "+1$ extra",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [
      "rules",
      "commerce_line_item",
      "rules_conditional",
      "commerce_shipping"
    ],
    "ON" : { "commerce_shipping_calculate_rate" : [] },
    "DO" : [
      { "LOOP" : {
          "USING" : { "list" : [ "commerce-line-item:order:commerce-line-items" ] },
          "ITEM" : { "list_item" : "Current list item" },
          "DO" : [
            { "data_calc" : {
                "USING" : { "input_1" : [ "list-item:quantity" ], "op" : "*", "input_2" : "100" },
                "PROVIDE" : { "result" : { "result" : "Calculation result" } }
              }
            },
            { "commerce_line_item_unit_price_add" : {
                "commerce_line_item" : [ "commerce_line_item" ],
                "amount" : [ "result" ],
                "component_name" : "flat_rate_flat_rate",
                "round_mode" : "0"
              }
            }
          ]
        }
      },
      { "commerce_line_item_unit_price_subtract" : {
          "commerce_line_item" : [ "commerce_line_item" ],
          "amount" : "100",
          "component_name" : "flat_rate_flat_rate",
          "round_mode" : "0"
        }
      },
      { "CONDITIONAL" : [] }
    ]
  }
}
0

From the screenprint of your calculation rule it's hard to tell what exactly the logic is that you implemented (an exported rule, created with the Rules UI, provides ALL the details).

Anyway, it seems that your Rules Loop is adding "an amount to the unit price" for EACH line item, so it doesn't check (within that Rules Loop) if it is "Physical" or "Digital", which explains why for Digital items shipping gets calculated also (which is not what you want).

The easiest way to correct this, is to use the Conditional Rules module to add an extra test (Rules Condition!) within your Rules Loop to NOT calculate shipping for Digital items (AND remove all Rules Conditions starting from the "AND" you added). As a variation (to not have to use this extra module), transform the 2 Rules Actions within your loop to an equivalent Rules Component (by passing the line-item as a parameter), and within that Rules Component add an extra Rules Condition to check ... indeed ... if it is a Physical item.

Update 1

As per the update that was applied to your question (by adding your improved rule using the Conditional Rules module I suggested before), it seems that you've for sure not correctly used that module. Because the CONDITIONAL near the end of your exported rule is NOT supposed to be empty. Therefor have a look at this variation of your exported rule (if needed, just import it in your own setup to look at it with the Rules UI):

{ "rules__1_extra_not_for_digital" : {
    "LABEL" : "+1$ extra not for digital",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [
      "rules_conditional",
      "rules",
      "commerce_line_item",
      "commerce_shipping"
    ],
    "ON" : { "commerce_shipping_calculate_rate" : [] },
    "DO" : [
      { "LOOP" : {
          "USING" : { "list" : [ "commerce-line-item:order:commerce-line-items" ] },
          "ITEM" : { "list_item" : "Current list item" },
          "DO" : [
            { "CONDITIONAL" : [
                {
                  "IF" : { "data_is" : { "data" : [ "commerce-line-item:type" ], "value" : "product" } },
                  "DO" : [
                    { "data_calc" : {
                        "USING" : { "input_1" : [ "list-item:quantity" ], "op" : "*", "input_2" : "100" },
                        "PROVIDE" : { "result" : { "result" : "Calculation result" } }
                      }
                    },
                    { "commerce_line_item_unit_price_add" : {
                        "commerce_line_item" : [ "commerce_line_item" ],
                        "amount" : [ "result" ],
                        "component_name" : "flat_rate_flat_rate",
                        "round_mode" : "0"
                      }
                    }
                  ]
                }
              ]
            }
          ]
        }
      },
      { "commerce_line_item_unit_price_subtract" : {
          "commerce_line_item" : [ "commerce_line_item" ],
          "amount" : "100",
          "component_name" : "flat_rate_flat_rate",
          "round_mode" : "0"
        }
      }
    ]
  }
}

Note these changes I applied as compared to your exported rule:

  • The CONDITIONAL is to be contained within your Rules Loop (not after it).
  • Within that CONDITIONAL, I added some other condition. And only if that condition is satisfied, the 2 Rules Actions (as in your own exported rule) are to be executed.
  • Attention about that "some other condition": the actual condition I added is for sure not correct yet to make it match your question, so make sure to rework that to fit your case (I just added this condition here to show how to use that CONDITION statement).

Additionally, I'm not sure (actually I doubt) if the very last Rules Action in my updated Rule is still correct. Because you'd only want to do that subtract again if the very first line item actually did pass the test about CONDITION. But after you understand how to use the Conditional Rules module, I'm sure you'll get that part fixed also.

Update 2

Yet another update, as per this additional comment you added after I added my "update 1":

I can't find my term field in Data Comparison to select if product is Digital or Physical

That is not a surprise (at least not to me), because think about what kind of data about a product are available when processing a "line item" (inside a Rules Loop in this case here) ... No panic, because if it is not available, you can make it available, similar to what is explained in my answer to "How to access commerce_product field of line-items using Rules to flag the Commerce Product?" ...

Here is a blueprint of what you need to do (to further improve your rule):

  1. Create a Rules Component, similar to the Rules Component of Step 1 in my related answer, just an import of that Rules Component should be enough (to get started and further improve it as detailed below).
  2. Execute that Rules Component inside your Rules Loop of the rule you already have. But make sure to do so BEFORE the "CONDITIONAL" Rules Action.
  3. Move the "CONDITIONAL" Rules Action (and everything inside of it) to the Rules Actions of the new Rules Component you need to create. Make sure to place them AFTER that Rules Action (in the Rules Component) that performs "Fetch entity by ID". At that point you should have access to your field to indicate "if product is Digital or Physical" (because of the "Fetch entity by ID").
  4. Make sure that in that new Rules Component you also add a "Provided" variable (= value returned by the Rules Component to the calling Rule), which actually will, in the end, contain the "Calculation result" (BTW, result is a terrible variable name, hard to know what it is about). And it is that Calculation result that is what your main (further improved) rule should calculate, right?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.