close: add the --interleaved flag; refactor a little
Interleaved equity postings make troubleshooting easier.
This commit is contained in:
		
							parent
							
								
									a5ff9d6a63
								
							
						
					
					
						commit
						1e9f30bafc
					
				| @ -27,14 +27,18 @@ closemode = hledgerCommandMode | ||||
|   ,flagNone ["opening"] (setboolopt "opening") "show just opening transaction" | ||||
|   ,flagReq  ["close-to"] (\s opts -> Right $ setopt "close-to" s opts) "ACCT" ("account to transfer closing balances to (default: "++defclosingacct++")") | ||||
|   ,flagReq  ["open-from"] (\s opts -> Right $ setopt "open-from" s opts) "ACCT" ("account to transfer opening balances from (default: "++defopeningacct++")") | ||||
|   ,flagNone ["interleaved"] (setboolopt "interleaved") "keep equity and non-equity postings adjacent" | ||||
|   ] | ||||
|   [generalflagsgroup1] | ||||
|   hiddenflags | ||||
|   ([], Just $ argsFlag "[QUERY]") | ||||
| 
 | ||||
| -- debugger, beware: close is incredibly devious. simple rules combine to make a horrid maze. | ||||
| close CliOpts{rawopts_=rawopts, reportopts_=ropts} j = do | ||||
|   today <- getCurrentDay | ||||
|   let | ||||
|       -- interleave equity postings next to the corresponding closing posting, or put them all at the end ? | ||||
|       interleaved = boolopt "interleaved" rawopts | ||||
|       (opening, closing) = | ||||
|         case (boolopt "opening" rawopts, boolopt "closing" rawopts) of | ||||
|           (False, False) -> (True, True) -- by default show both opening and closing | ||||
| @ -46,51 +50,78 @@ close CliOpts{rawopts_=rawopts, reportopts_=ropts} j = do | ||||
|       openingdate = fromMaybe today $ queryEndDate False q | ||||
|       closingdate = addDays (-1) openingdate | ||||
|       (acctbals,_) = balanceReportFromMultiBalanceReport ropts_ q j | ||||
|       balancingamt = negate $ sum $ map (\(_,_,_,b) -> normaliseMixedAmount b) acctbals | ||||
|       balancingamt = sum $ map (\(_,_,_,b) -> normaliseMixedAmount b) acctbals | ||||
| 
 | ||||
|       -- since balance assertion amounts are required to be exact, the | ||||
|       -- amounts in opening/closing transactions should be too (#941, #1137) | ||||
|       setprec = setFullPrecision | ||||
|       -- balance assertion amounts will be unpriced (#824) | ||||
|       -- only the last posting in each commodity will have a balance assertion (#1035) | ||||
|       closingps = [posting{paccount          = a | ||||
|                           ,pamount           = mixed [setprec $ negate b] | ||||
|                           ,pbalanceassertion = if islast then Just nullassertion{baamount=setprec b{aquantity=0, aprice=Nothing}} else Nothing | ||||
|                           } | ||||
|                   | (a,_,_,mb) <- acctbals | ||||
|                     -- the balances in each commodity, and for each transaction price | ||||
|                   , let bs = amounts $ normaliseMixedAmount mb | ||||
|                     -- mark the last balance in each commodity | ||||
|                   , let bs' = concat [reverse $ zip (reverse bs) (True : repeat False) | ||||
|                                      | bs <- groupBy ((==) `on` acommodity) bs] | ||||
|                   , (b, islast) <- bs' | ||||
|       closingps = concat | ||||
|                   [[posting{paccount          = a | ||||
|                            ,pamount           = mixed [setprec $ negate b] | ||||
|                            -- after each commodity's last posting, assert 0 balance (#1035) | ||||
|                            -- balance assertion amounts are unpriced (#824) | ||||
|                            ,pbalanceassertion = | ||||
|                                if islast | ||||
|                                then Just nullassertion{baamount=setprec b{aquantity=0, aprice=Nothing}} | ||||
|                                else Nothing | ||||
|                            } | ||||
|                    ] ++ | ||||
|                    if interleaved then | ||||
|                    -- a corresponding posting transferring the above balance to equity | ||||
|                    [posting{paccount = closingacct | ||||
|                            ,pamount  = Mixed [b] | ||||
|                            } | ||||
|                    ] | ||||
|                    else [] | ||||
|                    | (a,_,_,mb) <- acctbals | ||||
|                      -- the balances in each commodity, and for each transaction price | ||||
|                    , let bs = amounts $ normaliseMixedAmount mb | ||||
|                      -- mark the last balance in each commodity | ||||
|                    , let bs' = concat [reverse $ zip (reverse bs) (True : repeat False) | ||||
|                                       | bs <- groupBy ((==) `on` acommodity) bs] | ||||
|                    , (b, islast) <- bs' | ||||
|                   ] | ||||
|                   -- The balancing posting to equity. Allow this one to have a multicommodity amount, | ||||
|                   -- and don't try to assert its balance. | ||||
|                   ++ | ||||
|                   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  = negate balancingamt | ||||
|                           ,pamount  = balancingamt | ||||
|                           } | ||||
|                   ] | ||||
| 
 | ||||
|       openingps = [posting{paccount          = a | ||||
|       openingps = concat | ||||
|                   [[posting{paccount         = a | ||||
|                           ,pamount           = mixed [setprec b] | ||||
|                           ,pbalanceassertion = case mcommoditysum of | ||||
|                                                  Just s  -> Just nullassertion{baamount=setprec s{aprice=Nothing}} | ||||
|                                                  Nothing -> Nothing | ||||
|                           } | ||||
|                   | (a,_,_,mb) <- acctbals | ||||
|                     -- the balances in each commodity, and for each transaction price | ||||
|                   , let bs = amounts $ normaliseMixedAmount mb | ||||
|                     -- mark the last balance in each commodity, with the unpriced sum in that commodity | ||||
|                   , let bs' = concat [reverse $ zip (reverse bs) (Just commoditysum : repeat Nothing) | ||||
|                                      | bs <- groupBy ((==) `on` acommodity) bs | ||||
|                                      , let commoditysum = (sum bs)] | ||||
|                   , (b, mcommoditysum) <- bs' | ||||
|                    ] ++ | ||||
|                    if interleaved then | ||||
|                    -- a corresponding posting transferring the above balance from equity | ||||
|                    [posting{paccount = openingacct | ||||
|                            ,pamount  = Mixed [negate b] | ||||
|                            } | ||||
|                    ] | ||||
|                    else [] | ||||
|                    | (a,_,_,mb) <- acctbals | ||||
|                      -- the balances in each commodity, and for each transaction price | ||||
|                    , let bs = amounts $ normaliseMixedAmount mb | ||||
|                      -- mark the last balance in each commodity, with the unpriced sum in that commodity | ||||
|                    , let bs' = concat [reverse $ zip (reverse bs) (Just commoditysum : repeat Nothing) | ||||
|                                       | bs <- groupBy ((==) `on` acommodity) bs | ||||
|                                       , let commoditysum = (sum bs)] | ||||
|                    , (b, mcommoditysum) <- bs' | ||||
|                   ] | ||||
|                   ++ | ||||
|                   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  = balancingamt | ||||
|                           ,pamount  = negate balancingamt | ||||
|                           } | ||||
|                   ] | ||||
| 
 | ||||
