SfSkills Domains Docs GitHub

Home / data / multi-currency-and-advanced-currency-management

multi-currency-and-advanced-currency-management

Use when designing or reviewing Salesforce multi-currency behavior, especially irreversible activation, `CurrencyIsoCode`, `convertCurrency()`, dated exchange rates, and Advanced Currency Management tradeoffs.

Open the skill folder on GitHub


Multi Currency And Advanced Currency Management

Use this skill when currency is no longer just a formatting concern. Multi-currency and Advanced Currency Management (ACM) change how data is stored, queried, reported, and explained to the business. The design rule: keep every amount next to its currency, and convert only where the consumer asked for a converted value.


Before Starting

Gather this context before working on anything in this domain:


Questions to Ask Before Configuring

QuestionWhy it mattersWhat a good answer addsWhat proper configuration adds over just doing it
"Have the sponsors signed off that turning on multiple currencies is permanent?"The Metadata API says enableMultiCurrency "can't be set to false" after it is set to trueA recorded decision and a full sandbox rehearsal before productionNo surprise one-way change to every record's data model
"Which amounts need historical rates, and on which objects?"The SOQL guide says ACM dated rates apply to opportunities, opportunity line items, and opportunity history; other currency fields use the static rateA list of reports that will change meaning under ACM, and those that will notFinance knows which numbers are dated and which are not
"Who loads exchange rates, how often, and through which API?"CurrencyType and DatedConversionRate do not support Apex DML; rates come in through the API or SetupA named owner and an API-only job for rate loadsRates that stay current without a manual Setup task
"Do integrations send the ISO code with every amount?"CurrencyIsoCode exists only in multi-currency orgs and the stored amount is in that currencyA payload contract of amount plus ISO codeDownstream systems stop guessing the currency
"Do any queries total money with GROUP BY?"Aggregates with GROUP BY or HAVING return the org's default currency, and convertCurrency() cannot wrap themReports or code that label totals as corporate currencyTotals that match what users expect to see
"Does code need to run in single-currency orgs too?"Static SOQL naming CurrencyIsoCode or CurrencyType assumes multi-currencyA UserInfo.isMultiCurrencyOrganization() guard and dynamic SOQLPackages and shared code that install in any org

What a proper configuration adds over just ticking the box: the irreversible switch is rehearsed, every amount travels with its ISO code, the team knows exactly which reports use dated rates, and rate loads are an owned, automated job.


Core Concepts

Enabling multi-currency is one-way

CurrencySettings (Metadata API, Currency.settings) holds enableMultiCurrency, enableCurrencyEffectiveDates, enableCurrencySymbolWithMultiCurrency, and isParenCurrencyConvDisabled. After enableMultiCurrency is true it cannot be set to false. enableCurrencyEffectiveDates (ACM) requires enableMultiCurrency.

Where currency lives

Object or fieldWhat it holdsWritable how
CurrencyIsoCode on recordsThe record's currency; available only in multi-currency orgsNormal DML
CurrencyTypeOne row per currency: IsoCode, ConversionRate against the corporate currency, DecimalPlaces, IsActive, IsCorporateAPI create() and update(); no Apex DML; cannot be deleted
DatedConversionRateRate per currency per date range: IsoCode, ConversionRate, StartDate, read-only NextStartDateAPI update() and delete() listed in the Object Reference; no Apex DML; exists only with ACM

When updating a CurrencyType record, send every field. The Object Reference warns that a missing IsActive defaults to false and can deactivate an active currency.

convertCurrency() rules

ACM scope

ACM adds a time dimension only where the SOQL guide says dated rates apply. Everything else keeps converting at the static CurrencyType rate. UNVERIFIED (2026-10-03): the help-only statements about ACM and roll-up summary fields on Account; help.salesforce.com does not return article text to a fetch, so test roll-ups in a sandbox before enabling ACM.


Common Patterns

Currency-aware query

Query CurrencyIsoCode with every amount you expose. Use convertCurrency() only when the requirement is the viewer's currency. Example with a test class in references/examples.md.

Code that runs in any org

Guard with UserInfo.isMultiCurrencyOrganization() and build the field list dynamically. UserInfo.getDefaultCurrency() returns the user's currency in a multi-currency org and the org currency in a single-currency org.

Rate loads from finance

An API-only integration user updates CurrencyType (static rates) or DatedConversionRate (ACM rates) on a schedule. Apex cannot do this with DML.

Integration DTO with currency context

Send amount and ISO code together. Never send a bare decimal.


Decision Guidance

SituationRecommended ApproachReason
Org needs multiple transactional currenciesMulti-currency, after a rehearsalOne-way switch
Historical opportunity reporting needs period ratesACMDated rates apply to opportunity, line item, and history amounts
Historical rates needed on a custom objectStore the rate or converted amount on the recordDated rates do not apply outside the opportunity family
Apex exposes money values externallyInclude CurrencyIsoCode with the amountPrevents silent interpretation errors
Filter by amount across currenciesISO-prefixed literal in WHEREconvertCurrency() is not allowed in WHERE
Total money in SOQLLabel the result as corporate currencyAggregates return the org default currency
Change exchange rates from ApexDo not; use the API from an integrationNo DML on CurrencyType or DatedConversionRate

  1. Inventory currency consumers. List reports, forecasts, roll-ups, Apex, integrations, and analytics that read money.
  2. Decide the switch. If multi-currency is not enabled, run it in a full sandbox, review the inventory, and record sign-off that it is permanent.
  3. Scope ACM. Mark which consumers use opportunity-family amounts (dated) and which use static rates.
  4. Fix the code. Add CurrencyIsoCode next to amounts, remove convertCurrency() from WHERE and ORDER BY, guard shared code with isMultiCurrencyOrganization(), and run python3 scripts/check_multi_currency_and_advanced_currency_management.py --manifest-dir force-app.
  5. Automate rate loads. Build the API job that updates CurrencyType or DatedConversionRate, sending all fields on CurrencyType updates.
  6. Deploy settings and verify. Deploy Currency.settings from references/metadata-examples.md and check converted amounts in a report and in SOQL for a known record.

Review Checklist


Salesforce-Specific Gotchas

See references/gotchas.md. The two that cause the most rework: a CurrencyType update that omits IsActive deactivates the currency, and aggregates return the corporate currency no matter who runs the query.


Output Artifacts

ArtifactDescription
Currency design reviewFindings on activation, conversion, reporting, and Apex handling
Query guidanceStored-currency versus converted-currency retrieval per consumer
ACM decisionWhich amounts get dated rates and which do not
Currency.settings and rate-load jobDeployable settings and the API job for rates

Package files