Hello there,

Hope all is well. In the latest 7.x-1.x dev ( Feb 2015). An issue referred at there https://www.drupal.org/node/1853638
has been resolved by that implementing hook_commerce_cart_line_item_refresh. But it produces another very serious bug which is extremely hard to detect. It produces following error if line item refers to the disabled items.

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'commerce_line_item-32-0-0-und' for key 'PRIMARY': INSERT INTO {field_data_commerce_unit_price} (entity_type, entity_id, revision_id, bundle, delta, language, commerce_unit_price_amount, commerce_unit_price_currency_code, commerce_unit_price_data) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8); Array ( [:db_insert_placeholder_0] => commerce_line_item [:db_insert_placeholder_1] => 32 [:db_insert_placeholder_2] => 32 [:db_insert_placeholder_3] => product [:db_insert_placeholder_4] => 0 [:db_insert_placeholder_5] => und [:db_insert_placeholder_6] => 1195 [:db_insert_placeholder_7] => USD [:db_insert_placeholder_8] => a:1:{s:10:"components";a:1:{i:0;a:3:{s:4:"name";s:10:"base_price";s:5:"price";a:3:{s:6:"amount";s:4:"1195";s:13:"currency_code";s:3:"USD";s:4:"data";a:1:{s:10:"components";a:0:{}}}s:8:"included";b:1;}}} ) in field_sql_storage_field_storage_write() (line 448 of /drupal/modules/field/modules/field_sql_storage/field_sql_storage.module).

TO mitigate this you should never ever save the line item as we just need torefresh the line item not to save the line item after customization as this is going to handle by the core. Since core is taking care for disabled items but your solution not. if you save the line item having disabled product then product pricing rules that has already emptied the unit price and currency conversion does still produce empty unit price. And unit price is required in the database schema and thus producing error. So to overcome this just remove from following

function commerce_multicurrency_commerce_cart_line_item_refresh($line_item, $order_wrapper) {
$line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
$currency_code = commerce_multicurrency_get_user_currency_code();
if ($line_item_wrapper->commerce_total->currency_code->value() != $currency_code) {
$amount = commerce_currency_convert(
$line_item_wrapper->commerce_total->amount->value(),
$line_item_wrapper->commerce_total->currency_code->value(),
$currency_code
);
$line_item_wrapper->commerce_total->amount = $amount;
$line_item_wrapper->commerce_total->currency_code = $currency_code;
}
// $line_item_wrapper->save(); // remove this line as drupal commerce will take care of it.
}

thanks

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rahu231086’s picture

Issue summary: View changes
das-peter’s picture

Title: A very serious bug found and must be resolve » commerce_multicurrency_commerce_cart_line_item_refresh() shouldn't save line items
Parent issue: » #1853638: Commerce Kickstart shopping cart (Commerce Order) block not converting currency until going to cart page

Set speaking title.
Set properly related ticket.

@rahu231086 Would you mind to provide a properly formatted patch? I guess test's would be great too but looks quite hard to create proper ones.

rossb89’s picture

I have encountered unintended behaviour due to this line of code being in place in this function.

On a highly customised commerce based site, some unwanted performance issues were caused by this line of code, as it triggered off an uneccessary entity save, with all the related hooks down the chain which were slowing down page load times slightly.

The first question I asked was, why does the code added in the patch in #1853638: Commerce Kickstart shopping cart (Commerce Order) block not converting currency until going to cart page save the line item wrapper NOT inside the

if ($line_item_wrapper->commerce_total->currency_code->value() != $currency_code) {}

statement.

If the currency code has not changed, then there is no need to *always* save the line item at this point in time.

I tested moving the $line_item_wrapper->save() line to inside the if statement, and this was then correctly only save the line item when the currency code had actually changed, not every single time the function was being called, regardless of if the currency code had changed or not.

After some further searching I then came across this issue that @rahu231086 has raised, which raises a good point of saying the line item wrapper save is unnecessary, which I believe to be correct - as we should only be modifying the line item here, leaving the save to occur further down the chain.

I've tested removing the line entirely and everything still works as expected with the currency code being changed on the line item.

rossb89’s picture

Status: Active » Needs review

das-peter’s picture

Status: Needs review » Fixed

@rossb89 Thank you very much for the patch. Committed and pushed.
I've also decided to create a new version: https://www.drupal.org/project/commerce_multicurrency/releases/7.x-1.4 should be online soon.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.