Drupal 7 commerce multi currency site using a price list

Below are my notes taken as I investigate techniques to achieve my Objective,
(This post is not a normalised set of instructions but the process I went through to figure out the best way to handle multiple currencies c objective)
if I get a chance ill create another post with a normalised set of instructions/explanation.


Objective

Create a Drupal 7 commerce site supporting two currencies: GBP (pound sterling) and Euro; both currencies should have a fixed price per product i.e. no automatic currency rate conversion.
I am using the Commerce Kickstart Drupal 7 installation profile.

Add euro price to the commerce product type

Add the Euro currency and add a new price field to the product entity type called field_euro_price.
This doesn’t need to be a price field, infact it can be an integer as we are only interested in the value and commerce price fields store this as a integer, however a price field may be easier to display to the user for editing.

Enter euro prices for your products

Create a new rule with a condition to switch to Euro for non UK languages
The first step was to identify when to switch and the solution “Rules 2”
I created a new “product Pricing rule” called “euro_price”
And added a Custom PHP condition with the following code:

<?php
 
global $language;
 
$lang_name = $language->language ;
   return (
$lang_name != "en";);
?>

I can also check that I actually have the euro price field available using a similar technique to "Adding a Taxonomy Term To Drive Discounts" http://www.drupalcommerce.org/node/461 however I shouldn't have a mixture of pound and euro prices so will have to handle this at a later stage.

First action: Switch to the euro currency symbol
Create an action using the commerce “Set the unit price's currency code” to set the line_item to EUR

Second action (using custom action): Convert the price to the euro value.
As I don’t have access to my field_price_euro I have decided to create a custom action as the first step (see notes about improvements in 'looking forward')

Declared my action in “hook_rules_action_info” with a parameter of type “commerce_line_item”

<?php
  t
('Convert the unit price to the euro currency'), 'parameter' => array( 'line_item' => array('type' => 'commerce_line_item', 'label' => t('Line item'), ), ), 'group' =' t('Commerce Line Item', );
  return $actions;
    }
?>

And in the implementation I get the product_id from the line item (debugged to see how I can access it $line_item->commerce_product['und'][0]['product_id']; looks a bit messy - must be a better way).  Loaded the product using the commerce_product_load() function and retrieved my euro price field

<?php
/**
* Rules action: convert the unit price to a different currency.
*/
<br/>
   function
mymodule_line_item_unit_price_currency_convert_to_euro($line_item) {
    
$wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
    
//Load the product and get the euro price
   
$pid = $line_item->commerce_product['und'][0]['product_id'];
   
$prod = commerce_product_load($pid);
   
$wrapper->commerce_unit_price->amount = $prod->field_euro_price['en']['0']['amount'];
    }
?>

Looking forward Although this worked I have a few problems with the techniques I used and I will be looking at those next

  1. Do I need to load the entire product? maybe I can use EntityFieldQuery() to load only the euro price.
  2. Do I need a custom action? I should try and make my euro price available to the line_item using hook_entity_property_info()
  3. I should make sure I have a euro price, if not I can maybe call the commerce commerce_line_item_unit_price_currency_convert action to dynamically convert it using an exchange rate.

Revised code for Convert the price to the euro value (using standard actions)
This will replace our "second action (using custom action)"
in order to use the commerce "Set the unit price to a specific amount" action we will need to make sure rules knows about our euro price field. for this to happen we need to do two things

  1. Bring the commerce_product referenced by the line item into scope
  2. Add metadata to the commerce_product about our euro price field

Once that is done we will be able to set our line item amount to that of the euro field amount using the rules 2 "Data selector"

Bring the commerce_product referenced by the line_item into scope
add a condition:
- "Entity has field" Entity = "line-item", Field value = "commerce_product".

We should also add drill down rules from the product down to the euro amount:
- "Entity has field" Parameter: Entity: [line-item:commerce-product], Field: field_euro_price
- "NOT Data value is empty" Parameter: Data to check: line-item:commerce-product:field-euro-price.
- "NOT Data value is empty" Parameter: Data to check: line-item:commerce-product:field-euro-price:amount.

to get the "NOT" use a "Data value is empty" with the "Negate" check-box ticked.

Add metadata to the commerce_product about our euro price field
the commerce drupal module provides metadata about the commerce_product using the hook hook_entity_property_info().
In order to add our new price field we will need to use the hook_entity_property_info_alter() that will allow us to make changes to the commerce_product.

<?php
/**
* Implements hook_entity_property_info_alter()
*
*/
function mymodule_entity_property_info_alter(&$info) {
 
// Copy metadata about our euro field from the product bundle to the
  // commerce_product entity, referenced by the line_item
 
$euro_field $info['commerce_product']['bundles']['product']['properties']['field_euro_price'];
 
$info['commerce_product']['properties']['field_euro_price'] = $euro_field
}
?>

Update Fri 3 June 2011
After spiking to Ryan, I realised that my new price field was already in scope and did not need the hook_entity_property_info_alter(), its ok to use it if all your product types have the euro field (as is our case) but not essential as the conditions bring the euro field into scope see http://www.drupalcommerce.org/faq/rules-field-data-selection and the Product Pricing Rules (with screencasts) "Adding a Taxonomy Term To Drive Discounts" section

Update Mon 6 June 2011
Attempted to implement my Friday notes and could not get it to work – I am under the impression that bringing addional commerce product fields into scope using Rules 2 only makes them available to the conditions and if you need to use them in actions you will need to use the hook_entity_property_info_alter() technique to let rules know of their existence.

I will try and get confirmation on this or if anyone has an answer please comment.

Guy,

Guy great talk at BADAss Camp. I'm delving into Commerce as we speak. Immediately regretting not using the Commerce Install profile.

Is this the only change I need in order to render prices in GBP?
Create an action using the commerce “Set the unit price's currency code” to set the line_item to EUR

Thanks!

John

BADAss John

Hi Johnsorry for not responding earlier missed this comment
hope the project is going wellWe use one rule with two actions one to set the currency and the second to set the unit price (copy the value from our euro field).