Download & Extend

Multicurrency support

Project:Ubercart
Version:6.x-2.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:needs work

Issue Summary

I am working on adding multicurrency support in 6.x, and have made a patch series for core that is needed to implement this fully. The four attached patches are as follows:

1. Backports the UcOrder object and use of drupal_write_record() from 7.x, reducing some code duplication and allowing other modules to work with order objects more easily.

2. Adds a currency code field to the order table/object, defaulting to the store currency. This is needed in core because there is no other way of specifying to a payment method the currency that should be used; the payment methods still need updating to use this new field. Implementing this will close #607708: Allow defining currency code per order.

3. Locks product prices at checkout time. This is a longstanding bug in core where price alterers are invoked on orders after they have left checkout, which should not happen - all order prices stored in the database should be fixed amounts. This will break compatibility with uc_vat, but I will handle fixing that later, and also possibly uc_discount, but that seems pretty broken in a number of ways anyway. It will also require an update function to alter existing prices one final time, before saving them to the database. See #854638: order products price should locked in altered price.

4. Makes full order objects available in the order admin and user order history pages. This is needed so currency formatting can be done correctly. Previously requested in #727404: Various order pane functions need to pass order in uc_price context['subject'] variable.

A number of calls to uc_price() can be simplified and cleaned up further once this patch is committed.

The multicurrency module itself is pretty much just a price alterer and a UI to administer currencies and product prices in different currencies (automatic conversion based on a conversion factor is also supported). This needs some more testing and UI polish before I am ready to upload it. This could be uploaded as contrib but I also see no reason why it shouldn't go into core for 6.x, and then we can work towards implementing it in 7.x as well.

Marking "needs work" for now as some of the items above need further implementation and testing, but discussion on the above is welcomed!

AttachmentSizeStatusTest resultOperations
0001-Backport-UcOrder-object-from-D7-allowing-other-modu.patch8.17 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 0001-Backport-UcOrder-object-from-D7-allowing-other-modu.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.View details | Re-test
0002-Add-currency-code-field-to-orders.patch1.84 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 0002-Add-currency-code-field-to-orders.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.View details | Re-test
0003-Lock-product-prices-at-checkout-time.patch2.15 KBIdlePASSED: [[SimpleTest]]: [MySQL] 1,300 pass(es).View details | Re-test
0004-Make-full-order-object-available-in-order-listings.patch4.4 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 0004-Make-full-order-object-available-in-order-listings.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.View details | Re-test

Comments

#1

Forgot to add: this work and the forthcoming multicurrency module were sponsored by Opsview.

#2

Glad to know Ubercart will be supporting multicurrency. Do you have the timelines for the production-ready release? Specifically for Drupal 6? Thanks!

#3

Subscribing.

#4

Subscribing

#5

Updated version of patch #4 as the original no longer applies.

AttachmentSizeStatusTest resultOperations
0004-Make-full-order-object-available.patch3.94 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 0004-Make-full-order-object-available.patch. Unable to apply patch. See the log in the details link for more information.View details | Re-test

#6

A test version of the uc_multicurrency module and another Ubercart core patch are attached. The patch enables multicurrency display in the cart, checkout and order admin pages, though the order preview pane at checkout is wrong for the time being.

You will need to apply the first three patches from the initial post, patch #4 above, patch #5 attached here, then run update.php before installing the module.

After installing, currency setup is located at /admin/store/settings/store/edit/currency. A new block allows you to switch currency. When editing products you have the option to enter fixed prices in all currencies; leaving a price blank will use the conversion rate specified on the main currency settings page.

Currency switching doesn't work for anonymous users if the page cache is enabled; I hope to work around this with JavaScript eventually, but for now you will have to disable page caching. This only works for product nodes and has not yet been tested with attributes, shipping, or anything like that. Payment gateways will need updating to support multicurrency, this is not yet implemented for the core payment modules.

Any feedback is welcome if anyone would like to try testing this, or help out with debugging or implementing missing features.

@marvzz: There is no set timeline for this, but the more people that show interest and are willing to test patches and the module, the quicker this will be added to Ubercart.

AttachmentSizeStatusTest resultOperations
uc_multicurrency.tar_.gz5.33 KBIgnored: Check issue status.NoneNone
0005-Multicurrency-cart-and-order-pages.patch9.58 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 0005-Multicurrency-cart-and-order-pages.patch. This may be a -p0 (old style) patch, which is no longer supported by the testbots.View details | Re-test

#7

Also wondering whether it is feasible to commit this in the 6.x-2.x branch, or whether it would be a good idea to entirely overhaul uc_price() and related functions in a new branch. The price locking is definitely an issue here that is difficult or impossible to solve while keeping backward compatibility with other price altering modules. If successful it could then be forward ported to 7.x (which currently has no price altering functions), with the possible aim of getting both multicurrency and VAT in core.

#8

Hi longwave, I have applied your patches and tried your module!, so far so good. I will test this more in these coming days, and will post here if I encounter issues.

By the way, am I correct to assume that for now we will still be expecting series of patches instead of a downloadable dev branch? (either existing or new branch)

#9

Subscribing.

This looks very promising, including the much needed fix for locking product prices at checkout time. Should that be split off into the existing issue at #854638: order products price should locked in altered price ?

#10

If possible I would like someone to review the initial set of four patches. I am wary of committing the price locking patch but patches 1, 2 and 4 (UcOrder backport, order currency field and full order objects in admin pages) should not break backward compatibility, so perhaps we can get these into -dev and then concentrate on the price locking issue separately.

