Apex SOQL – Insert a Currency with Non-Default Currency Type in Multi-Currency

I am new to multi-currency. Suppose I have used Australia Dollar and Japanese Yen in the system. And when I am executing the below code:

Merchandise__c mer = new Merchandise__c();
mer.Name = 'Sample Product2';
mer.Price__c = 1000;
insert mer;

It appears to me that whether this means 1000 AUD or JPY totally depends on my current currency setting. So this result will vary depending on the user who runs the code. Is there a way I can make this more fixed?

Also, when I do a SOQL on these merchandises, it only tell me the price number, without the currency type. So I can't tell the difference between 100 AUD and 100 JPY based on the SOQL result. Is there a way I can query this?

Best Answer

The values in Apex are always the organization's default currency by default. This means that when you specify: mer.Price__c = 1000;, you're saying that the product's price is 1000 of whatever currency is the default for the organization. This means that you need to do some math if the values originate within Apex Code.

To do this, query the CurrencyType object for the ConversionRate where the IsoCode matches your intended currency (the CurrencyIsoCode field). If you use Dated Conversion Rates, you'll need to query the appropriate DatedConversionRate table instead. The system can't do this automatically because it doesn't know how to handle that on custom objects (you may as well call it unsupported, because it gets incredibly messy to try and figure this out in reporting).

This question gives some more concrete data to work with, but basically, as long as you're not using dated conversion rates, it's just:

SELECT Id, ConversionRate 
FROM CurrencyType 
WHERE IsoCode = :mer.CurrencyISOCode

If you want the results from a query to be in the user's currency, there is a SOQL option for that:

SELECT convertCurrency(Price__c)
FROM Merchandise__c
WHERE ...

This works in Apex Code. Please note that because of aliasing rules, you can't query the organization default value and the converted value in one query. This notation is also not supported in aggregate calls, such as GROUP BY, SUM, AVG, etc.

Note that values entered in through an apex:inputField should show the correct value to the user, but will internally be converted to the organization's default currency before your controller methods are called.

To specify the record's currency, use the CurrencyIsoCode field:

mer.CurrencyIsoCode = 'JPY';

Note that even though you put in some other currency, the value itself should still be in the corporate currency. The UI will translate the value for you automatically when displayed in reports and the UI, but not when using the Data Loader or Apex Code.

Related Topic