|  | ||||
| @ -13,6 +13,9 @@ or you can customise these with the `--close-to` and `--open-from` options. | ||||
| You can choose to print just one of the transactions by using the | ||||
| `--opening` or `--closing` flag. | ||||
| 
 | ||||
| The equity postings appear at the end of the transaction by default;  | ||||
| with `--interleaved`, they appear beside their corresponding closing postings. | ||||
| 
 | ||||
| If you split your journal files by time (eg yearly), you will | ||||
| typically run this command at the end of the year, and save the | ||||
| closing transaction as last entry of the old file, and the opening | ||||
|  | ||||
| @ -237,3 +237,33 @@ $ hledger -f- close -p 2016 assets liabilities | ||||
| 
 | ||||
| >=0 | ||||
| 
 | ||||
| # 9. With --interleaved, balanced posting pairs are adjacent. | ||||
| # (And balances with the same cost are not necessarily combined into | ||||
| # a single posting. Eg the 5734 EUR above is 5733 EUR and 1 EUR below.) | ||||
| $ hledger -f- close -p 2016 assets liabilities --interleaved | ||||
| 2016-12-31 closing balances | ||||
|     assets:bank                        -5,733.00 EUR = 0.00 EUR | ||||
|     equity:closing balances             5,733.00 EUR | ||||
|     liabilities:employer                 $-10,000.00 | ||||
|     equity:closing balances               $10,000.00 | ||||
|     liabilities:employer        $5,000.00 @ 0.93 EUR | ||||
|     equity:closing balances    $-5,000.00 @ 0.93 EUR | ||||
|     liabilities:employer        $5,000.00 @ 0.95 EUR = $0.00 | ||||
|     equity:closing balances    $-5,000.00 @ 0.95 EUR | ||||
|     liabilities:employer                   -1.00 EUR = 0.00 EUR | ||||
|     equity:closing balances                 1.00 EUR | ||||
| 
 | ||||
| 2017-01-01 opening balances | ||||
|     assets:bank                         5,733.00 EUR = 5,733.00 EUR | ||||
|     equity:opening balances            -5,733.00 EUR | ||||
|     liabilities:employer                  $10,000.00 | ||||
|     equity:opening balances              $-10,000.00 | ||||
|     liabilities:employer       $-5,000.00 @ 0.93 EUR | ||||
|     equity:opening balances     $5,000.00 @ 0.93 EUR | ||||
|     liabilities:employer       $-5,000.00 @ 0.95 EUR = $0.00 | ||||
|     equity:opening balances     $5,000.00 @ 0.95 EUR | ||||
|     liabilities:employer                    1.00 EUR = 1.00 EUR | ||||
|     equity:opening balances                -1.00 EUR | ||||
| 
 | ||||
| >=0 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user