I am facing an issue wherein our custom currency conversion is seemingly being short-circuited by the standard multi-currency functionality, but only sometimes. Our organization has multi-currency enabled, but because of the lack of dated exchange rates for custom objects, we have added a custom object Exchange_Rate__c that is populated daily by scheduled Apex, and we use triggers to apply conversions.
Background:
- Employees log client work by creating records of Work_Log__c, which has a lookup to Contact and a lookup to Project__c
- Before insert, a trigger populates Work_Log__c.Current_Salary__c from Contact.Monthly_Salary__c
- The Contact CurrencyIsoCode reflects the currency in which the employee is paid
- The same trigger populates Work_Log__c.Billing_Rate__c from Contact.Role__r.Default_Billing_Rate__c
- Each employee has a default hourly billing rate based on their role and location in the company, and these rates are stored in USD on the Role__c object (there is a lookup from Contact to Role__c)
- Client projects may be managed in any currency, and the salaries and billing rates must be converted on the fly as needed.
Scenario/Expected:
- An American employee logs work to an Indian project over the period of several weeks
- His monthly salary (say, $2000), stored in USD on his Contact, should be converted to INR according to the rate on the day the work was logged
- His default billing rate (say, $100), also stored in USD, should be converted to INR according to the rate on the day the work was logged
Result:
- The billing rate is being successfully converted. The INR value is slightly different on each work log, reflecting the drift in the USD-INR exchange rate that is captured in our custom object (currently 67.35)
- The monthly salary is converting according to the exchange rate stored in the standard CurrencyType object, which is outdated and remains at 66, so the value is the same for all days
Trigger flow for salary conversion (the same steps are working for billing rate):
- Set the work log currency to the project currency (INR in this example; the default work log currency is determined by the User currency, so can be expected to have been USD here)
- Stamp 2000 into the salary field
- Notice that source and destination currencies are different and, accordingly, multiply the field value by the must recent rate found in table Exchange_Rate__c (e.g. 67.35) to arrive at the INR value of 134,700 (a.k.a. 1,34,700 if you prefer lakh notation)
Clues:
- I implemented this conversion solution in phases, and for a couple of weeks I was aligning the work log currency with project currency without performing any conversion. The billing rate was being stamped incorrectly as 100 Rupees, and I would expect that the salary would have been stamped as 5,000 Rupees. However, the salary was being converted for those several weeks, like now according to the CurrencyType table. Seemingly something about that action of setting the work log currency is triggering a conversion to occur
- After we discovered this issue, we updated our test classes and added assert statements that specifically tested this outcome. Those test classes pass in sandbox (i.e. both billing rate and salary convert as expected) but fail in production (billing rate converts as expected, salary converts according to CurrencyType)