;close: refactor (#1165)

This commit is contained in:
Simon Michael 2020-01-22 08:26:39 -08:00
parent 42840dd4c2
commit aa8c18fcc8

View File

@ -38,94 +38,88 @@ closemode = hledgerCommandMode
close CliOpts{rawopts_=rawopts, reportopts_=ropts} j = do close CliOpts{rawopts_=rawopts, reportopts_=ropts} j = do
today <- getCurrentDay today <- getCurrentDay
let let
-- interleave equity postings next to the corresponding closing posting, or put them all at the end ? -- show opening entry, closing entry, or (default) both ?
interleaved = boolopt "interleaved" rawopts
(opening, closing) = (opening, closing) =
case (boolopt "opening" rawopts, boolopt "closing" rawopts) of case (boolopt "opening" rawopts, boolopt "closing" rawopts) of
(False, False) -> (True, True) -- by default show both opening and closing (False, False) -> (True, True)
(o, c) -> (o, c) (o, c) -> (o, c)
-- accounts to close to and open from
closingacct = T.pack $ fromMaybe defclosingacct $ maybestringopt "close-to" rawopts closingacct = T.pack $ fromMaybe defclosingacct $ maybestringopt "close-to" rawopts
openingacct = T.pack $ fromMaybe defopeningacct $ maybestringopt "open-from" rawopts openingacct = T.pack $ fromMaybe defopeningacct $ maybestringopt "open-from" rawopts
-- interleave equity postings next to the corresponding closing posting, or put them all at the end ?
interleaved = boolopt "interleaved" rawopts
-- since balance assertion amounts are required to be exact, the
-- amounts in opening/closing transactions should be too (#941, #1137)
precise = setFullPrecision
-- dates of the closing and opening transactions
ropts_ = ropts{balancetype_=HistoricalBalance, accountlistmode_=ALFlat} ropts_ = ropts{balancetype_=HistoricalBalance, accountlistmode_=ALFlat}
q = queryFromOpts today ropts_ q = queryFromOpts today ropts_
openingdate = fromMaybe today $ queryEndDate False q openingdate = fromMaybe today $ queryEndDate False q
closingdate = addDays (-1) openingdate closingdate = addDays (-1) openingdate
(acctbals,_) = balanceReportFromMultiBalanceReport ropts_ q j
totalbalancingamt = sum $ map (\(_,_,_,b) -> normaliseMixedAmount b) acctbals
-- since balance assertion amounts are required to be exact, the -- the balances to close
-- amounts in opening/closing transactions should be too (#941, #1137) (acctbals,_) = balanceReportFromMultiBalanceReport ropts_ q j
setprec = setFullPrecision totalamt = sum $ map (\(_,_,_,b) -> normaliseMixedAmount b) acctbals
closingps = concat
[[posting{paccount = a -- the closing transaction
,pamount = mixed [setprec $ negate b] closingtxn = nulltransaction{tdate=closingdate, tdescription="closing balances", tpostings=closingps}
closingps =
concat [
[posting{paccount = a
,pamount = mixed [precise $ negate b]
-- after each commodity's last posting, assert 0 balance (#1035) -- after each commodity's last posting, assert 0 balance (#1035)
-- balance assertion amounts are unpriced (#824) -- balance assertion amounts are unpriced (#824)
,pbalanceassertion = ,pbalanceassertion =
if islast if islast
then Just nullassertion{baamount=setprec b{aquantity=0, aprice=Nothing}} then Just nullassertion{baamount=precise b{aquantity=0, aprice=Nothing}}
else Nothing else Nothing
} }
] ++
if interleaved then
-- a corresponding posting transferring the above balance to equity
[posting{paccount = closingacct
,pamount = Mixed [setprec b]
}
] ]
else [] -- maybe an interleaved posting transferring this balance to equity
| (a,_,_,mb) <- acctbals ++ [posting{paccount=closingacct, pamount=Mixed [precise b]} | interleaved]
-- the balances in each commodity, and for each transaction price
| -- get the balances for each commodity and transaction price
(a,_,_,mb) <- acctbals
, let bs = amounts $ normaliseMixedAmount mb , let bs = amounts $ normaliseMixedAmount mb
-- mark the last balance in each commodity -- mark the last balance in each commodity with True
, let bs' = concat [reverse $ zip (reverse bs) (True : repeat False) , let bs' = concat [reverse $ zip (reverse bs) (True : repeat False)
| bs <- groupBy ((==) `on` acommodity) bs] | bs <- groupBy ((==) `on` acommodity) bs]
, (b, islast) <- bs' , (b, islast) <- bs'
] ]
++
if interleaved then []
else
-- a final posting transferring all the balances to equity
-- (print will show it as multiple single-commodity postings)
[posting{paccount = closingacct
,pamount = mapMixedAmount setprec totalbalancingamt
}
]
openingps = concat -- or a final multicommodity posting transferring all balances to equity
[[posting{paccount = a -- (print will show this as multiple single-commodity postings)
,pamount = mixed [setprec b] ++ [posting{paccount=closingacct, pamount=mapMixedAmount precise totalamt} | not interleaved]
,pbalanceassertion = case mcommoditysum of
Just s -> Just nullassertion{baamount=setprec s{aprice=Nothing}} -- the opening transaction
openingtxn = nulltransaction{tdate=openingdate, tdescription="opening balances", tpostings=openingps}
openingps =
concat [
[posting{paccount = a
,pamount = mixed [precise b]
,pbalanceassertion =
case mcommoditysum of
Just s -> Just nullassertion{baamount=precise s{aprice=Nothing}}
Nothing -> Nothing Nothing -> Nothing
} }
] ++
if interleaved then
-- a corresponding posting transferring the above balance from equity
[posting{paccount = openingacct
,pamount = Mixed [setprec $ negate b]
}
] ]
else [] ++ [posting{paccount=openingacct, pamount=Mixed [precise $ negate b]} | interleaved]
| (a,_,_,mb) <- acctbals | (a,_,_,mb) <- acctbals
-- the balances in each commodity, and for each transaction price
, let bs = amounts $ normaliseMixedAmount mb , let bs = amounts $ normaliseMixedAmount mb
-- mark the last balance in each commodity, with the unpriced sum in that commodity -- mark the last balance in each commodity with the unpriced sum in that commodity (for a balance assertion)
, let bs' = concat [reverse $ zip (reverse bs) (Just commoditysum : repeat Nothing) , let bs' = concat [reverse $ zip (reverse bs) (Just commoditysum : repeat Nothing)
| bs <- groupBy ((==) `on` acommodity) bs | bs <- groupBy ((==) `on` acommodity) bs
, let commoditysum = (sum bs)] , let commoditysum = (sum bs)]
, (b, mcommoditysum) <- bs' , (b, mcommoditysum) <- bs'
] ]
++ ++ [posting{paccount=openingacct, pamount=mapMixedAmount precise $ negate totalamt} | not interleaved]
if interleaved then []
else
-- a final posting transferring all the balances from equity
-- (print will show it as multiple single-commodity postings)
[posting{paccount = openingacct
,pamount = mapMixedAmount setprec $ negate totalbalancingamt
}
]
when closing $ putStr $ showTransaction (nulltransaction{tdate=closingdate, tdescription="closing balances", tpostings=closingps}) -- print them
when opening $ putStr $ showTransaction (nulltransaction{tdate=openingdate, tdescription="opening balances", tpostings=openingps}) when closing $ putStr $ showTransaction closingtxn
when opening $ putStr $ showTransaction openingtxn