This is a wonderful module and system. I've been using drupal for a few weeks and love it.

I'm developing a financial analysis application and it has a good amount of fields. In one create content node, there are:

37 data input fields (not that many if you were doing a survey)
23 simple calculated fields (add field 1 and field 2, divide by 100, etc.)
12 calculated fields based on calculated fields (add three previously calculated fields together, etc.)

all running smoothly. until i started getting a "division by zero" warning upon saving a node. I can see in the display that a number of calculations are not complete (still zeros). Now, if i just toggle back to edit and save again, the form completes fine w/out errors.

Later, if i change a number, i need to save, toggle edit again, and save again for all the computations to take place.

I've started deleting fields going backwards to see where the limits are but i'm now well smaller than when it was working a few days ago.

please help...thanks,
/TL

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tlash’s picture

Oh.
Drupal 6.9
Mysql
PHP 5

No multi-value fields
most fields are formatted decimal, a few integer (for select lists of numbers)

fields are mostly grouped, but there are calculated fields that are at the end of the field list and outside of any field group.

tlash’s picture

Category: bug » support
Status: Active » Closed (fixed)

i copied each field to a new content type and created a record. I got to the last field and it all worked. So I'm not sure what's going on. The same set of fields are in the old content type and still the node is saved before it's finished computing. anyway, i'm closing this support request.

BWPanda’s picture

Title: Lots of fields, I need to save twice to complete computation » Fields computed in 'weight' order
Version: 6.x-1.0-beta2 » 6.x-1.x-dev
Category: support » feature
Status: Closed (fixed) » Active

