Skip to content

Commit

Permalink
imp:print:beancount: remove redundant conversion postings automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
simonmichael committed Nov 9, 2024
1 parent d02ca4b commit f8e6b49
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 11 deletions.
25 changes: 21 additions & 4 deletions hledger/Hledger/Cli/Commands/Print.hs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import Hledger.Cli.Utils
import Hledger.Cli.Anchor (setAccountAnchor)
import qualified Lucid
import qualified System.IO as IO
import Data.Maybe (isJust)

printmode = hledgerCommandMode
$(embedFileRelative "Hledger/Cli/Commands/Print.txt")
Expand Down Expand Up @@ -186,17 +187,33 @@ entriesReportAsTextHelper showtxn = TB.toLazyText . foldMap (TB.fromText . showt
entriesReportAsBeancount :: EntriesReport -> TL.Text
entriesReportAsBeancount ts =
-- PERF: gathers and converts all account names, then repeats that work when showing each transaction
opendirectives <> "\n" <> entriesReportAsTextHelper showTransactionBeancount allrealts
opendirectives <> "\n" <> entriesReportAsTextHelper showTransactionBeancount ts3
where
allrealts = [t{tpostings=filter isReal $ tpostings t} | t <- ts]
-- Remove any virtual postings.
ts2 = [t{tpostings=filter isReal $ tpostings t} | t <- ts]

-- Remove any conversion postings that are redundant with costs.
-- It would be easier to remove the costs instead,
-- but those are more useful to Beancount than conversion postings.
ts3 =
[ t{tpostings=filter (not . isredundantconvp) $ tpostings t}
| t <- ts2
-- XXX But how to do it ? conversion-posting tag is on non-redundant postings too.
-- Assume the simple case of no more than one cost + conversion posting group in each transaction.
-- Actually that seems to be required by hledger right now.
, let isredundantconvp p =
matchesPosting (Tag (toRegex' "conversion-posting") Nothing) p
&& any (any (isJust.acost) . amounts . pamount) (tpostings t)
]

opendirectives
| null ts = ""
| otherwise = TL.fromStrict $ T.unlines [
firstdate <> " open " <> accountNameToBeancount a
| a <- nubSort $ concatMap (map paccount.tpostings) allrealts
| a <- nubSort $ concatMap (map paccount.tpostings) ts3
]
where
firstdate = showDate $ minimumDef err $ map tdate allrealts
firstdate = showDate $ minimumDef err $ map tdate ts3
where err = error' "entriesReportAsBeancount: should not happen"

entriesReportAsSql :: EntriesReport -> TL.Text
Expand Down
17 changes: 10 additions & 7 deletions hledger/hledger.m4.md
Original file line number Diff line number Diff line change
Expand Up @@ -830,12 +830,14 @@ using various utilities like `libreoffice --headless` or
This is [Beancount's journal format][beancount journal].
You can use this to export your hledger data to [Beancount],
perhaps to query it with [Beancount Query Language] or with the [Fava] web app.

hledger will try to adjust your data to suit Beancount.
If you plan to export often, you may want to follow Beancount's conventions in your hledger data,
to ease conversion. Eg use Beancount-friendly account names, currency codes instead of currency symbols,
and avoid virtual postings, redundant cost notation, etc.
Here are more details
(see also "hledger and Beancount" <https://hledger.org/beancount.html>).
You should be cautious and check the conversion carefully until you are confident it is good.
If you plan to export to Beancount often, you may want to follow its conventions in your hledger data, to make conversion easier.
Eg use Beancount-friendly account names, currency codes instead of currency symbols, costs instead of equity conversion postings, no virtual postings, etc.

Here are more details.
<!-- (see also "hledger and Beancount" <https://hledger.org/beancount.html>). -->

#### Beancount account names

Expand Down Expand Up @@ -866,8 +868,9 @@ if you have any, they will not appear in beancount output.

#### Beancount costs

Beancount doesn't allow [redundant cost notation](https://hledger.org/hledger.html#combining-costs-and-equity-conversion-postings)
as hledger does. If you have entries like this, you will need to comment out either the costs or the equity postings.
Beancount doesn't allow [redundant costs and conversion postings](https://hledger.org/hledger.html#combining-costs-and-equity-conversion-postings) as hledger does.
If you have entries like this, the conversion postings will be dropped.
Currently we support at most one cost + conversion postings group per transaction.

#### Beancount operating currency

Expand Down
60 changes: 60 additions & 0 deletions hledger/test/print/beancount.test
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,63 @@ $ hledger -f- print -O beancount
Assets:A 0 USD

>=

# ** 5. Conversion postings that are not redundant are preserved.
# If the accounts are named after currency symbols, they will look strange.
# (A better conversion would be this, but it seems hard to automate:
# Equity:Conversion:EUR-USD:USD, Equity:Conversion:EUR-USD:EUR.)
<
2000-01-01
Assets $1
equity:conversion:€-$:$ -$1
equity:conversion:€-$:€ €1
Assets €-1

$ hledger -f- print -O beancount
2000-01-01 open Assets:A
2000-01-01 open Equity:Conversion:C20ac-C24:C24
2000-01-01 open Equity:Conversion:C20ac-C24:C20ac

2000-01-01 *
Assets:A 1 USD
Equity:Conversion:C20ac-C24:C24 -1 USD
Equity:Conversion:C20ac-C24:C20ac 1 EUR
Assets:A -1 EUR

>=

# ** 6. Conversion postings that are redundant with costs are dropped.
<
2000-01-01
Assets $1 @@ €1
equity:conversion:€-$:$ -$1
equity:conversion:€-$:€ €1
Assets €-1

$ hledger -f- print -O beancount
2000-01-01 open Assets:A

2000-01-01 *
Assets:A 1 USD @@ 1 EUR
Assets:A -1 EUR

>=

# ** 7. Multiple cost/conversion groups within a transaction are not supported
# (by hledger generally, apparently ?)
<
2000-01-01
Assets $1 @@ €1
equity:conversion:€-$:$ -$1
equity:conversion:€-$:€ €1
Assets €-1
;
Assets A1 @@ B1
equity:conversion:€-$:$ -A1
equity:conversion:€-$:€ B1
Assets B-1

$ hledger -f- print -O beancount
>2 /unbalanced/
>=1

0 comments on commit f8e6b49

Please sign in to comment.