From 797dcd9771e5a1c77a02a029521ff4a532a4385d Mon Sep 17 00:00:00 2001 From: Michael Manganiello Date: Thu, 18 Jan 2024 09:37:07 -0300 Subject: [PATCH] fix: Consider all amounts in multi-currency postings For a transaction like: ```ledger 2024/01/01 Cash transfer Assets:Savings Assets:Checking -20,000 INR Assets:Checking -500 USD ``` The posting returned by `hledger` will have a list of two amounts in the JSON key `pamount`, for the `Assets:Savings` account. Currently, we are only consider the first one we find, so the one for USD is ignored. This change iterates over all the received amounts for each posting, to avoid incorrect calculations when this type of transactions are present. --- internal/ledger/ledger.go | 109 +++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/internal/ledger/ledger.go b/internal/ledger/ledger.go index 578a193e..b46c5d0c 100644 --- a/internal/ledger/ledger.go +++ b/internal/ledger/ledger.go @@ -787,41 +787,6 @@ func execHLedgerCommand(journalPath string, prices []price.Price, flags []string if len(p.Amount) == 0 { continue } - amount := p.Amount[0] - totalAmount := decimal.NewFromFloat(amount.Quantity.Value) - totalAmountSet := false - - if amount.Commodity != config.DefaultCurrency() { - if amount.Price.Contents.Quantity.Value != 0 { - var unconvertedTotal decimal.Decimal - if amount.Price.Tag == "TotalPrice" { - unconvertedTotal = decimal.NewFromFloat(amount.Price.Contents.Quantity.Value) - } else { - unconvertedTotal = decimal.NewFromFloat(amount.Price.Contents.Quantity.Value).Mul(decimal.NewFromFloat(amount.Quantity.Value)) - } - - if amount.Price.Contents.Commodity != config.DefaultCurrency() { - pr := lookupPrice(pricesTree, amount.Commodity, date) - if !pr.Equal(decimal.Zero) { - totalAmount = decimal.NewFromFloat(amount.Quantity.Value).Mul(pr) - totalAmountSet = true - } - if !totalAmountSet { - pr = lookupPrice(pricesTree, amount.Price.Contents.Commodity, date) - if !pr.Equal(decimal.Zero) { - totalAmount = unconvertedTotal.Mul(pr) - } - } - } else { - totalAmount = unconvertedTotal - } - } else { - pr := lookupPrice(pricesTree, amount.Commodity, date) - if !pr.Equal(decimal.Zero) { - totalAmount = decimal.NewFromFloat(amount.Quantity.Value).Mul(pr) - } - } - } var tagRecurring, tagPeriod string @@ -859,30 +824,64 @@ func execHLedgerCommand(journalPath string, prices []price.Price, flags []string if err != nil { return nil, err } - } - posting := posting.Posting{ - Date: date, - Payee: t.Description, - Account: p.Account, - Commodity: amount.Commodity, - Quantity: decimal.NewFromFloat(amount.Quantity.Value), - Amount: totalAmount, - TransactionID: strconv.FormatInt(t.ID, 10), - Status: strings.ToLower(t.Status), - TagRecurring: tagRecurring, - TagPeriod: tagPeriod, - TransactionBeginLine: t.TSourcePos[0].SourceLine, - TransactionEndLine: t.TSourcePos[1].SourceLine, - Forecast: forecast, - FileName: fileName, - Note: p.Comment, - TransactionNote: t.Comment} - postings = append(postings, &posting) + for _, amount := range p.Amount { + totalAmount := decimal.NewFromFloat(amount.Quantity.Value) + totalAmountSet := false + + if amount.Commodity != config.DefaultCurrency() { + if amount.Price.Contents.Quantity.Value != 0 { + var unconvertedTotal decimal.Decimal + if amount.Price.Tag == "TotalPrice" { + unconvertedTotal = decimal.NewFromFloat(amount.Price.Contents.Quantity.Value) + } else { + unconvertedTotal = decimal.NewFromFloat(amount.Price.Contents.Quantity.Value).Mul(decimal.NewFromFloat(amount.Quantity.Value)) + } - } + if amount.Price.Contents.Commodity != config.DefaultCurrency() { + pr := lookupPrice(pricesTree, amount.Commodity, date) + if !pr.Equal(decimal.Zero) { + totalAmount = decimal.NewFromFloat(amount.Quantity.Value).Mul(pr) + totalAmountSet = true + } + if !totalAmountSet { + pr = lookupPrice(pricesTree, amount.Price.Contents.Commodity, date) + if !pr.Equal(decimal.Zero) { + totalAmount = unconvertedTotal.Mul(pr) + } + } + } else { + totalAmount = unconvertedTotal + } + } else { + pr := lookupPrice(pricesTree, amount.Commodity, date) + if !pr.Equal(decimal.Zero) { + totalAmount = decimal.NewFromFloat(amount.Quantity.Value).Mul(pr) + } + } + } + posting := posting.Posting{ + Date: date, + Payee: t.Description, + Account: p.Account, + Commodity: amount.Commodity, + Quantity: decimal.NewFromFloat(amount.Quantity.Value), + Amount: totalAmount, + TransactionID: strconv.FormatInt(t.ID, 10), + Status: strings.ToLower(t.Status), + TagRecurring: tagRecurring, + TagPeriod: tagPeriod, + TransactionBeginLine: t.TSourcePos[0].SourceLine, + TransactionEndLine: t.TSourcePos[1].SourceLine, + Forecast: forecast, + FileName: fileName, + Note: p.Comment, + TransactionNote: t.Comment} + postings = append(postings, &posting) + } + } } return postings, nil