We have noticed the following on one of our pages.
Some mails were sent twice.
The mail was sent at the "After updating an existing commerce order" event.
At the conditions we check the order's status [commerce-order:status] and the order's previous status [commerce-order-unchanged:status], if they have the values we need then we send the mail.
But then for some reason these mails arrived twice.
At the same time if the cart was owned by an anonymous user, then another rule ran, which from the given email address created a new user account (if it did'nt exist before, otherwise it returned the already existing user). It set the order's uid value to this user account's uid value. And at this point the mail was sent again.
To simulate this behavior I've created two rules which you can see below:
{ "rules_show_a_debug_message" : {
"LABEL" : "Show a debug message",
"PLUGIN" : "reaction rule",
"REQUIRES" : [ "rules", "entity" ],
"ON" : [ "commerce_order_update" ],
"IF" : [
{ "data_is" : { "data" : [ "commerce-order:status" ], "value" : "checkout_review" } },
{ "data_is" : {
"data" : [ "commerce-order-unchanged:status" ],
"value" : "checkout_checkout"
}
}
],
"DO" : [
{ "drupal_message" : { "message" : "Status: [commerce-order:status] - [commerce-order-unchanged:status] Total: [commerce-order:commerce-order-total]" } }
]
}
}
{ "rules_change_order_uid" : {
"LABEL" : "Change the uid of an order",
"PLUGIN" : "reaction rule",
"REQUIRES" : [ "rules", "entity" ],
"ON" : [ "commerce_order_update" ],
"IF" : [
{ "data_is" : { "data" : [ "commerce-order:status" ], "value" : "checkout_review" } },
{ "data_is" : {
"data" : [ "commerce-order-unchanged:status" ],
"value" : "checkout_checkout"
}
},
{ "data_is" : { "data" : [ "commerce-order:uid" ], "value" : "0" } }
],
"DO" : [
{ "data_set" : { "data" : [ "commerce-order:uid" ], "value" : "1" } },
{ "entity_save" : { "data" : [ "commerce-order" ] } }
]
}
}
Comments
Comment #1
damien tournoud commentedThe way you set up the rules mean that you are saving the order twice. While this is likely not the root cause of the issue, you could easily fix that:
^ This happens *after* an order is saved.
^ This triggers another save of the order.
You should be able to use the "before the order is saved" trigger instead of this.
Comment #2
rszrama commentedI'm torn. We could resolve this by updating commerce-order-unchanged after the initial order save, but I'm not sure this ought to happen. It could be that that token is supposed to represent the unchanged order from the very beginning of the event invocation, not from after the most recent forced save.
Personally, I'd change your condition to something else, but without more details it's hard to know what else I'd change it to. As of right now, I'm not sure this is accurately described as a "repeated rules evaluation bug", because what's happening is actually expected behavior.
Comment #3
dready2011 commentedI had the same issue. I wanted to send an email to a fulfillment center after a status-change.
I used the "After updating an existing commerce order" event, checked that commerce-order:status = processing and commerce-order-unchanged:status <> processing.
But a rule that calculates the shipping cost also saves the order. As commerce-order-unchanged does not change after the initial save as Ryan mentions, this lead to the email being sent twice.
The only solution i came up with, is changing commerce-order-unchanged:status myself in the rule that sends the message. If it comes to the rule the second time, the condition does prevent it from firing twice.
Maybe it helps someone, so here my rule
Comment #4
rszrama commentedI'm going to close this out as a duplicate of #2140165: While reloading $entity->original in the controller, track the save_depth where we're pursuing a fix for entity original loss in general.