--basis/-B flag, to show all priced amounts on cost basis. Also a --cost alias.
This commit is contained in:
parent
2d49bc4100
commit
52ff46a326
@ -83,35 +83,39 @@ filterRawLedgerTransactionsByRealness True (RawLedger ms ps es f) =
|
|||||||
-- | Give all a ledger's amounts their canonical display settings. That
|
-- | Give all a ledger's amounts their canonical display settings. That
|
||||||
-- is, in each commodity, amounts will use the display settings of the
|
-- is, in each commodity, amounts will use the display settings of the
|
||||||
-- first amount detected, and the greatest precision of the amounts
|
-- first amount detected, and the greatest precision of the amounts
|
||||||
-- detected.
|
-- detected. Also, amounts are converted to cost basis if that flag is
|
||||||
canonicaliseAmounts :: RawLedger -> RawLedger
|
-- active.
|
||||||
canonicaliseAmounts l@(RawLedger ms ps es f) = RawLedger ms ps (map fixEntryAmounts es) f
|
canonicaliseAmounts :: Bool -> RawLedger -> RawLedger
|
||||||
|
canonicaliseAmounts costbasis l@(RawLedger ms ps es f) = RawLedger ms ps (map fixEntryAmounts es) f
|
||||||
where
|
where
|
||||||
fixEntryAmounts (Entry d s c de co ts pr) = Entry d s c de co (map fixRawTransactionAmounts ts) pr
|
fixEntryAmounts (Entry d s c de co ts pr) = Entry d s c de co (map fixRawTransactionAmounts ts) pr
|
||||||
fixRawTransactionAmounts (RawTransaction ac a c t) = RawTransaction ac (fixMixedAmount a) c t
|
fixRawTransactionAmounts (RawTransaction ac a c t) = RawTransaction ac (fixMixedAmount a) c t
|
||||||
fixMixedAmount (Mixed as) = Mixed $ map fixAmount as
|
fixMixedAmount (Mixed as) = Mixed $ map fixAmount as
|
||||||
fixAmount (Amount c q pri) = Amount (canonicalcommodity c) q pri
|
fixAmount | costbasis = fixcommodity . costOfAmount
|
||||||
canonicalcommodity c@(Commodity {symbol=s}) =
|
| otherwise = fixcommodity
|
||||||
(firstoccurrenceof c){precision=maximum $ map precision $ commoditieswithsymbol s}
|
fixcommodity a = a{commodity=canonicalcommodity $ commodity a}
|
||||||
firstoccurrenceof Commodity{symbol=s} = head $ commoditieswithsymbol s
|
canonicalcommodity c = (firstoccurrenceof c){precision=maxprecision c}
|
||||||
-- Get ledger's amounts' commodities with a given symbol, in the order parsed.
|
|
||||||
-- Call with a good symbol or it will fail.
|
|
||||||
commoditieswithsymbol :: String -> [Commodity]
|
|
||||||
commoditieswithsymbol s = fromMaybe (error $ "no such commodity "++s) (Map.lookup s commoditiesmap)
|
|
||||||
where
|
where
|
||||||
commoditiesmap :: Map.Map String [Commodity]
|
firstoccurrenceof c = head $ rawLedgerCommoditiesWithSymbol l (symbol c)
|
||||||
commoditiesmap = Map.fromList [(symbol $ head cs,cs) |
|
maxprecision c = maximum $ map precision $ rawLedgerCommoditiesWithSymbol l (symbol c)
|
||||||
cs <- groupBy samesymbol $ rawLedgerCommodities l]
|
|
||||||
samesymbol c1 c2 = symbol c1 == symbol c2
|
|
||||||
|
|
||||||
-- | Get just the amounts from a ledger, in the order parsed.
|
-- | Get all amount commodities with a given symbol, in the order parsed.
|
||||||
rawLedgerAmounts :: RawLedger -> [MixedAmount]
|
-- Must be called with a good symbol or it will fail.
|
||||||
rawLedgerAmounts = map amount . rawLedgerTransactions
|
rawLedgerCommoditiesWithSymbol :: RawLedger -> String -> [Commodity]
|
||||||
|
rawLedgerCommoditiesWithSymbol l s =
|
||||||
|
fromMaybe (error $ "no such commodity "++s) (Map.lookup s map)
|
||||||
|
where
|
||||||
|
map = Map.fromList [(symbol $ head cs,cs) | cs <- groupBy same $ rawLedgerCommodities l]
|
||||||
|
same c1 c2 = symbol c1 == symbol c2
|
||||||
|
|
||||||
-- | Get just the ammount commodities from a ledger, in the order parsed.
|
-- | Get just the ammount commodities from a ledger, in the order parsed.
|
||||||
rawLedgerCommodities :: RawLedger -> [Commodity]
|
rawLedgerCommodities :: RawLedger -> [Commodity]
|
||||||
rawLedgerCommodities = map commodity . concatMap amounts . rawLedgerAmounts
|
rawLedgerCommodities = map commodity . concatMap amounts . rawLedgerAmounts
|
||||||
|
|
||||||
|
-- | Get just the amounts from a ledger, in the order parsed.
|
||||||
|
rawLedgerAmounts :: RawLedger -> [MixedAmount]
|
||||||
|
rawLedgerAmounts = map amount . rawLedgerTransactions
|
||||||
|
|
||||||
-- | Get just the amount precisions from a ledger, in the order parsed.
|
-- | Get just the amount precisions from a ledger, in the order parsed.
|
||||||
rawLedgerPrecisions :: RawLedger -> [Int]
|
rawLedgerPrecisions :: RawLedger -> [Int]
|
||||||
rawLedgerPrecisions = map precision . rawLedgerCommodities
|
rawLedgerPrecisions = map precision . rawLedgerCommodities
|
||||||
|
|||||||
1
NOTES
1
NOTES
@ -15,7 +15,6 @@ implementations were its consequences." --Niklaus Wirth
|
|||||||
*** flexible date expressions, for easier time reports
|
*** flexible date expressions, for easier time reports
|
||||||
**** more formats
|
**** more formats
|
||||||
**** periods
|
**** periods
|
||||||
*** commodity @ rate, for tracking client hours in main ledger
|
|
||||||
*** actual/effective entry & txn dates, for ?
|
*** actual/effective entry & txn dates, for ?
|
||||||
*** --display, for reconciling recent transactions with real balance
|
*** --display, for reconciling recent transactions with real balance
|
||||||
*** more ledger features from README
|
*** more ledger features from README
|
||||||
|
|||||||
@ -29,6 +29,7 @@ options = [
|
|||||||
Option ['b'] ["begin"] (ReqArg Begin "YYYY/MM/DD") "report on entries on or after this date",
|
Option ['b'] ["begin"] (ReqArg Begin "YYYY/MM/DD") "report on entries on or after this date",
|
||||||
Option ['e'] ["end"] (ReqArg End "YYYY/MM/DD") "report on entries prior to this date",
|
Option ['e'] ["end"] (ReqArg End "YYYY/MM/DD") "report on entries prior to this date",
|
||||||
Option ['C'] ["cleared"] (NoArg Cleared) "report only on cleared entries",
|
Option ['C'] ["cleared"] (NoArg Cleared) "report only on cleared entries",
|
||||||
|
Option ['B'] ["cost","basis"] (NoArg CostBasis) "report cost basis of commodities",
|
||||||
Option [] ["depth"] (ReqArg Depth "N") "balance report: maximum account depth to show",
|
Option [] ["depth"] (ReqArg Depth "N") "balance report: maximum account depth to show",
|
||||||
Option ['E'] ["empty"] (NoArg Empty) "balance report: show accounts with zero balance",
|
Option ['E'] ["empty"] (NoArg Empty) "balance report: show accounts with zero balance",
|
||||||
Option ['R'] ["real"] (NoArg Real) "report only on real (non-virtual) transactions",
|
Option ['R'] ["real"] (NoArg Real) "report only on real (non-virtual) transactions",
|
||||||
@ -44,6 +45,7 @@ data Opt =
|
|||||||
Begin String |
|
Begin String |
|
||||||
End String |
|
End String |
|
||||||
Cleared |
|
Cleared |
|
||||||
|
CostBasis |
|
||||||
Depth String |
|
Depth String |
|
||||||
Empty |
|
Empty |
|
||||||
Real |
|
Real |
|
||||||
|
|||||||
10
README
10
README
@ -73,14 +73,18 @@ This version of hledger mimics a subset of ledger 2.6.1:
|
|||||||
-E, --empty balance report: show accounts with zero balance
|
-E, --empty balance report: show accounts with zero balance
|
||||||
-n, --collapse balance report: no grand total
|
-n, --collapse balance report: no grand total
|
||||||
|
|
||||||
|
Commodity reporting:
|
||||||
|
-B, --basis, --cost report cost basis of commodities
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
balance [REGEXP]... show balance totals for matching accounts
|
balance [REGEXP]... show balance totals for matching accounts
|
||||||
register [REGEXP]... show register of matching transactions
|
register [REGEXP]... show register of matching transactions
|
||||||
print [REGEXP]... print all matching entries
|
print [REGEXP]... print all matching entries
|
||||||
|
|
||||||
hledger-only features:
|
hledger-specific features:
|
||||||
|
|
||||||
- --depth=N balance report: maximum account depth to show
|
--depth=N balance report: maximum account depth to show
|
||||||
|
--cost alias for basis
|
||||||
|
|
||||||
ledger features not supported:
|
ledger features not supported:
|
||||||
|
|
||||||
@ -146,7 +150,6 @@ ledger features not supported:
|
|||||||
-L, --price-exp MINS download quotes only if newer than MINS (def: 1440)
|
-L, --price-exp MINS download quotes only if newer than MINS (def: 1440)
|
||||||
-Q, --download download price information when needed
|
-Q, --download download price information when needed
|
||||||
-O, --quantity report commodity totals (this is the default)
|
-O, --quantity report commodity totals (this is the default)
|
||||||
-B, --basis report cost basis of commodities
|
|
||||||
-V, --market report last known market value
|
-V, --market report last known market value
|
||||||
-g, --performance report gain/loss for each displayed transaction
|
-g, --performance report gain/loss for each displayed transaction
|
||||||
-G, --gain report net gain/loss
|
-G, --gain report net gain/loss
|
||||||
@ -162,3 +165,4 @@ Some other differences:
|
|||||||
- hledger talks about the entry and transaction "description", which ledger calls "note"
|
- hledger talks about the entry and transaction "description", which ledger calls "note"
|
||||||
- hledger always shows timelog balances in hours
|
- hledger always shows timelog balances in hours
|
||||||
- hledger doesn't require a space after flags like -f
|
- hledger doesn't require a space after flags like -f
|
||||||
|
- hledger keeps differently-priced amounts of the same commodity separate
|
||||||
19
Tests.hs
19
Tests.hs
@ -88,7 +88,7 @@ misc_tests = TestList [
|
|||||||
,
|
,
|
||||||
"canonicaliseAmounts" ~: do
|
"canonicaliseAmounts" ~: do
|
||||||
-- all amounts use the greatest precision
|
-- all amounts use the greatest precision
|
||||||
assertequal [2,2] (rawLedgerPrecisions $ canonicaliseAmounts $ rawLedgerWithAmounts ["1","2.00"])
|
assertequal [2,2] (rawLedgerPrecisions $ canonicaliseAmounts False $ rawLedgerWithAmounts ["1","2.00"])
|
||||||
,
|
,
|
||||||
"timeLog" ~: do
|
"timeLog" ~: do
|
||||||
assertparseequal timelog1 (parsewith timelog timelog1_str)
|
assertparseequal timelog1 (parsewith timelog timelog1_str)
|
||||||
@ -239,6 +239,23 @@ balancecommand_tests = TestList [
|
|||||||
" $-2 cash\n" ++
|
" $-2 cash\n" ++
|
||||||
" $1 saving\n" ++
|
" $1 saving\n" ++
|
||||||
"")
|
"")
|
||||||
|
,
|
||||||
|
"balance report with cost basis" ~: do
|
||||||
|
let l = cacheLedger [] $
|
||||||
|
filterRawLedger Nothing Nothing [] False False $
|
||||||
|
canonicaliseAmounts True $ -- enable cost basis adjustment
|
||||||
|
rawledgerfromstring
|
||||||
|
("" ++
|
||||||
|
"2008/1/1 test \n" ++
|
||||||
|
" a:b 10h @ $50\n" ++
|
||||||
|
" c:d \n" ++
|
||||||
|
"\n")
|
||||||
|
assertequal
|
||||||
|
(" $500 a\n" ++
|
||||||
|
" $-500 c\n" ++
|
||||||
|
""
|
||||||
|
)
|
||||||
|
(showBalanceReport [] [] l)
|
||||||
] where
|
] where
|
||||||
gives (opts,pats) e = do
|
gives (opts,pats) e = do
|
||||||
l <- ledgerfromfile pats "sample.ledger"
|
l <- ledgerfromfile pats "sample.ledger"
|
||||||
|
|||||||
@ -70,10 +70,11 @@ parseLedgerAndDo :: [Opt] -> [String] -> ([Opt] -> [String] -> Ledger -> IO ())
|
|||||||
parseLedgerAndDo opts args cmd =
|
parseLedgerAndDo opts args cmd =
|
||||||
ledgerFilePathFromOpts opts >>= parseLedgerFile >>= either printParseError runcmd
|
ledgerFilePathFromOpts opts >>= parseLedgerFile >>= either printParseError runcmd
|
||||||
where
|
where
|
||||||
runcmd = cmd opts args . cacheLedger apats . filterRawLedger b e dpats c r . canonicaliseAmounts
|
runcmd = cmd opts args . cacheLedger apats . filterRawLedger b e dpats c r . canonicaliseAmounts costbasis
|
||||||
b = beginDateFromOpts opts
|
b = beginDateFromOpts opts
|
||||||
e = endDateFromOpts opts
|
e = endDateFromOpts opts
|
||||||
(apats,dpats) = parseAccountDescriptionArgs args
|
(apats,dpats) = parseAccountDescriptionArgs args
|
||||||
c = Cleared `elem` opts
|
c = Cleared `elem` opts
|
||||||
r = Real `elem` opts
|
r = Real `elem` opts
|
||||||
|
costbasis = CostBasis `elem` opts
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user