This Satchmo fork adds multi-currency support.
The basic concept is to add a currency model to specify the currencies of the store (e.g. GBP, USD and EUR). Each product price will be assigned a currency. To sell a product in USD and EUR it is necessary to add a USD price and a EUR price.
When a shopper arrives at the store they will be able to select their currency that is then used to determine the products and their prices. The user's selected currency is stored in the session.
The store Config model has two new fields:
- currency - to set the default currency of the store.
- store_currencies- a list of currencies accepted by the store.
Cart currency field
Carts have a currency, set from the user's session currency.
Order currency field
Orders have a currency, set from the user's session currency.
The shop models includes a new Currency model, to specify a name (e.g. British pound), code (e.g. GBP), symbol (e.g. £) and rate_to_base.
The rate_to_base functionality is not yet implemented.The idea of the rate_to_base is to calculate a price in one currency from a price in another currency (the base or default currency for the store). For example, you can set GBP to be 0.6 related to USD.
Originally we intended the rate_to_base currency to be calculated on-the-fly but we later decided it may be more practical to run this as a management command periodically to recalculate all prices or even when the rate_to_base is changed (using a signal).
class Currency(models.Model): """ A currency for using with a price """ name = models.CharField(max_length=255) code = models.CharField(max_length=3) symbol = models.CharField(max_length=16, null=True, blank=True) rate_to_base = models.FloatField(default=1.0, help_text=_("This rate is used to calculate the price from the base currency if a product has no price for this currency."))
Discounts have a currency and can only be applied to orders / carts in that currency.
Prices have a currency.
Get the user's (thread) current currency
The user's currency can be obtained from the (session in the) request. Satchmo uses threaded_multihost.threadlocals to store the request in the thread so it is possible to get the current currency (from the thread) using satchmo_utils/currency.get_current_currency
Other Product types
We have not added multi-currency to all the other product types such as ConfigurableProducts. We'll probably need to add currency to Options, CustomTextField and Trial.
We created our own payment method. It should be relatively trivial to simply supply the appropriate currency code to each merchant (if they accept multi-currency).
OrderPayments should probably have a currency (that defaults to the currency of their order. It is possible that a payment method may allow the user to use a different currency.
We created our own shipping module as our site had specific shipping / distribution options. Either the core shipping modules should be altered to work with multi-currency or new multi-currency modules are needed.
Calculate prices using exchange rates
The Currency model includes a field rate_to_base to set an exchange rate (to the stores base or default currency). This rate_to_base value could be used to calculate prices, either on the fly, periodically or maybe when the rate_to_base is changed (using a signal).
Please fell free to fork this project and submit back any patches. Ideally we'd like to get this pushed upstream to the main Satchmo project but we'll need a lot more testing and tidy up before that's possible.