2016-06-30 01:01:24 +03:00
|
|
|
#!/usr/bin/env stack
|
|
|
|
{- stack runghc --verbosity info
|
|
|
|
--package hledger-lib
|
|
|
|
--package hledger
|
2017-01-23 17:17:17 +03:00
|
|
|
--package here
|
2016-06-30 01:01:24 +03:00
|
|
|
--package time
|
|
|
|
-}
|
2017-01-08 21:24:33 +03:00
|
|
|
|
2017-01-23 17:17:17 +03:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
{-# LANGUAGE QuasiQuotes #-}
|
|
|
|
|
|
|
|
import Data.Maybe
|
|
|
|
import Data.String.Here
|
|
|
|
import Data.Time.Calendar
|
|
|
|
import Hledger.Cli
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------
|
2017-01-24 19:59:22 +03:00
|
|
|
cmdmode :: Mode RawOpts
|
|
|
|
cmdmode = (defAddonCommandMode "equity") {
|
|
|
|
modeHelp = [here|
|
2017-01-25 01:58:48 +03:00
|
|
|
|
2017-01-24 19:59:22 +03:00
|
|
|
Print a "closing balances" transaction that brings all accounts (or with
|
|
|
|
query arguments, just the matched accounts) to a zero balance, followed by an
|
|
|
|
opposite "opening balances" transaction that restores the balances from zero.
|
|
|
|
Such transactions can be useful, eg, for bringing account balances across
|
|
|
|
file boundaries.
|
2017-01-25 01:58:48 +03:00
|
|
|
|
2017-01-24 19:59:22 +03:00
|
|
|
|]
|
|
|
|
,modeHelpSuffix=lines [here|
|
2017-01-25 01:58:48 +03:00
|
|
|
|
2016-06-30 01:01:24 +03:00
|
|
|
The opening balances transaction is useful to carry over
|
|
|
|
asset/liability balances if you choose to start a new journal file,
|
|
|
|
eg at the beginning of the year.
|
|
|
|
|
|
|
|
The closing balances transaction is useful to zero out balances in
|
|
|
|
the old file, which gives you the option of reporting on both files
|
|
|
|
at once while still seeing correct balances.
|
2013-09-20 20:38:54 +04:00
|
|
|
|
2016-06-30 01:01:24 +03:00
|
|
|
Balances are calculated, and the opening transaction is dated, as of
|
|
|
|
the report end date, which you should specify with -e or date: (and
|
|
|
|
the closing transaction is dated one day earlier). If a report end
|
|
|
|
date is not specified, it defaults to today.
|
2013-09-20 20:38:54 +04:00
|
|
|
|
2016-06-30 01:01:24 +03:00
|
|
|
Example:
|
2017-01-25 01:58:48 +03:00
|
|
|
```shell
|
2016-06-30 01:01:24 +03:00
|
|
|
$ hledger equity -f 2015.journal -e 2016/1/1 assets liabilities >>2015.journal
|
2017-01-25 01:58:48 +03:00
|
|
|
# move the opening balances transaction to 2016.journal
|
|
|
|
$ hledger -f 2015.journal bal assets liabilities not:desc:closing # shows correct 2015 balances
|
|
|
|
$ hledger -f 2016.journal bal assets liabilities # shows correct 2016 balances
|
|
|
|
$ hledger -f 2015.journal -f 2016.journal bal assets liabilities # still shows correct 2016 balances
|
2017-01-23 17:17:17 +03:00
|
|
|
```
|
2016-06-30 01:01:24 +03:00
|
|
|
Open question: how to handle txns spanning a file boundary ? Eg:
|
2017-01-23 17:17:17 +03:00
|
|
|
```journal
|
2016-06-30 01:01:24 +03:00
|
|
|
2015/12/30 * food
|
|
|
|
expenses:food:dining $10
|
|
|
|
assets:bank:checking -$10 ; date:2016/1/4
|
2017-01-23 17:17:17 +03:00
|
|
|
```
|
|
|
|
This command might or might not have some connection to the concept of
|
2016-06-30 01:01:24 +03:00
|
|
|
"closing the books" in accounting.
|
2017-01-25 01:58:48 +03:00
|
|
|
|
2017-01-24 19:59:22 +03:00
|
|
|
|]
|
2017-01-23 17:17:17 +03:00
|
|
|
,modeArgs = ([], Just $ argsFlag "[QUERY]")
|
|
|
|
}
|
2017-01-24 19:59:22 +03:00
|
|
|
------------------------------------------------------------------------------
|
2014-04-14 23:03:52 +04:00
|
|
|
|
|
|
|
main :: IO ()
|
2013-09-20 20:38:54 +04:00
|
|
|
main = do
|
2017-01-24 19:59:22 +03:00
|
|
|
opts <- getHledgerCliOpts cmdmode
|
2014-04-14 23:03:52 +04:00
|
|
|
withJournalDo opts $
|
|
|
|
\CliOpts{reportopts_=ropts} j -> do
|
2014-07-15 18:02:14 +04:00
|
|
|
today <- getCurrentDay
|
2015-05-25 18:39:50 +03:00
|
|
|
let ropts_ = ropts{accountlistmode_=ALFlat}
|
2014-07-15 18:02:14 +04:00
|
|
|
q = queryFromOpts today ropts_
|
|
|
|
(acctbals,_) = balanceReport ropts_ q j
|
2017-01-11 18:53:01 +03:00
|
|
|
balancingamt = negate $ sum $ map (\(_,_,_,b) -> normaliseMixedAmountSquashPricesForDisplay b) acctbals
|
2017-01-26 00:56:10 +03:00
|
|
|
ps = [posting{paccount=a
|
|
|
|
,pamount=mixed [b]
|
|
|
|
,pbalanceassertion=Just b
|
|
|
|
}
|
|
|
|
|(a,_,_,mb) <- acctbals
|
|
|
|
,b <- amounts $ normaliseMixedAmountSquashPricesForDisplay mb
|
|
|
|
]
|
2014-04-14 23:03:52 +04:00
|
|
|
++ [posting{paccount="equity:opening balances", pamount=balancingamt}]
|
2014-07-15 18:02:14 +04:00
|
|
|
enddate = fromMaybe today $ queryEndDate (date2_ ropts_) q
|
2017-01-26 00:56:10 +03:00
|
|
|
nps = [posting{paccount=a
|
|
|
|
,pamount=mixed [negate b]
|
|
|
|
,pbalanceassertion=Just b{aquantity=0}
|
|
|
|
}
|
|
|
|
|(a,_,_,mb) <- acctbals
|
|
|
|
,b <- amounts $ normaliseMixedAmountSquashPricesForDisplay mb
|
|
|
|
]
|
2014-07-24 04:16:13 +04:00
|
|
|
++ [posting{paccount="equity:closing balances", pamount=negate balancingamt}]
|
2016-06-30 01:01:24 +03:00
|
|
|
putStr $ showTransaction (nulltransaction{tdate=addDays (-1) enddate, tdescription="closing balances", tpostings=nps})
|
|
|
|
putStr $ showTransaction (nulltransaction{tdate=enddate, tdescription="opening balances", tpostings=ps})
|