Multi Currency Exchange Blueprint
Manage exchange rates, perform multi-currency transactions, and revalue accounts for unrealized foreign exchange gains and losses
| Feature | multi-currency-exchange |
| Category | Payment |
| Version | 1.0.0 |
| Tags | multi-currency, exchange-rates, revaluation, forex, erp, accounting |
| YAML Source | View on GitHub |
| JSON API | multi-currency-exchange.json |
Fields
| Name | Type | Required | Label | Description |
|---|---|---|---|---|
from_currency | text | Yes | From Currency | Validations: pattern |
to_currency | text | Yes | To Currency | Validations: pattern |
exchange_rate | number | Yes | Exchange Rate | Validations: min |
date | date | Yes | Date | |
for_buying | boolean | No | For Buying | |
for_selling | boolean | No | For Selling | |
rounding_loss_allowance | number | No | Rounding Loss Allowance | Validations: min, max |
company | text | Yes | Company | Validations: minLength |
posting_date | date | Yes | Posting Date | |
accounts | json | No | Accounts | |
gain_loss_booked | number | No | Gain Loss Booked | |
gain_loss_unbooked | number | No | Gain Loss Unbooked |
Rules
- same_currency_rejected:
- description: From currency and to currency cannot be the same. Same-currency exchange rate entries are rejected.
- date_based_lookup:
- description: Exchange rates are fetched by date and currency pair. The most recent rate for the requested date is used.
- revaluation_journal:
- description: Revaluation creates journal entries for unrealized gain or loss on open foreign currency balances.
- zero_balance_exclusion:
- description: Zero-balance accounts in foreign currency are excluded from revaluation processing.
- rounding_loss:
- description: Rounding loss allowance must be between 0 and 1. Amounts within this threshold are written off automatically as rounding loss.
- direction_flags:
- description: Exchange rates can be flagged for buying, selling, or both directions. Separate rates may exist for each direction.
- fallback_rate:
- description: When no rate exists for the exact date, the most recent prior rate is used as a fallback.
- gain_loss_account:
- description: Revaluation gain or loss is posted to a designated exchange gain/loss account in the general ledger.
- reversal_on_rerun:
- description: Subsequent revaluations reverse previous unrealized entries before posting new ones to avoid double counting.
Outcomes
Fetch_exchange_rate (Priority: 10) — Error: EXCHANGE_RATE_NOT_FOUND
Given:
from_currencyexiststo_currencyexistsdateexists
Then:
- call_service target:
exchange_rate_provider— Fetch exchange rate for the currency pair on the specified date - emit_event event:
exchange_rate.updated
Result: Exchange rate is returned for the specified currency pair and date
Revalue_accounts (Priority: 11) — Error: REVALUATION_NO_ACCOUNTS
Given:
companyexistsposting_dateexists- at least one foreign currency account has a non-zero balance
Then:
- call_service target:
account_revaluation_engine— Calculate unrealized gain/loss for each open foreign currency account - set_field target:
accounts— Populated with account balances and calculated gain/loss per account - emit_event event:
revaluation.completed
Result: All open foreign currency accounts are revalued and gain/loss amounts calculated
Create_gain_loss_journal (Priority: 12) | Transaction: atomic
Given:
- revaluation has been completed with non-zero gain/loss amounts
accountsexists
Then:
- create_record target:
journal_entry— Create journal entry posting unrealized exchange gain or loss - set_field target:
gain_loss_booked— Set to total gain/loss from revaluation - emit_event event:
gain_loss.booked
Result: Journal entry is created for the unrealized exchange gain or loss and posted to the general ledger
Errors
| Code | Status | Message | Retry |
|---|---|---|---|
EXCHANGE_SAME_CURRENCY | 400 | Source and target currencies cannot be the same. | No |
EXCHANGE_RATE_NOT_FOUND | 404 | No exchange rate found for the specified currency pair and date. | No |
REVALUATION_NO_ACCOUNTS | 404 | No foreign currency accounts with open balances found for revaluation. | No |
Events
| Event | Description | Payload |
|---|---|---|
exchange_rate.updated | Exchange rate is fetched or manually updated for a currency pair | from_currency, to_currency, exchange_rate, date |
revaluation.completed | Account revaluation run completes for a company | company, posting_date, total_gain_loss, account_count |
gain_loss.booked | Journal entry for unrealized exchange gain/loss is posted | journal_entry_id, company, posting_date, gain_loss_booked |
Related Blueprints
| Feature | Relationship | Reason |
|---|---|---|
| general-ledger | required | Revaluation posts journal entries to the general ledger |
| sales-purchase-invoicing | recommended | Multi-currency invoices require exchange rate conversion |
AGI Readiness
Goals
Reliable Multi Currency Exchange
Manage exchange rates, perform multi-currency transactions, and revalue accounts for unrealized foreign exchange gains and losses
Success Metrics:
| Metric | Target | Measurement |
|---|---|---|
| policy_violation_rate | 0% | Operations that violate defined policies |
| audit_completeness | 100% | All decisions have complete audit trails |
Constraints:
- regulatory (non-negotiable): All operations must be auditable and traceable
Autonomy
Level: supervised
Human Checkpoints:
- before making irreversible changes
Escalation Triggers:
error_rate > 5consecutive_failures > 3
Verification
Invariants:
- error messages never expose internal system details
Tradeoffs
| Prefer | Over | Reason |
|---|---|---|
| accuracy | speed | financial transactions must be precise and auditable |
Coordination
Protocol: request_response
Consumes:
| Capability | From | Fallback |
|---|---|---|
general_ledger | general-ledger | fail |
Safety
| Action | Permission | Cooldown | Max Auto |
|---|---|---|---|
| fetch_exchange_rate | supervised | - | - |
| revalue_accounts | autonomous | - | - |
| create_gain_loss_journal | supervised | - | - |