Currencies and exchange rates
Every transaction in SavingStat stores two amounts, one per currency. Why both are kept, what that buys you, and where the exchange rates come from.
Every transaction has two amounts
A transaction in SavingStat records two amounts, not one. The first is what the thing cost, in the currency it was priced in: the figure on the receipt. The second is what actually left the wallet, in that wallet's own currency.
Most of the time the two currencies match, the amounts are identical, and you never think about them. When the currencies differ, the amounts are two genuinely different numbers, and SavingStat keeps both rather than picking one.
Why both amounts are kept
The pair is the record of the exchange rate that was actually applied. SavingStat stores it on the transaction rather than working it out on the way to the screen, so nothing restates last March's coffee at today's rate.
A rate service is consulted while you type, but only to offer you a number. Enter or edit a transaction in a currency other than the wallet's and the rate for that date is fetched and shown greyed out in the wallet-amount field, as a suggestion rather than an entry. Type your own figure and yours is what is saved. Leave the field empty and the suggestion is used instead.
That matters because the figure your bank booked is rarely the figure a rate table would produce: the bank's own spread is inside it. When a statement says what it charged the account, an import keeps that number rather than reconverting the price, because no rate looked up afterwards would reproduce it.
The wallet amount is also the one that moves your balance, so it has to be exact rather than recomputed. Keep only the price and the balance becomes an estimate; keep only what left the wallet and you have lost what the thing cost.
Where exchange rates come from
SavingStat looks a rate up where a conversion is genuinely needed, when a month of mixed-currency spending is totalled into one figure, for instance. Rates are stored per base currency, target currency and date, so each one is tied to the day it belongs to rather than to now.
Rates come from an external rate service, fetched on demand rather than on a schedule: the first time a pair and date is wanted the rate is fetched and kept, and every later use reads the stored one. Nothing refreshes rates in the background, so a rate stamped with today's date is whatever the service first returned that day.
If a rate cannot be had at all, none is guessed. The amount is carried across as it stands, as though the two currencies had been the same. Where that happens on an import you are told, because the draft's comment picks up a note saying the wallet amount needs review. Where it happens inside a total assembled later there is no note, and the figure simply reads a little low or a little high with nothing on the page to say why.
Currencies on imported rows
Import a statement into a wallet whose currency is not the statement's and both amounts are filled in for you. The first takes whatever the statement shows. The second is always in the wallet's own currency, and it is never relabelled to match the file, however the file is denominated.
Which number fills the wallet side depends on what the statement offers. If the statement says what it booked to the account, that figure is used as it stands, spread and all. Otherwise the amount is converted at the rate for that row's own date, and failing that it is carried across unchanged, with a note appended to the draft's comment saying the wallet amount needs review. Fix it before you publish.