journal: inclusive balance assignments now work (#1207)
This commit is contained in:
		
							parent
							
								
									41bb7865f3
								
							
						
					
					
						commit
						21fdcec6b7
					
				| @ -92,6 +92,7 @@ import Control.Monad.ST | |||||||
| import Data.Array.ST | import Data.Array.ST | ||||||
| import Data.Default (Default(..)) | import Data.Default (Default(..)) | ||||||
| import Data.Function ((&)) | import Data.Function ((&)) | ||||||
|  | import qualified Data.HashTable.Class as H (toList) | ||||||
| import qualified Data.HashTable.ST.Cuckoo as H | import qualified Data.HashTable.ST.Cuckoo as H | ||||||
| import Data.List | import Data.List | ||||||
| import Data.List.Extra (groupSort, nubSort) | import Data.List.Extra (groupSort, nubSort) | ||||||
| @ -632,13 +633,13 @@ data BalancingState s = BalancingState { | |||||||
| withRunningBalance :: (BalancingState s -> ST s a) -> Balancing s a | withRunningBalance :: (BalancingState s -> ST s a) -> Balancing s a | ||||||
| withRunningBalance f = ask >>= lift . lift . f | withRunningBalance f = ask >>= lift . lift . f | ||||||
| 
 | 
 | ||||||
| -- | Get this account's current running balance (exclusive). | -- | Get this account's current exclusive running balance. | ||||||
| getRunningBalanceB :: AccountName -> Balancing s MixedAmount | getRunningBalanceB :: AccountName -> Balancing s MixedAmount | ||||||
| getRunningBalanceB acc = withRunningBalance $ \BalancingState{bsBalances} -> do | getRunningBalanceB acc = withRunningBalance $ \BalancingState{bsBalances} -> do | ||||||
|   fromMaybe 0 <$> H.lookup bsBalances acc |   fromMaybe 0 <$> H.lookup bsBalances acc | ||||||
| 
 | 
 | ||||||
| -- | Add this amount to this account's running balance, | -- | Add this amount to this account's exclusive running balance. | ||||||
| -- and return the new running balance (exclusive). | -- Returns the new running balance. | ||||||
| addToRunningBalanceB :: AccountName -> MixedAmount -> Balancing s MixedAmount | addToRunningBalanceB :: AccountName -> MixedAmount -> Balancing s MixedAmount | ||||||
| addToRunningBalanceB acc amt = withRunningBalance $ \BalancingState{bsBalances} -> do | addToRunningBalanceB acc amt = withRunningBalance $ \BalancingState{bsBalances} -> do | ||||||
|   old <- fromMaybe 0 <$> H.lookup bsBalances acc |   old <- fromMaybe 0 <$> H.lookup bsBalances acc | ||||||
| @ -646,14 +647,28 @@ addToRunningBalanceB acc amt = withRunningBalance $ \BalancingState{bsBalances} | |||||||
|   H.insert bsBalances acc new |   H.insert bsBalances acc new | ||||||
|   return new |   return new | ||||||
| 
 | 
 | ||||||
| -- | Set this account's running balance (exclusive) to this amount, | -- | Set this account's exclusive running balance to this amount. | ||||||
| -- and return the difference from the previous value. | -- Returns the change in exclusive running balance. | ||||||
| setRunningBalanceB :: AccountName -> MixedAmount -> Balancing s MixedAmount | setRunningBalanceB :: AccountName -> MixedAmount -> Balancing s MixedAmount | ||||||
| setRunningBalanceB acc amt = withRunningBalance $ \BalancingState{bsBalances} -> do | setRunningBalanceB acc amt = withRunningBalance $ \BalancingState{bsBalances} -> do | ||||||
|   old <- fromMaybe 0 <$> H.lookup bsBalances acc |   old <- fromMaybe 0 <$> H.lookup bsBalances acc | ||||||
|   H.insert bsBalances acc amt |   H.insert bsBalances acc amt | ||||||
|   return $ amt - old |   return $ amt - old | ||||||
| 
 | 
 | ||||||
|  | -- | Set this account's exclusive running balance to whatever amount | ||||||
|  | -- makes its *inclusive* running balance (the sum of exclusive running | ||||||
|  | -- balances of this account and any subaccounts) be the given amount. | ||||||
|  | -- Returns the change in exclusive running balance. | ||||||
|  | setInclusiveRunningBalanceB :: AccountName -> MixedAmount -> Balancing s MixedAmount | ||||||
|  | setInclusiveRunningBalanceB acc newibal = withRunningBalance $ \BalancingState{bsBalances} -> do | ||||||
|  |   oldebal  <- fromMaybe 0 <$> H.lookup bsBalances acc | ||||||
|  |   allebals <- H.toList bsBalances | ||||||
|  |   let subsibal =  -- sum of any subaccounts' running balances | ||||||
|  |         sum $ map snd $ filter ((acc `isAccountNamePrefixOf`).fst) allebals | ||||||
|  |   let newebal = newibal - subsibal | ||||||
|  |   H.insert bsBalances acc newebal | ||||||
|  |   return $ newebal - oldebal | ||||||
|  | 
 | ||||||
| -- | Update (overwrite) this transaction in the balancing state. | -- | Update (overwrite) this transaction in the balancing state. | ||||||
| updateTransactionB :: Transaction -> Balancing s () | updateTransactionB :: Transaction -> Balancing s () | ||||||
| updateTransactionB t = withRunningBalance $ \BalancingState{bsTransactions}  -> | updateTransactionB t = withRunningBalance $ \BalancingState{bsTransactions}  -> | ||||||
| @ -754,19 +769,19 @@ addOrAssignAmountAndCheckAssertionB p@Posting{paccount=acc, pamount=amt, pbalanc | |||||||
| 
 | 
 | ||||||
|   -- no explicit posting amount, but there is a balance assignment |   -- no explicit posting amount, but there is a balance assignment | ||||||
|   -- TODO this doesn't yet handle inclusive assignments right, #1207 |   -- TODO this doesn't yet handle inclusive assignments right, #1207 | ||||||
|   | Just BalanceAssertion{baamount,batotal} <- mba = do |   | Just BalanceAssertion{baamount,batotal,bainclusive} <- mba = do | ||||||
|       (diff,newbal) <- case batotal of |       (diff,newbal) <- case batotal of | ||||||
|         -- a total balance assignment (==, all commodities) |         -- a total balance assignment (==, all commodities) | ||||||
|         True  -> do |         True  -> do | ||||||
|           let newbal = Mixed [baamount] |           let newbal = Mixed [baamount] | ||||||
|           diff <- setRunningBalanceB acc newbal |           diff <- (if bainclusive then setInclusiveRunningBalanceB else setRunningBalanceB) acc newbal | ||||||
|           return (diff,newbal) |           return (diff,newbal) | ||||||
|         -- a partial balance assignment (=, one commodity) |         -- a partial balance assignment (=, one commodity) | ||||||
|         False -> do |         False -> do | ||||||
|           oldbalothercommodities <- filterMixedAmount ((acommodity baamount /=) . acommodity) <$> getRunningBalanceB acc |           oldbalothercommodities <- filterMixedAmount ((acommodity baamount /=) . acommodity) <$> getRunningBalanceB acc | ||||||
|           let assignedbalthiscommodity = Mixed [baamount] |           let assignedbalthiscommodity = Mixed [baamount] | ||||||
|               newbal = oldbalothercommodities + assignedbalthiscommodity |               newbal = oldbalothercommodities + assignedbalthiscommodity | ||||||
|           diff <- setRunningBalanceB acc newbal |           diff <- (if bainclusive then setInclusiveRunningBalanceB else setRunningBalanceB) acc newbal | ||||||
|           return (diff,newbal) |           return (diff,newbal) | ||||||
|       let p' = p{pamount=diff, poriginal=Just $ originalPosting p} |       let p' = p{pamount=diff, poriginal=Just $ originalPosting p} | ||||||
|       whenM (R.reader bsAssrt) $ checkBalanceAssertionB p' newbal |       whenM (R.reader bsAssrt) $ checkBalanceAssertionB p' newbal | ||||||
|  | |||||||
| @ -419,20 +419,32 @@ $ hledger -f- print | |||||||
| 
 | 
 | ||||||
| >=0 | >=0 | ||||||
| 
 | 
 | ||||||
| ## 25. Inclusive balance assignments also work (#1207). | # 25. Inclusive balance assignments also work (#1207). | ||||||
| #< | < | ||||||
| #2020-01-25 | 2020-01-25 | ||||||
| #    (a:aa)   1 |     (a:aa)   1 | ||||||
| # | 
 | ||||||
| #2020-01-31 | 2020-01-25 | ||||||
| #    (a)        ==* 1 |     (a:bb)   1 | ||||||
| # | 
 | ||||||
| #$ hledger -f- print -x | 2020-01-25 | ||||||
| #> |     (a)      1 | ||||||
| #2020-01-25 | 
 | ||||||
| #    (a:aa)               1 | 2020-01-31 | ||||||
| # |     (a)        ==* 1 | ||||||
| #2020-01-31 | 
 | ||||||
| #    (a)               0 ==* 1 | $ hledger -f- print -x | ||||||
| # | > | ||||||
| #>=0 | 2020-01-25 | ||||||
|  |     (a:aa)               1 | ||||||
|  | 
 | ||||||
|  | 2020-01-25 | ||||||
|  |     (a:bb)               1 | ||||||
|  | 
 | ||||||
|  | 2020-01-25 | ||||||
|  |     (a)               1 | ||||||
|  | 
 | ||||||
|  | 2020-01-31 | ||||||
|  |     (a)              -2 ==* 1 | ||||||
|  | 
 | ||||||
|  | >=0 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user