#11

Status:needs work» reviewed & tested by the community

Patches from #0:

1. Tested, works fine, after all this is just a back port of what is in 7.x-3.x
2. Update runs fine, appears to have no side effects.
3. Abandoned as per #854638-8: order products price should locked in altered price
4. (Updated in #5) Works fine and gets rid of code duplication.

I'd say 1, 2 and 4 are ready to go.

I haven't had a chance to test uc_multicurrency in #6

#12

Hi, longwave

Thank you for your work on this. multi-currency is a real weak point in Ubercart and I for one will be on D6 for a while yet. I spent the last two days hacking the official abandoned multicurrency module and also this one: http://drupal.org/node/931764 . Neither do what I need. Your code is nicely clear and simple, and works :)

I downloaded the dev branch of ubercart, your multi-currency module, applied your patches and tested. The images with my results should hopefully be self explanatory, I paid attention to the consistency of currencies and symbols throughout the process.

I'll keep looking at this as I need product attribute options with different prices too. The currency_api could be used to provide realtime currency updates against the store master as well I suppose. I haven't tested this with a real payment gateway (but plan to) so what happens there? Presumably the total and currency get sent in the request to the payment gateway?

I've not done any real transactions with ubercart yet, still in development.

Thanks.

EDIT: image checkout6.png actually has the wrong total, so my comment in green is wrong. oops.

AttachmentSizeStatusTest resultOperations
checkout1.png51.53 KBIgnored: Check issue status.NoneNone
checkout4.png25.14 KBIgnored: Check issue status.NoneNone
checkout5.png22.57 KBIgnored: Check issue status.NoneNone
checkout6.png20.47 KBIgnored: Check issue status.NoneNone

#13

@furzey: Thanks for testing, the payment preview pane is a known issue that I have yet to finish working on but that should be in the next update. I will take a look at the other comments you made then as well.

Regarding payment gateways, whatever gateway you use will need updating to support this - instead of using variable_get('uc_currency_code', 'USD') to find the currency, they should use $order->currency instead. This should be done for the core payment methods in the next update, other gateways will need patches or issues raising if/when this is committed.

#14

Awesome, thanks again. I'll keep testing and posting.

#15

Can this work with i18n ? I mean, change default currency with page language changes ?! also, is this production ready yet or what ?!

Thanks for your efforts :)

#16

Couple more issue that I found with this patches and uc_multicurrency module (EUR is set as current currency on the screen shot):

- Example field in Currency settings always shows current currency formatting.
- My Cart block displays correct amount value for EUR, but formatter applies default currency (SEK) formatting.

AttachmentSizeStatusTest resultOperations
currency_settings_example.png120.05 KBIgnored: Check issue status.NoneNone
my_cart.png8.84 KBIgnored: Check issue status.NoneNone

#17

Fixed first issue - fixes Example field, but may affect some other parts I did not tested.

In uc_multicurrency_price_handler_alter -> case 'amount': add one more condition, so the whole case section will be:

<?php
   
case 'amount':
      if (isset(
$context['subject']['order'])) {
       
$code = $context['subject']['order']->currency;
      }
      elseif (isset(
$context['currency'])) {
       
$code = $context['currency'];
      }
      else {
       
$code = uc_multicurrency_code();
      }
     
$options = uc_multicurrency_options($code) + $options;
      break;
?>
AttachmentSizeStatusTest resultOperations
currency_settings_example-fixed.png119.67 KBIgnored: Check issue status.NoneNone

#18

Status:reviewed & tested by the community» needs work

BTW, updating status to "needs work" as there are at least 2 known issues with this patches:

