Add exchange rate feature with multi-currency transactions and transfers support (#1099)

Co-authored-by: Pedro J. Aramburu <pedro@joakin.dev>
This commit is contained in:
Pedro J. Aramburu
2026-04-08 21:05:58 +02:00
committed by GitHub
co-authored by Pedro J. Aramburu
parent 8e81e967fc
commit f699660479
48 changed files with 1886 additions and 73 deletions
+12 -4
View File
@@ -1,10 +1,18 @@
class Transfer::Creator
def initialize(family:, source_account_id:, destination_account_id:, date:, amount:)
def initialize(family:, source_account_id:, destination_account_id:, date:, amount:, exchange_rate: nil)
@family = family
@source_account = family.accounts.find(source_account_id) # early throw if not found
@destination_account = family.accounts.find(destination_account_id) # early throw if not found
@date = date
@amount = amount.to_d
if exchange_rate.present?
rate_value = exchange_rate.to_d
raise ArgumentError, "exchange_rate must be greater than 0" unless rate_value > 0
@exchange_rate = rate_value
else
@exchange_rate = nil
end
end
def create
@@ -23,7 +31,7 @@ class Transfer::Creator
end
private
attr_reader :family, :source_account, :destination_account, :date, :amount
attr_reader :family, :source_account, :destination_account, :date, :amount, :exchange_rate
def outflow_transaction
name = "#{name_prefix} to #{destination_account.name}"
@@ -62,13 +70,13 @@ class Transfer::Creator
end
# If destination account has different currency, its transaction should show up as converted
# Future improvement: instead of a 1:1 conversion fallback, add a UI/UX flow for missing rates
# Uses user-provided exchange rate if available, otherwise requires a provider rate
def inflow_converted_money
Money.new(amount.abs, source_account.currency)
.exchange_to(
destination_account.currency,
date: date,
fallback_rate: 1.0
custom_rate: exchange_rate
)
end