imp:print:beancount: remove redundant conversion postings automatically

This commit is contained in:
Simon Michael 2024-11-09 01:09:38 -10:00
parent d925c8a042
commit b4f4374dfa
3 changed files with 91 additions and 11 deletions

View File

@ -44,6 +44,7 @@ import Hledger.Cli.Utils
import Hledger.Cli.Anchor (setAccountAnchor) import Hledger.Cli.Anchor (setAccountAnchor)
import qualified Lucid import qualified Lucid
import qualified System.IO as IO import qualified System.IO as IO
import Data.Maybe (isJust)
printmode = hledgerCommandMode printmode = hledgerCommandMode
$(embedFileRelative "Hledger/Cli/Commands/Print.txt") $(embedFileRelative "Hledger/Cli/Commands/Print.txt")
@ -186,17 +187,33 @@ entriesReportAsTextHelper showtxn = TB.toLazyText . foldMap (TB.fromText . showt
entriesReportAsBeancount :: EntriesReport -> TL.Text entriesReportAsBeancount :: EntriesReport -> TL.Text
entriesReportAsBeancount ts = entriesReportAsBeancount ts =
-- PERF: gathers and converts all account names, then repeats that work when showing each transaction -- 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 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 opendirectives
| null ts = "" | null ts = ""
| otherwise = TL.fromStrict $ T.unlines [ | otherwise = TL.fromStrict $ T.unlines [
firstdate <> " open " <> accountNameToBeancount a firstdate <> " open " <> accountNameToBeancount a
| a <- nubSort $ concatMap (map paccount.tpostings) allrealts | a <- nubSort $ concatMap (map paccount.tpostings) ts3
] ]
where where
firstdate = showDate $ minimumDef err $ map tdate allrealts firstdate = showDate $ minimumDef err $ map tdate ts3
where err = error' "entriesReportAsBeancount: should not happen" where err = error' "entriesReportAsBeancount: should not happen"
entriesReportAsSql :: EntriesReport -> TL.Text entriesReportAsSql :: EntriesReport -> TL.Text

View File

@ -830,12 +830,14 @@ using various utilities like `libreoffice --headless` or
This is [Beancount's journal format][beancount journal]. This is [Beancount's journal format][beancount journal].
You can use this to export your hledger data to [Beancount], 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. perhaps to query it with [Beancount Query Language] or with the [Fava] web app.
hledger will try to adjust your data to suit Beancount. 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, You should be cautious and check the conversion carefully until you are confident it is good.
to ease conversion. Eg use Beancount-friendly account names, currency codes instead of currency symbols, If you plan to export to Beancount often, you may want to follow its conventions in your hledger data, to make conversion easier.
and avoid virtual postings, redundant cost notation, etc. 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>). Here are more details.
<!-- (see also "hledger and Beancount" <https://hledger.org/beancount.html>). -->
#### Beancount account names #### Beancount account names
@ -866,8 +868,9 @@ if you have any, they will not appear in beancount output.
#### Beancount costs #### Beancount costs
Beancount doesn't allow [redundant cost notation](https://hledger.org/hledger.html#combining-costs-and-equity-conversion-postings) Beancount doesn't allow [redundant costs and conversion postings](https://hledger.org/hledger.html#combining-costs-and-equity-conversion-postings) as hledger does.
as hledger does. If you have entries like this, you will need to comment out either the costs or the equity postings. 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 #### Beancount operating currency

View File

@ -59,3 +59,63 @@ $ hledger -f- print -O beancount
Assets:A 0 USD 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