TheInfiniteKind / moneydance_open

17 stars 12 forks source link

Incorrect Foreign Amt in OFX import #68

Open jameslarus opened 2 years ago

jameslarus commented 2 years ago

In a credit card account in a non-base currency, importing a card transaction from an OFX file creates an MD transaction with the correct parent amount, but with a "Rate" 100x the correct rate between the card currency and the base currency and a "Foreign Amt" 100x the correct rate.

Attached is an example, with the .ofx extension renamed to .txt to satisfy GitHub: example-cc-trans.txt .

(Need CC account in foreign (non-base) currency. The charge is 101.01 in this currency.)

jameslarus commented 2 years ago

This is caused by a bug in TxnUtil.setRatesInTxn. This method is only called by OnlineTxnMerger. It adjusts the split amount after it changes the category of a split. Most of the time, this is a nop. But if the new category uses a different currency, so the rate needs to be changed, the calculation is wrong (too high by a factor of 100).

The bug is that setRatesInTxn calls the deprecated two-argument version of SplitTxn.setAmount:

         for(int i = 0; i < ptxn.getSplitCount(); ++i) {
            SplitTxn split = ptxn.getSplit(i);
            split.setAmount(CurrencyUtil.convertValue(-split.getParentAmount(), ptxn.getAccount().getCurrencyType(), split.getAccount().getCurrencyType(), ptxn.getDateInt()),
                                       -split.getParentAmount());
         }

This function passes in 1.0 is the rate to the 3 argument version of setAmount, which (re)computes the rate incorrectly.

The fix is to use the three-argument version of setAmount in setRatesInTxn:

    for(int i = 0; i < ptxn.getSplitCount(); ++i) {
            SplitTxn split = ptxn.getSplit(i);
            CurrencyType parentCurrency = ptxn.getAccount().getCurrencyType();
            CurrencyType splitCurrency = split.getAccount().getCurrencyType();
            double rate = parentCurrency.getRate(splitCurrency, ptxn.getDateInt());
            split.setAmount(CurrencyUtil.convertValue(-split.getParentAmount(), parentCurrency, splitCurrency, ptxn.getDateInt()), 
                           rate,
                            -split.getParentAmount());
         }
sreilly commented 2 years ago

Just an update that I haven't included this code in a recent update because it reverses the amounts for downloaded transactions in credit card (and possibly other) accounts. I'm not seeing the error you're describing, but I will get back to this.