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