Just a quick update for the readers to inform that we found the quirk that causes the data duplication. It’s actually linked to the WooCommerce core. We have a piece of logic that changed slightly. Here’s an example of what changed, simplified for easier understanding:
add_action('woocommerce_after_order_object_save', function(WC_Order $order) {
$exchange_rate = get_exchange_rate();
$order->update_meta_data('_order_total_base_currency', $order->get_total() * $exchange_rate);
$order->update_meta_data('_order_total_tax_base_currency', $order->get_total_tax() * $exchange_rate);
// Save more meta, converting order properties
// Save the exchange rate last
$order->update_meta_data('_base_currency_exchange_rate', $exchange_rate);
$order->save_meta_data();
});
To this:
add_action('woocommerce_after_order_object_save', function(WC_Order $order) {
$exchange_rate = get_exchange_rate();
// Save the exchange rate first
$order->update_meta_data('_base_currency_exchange_rate', $exchange_rate);
$order->update_meta_data('_order_total_base_currency', $order->get_total() * $exchange_rate);
$order->update_meta_data('_order_total_tax_base_currency', $order->get_total_tax() * $exchange_rate);
// Save more meta, converting order properties
$order->save_meta_data();
});
For reasons that I can’t explain, if action woocommerce_after_order_object_save is triggered more than once, the behaviour will be different in the two cases:
- In the first case, the call to
$order->update_meta_data('_base_currency_exchange_rate', $exchange_rate); adds the meta the first time and updates it the second time.
- In the second case, the call to
$order->update_meta_data('_base_currency_exchange_rate', $exchange_rate); adds the meta twice, resulting in data duplication.
We couldn’t figure out the reason behind this inconsistent behaviour. The only speculation, which hasn’t been proven, is that calling the WC_Order::get_total(), WC_Order::get_total_tax() and so on causes the custom meta set by WC_Order::update_meta_data() to be “forgotten”, so to speak, despite the call to WC_Order::save_meta_data(). I’m aware that it doesn’t make much sense, but the test results are consistent. Saving the exchange rate last doesn’t cause any duplication, for some reason.
We’re now implementing a safeguard, so that the meta won’t be duplicated despite this unexpected behaviour.
Additional note
So far, we’ve only noticed this behaviour on a site with the HPOS feature disabled, where the orders are stored in the wp_posts table. With the HPOS feature enabled, this doesn’t seem to happen. However, we will run more tests to check if that actually makes a difference.
-
This reply was modified 1 year, 1 month ago by
Diego. Reason: Added note about HPOS