Drupal Answers is a question and answer site for Drupal developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a field collection with unlimited values.

Inside this field collection, there is a field called Price (field_price).

I would like to addup all prices that are inside the field collection to get the total value (which I will then set to the total value field that is inside the content type).

I know I can get all the prices like this:

enter image description here

But the tricky part is adding them up.

I tried adding Calculate a value to the loop but for data selectors I only get something like this:

enter image description here

And list-item:field-price is not available either.

All signs point that this is not the right approach.

Race ya to the answer.

share|improve this question
    
Is this your next Rules challenge? By when do you need a "solution"? You want an answer, or a hint (in the format of a comment)? – Pierre.Vriens 8 hours ago
    
Is this your next Rules challenge? yes By when do you need a "solution" the sooner the better. You want an answer, or a hint (in the format of a comment) sounds like you already know the answer?. – No Sssweat 8 hours ago
    
Honestly, right now I don't know the exact answer for sure (I'd first have to do some experiments), using a Rules Component (= hint 1) named (eg) Calculate. That component would use 2 parameters (say 'current_total' and 'next_item') and simply calculate the sum of both, and return that sum to the Rule (using "provides" for that component parm!!!). All that's left is to update current_total with the provided sum, before the loop in your rule ends. Makes sense? Will it work? Wanny try? Should I move this comment to a real answer? With or without the rule+component? By when? – Pierre.Vriens 8 hours ago
1  
@Pierre.Vriens You have 5 mins left ... what the... lol. return that sum to the Rule (using "provides" for that component parm!!!) this is news to me. – No Sssweat 8 hours ago
1  
@Pierre.Vriens how does the passing back part work? does it do it automatically? or do I need to add some action? looks to me as if it is automatic. – No Sssweat 8 hours ago
up vote 3 down vote accepted

At first I thought your Rule needs to perform a Rules Component with 2 parameters (say 'current_total' and 'next_item') and simply calculate the sum of both, and return that sum to the Rule (using "provides" for that component parm). And then in your Rule update current_total with the provided sum, before the loop in your Rule ends.

However you don't need such Rules Component, only 1 rule will do. Have a look at this Rule (in Rules export format), which IMO is a prototype that does exactly what this question is about:

{ "rules_calculate_sum_of_prices_in_all_field_collection_items" : {
    "LABEL" : "Calculate sum of prices in all field collection items",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "ON" : { "node_view--article" : { "bundle" : "article" } },
    "IF" : [
      { "entity_has_field" : { "entity" : [ "node" ], "field" : "field_article_details" } }
    ],
    "DO" : [
      { "drupal_message" : { "message" : "\u003Cstrong\u003EDrupal calculator\u003C\/strong\u003E started ..." } },
      { "variable_add" : {
          "USING" : { "type" : "decimal", "value" : "0" },
          "PROVIDE" : { "variable_added" : { "total_price" : "Price total" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "node:field-article-details" ] },
          "ITEM" : { "article_details_item" : "Article details item" },
          "DO" : [
            { "data_calc" : {
                "USING" : {
                  "input_1" : [ "total-price" ],
                  "op" : "+",
                  "input_2" : [ "article-details-item:field-price" ]
                },
                "PROVIDE" : { "result" : { "calculation_result" : "Calculation result" } }
              }
            },
            { "data_set" : { "data" : [ "total-price" ], "value" : [ "calculation-result" ] } },
            { "drupal_message" : { "message" : "After adding a price of \u003Cstrong\u003E[article-details-item:field-price]\u003C\/strong\u003E for field collection item with id \u003Cstrong\u003E[article-details-item:item-id]\u003C\/strong\u003E, subtotal is \u003Cstrong\u003E[calculation-result:value]\u003C\/strong\u003E." } }
          ]
        }
      },
      { "drupal_message" : { "message" : "The \u003Cstrong\u003ETotal price\u003C\/strong\u003E for all prices included as field collection items is \u003Cstrong\u003E[total-price:value]\u003C\/strong\u003E." } },
      { "drupal_message" : { "message" : "\u003Cstrong\u003EDrupal calculator\u003C\/strong\u003E ended ..." } }
    ]
  }
}

Some more details about this rule are below ...

Rules Event:

Content is viewed (of type Article), adapt the machine name of the content type article to whatever fits (or use any other Rules Event that fits).

Rules Condition:

Entity has field, whereas the entity is "node", and the machine name of my field collection field is field_article_details (adapt this machine name to whatever fits, but make sure you use the field collection field itself).

Rules Actions:

Wake up, here is where the magic (fun?) is going to happen ... These are the Rules Actions involved:

  1. Show a message on the site, with a message like so:

    Drupal calculator started ...

  2. Show a message on the site, with a message like so:

    The Total price for all prices included as field collection items is 26.23.

  3. Add a variable, whereas it is a variable named total_price, decimal (2 digits), initial value 0.

  4. Add a loop, to iterate over each item of my field collection field (with machine name field_article_details), and perform these Rules Actions for each iteration:

    • Calculate a value, which calculates the sum of total_price (defined in Rules Action 3 above) and article-details-item:field-price (this is the machine name of the field in the field collection that contains the prices, decimal with 2 digits), and stores the result (sum) in variable calculation_result.

    • Set a data value, which simply copies the value stored in variable calculation_result in my total_price (defined in Rules Action 3 above). Remark: not sure (not tested), but maybe this calculation_result variable can be replaced straight by total_price (in the previous action), so that you would not need this action.

    • Show a message on the site, with a message like so:

    After adding a price of 3.40 for field collection item with id 3, subtotal is 15.00.

  5. Show a message on the site, with a message like so:

    The Total price for all prices included as field collection items is 26.23.

  6. Show a message on the site, with a message like so:

    Drupal calculator ended ...