- wrong order total (reported by furzey in #12, reproduces for me too)
- My Cart block currency formatting

#19

And one more partial fix - added new case section to uc_multicurrency_price_handler_alter

<?php
   
case 'price':
      if (
$context['revision'] == 'themed') {
       
$code = uc_multicurrency_code();
       
$options = uc_multicurrency_options($code) + $options;
      }
      break;
?>

This fixes Total section for My Cart block.

AttachmentSizeStatusTest resultOperations
my_cart-total_fixed.png8.66 KBIgnored: Check issue status.NoneNone

#20

Found where the problem with cart items currency was.

My Cart block is handled with the Ajax Driven Cart (uc_ajax_cart) module. It uses the following code to build cart item total cost:

<?php
'total'    => uc_price($display_item['#total'], array(
               
'revision' => 'themed-original',
               
'type' => 'amount',
                )),
?>

And patched uc_price function has the following "Exit early" verification:

<?php
 
// Exit early if no alterations are needed.
 
switch ($context['revision']) {
    case
'formatted-original':
      return
$formatter($original, $options);

    case
'themed-original':
      return
theme('uc_price', $formatter($original, $options), $context, $options);
  }
?>

So item price is not altered with the uc_multicurrency but themed as is with the default currency (SEK for me).

I'm sure what is the right way to fix this behaviour, so I just patched uc_ajax_cart to use 'revision' => 'themed'

#21

And one more issue - Flatrate (uc_flatrate) bundled with Ubercart within shipping group has context set to the following value:

<?php
  $context
= array(
   
'revision' => 'themed',
   
'type' => 'amount',
  );
?>

So rates are not converted on settings page admin/store/settings/quotes/methods/flatrate but are formatted with the currently active currency.

#22

Another problem are Taxes (uc_taxes). Values are calculated within AJAX requests from checkout page by sending serialized order information. The problem is that sent order prices not altered with any handlers and default currency price is used for calculations.

Order contents can be changed with the hook_uc_cart_alter(&$items) and I tried to use something like this:

<?php
function uc_multicurrency_uc_cart_alter(&$items) {
 
// Do nothing for the default currency.
 
$code = uc_multicurrency_code();
  if (
$code == variable_get('uc_currency_code', 'USD')) {
    return;
  }

 
$options = uc_multicurrency_options($code);
  foreach (
$items as &$item) {
   
$node = node_load($item->nid);
   
$prices = $node->multicurrency;
   
$field = 'sell_price';
   
// Use the specific price if set, otherwise use the currency conversion factor.
   
if ($prices[$code][$field] > 0.001) {
     
$item->price = $prices[$code][$field];
    }
    else {
     
$item->price *= $options['factor'];
    }
   
// mark price as altered by Multicurrency module to avoid second multiplication by currency factor in price handler
   
$item->multicurrency_price_altered = TRUE;
  }
}
?>

But this makes currency conversion factor being applied twice for all cart items - first time after order items are loaded, second time with the price handler. To solve this I added a flag for Order items that is verified in price handler, so modified case now is:

<?php
   
case 'cart_item':
    case
'product':
     
// Do nothing for the default currency.
     
$code = uc_multicurrency_code();
      if (
$code == variable_get('uc_currency_code', 'USD')) {
        return;
      }

     
$options = uc_multicurrency_options($code) + $options;
     
$prices = &$context['subject']['node']->multicurrency;
     
$field = isset($context['field']) ? $context['field'] : 'sell_price';

      if (empty(
$context['subject']['cart_item']->multicurrency_price_altered)) {
       
// Use the specific price if set, otherwise use the currency conversion factor.
       
if ($prices[$code][$field] > 0.001) {
         
$price['price'] = $prices[$code][$field];
        }
        else {
         
$price['price'] *= $options['factor'];
        }
      }
      break;
?>

#23

Final version of the Multicurrency module that I use

#24

Sorry, missed file

AttachmentSizeStatusTest resultOperations
uc_multicurrency.tar_.gz5.61 KBIgnored: Check issue status.NoneNone

#25

@vgarvardt: Thank you for posting your issues, changes and code. I have made more updates to my copy of the module (including support for product kits, and anonymous page caching in different currencies) and hope to include your changes and post an updated version next week.

#26

Hello!

Many thanks for improving the multicurrency module! I tried out the latest file from post #24 and got the error message at the product editing page:

"Fatal error: Call to undefined function dpm() in /home/****************/sites/all/modules/uc_multicurrency/uc_multicurrency.module on line 67"

And on the price editing page:

user warning: Table '*************************.uc_product_multicurrency' doesn't exist query: SELECT currency, list_price, cost, sell_price FROM uc_product_multicurrency WHERE vid = 4 in /home/**************************/sites/all/modules/uc_multicurrency/uc_multicurrency.module on line 127.

I have a multi language site and tried out the older version of multi currency module as well as multi price module.

#27

"Fatal error: Call to undefined function dpm() in /home/****************/sites/all/modules/uc_multicurrency/uc_multicurrency.module on line 67"

Sorry, forgot to remove debug call - this function is from devel module. You may simply remove this string.

user warning: Table '*************************.uc_product_multicurrency' doesn't exist query: SELECT currency, list_price, cost, sell_price FROM uc_product_multicurrency WHERE vid = 4 in /home/**************************/sites/all/modules/uc_multicurrency/uc_multicurrency.module on line 127.

uc_product_multicurrency table is installed on uc_multicurrency module install. Did you get any errors while installing the module?

#28

Thank you for the fast answer!

The second error message: I installed the module again and got no error message while activating. I also installed it on a second drupal test environment and got the following messages:

user warning: Table '********************.uc_product_multicurrency' doesn't exist query: SELECT currency, list_price, cost, sell_price FROM uc_product_multicurrency WHERE vid = 54 in ********************drupal/sites/all/modules/uc_multicurrency/uc_multicurrency.module on line 126.
user warning: Table '*******************.uc_product_multicurrency' doesn't exist query: SELECT currency, list_price, cost, sell_price FROM uc_product_multicurrency WHERE vid = 96 in *************************/drupal/sites/all/modules/uc_multicurrency/uc_multicurrency.module on line 126.
user warning: Table ***************.uc_product_multicurrency' doesn't exist query: SELECT currency, list_price, cost, sell_price FROM uc_product_multicurrency WHERE vid = 97 in **********************/drupal/sites/all/modules/uc_multicurrency/uc_multicurrency.module on line 126.

I am working in a godaddy shared hosting linux environment.

Thank you for your support!

#29

Just checked that the table was not created.

#30

Found one more issue. When order was created from cart items prices were altered twice.
Here is patch for the module from #24 that fixes this issue and my current module version.

AttachmentSizeStatusTest resultOperations
create_order_fix.patch1.7 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch create_order_fix.patch. Unable to apply patch. See the log in the details link for more information.View details | Re-test
uc_multicurrency.tar_.gz5.61 KBIgnored: Check issue status.NoneNone

#31

Hello vgarvardt,

Must it not be:

function uc_multicurrency_install() {
drupal_install_schema('uc_product_multicurrency');
}

However even with that it does not install the table. How can I debug this? Do you have a suggestion?

Thank you!

#32

@stesind: You say you tried the other multicurrency module previously - this may have confused your installation. Try disabling then uninstalling the Multicurrency module from /admin/build/modules/uninstall (there may be some errors, which you can ignore) before enabling it again.

#33

subscribed

#34

Thank you longwave,

I had to delete the module information in the system table. Then I was able to install. And also thank all the developers for their work!

On a first test it looked great for the product itself. But the shipping quotes seem not to be converted. I mean the quote itself does not have to be converted. It would be enough if the order total is calculated correctly. One more question. Did anybody patch the paypal payment module to accept the other currency?

#35

I had to patch several modules to work correctly with multicurrency, e.g. uc_flatrate, uc_discounts, uc_pma, uc_fee etc. Just added drupal_alter() to the modules and implemented alteration hooks in my support module. Did not use Paypal, so can't say anything about this.

#36

subscribed

#37

Any updates on this? I'm looking to use this with product kit and the flatrate shipping modules.

#38

subscribe

#39

Hi longwave,

What's the status of this project?

Thanks.

#40

This has taken longer than expected to work on due to various things, but I am still working on this and should be submitting an updated module soon.

In the meantime, I committed http://drupal.org/files/issues/0001-Backport-UcOrder-object-from-D7-allo... as it doesn't seem to be causing any problems.

#41

Committed the attached patch which is an update to 0002-Add-currency-code-field-to-orders.patch. This needs porting to 7.x, which will be done in #607708: Allow defining currency code per order to keep things separate.

AttachmentSizeStatusTest resultOperations
607708-currency-per-order.patch1.42 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 607708-currency-per-order.patch. Unable to apply patch. See the log in the details link for more information.View details | Re-test

#42

Further updated version of patch 0004 from the original is attached.

So, to use multicurrency with current 6.x-2.x-dev, you need to apply the following:

http://drupal.org/files/issues/0003-Lock-product-prices-at-checkout-time...
1097668-full-order-object-admin-listings.patch (attached)
http://drupal.org/files/issues/0005-Multicurrency-cart-and-order-pages.p...

AttachmentSizeStatusTest resultOperations
1097668-full-order-object-admin-listings.patch5 KBIdleFAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 1097668-full-order-object-admin-listings.patch. Unable to apply patch. See the log in the details link for more information.View details | Re-test

#43

subscribed

#44

There has been mention of multi-currency not working properly with full page cache for logged out users, for obvious reasons, and the idea of a JS solution to solve that.

I'll get booed at, but it is possible to make full page cache work by hacking the core in two places.

common.inc page_set_cache()
bootstrap.inc page_get_cache()

you can work out the details but basically just pull out the current currency and append it it to the url which is pased to cache_get() and cache_set() respectively. I guess the cleanest way to do this would be to delegate cache url generation to a hook function so the default url generated is the same as it is now in the core, then add the currency to that url via a hook implementation in your own module.

Not ideal for Pressflow though due to session starting, and if you support many currencies, it'll obviously bloat your cache.

---
However, longwave, you mentioned you'd be posting an updated module soon including a solution for anonymous caching; any news? :)

#45

subscribe

#46

So I was getting double currency calculation happening in the checkout page, in the cart contents page for a product row. Either I missed something or this seems to fix it:

uc_multicurrency.module uc_multicurrency_price_handler_alter()

I added $context['subject'][$subject_item] != 'cart' to the if statement.

<?php
// when order is prepared from cart items 'product' contains copied 'cart_item' value
$subject_item = !empty($context['subject']['product']) ? 'product' : 'cart_item';
if (
$context['subject'][$subject_item] != 'cart' &&  empty($context['subject'][$subject_item]->multicurrency_price_altered)) {
..
..
?>

I was also looking at getting this working for product options with different prices, on the node product page, this appears to fix alter the currency properly, in uc_multicurrency_price_handler_alter(), just add another case

case 'attribute_option':

under

case 'product':

No joy so far with getting the shopping cart of checkout working though.

#47

Some more places to change, please someone else try and test this too, this is against the latest dev branch of ubercart, and all the patches and multi-currency module listed here applied. This is to make the orders list and view of individual orders correct:

uc_payment_order_pane.inc

<?php
function uc_order_pane_payment($op, $arg1) {
  switch (
$op) {
    case
'view':
     
$output = '';
      if (
variable_get('uc_payment_tracking', TRUE)) {
       
$context = array(
         
'revision' => 'formatted', // CHANGE from formatted-original
..
?>

uc_order.order_pane.inc

<?php
function op_products_view_table($order) {
..
.
$data['price'] = array(
       
'#value' => uc_price($product->price, $context), // CHANGE added $context
       
'#cell_attributes' => array('align' => 'right', 'nowrap' => 'nowrap'),
      );
..
?>

uc_order.admin.inc

And this is a nice extra to show us the currency in the orders list.

<?php
function uc_order_admin($sql = NULL, $args = NULL, $search = FALSE) {
 
$header = array(
    array(
'data' => t('Actions')),
    array(
'data' => t('Order ID'), 'field' => 'o.order_id', 'sort' => 'desc'),
    array(
'data' => t('Currency')), // CHANGED, this was added
   
array('data' => t('Customer')),
    array(
'data' => t('Total'), 'align' => 'center', 'field' => 'o.order_total'),
    array(
'data' => t('Purchase date'), 'align' => 'center', 'field' => 'o.created'),
    array(
'data' => t('Status'), 'field' => 'os.title'),
  );
..
..
// CHANGE added currency
   
$sql = 'SELECT o.order_id, os.title, currency FROM {uc_orders} o LEFT JOIN {uc_order_statuses} os ON o.order_status = os.order_status_id ';

..
..
$context = array(
   
'revision' => 'themed', // CHANGE was themed-original
   
'type' => 'amount',
  );
..
..
$rows[] = array(
     
'data' => array(
        array(
'data' => uc_order_actions($order, TRUE), 'nowrap' => 'nowrap'),
        array(
'data' => $order->order_id),
        array(
'data' => $row->currency), // CHANGE added.
..
?>

--
EDIT, there is an issue with the products pane at checkout, price is correct, currency symbol is not, I'll continue tomorrow.

#48

At the end of the day yesterday I had an issue with the cart pane in the checkout page, issue was correct price but wrong currency symbol. This appears to fix it, I'll keep working and testing this, I need multicurrency working:

<?php
function theme_uc_discounts_cart_checkout_table($show_subtotal = TRUE) {
..
..
// Remove node from context to prevent the price from being altered.
$context['revision'] = 'themed'; // CHANGED was themed-original
$context['type'] = 'amount';
    unset(
$context['subject']);
   
$rows[] = array(
      array(
'data' => t('@qty&times;', array('@qty' => $item->qty)), 'class' => 'qty'),
      array(
'data' => $description
..
?>

#49

Great! Just found this after doing a little work on #621494: Provide order data as context for uc_price (for multicurrency support) and noticing that some of the ideas from there had already surfaced in 6.x-2.x-dev.

I suspect that issue will be duped as a result of work here, but there is a patch in that issue which may be pertinent (adds order context to uc_price() for various payment methods, etc).

@furzey: If you do not run DB updates after updating Ubercart (since 2011-07-01), you will be unable to progress beyond checkout screen. Errors in your site log will show Unknown column 'currency' in 'field list' query: INSERT INTO uc_orders ( ... ). Could that be the issue you were having?

#50

I uploaded the latest version of uc_multicurrency to http://drupal.org/sandbox/longwave/1231110

Patches welcome here or in the sandbox queue.

#51

I can verify that the attributes don't work properly with multicurrency (unless I've applied the patches incorrectly). What I'm seeing is that the base price is showing correctly with the correct amount and currency, however, the attributed prices aren't adjusted, they show as the same price as the base price. I'll poke around a bit, but I'm not sure exactly where to start - I would have expected if the attributes pull the correct price and currency symbol from multicurrency, then they would just auto-magically adjust. I would guess that the attributed prices are just modified, and I can't imagine why it wouldn't just work. But, my imagination and knowledge probably aren't that in sync!

#52

Ok, so after poking around, the attributes work correctly only if you use the conversion factor (don't set the amount in the product price), and only show attribute as totals (not adjustment - that only displays in default currency, in my case, USD). However, Ubercart will happily treat the sell price and the attribute adjustment as if they are the same currency. I have not checked the case where the currency uses different thousands and decimal markers - this could cause confusion.

What I finally came to was in line 1176 in uc_attribute.module, where $product->sell_price seem to be the default currency price as set in the product and $option->price is the adjustment factor as set in the attribute, but once the whole thing goes through uc_price(), it all seems to become whatever is set in the currency that is selected:

$display_price = in_array($attribute->aid, $priced_attributes) ? ', '. uc_price($product->sell_price + $option->price, $context) : '';

So, for example, if the product sell price is set to $400 USD (default) and €500, with an adjustment attribute of -25 and another of +50, then when Euros are selected (and attribute is set to show totals), both prices for the attribute options show up as €500. However, if the sell price in Euros is set to blank, but the conversion factor is set to 1 for Euros, the attribute prices show up as €475 and €550.

I'm not sure how to fix it, but I wanted to let folks know the details in case anyone was interested in pursuing it further.

Great module - I have had people begging me for this functionality for some time now!

#53

subscribing

#54

was just testing this out and noticed that 0005-Multicurrency-cart-and-order-pages.patch does not apply, I think due to #1014782: Subtotal in bold/strong at checkout page:

patch -p1 < 0005-Multicurrency-cart-and-order-pages.patch
patching file uc_cart/uc_cart.module
Hunk #1 succeeded at 673 (offset 4 lines).
Hunk #2 succeeded at 713 (offset 4 lines).
Hunk #3 succeeded at 901 (offset 4 lines).
Hunk #4 succeeded at 935 (offset 4 lines).
Hunk #5 FAILED at 1105.
1 out of 5 hunks FAILED -- saving rejects to file uc_cart/uc_cart.module.rej
patching file uc_cart/uc_cart_checkout_pane.inc
Hunk #1 succeeded at 628 (offset -10 lines).
patching file uc_order/uc_order.admin.inc
Hunk #1 succeeded at 1329 (offset 29 lines).
patching file uc_order/uc_order.module
Hunk #1 succeeded at 453 with fuzz 2 (offset 4 lines).
Hunk #2 succeeded at 1490 (offset 16 lines).
patching file uc_order/uc_order.order_pane.inc
Hunk #1 succeeded at 768 (offset 5 lines).
Hunk #2 succeeded at 789 (offset 5 lines).
Hunk #3 succeeded at 875 (offset 5 lines).
Hunk #4 succeeded at 896 (offset 5 lines).

#55

Assigned to:Anonymous» stellar124

Hello,

I have a problem, I think it's near by:

// Use the specific price if set, otherwise use the currency conversion factor.

So it doesn't work, the altered price is 0 if i don't fill the multicurrency price,
In the settings, "admin/store/settings/price-handlers" I've checked the "Multicurrency price alterer" but no result.

I try:

  // Use the specific price if set, otherwise use the currency conversion factor.
      if (isset($prices[$code][$field]) && $prices[$code][$field] > 0.001) {
        // $price['price'] = $prices[$code][$field]; 
$price['price'] *= $options['factor'];
      }
      else {
        $price['price'] *= $options['factor'];
      }

but doesnt work

Any idea?
Thanks!

#56

For those who (like me) are testing this, you may be bitten by #1287948: Cart pane always displays default store currency prefix, regardless of currency setting for products which seems to not be caused by multicurrency -- but instead multicurrency seems to expose the issue, just like the other multiple-currency contrib modules do.

#57

subscribe

#58

Where can I get a copy of this module to test? I have tried cloning from the sandbox but just get 2 uc_coupon files.

#59

Marcus, if it helps, you can do git clone git://git.drupal.org/sandbox/longwave/1231110.git. Note, I don't use this module at this point -- but that repo is what I cloned from when I tested.

Note that there hasn't been any activity in that repo since its initial commit on 7/27/2011, so there may be a more current version somewhere.

Perhaps someone (longwave?) could shed some light on the current status of multicurrency support in Ubercart?

#60

There has been no further progress; the client that requested this feature is happily using it, but there was no further time or money available to merge this directly into Ubercart. Further patches or offers of sponsorship to complete this are welcome, however.

#61

Dave, can you explain what the client did to work around or bypass #1287948: Cart pane always displays default store currency prefix, regardless of currency setting for products? Are they using your Ubercart core patch from comment #6?

Also, has anyone put work into the PayPal payment module so it doesn't always submit payments in the default store currency?

#62

Yes, they are using the core patches from this issue, which I believe solves that problem.

The client in question didn't use PayPal but it should be fairly straightforward to modify all payment modules to use $order->currency to get the currency code.

#63

Dave, I've just made an attempt to rebase that patch set onto the current ubercart 6.x-2.x branch.

0001 seems to have gone upstream in the meantime.
0002 seems to have gone upstream in the meantime.
0003 applies cleanly.

0004 produces a conflict in uc_order/uc_order.admin.inc:

<<<<<<< HEAD
  $result = pager_query("SELECT o.order_id, o.created, os.title, SUM(op.qty) AS products, o.order_total AS total, o.order_status FROM {uc_orders} AS o LEFT JOIN {uc_order_statuses} AS os ON o.order_status = os.order_status_id LEFT JOIN {uc_order_products} AS op ON o.order_id = op.order_id WHERE o.uid = %d AND o.order_status IN ". uc_order_status_list('general', TRUE) ." GROUP BY o.order_id, o.created, os.title, o.order_total, o.order_status". tablesort_sql($header), 20, 0, "SELECT COUNT(*) FROM {uc_orders} WHERE uid = %d AND order_status NOT IN ". uc_order_status_list('specific', TRUE), $user->uid);
=======
  $result = pager_query("SELECT o.order_id FROM {uc_orders} o WHERE o.uid = %d AND o.order_status IN ". uc_order_status_list('general', TRUE) ." ". tablesort_sql($header), 20, 0, NULL, $user->uid);
>>>>>>> Make full order object available in order listings.

0005 produces a conflict in uc_cart/uc_cart.module:

<<<<<<< HEAD
      '#value' => '<span id="subtotal-title">'. t('Subtotal:') .'</span> '. uc_price($subtotal, $context),
=======
      '#value' => '<strong>'. t('Subtotal:') .'</strong> '. uc_price($subtotal),
>>>>>>> Enable multicurrency display in the cart, checkout and order admin pages

Could you advise how to resolve these conflicts correctly?

#64

I just wanted to say big thank you to longwave for this module and idea of all this. I'm using drupal 7 and i searched all the web to find any appropriate solution for multicurrency but without luck. That's why i took this module as a frame and idea of it and somehow managed to adjust it for my needs (on drupal 7) but with several ubercart core updates. This is temporary-working solution for me and i really hope that some day there will be real multicurrency support in the core of ubercart.

Thank you.

#65

@lagreen: Please post your patches and code if you have ported this to Drupal 7, it would be hugely appreciated!

#66

@longwave, I contacted you a while back via your contact form regarding possible sponsorship for getting multicurrency fully supported (for D6, in our case), but never received any reply. Should I presume your swamped at this time, and if so, when would be a good time to revisit this?

#67

I don't recall receiving that (sometimes the contact forms on d.o seem flaky, either that or they get treated as spam I'm not sure), but right now I am indeed pretty busy. Depending on how much support/time you need I might be able to help, please try contacting me again.

#68

@longwave Yes, i can do so. But at first i have to try this on the clean instal to verify that this works properly :)

#69

Hi, I would be interested in using multicurrency with D7 Ubercart. What does it take to sponsor this feature? Many thanks.

#70

@longwave, I just shot you another email via the contact form. Let me know whether you got it, thanks!

#71

Is there any solution for paypal and ubercart 2.x?

#72

Here's a patch to enable multicurrency support in uc_paypal.

One thing to note: since uc_paypal provides a list of PayPal currencies, the patch tests the order currency against that list. It will change the submitted PayPal currency only when the order currency is in _uc_paypal_currency_array()

edit: patch created against Ubercart 6.x-2.7

AttachmentSizeStatusTest resultOperations
uc_multicurrency-paypal_currency_fix-1097668-72.patch4.94 KBIdlePASSED: [[SimpleTest]]: [MySQL] 1,544 pass(es).View details | Re-test

#73

Status:needs work» needs review

comment removed

#74

Status:needs review» needs work

#75

Is there a version working with ubercart 6.x-2.0 ?

This is the link to the patch but it down't work ?

Thank you

#76

@meandrew you can follow this link uc_multi_currency. follow #32 dukem's modified code, It's not an official release but it works. :)

All you have to do is follow the instruction given.
plus additional notes:

  • use the same ubercart version dukem was using.
  • patch ubercart's code (i'm not giving an idea to hack the core but it's the only choice as of now)
  • create a column 'currency' in uc_orders table. This stores the currency settings for each orders.

hope this saved you some time. :)

#77

This is working up to a point and is proving positive so far :) I am yet to add a new column as I wanted to run the patches first.

Is there a particular way to run patches? Not really sure where code is to be replaced in each respective file?

The currency switches over ie it is converted to the rate howver it is only for each product in the cart and the currency doesn't switch over in the actual shopping cart and checking out process.

Thanks

#78

I think you might have just missed a few steps. All you have to do is to patch them all up (with the same version of ubercart). Replace the existing files and install the required modules for the multi-currency.

Can you please tell me what versions do you use? drupal version, ubercart version, and other possible conflicting modules that you might have installed.

And can you message Multi-Currency Support for Ubercart instead of here so people will not be confused.

#79

Any luck with this for D7?

#80

Assigned to:stellar124» Anonymous

#81

Summary request, can someone kindly give me a summary of what has happened since on this issue or efforts towards a definite solution for either 6.x or 7.x?

What's the difference between this issue and #931764: Modified code to make it mostly work with Drupal 6 and Ubercart 2?

@longwave, If I were to tackle this for D7, can you outline very quickly what you did and the problems you found and advices into what I should look at?

I read through this issue and a whole and it seems that some momentum was lost toward the end and it seems that reviewing the latest patch should give me a fairly good idea, but words help as well.

Thanks.

#82

This issue has basically stalled for 6.x; I haven't had time or inclination to work on it since my last post in this issue. As uc_price() has been removed in 7.x, I am fairly certain a different approach will be required to achieve multicurrency support here.

I guess it would still be good to get the uncommitted 6.x patches in this queue rebased and re-tested, then ported forward to 7.x, at which point we can take stock of what we have and what we need to do to get multicurrency support in both versions.

#83

And we're not yet any nearer to a D7 version I'm afraid... Any chance of discussing approaches, possibilities and potential sponsoring?

#84

I am the maintainer of Currency, which manages currencies and exchange rates, and does locale-based price formatting.

If you're interested, we're doing a BoF about this at DrupalCon Portland today. Room A103, 14:00/2pm.

#85

Yes, we discussed some input approach questions in Currency a couple of days ago in your issue queue over there. :-)

Right now I'm working on a new Multi-Currency module (out of immediate need), I expect to be able to present it for peer review in a couple of days at most. D7, Ubercart 3, strictly without any currency rate conversion, only separate prices for any installed currency. I'd like to be able to discuss solutions. Right now, also because I needed very strict integration with the module, and only partly due to the import issue we discussed, I wrote my own currency support into the module (actually, currency support is done, product prices are done, attribute/options prices are done, I'm working on some display issues and order handling right now).

But, just because of that, I'm a bit torn between approaches. One one hand, I don't really want to duplicate functionality. On the other hand, my currency approach is different from yours in many places (and not only because of the different installation method). Locale and display settings are handled differently, besides, it's really cross-linked into the multi-currency module completely. Also, I have extra functionality like currency selection providers to decide what currency to actually use, based on a plugin-like architecture.

So, either here or preferably in the new module's issue queue, I'd very much like to discuss these issues and anything related.

#86

So what functionality do you need that is not offered by Currency? Also, your approach of linking locales/display and currencies is still unclear to me. From what I understand now, your approach in that regard is wrong, but I'd need some more info to confirm that.

#87

Yes, I know. To start with, it's really a pain that a large system like Drupal doesn't offer locale information out of the box. Currency handling for me is just a background helper, I concentrate on the Ubercart part now. For now, I made simplifications that will not remain in a finished version for sure. Right now I use a unified formatting string per currency (eg. $#,###.##) that handles both symbol and decimal/grouping characters in one go but that will need changing because of currencies that span several countries with possibly different display requirements.

However, one thing that I did implement is the install mechanism we already discussed. If you would be interested in checking it out and maybe adding to Currency some time, that would handle it. Of course, with the install mechanism comes the need to convert all the .yml files to the new format (I used the same approach as Ubercart Countries, as I already mentioned) but that can be automated.

Having said that, just like my current approach is cutting corners temporarily, I still feel that Currency bundling currency and locale information is still not the right way, either. The locale info should be moved out into a third module, I guess, something that offers general and universal locale information for Drupal...

#88

but that will need changing because of currencies that span several countries with possibly different display requirements.

Note that formatting patterns have *NOTHING* to do with the currency of the price that is being formatted, but only with the locale. Say I were to visit a Hungarian webshop that only lists prices in Forints (which is solely used in Hungary), the prices would still have to be formatted using en_NL, which is the locale I use on my laptop.

Having said that, just like my current approach is cutting corners temporarily, I still feel that Currency bundling currency and locale information is still not the right way, either. The locale info should be moved out into a third module, I guess, something that offers general and universal locale information for Drupal...

I share your opinion that this is the way it should be. The reason I never did it has to do with not being familiar enough with other parts of locale management, and a lack of time. I would likely support efforts to centralize this.

#89

Actually, there are many circumstances to cater for. The webshop I now have to set up will link currency to localization (the currency actually offered will depend on the locale used by the current user to view the site), so I'll be able to get away with the simpler approach temporarily.

Now I'm mostly finished with the Multi-Currency module, orders are saved all right, the only still remaining issues are some display and edit screens in the order management admin parts. I'd be very glad to hear something from the UC crowd about the likelihood to add some (very simple and very straightforward) modifications to the UC core. Basically, all that would be needed is to add an extra argument to theme_uc_price() and theme_uc_product_price(). If I were to move the whole multi-currency handling into the core, that extra argument would obviously be $currency. But a more universal approach and one that caters for any external module (either this one or any other) is to add $order to these theme functions. This single optional argument wouldn't break any existing functionality for sure so it would be rather easy to accept it into the core but it would help tremendously: instead of letting core do single-currency stuff and then repeat some work to change it to multi-currency, it would automagically do the right thing during the first run.

As far as I can see now, the optimal solution would be to have Currency do its currency stuff, hopefully with my installation additions if you consider them worthy, to move Locale out into a separate module and to add these slight changes to UC core to help the work of all the others.

#90

Actually, there are many circumstances to cater for. The webshop I now have to set up will link currency to localization (the currency actually offered will depend on the locale used by the current user to view the site), so I'll be able to get away with the simpler approach temporarily.

Ah, I understand. I only meant formatting. What you need is application-specific, and is not provided by currency right now, although Currency does provide the country-related metadata to support delegation like this.

#91

I've written a plugin-like infrastructure to provide this. There are providers that can decide, using whatever conditions they see fit, which currency to use. The user can configure, enable, disable and re-order these providers, just like with the stock localization selection providers. And the first provider that returns a definitive answer in the chain will be honored.

It's only plugin-like at the moment, not real plugins, meaning that although they do work along these lines, all providers are now implemented in the module itself and there is no provision for external modules to hook into this. But this will be added. Currently, I have four providers: selecting currency based on localization, user role, product content type and taxonomy.

#92

I wonder if we cannot add that to Currency itself, as it already contains relationships between countries and their currencies. Using hooks and Rules we can create a flexibly configurable solution.

#93

In theory, yes, but it only has meaning in the context of multi-currency Ubercart support itself.

Anyway, I'll try to contact Longwave in private message. I'm practically finished with it now but I did modify Ubercart in many places. If I could convince them to accept these changes (nothing else but adding a new argument to uc_currency_format() and a new attribute to the uc_price FAPI element, both are backward compatible so adding them has no influence on earlier modules), the situation would be much-much simpler. Actually, some issues can be solved without these modifications but not all.

In my own practice, I'd live with the added problems of modifying core and recreating it if a security fix arrives for now but this can't be so in a contrib module for sure.

#94

I did so, hopefully Dave can come here and look around. Here are the main features of the module as it is now:

  • Right now, it has its own currency support, instead of using Currency. In some places it provides less (no conversion, just plain and separate currencies), in other places more (providers, see below). Those parts could probably be merged into Currency or dissected into Currency and a Locale module.
  • All product admin pages (product base, options default, product options) override the original price related textfields to offer a way to enter multi-currency pages. Of all that, the product options page has a somewhat questionable UI, the others are just fine, I guess.
  • The module has a currency selection provider mechanism that allows built-in providers (later, extra modules) to decide which currency to present to the user, based on any condition (Drupal locale, user role, product type, taxonomy, GeoIP, user preference, etc).
  • Pre-order phases use the providers to determine the actual currency. As soon as an order object is started (actually, from the point of hook_uc_order('presave'), the currency is stored with the order. All later phases, including order management and invoicing uses the already stored currency.
  • The module has Views and Tokens support, with Rules in the oven.

There are two ways I could go forward now. As it is now, it can override many but not all currency operations in Ubercart. Both core and some bundled or contrib modules have very hardcoded ways of calling uc_currency_format (not even using theme('uc_price')). Basically, those outputs that stay in render arrays (eg. most of the order management) or use tokens (eg. invoicing) can be modified after the fact, although this means wasted resources as currency display has to be repeated. However, those already rendered cannot (eg. log entries).

A better solution would be if Ubercart could accept some changes to the core. They are quite numerous but actually, only two kinds, only they appear in many places. First, whenever uc_currency_format() is called, a new argument (the currency) should be passed as well. Sites not using multi-currency will not see any difference as either passing the default currency or not passing anything at all will use the default for sure. Second, all uc_price FAPI elements should also receive a new attribute, #currency, with the very same ramifications.

In my opinion, both changes are long overdue and would provide an avenue for this or any similar module to handle prices appropriately, with their units.

nobody click here