I too have been experiencing this issue (computed fields aren't being updated until node is re-saved) and have found the cause of the problem: the computed field's 'weight' value.

I started looking into this and discovered that my computed fields were being calculated in the wrong order (i.e. 'Grand Total' then 'Total1', 'Total2' ,etc.). I then spent the new few hours trying to work out how the order of field processing was determined (since it didn't seem to be top > bottom as per the node-edit form). After much to-ing and fro-ing through CCK's API documentation, I found out that the order fields are processed in is based on their 'weight' value, specifically: a field's 'weight' (asc) then 'label' (asc) taken from the 'content_node_field_instance' database table.

Knowing this, I then had a look at the weight of my computed fields (had to turn off javascript) on the 'Manage fields' page of my content type. Sure enough, my 'Total1', Total2', etc. fields had higher weights than my 'Grand Total' field since they were in a group (even though they were located before the 'Grand Total' field).
I therefore manually edited the weights of my computed fields so the first ones had a lower weight (-5, -4, etc.) and the last ones had a higher weight (3, 4, etc.). This did the trick - now my computed fields are all working properly the first time I save, I don't have to re-save the node multiple times.

Here's an example of my field weights before I changed them (when they weren't working):

Field        | Weight
-------------|-------
Title        |  -5
Work (Group) |  -4
  Hours1     |   1
  Rate1      |   2
  Total1     |   3
  Hours2     |   4
  Rate2      |   5
  Total2     |   6
  etc.       |
Grand Total  |  -3

And here's an example of my field weights after I changed them (when they started working properly):

Field        | Weight
-------------|-------
Title        |  -5
Work (Group) |  -4
  Hours1     |  -5
  Rate1      |  -4
  Total1     |  -3
  Hours2     |  -2
  Rate2      |  -1
  Total2     |   0
  etc.       |
Grand Total  |   5

Ideally, we shouldn't have to go through each of our computed fields and edit the weight for this to work properly.
I'd therefore like to request that this module implement a solution that allows it to calculate the computed fields in order from top to bottom (of the 'Manage fields' page) regardless of whether they're in groups or not.

Until then, the solution of manually editing field weights should fix this for people experiencing this issue.

BWPanda’s picture

BWPanda’s picture

GRRaka’s picture

Don't think this helps my issue:
I have a node divided into tabs. One tab contains several fields in a multigroup table.
Another tab contains a computed field which has a count of the number of entries in the multigroup table. The computed code looks like this
$node_field[0]['value'] = db_result(db_query("SELECT count(*) from content_field_amend_no where vid = %d and field_amend_no_value is not null",$node->vid));
When I add another entry to the multigroup table and save the node. The computed field is not updated. I realize that the multigroup fields are kept in separate tables, but aren't they part of the same "node"? A new version is created, why isn't the computed field updated?
If I re-edit the node and save, the computed field updates correctly.
The weights of the fields in question are below
Each amendment multigroup contains:
field_amend_no 13 | Amendment #
field_amend_date 14 | Amendment Date
field_amend_comm 15 | Amendment Comment
The computed field is:
field_amend_count 79 | Count of Amendments

I also checked the weight of the groups in content_group.
multigroup group_amend_det 4 - holds the amendments
standard group_character -2 - contains the computed field.

So I changed the weight of group_character to be higher than the group_amend_det - but that didn't work.

Problue Solutions’s picture

subscribing

billp44ruby’s picture

I'm attempting to use the suggested method of weighting fields in order to force the correct order of calculations, but without success. I'm using "Computed Fields" for a content type "Loan". There are a number of charges associated with a loan that are categorized and summed, which then roll up to a "Total Charges" field. As an example, you have:

Items Payable (5)
     Application Fee (3)
     Appraisal Fee (4)

Title Charges (8)
     Title Insurance (6)
     Title Examination (7)

Total Charges (9)

As part of the implementation, "Items Payable"=("Application Fee" + "Appraisal Fee"), "Title Charges"=("Title Insurance" + "Title Examination") and "Total Charges"=("Items Payable" + "Title Charges"). Items Payable, Title Charges and Total Charges are all field type "Computed", while the others are "Float". I've weighted the fields as shown in the parentheses.

When I save the content type and go to add "Loan" content, I input "Application Fee", "Appraisal Fee", "Title Insurance" and "Title Examination". When I save the content, Items Payable and Title Charges are summed correctly, but "Total Charges" remains at "0". In order to get Total Charges computed, I have to go back and re-save the content a second time. After that pass, the numbers are all calculated correctly.

What am I doing wrong? Why is this taking multiple saves to yield the correct results?

wjr’s picture

Version: 6.x-1.x-dev » 6.x-1.0

Having the same (multiple save required) issue here. I've got 5 computed fields that are pulling data from the Title field, all fields are weighted correctly (title is heavier than the computed fields).

I've tried grouping the computed fields, I've tried moving _computed_field_compute_value() from 'update' to 'presave', I've tried hook_nodeapi()-fu to perform a second node_save() and I'm really at a loss. Why do I need to save twice to get any of my computed fields to actually compute? Help!

Edit: nevermind, you can't use the title field by doing drupal_get_title() because the title isn't saved yet, probably. Solved the problem by adding another (non-title) field and referring to it as $node->field_field_name[0]['value'] and it works well.

one_hoopy_frood’s picture

As indicated in #3 I disabled JavaScript in EDIT [CONTENT TYPE]=>MANAGE FIELDS so I could see the weights:

  • Sure enough, all fields now appeared with weights between -5 and 52 (in my case)
  • And the incorrectly calculating Computed Field WAS lighter than the fields on whose data it relied

Original Weights

Group [20]
   Item A [22]
   Item B [23]
   Item C [24]
COMPUTEDFIELD [14]  (note, not in group)
Otherfield [5]
Otherfield [6]

Attempted remedy: Set COMPUTEDFIELD to [25] weight
After save though, CompField was now at the bottom of the page, since it is now the heaviest:

Group [20]
   Item A [22]
   Item B [23]
   Item C [24]
Otherfield [5]  (note, not in group)
Otherfield [6]
COMPUTEDFIELD [25]

In order to get it in the correct place, I had to set ALL of my weights again starting at the top.

Group [15]
   Item A [16]
   Item B [17]
   Item C [18]
COMPUTEDFIELD [19]
Otherfield [20]  (note, not in group)
Otherfield [21]

Some of the fields of my content type were added later ... and rearranged. After looking at it all ... it is obvious that the Drag-and-Drop rearrangement did not update the weights.

So, is it possible this is partly a flaw with the javascript Drag-and-Drop functionality (with the + Cross to grab) and that it should be setting their weights after reordering them?

And, where is the "Display Order" code that the "grab and move" functionality implements? Is there a good reason that weights are not updated after JavaScript rearrangement?

liquidcms’s picture

Title: Fields computed in 'weight' order » Fields NOT computed in 'weight' order
Version: 6.x-1.0 » 7.x-1.x-dev
Category: feature » bug

read through this thread and it sounded promising; but doesn't seem like CF works off weight anymore in D7; it now looks like it works off field id; which the user has no means of adjusting (as we could somewhat painfully) with weights in D6.

changing this to D7.

sadly though, i am guessing in D7 (and likely same in D6) that the processing order is how drupal core handles fields; and nothing to do with this module.

liquidcms’s picture

looking through the core field processing code it would seem like this is royally screwed for D7. the fields are loaded up for processing in the order defined by the field_read_instances() function and this orders by instance id as defined by the id column in the field_config_instance table.

we possibly could do a query_alter to modify how this query is run but we no longer in D7 have anything to sort on as weight is buried in a serialized data field.. hmm.. although, it should be possible to sort on field name and then the field creator simply has to use creative field names to ensure that their computed value fields are processed in the desired order.

the other thing that core might have provided for use would be a instances order hook where a module cold post process the ordering of the instances array; but alas, no such hook exists.

going to look into query alter with a sort on field name and see if that can work.

liquidcms’s picture

but, alas, the query to build the instances array is not tagged; and therefore can not be altered.

there is always going into the instances table and modifying the id value directly.. this actually does work.. clear cache_field after doing this though.

xumepadismal’s picture

Not sure if its the best way, but here is my solution that I used for my current project and it seems to works for me

/**
 * Implements hook_field_attach_load().
 */
function mymodule_field_attach_load($entity_type, $entities, $age, $options) {
  $info = _field_info_collate_fields();
  if (empty($info['sorted'])) {
    foreach($info['instances'] as $entity_type => &$bundles) {
      foreach ($bundles as $bundle => &$instances) {
        uasort($instances, function($a, $b){
          $a_weight = isset($a['widget']['weight']) ? $a['widget']['weight'] : 0;
          $b_weight = isset($b['widget']['weight']) ? $b['widget']['weight'] : 0;
          if ($a_weight == $b_weight) {
            return 0;
          }
          return ($a_weight < $b_weight) ? -1 : 1;
        });
      }
    }

    _field_info_collate_fields(TRUE);

    $info['sorted'] = TRUE;
    cache_set('field_info_fields', $info, 'cache_field');
  }
}
Martijn Houtman’s picture

Thanks, xumepadismal, patch #14 works as expected: it re-sorts the fields according to their widget weight (i.e., in 'manage display'). I am not sure if this is the correct place either, but as liquidcms already mentioned, there currently is no other place to alter the field order.

xumepadismal’s picture

My patch #14 must be reviewed because of this upcoming change in Drupal Core. I hope I will have some free time to make a review.

Also note that it re-sorts fields according to their weights on 'manage fields' section, not 'manage display'.

Martijn Houtman’s picture

Right, my bad, I meant 'manage fields'. I will most likely do a project with lots of computed fields, and I will use the latest version of D7, so I will have time to test it, and probably make a patch out of it. Any idea when 7.21 is due?

Martijn Houtman’s picture

Appears it works just fine with D7.21.

I currently have a different approach: I've added a field setting called 'weight', so you can define the calculation order by setting weights. Will roll out a patch when done.

Martijn Houtman’s picture

Attached a patch against current dev version. Could anyone try it out and give feedback?

Martijn Houtman’s picture

Comparison error, fixed patch attached.

nithinkolekar’s picture

hi Martijn,
your patch working fine checked with 4 computed field among which 2 are dependent , in a single content type .

For easy accessibility can it be provided in content_type's edit page where all other display setting,publishing options are available.
This way we can collect all computed fields at once and can easily modify their weight.

nithinkolekar’s picture

Patch doesn't take of computed fields inside field collection. Computed field Outside of field collection is calculating before the inner one, regardless of computation weight.

NancyDru’s picture

Status: Active » Needs work

I'm marking this as "Needs work" because [#1915646] specifically says not to use "_field_info_collate_fields()" any more. So this patch may not even work on 7.22 or above.

I really hate to believe that we are stuck with computing in the order the fields were defined...

NancyDru’s picture

It would seem, Martjin, that you assumed that all computed fields would be edited and saved with a weight. Given that I have more than 50 computed fields, I really didn't want to do that.

NancyDru’s picture

AArrgghh! With all the hooks implemented in Drupal, there is not one where it's really needed to control the order of field attachment.

After a lot of digging, I have found that the fields are attached to the entity in the order of the "id" column in the "field_config_instance" table. So you can manually fix this by deleting the row and re-adding it, which will give it a higher "id." Try this only if you are comfortable messing around in the database.

Now that I know this, I'm going to work on a module to do this without manual DB access.

NancyDru’s picture

FileSize
4.92 KB

Okay folks, here is a little module that will let you change the order of field computation.

Please read the README.txt file.

It works for me, but I would love to see more testing done.

NOTE: changing one entity_type / bundle does not change others. So if a field is attached to multiple bundles, you will have to change each one individually. However, that means you can do them in different orders for each bundle.

@Colan: I don't really want to maintain this as a separate module. You have my permission to bundle it with the CF distribution.

scalp’s picture

Works great! Thank you NancyDru.

colan’s picture

@NancyDru: Thanks for working on this.

If someone would provide this in patch format, and then someone else were to RTBC it, I'd happily commit it.

NancyDru’s picture

Issue summary: View changes
Status: Needs work » Needs review

It's brand new code. Unpack it into your directory and commit it.

8bitplateau’s picture

@NancyDru super thanks !

I was having trouble with Field Collections (ho hum) and computed fields where sometimes the value of the computed field was simply the field collection ID and some times it was the full rendered entity. Perhaps this is the difference between how it is in the form and how it is on a loaded node ?

I think what was happening was the computed field was executing before the field collection was compiled and saved. But works correctly now. Very sensible move to get this functionality into the module.

Field : 7.28
Computed Field : 7.x-1.0-beta1+2-dev
Field collection : 7.x-1.0-beta8

pineiden’s picture

Maybe this post has relation:

https://www.drupal.org/node/2407331

gramsuy’s picture

@NancyDru Thanks!! works like a charm

Drupal 7.36
Computed Field 7.x-1.0

ram4nd’s picture

Status: Needs review » Needs work
NancyDru’s picture

@ram4nd: What work does it need?

ram4nd’s picture

Needs to be a patch.

NancyDru’s picture

Status: Needs work » Needs review
FileSize
13.72 KB

Sigh... Here it is.

NancyDru’s picture

Adding related issue

jelhan’s picture

I also run into this issue. But I'm not convinced of proposed solutions. Is defining order in which computed fields are calculated manually really the way to go?

I have a case where one computed field depends on another computed field. Now on an update the computed field uses old (not updated) value of the other computed field. Many similar cases where described here. But lets give a small example to be make clear what we are talking about:

Having these fields:
* field_price
* field_tax_rate

And these computed fields:
* field_tax = field_price * field_tax_rate
* field_price_including_tax = field_price + field_tax

Having these values:
* field_price = 10
* field_tax_rate = 0,1
* field_tax = 1
* field_price_including_tax = 11

When updating field_price to 20 I get:
* field_tax = 2
* field_price_including_tax = 20 + 1 (old value of field_tax)

I think computed fields based on another computed field is a strong use case. I don't think we have to define an order manually because there is an obvious order computed fields should follow: If a computed field depends on another computed field, compute this one first.

There seems to be only one case where this computing order gets into trouble: Having to fields which depends on another. But there don't seem to be use cases for that. Defining fields like that seems to be a bug...

I'm not so familiar with drupal, so I don't know if implementing this with drupal api would be possible. Just want to put it in the discussion.

Currently I "fixed" my issue be not depending on another computed value but recomputing it. So staying with example above I'm doing field_price_including_tax = field_price + field_price * field_tax_rate. Not really maintainable for complex calculations...

Since this is not fixed I would suggest a notice about this in readme and/or documentation.

NancyDru’s picture

You are correct, but how would CF know that there is a dependency?

Just to make it more complicated, I have a field that depends on values in a field collection (or in one case, two collections). Since field_collection is a separate entity, how would that shake out?

jelhan’s picture

As I said I'm not so familiar with Drupal api. So perhaps my thoughts aren't possible with Drupal 7 api or causing other limitations I'm not aware of. But my idea of implementing something alike would a wrapper function for field_get_items. This wrapper function would be responsible to determine if a computed field is loaded. If so it will trigger this one to be recomputed before data is loaded. Site builders are still responsible to decide if they have to use this wrapper function cause the loaded field is or might be depending on another computed field or if they could use core function field_get_items safely.

NancyDru’s picture

If you don't mark it "store in database" then the field will be computed when it is loaded, but there is no guarantee that the fields it computes from have the latest data.

skylord’s picture

@NancyDru - great patch/module! Works like a charm, i think it has to be commited as a submodule for Conditional Fields. Manually set fields calculation order is quite better than just use content type fields order i.e.

giupenni’s picture

#36 works like a charm