Obviously, this rule is rather a prototype. After you're convinced it works as it should, just remove all Rules Actions with Show a message on the site. So that only item 3 and 4 (without its last sub-bullet) is left as Rules Actions.

Showtime ...

Here is a sample of my test results, i.e. the Drupal messages that are shown:

Drupal calculator started ...
After adding a price of 2.45 for field collection item with id 1, subtotal is 2.45.
After adding a price of 9.15 for field collection item with id 2, subtotal is 11.60.
After adding a price of 3.40 for field collection item with id 3, subtotal is 15.00.
After adding a price of 1.23 for field collection item with id 4, subtotal is 16.23.
The Total price for all prices included as field collection items is 26.23.
Drupal calculator ended ...

More info

Processing Field collection items with Rules is fun, really! If you're not familiar with that, try to first digest the answer to "How to iterate over all field collection items in the Rules module?".

share|improve this answer
2  
Fascinating, excellent work @Pierre.Vriens, it's worth noting that this would (probably) inherently be more secure than the Computed Field route as it doesn't need to rely on inputting custom PHP code. There would also be more flexibility over when to trigger the calculation. – HomoTechsual 4 hours ago
    
After re-reading your answer more carefully, seems like we cameup with the same answer, hence I am deleting mine. – No Sssweat 3 hours ago
    
@NoSssweat : since "I" can still see your deleted answer (one of the perks for users with sufficient rep ...), I think you should undelete it. Even if it is only because of the Rules UI screenprint in your answer (easier to digest for those who don't speak the Rules-export language). If you do, you may also want to explain what the purpose of the "fetch entity by id" actio is in your answer (are you sure you need that?). – Pierre.Vriens 3 hours ago
    
@Pierre.Vriens I think you meant by property. Yeah, that is not needed, it got there from testing other routes. I will make a correct screenshot of it tomorrow. – No Sssweat 3 hours ago
    
@NoSssweat yes by property ... BTW why defer something to tomorrow, if you can still do so ... AFTER tomorrow ... – Pierre.Vriens 3 hours ago

I've done this for a muti-valued entityreference field using calculated fields, the general premise is to add a hidden computed field to the entity holding the field collection, it's not particularly easy but it's possible - you'll need to write some custom PHP code to achieve this. I'm including my code (field names changed to generics) below:

// Setup Entity Metadata Wrapper.
$wrapper = entity_metadata_wrapper($entity_type, $entity);
// Loop through field_collection.
foreach ($wrapper->field_collection->getIterator() as $related_wrapper) {
  // Expose the parts of the commerce_price field type.
  $price_field_wrapper = commerce_price_wrapper_value($related_wrapper, 'commerce_price_field');
  // Get the amount from the price field.
  $price_field_amount = $price_field_wrapper['amount'];
  // Get the currency type.
  $price_field_currency_code = $price_field_wrapper['currency_code'];
  // Use the amount and currency to covert to a decimal value.
  $price = commerce_currency_amount_to_decimal($price_field_amount, $price_field_currency_code);
  // Increment $total by the decimal stored in $price.
  $total += $price;
}

// Set the field value to $total formatted to 2 decimal places, with no 1000's separator.
$entity_field[0]['value']  = number_format($total, 2, '.', '');
share|improve this answer
    
Part of the question is "with Rules" (eg: at the end of the title). Maybe I missing something, but nowhere in this answer I see anything that smells like it is related to Rules. – Pierre.Vriens 8 hours ago
    
I appreciate your time and effort to help. Unfortunately, I am looking for a rules answer only, as I was tasked to do it with Rules. Hopefully this will help/teach others though, so don't delete your programmatic answer. – No Sssweat 8 hours ago
    
I didn't see the comment chain before I posted this, that said you could use the value of the computed field in Rules - thus a Rules solution :-p - I'll work on a Rules solution. – HomoTechsual 8 hours ago
    
@HomoTechsual : don't worry (too much). Note however that the title was there before any comments got posted ... Though with your latest comment you made me curious also about how to use that computed field vaue in a rule. Hopefully without adding custom PHP in a Rules Condition or Rules Action (which is stored in the database and hence adds an extra securiity risk). – Pierre.Vriens 8 hours ago
    
@HomoTechsual (again, sorry) ... now I'm curious about your feedback about my answer, with no custom code involved ... And not that difficult either, would you agree? Just a matter of knowing some of the Rules features that are not commonly used ... Oeps, this comment crosses your comment below my answer already. You call it fascinating, I call it "having fun with a puzzle called Rules ...". – Pierre.Vriens 4 hours ago

I came up with the same answer as the accepted answer, as per request I have un-deleted my answer.

Set the field_total to 0

Then in loop add field_total + list-item:field_price and set result to field_total.

enter image description here

share|improve this answer
    
Great minds think alike ... And I get the impression that you're not sure either (yet) what the answer to my remark in my answer actually is (ie do we really need that calculation_result variable inside the loop?) ... – Pierre.Vriens 1 hour ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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