more matcher -> query renaming
This commit is contained in:
parent
a7ef0ba8dd
commit
a27eb7c29f
@ -35,8 +35,8 @@ module Hledger.Data.Journal (
|
|||||||
journalFilePaths,
|
journalFilePaths,
|
||||||
journalPostings,
|
journalPostings,
|
||||||
-- * Standard account types
|
-- * Standard account types
|
||||||
journalBalanceSheetAccountMatcher,
|
journalBalanceSheetAccountQuery,
|
||||||
journalProfitAndLossAccountMatcher,
|
journalProfitAndLossAccountQuery,
|
||||||
-- * Misc
|
-- * Misc
|
||||||
groupPostings,
|
groupPostings,
|
||||||
matchpats,
|
matchpats,
|
||||||
@ -163,17 +163,17 @@ balanceSheetAccountRegex, profitAndLossAccountRegex :: String
|
|||||||
balanceSheetAccountRegex = "^(assets?|liabilit(y|ies)|equity)(:|$)"
|
balanceSheetAccountRegex = "^(assets?|liabilit(y|ies)|equity)(:|$)"
|
||||||
profitAndLossAccountRegex = "^(income|expenses?|profits?|loss(es)?)(:|$)"
|
profitAndLossAccountRegex = "^(income|expenses?|profits?|loss(es)?)(:|$)"
|
||||||
|
|
||||||
-- | A matcher for Asset, Liability & Equity accounts in this journal.
|
-- | A query for Asset, Liability & Equity accounts in this journal.
|
||||||
-- Cf <http://en.wikipedia.org/wiki/Chart_of_accounts#Balance_Sheet_Accounts>.
|
-- Cf <http://en.wikipedia.org/wiki/Chart_of_accounts#Balance_Sheet_Accounts>.
|
||||||
-- This is currently hard-coded to the case-insensitive regex @^(assets?|liabilit(y|ies)|equity)(:|$)@.
|
-- This is currently hard-coded to the case-insensitive regex @^(assets?|liabilit(y|ies)|equity)(:|$)@.
|
||||||
journalBalanceSheetAccountMatcher :: Journal -> Matcher
|
journalBalanceSheetAccountQuery :: Journal -> Matcher
|
||||||
journalBalanceSheetAccountMatcher _ = MatchAcct balanceSheetAccountRegex
|
journalBalanceSheetAccountQuery _ = MatchAcct balanceSheetAccountRegex
|
||||||
|
|
||||||
-- | A matcher for Profit & Loss accounts in this journal.
|
-- | A query for Profit & Loss accounts in this journal.
|
||||||
-- Cf <http://en.wikipedia.org/wiki/Chart_of_accounts#Profit_.26_Loss_accounts>.
|
-- Cf <http://en.wikipedia.org/wiki/Chart_of_accounts#Profit_.26_Loss_accounts>.
|
||||||
-- This is currently hard-coded to the case-insensitive regex @^(income|expenses?|profits?|loss(es)?)(:|$)@.
|
-- This is currently hard-coded to the case-insensitive regex @^(income|expenses?|profits?|loss(es)?)(:|$)@.
|
||||||
journalProfitAndLossAccountMatcher :: Journal -> Matcher
|
journalProfitAndLossAccountQuery :: Journal -> Matcher
|
||||||
journalProfitAndLossAccountMatcher _ = MatchAcct profitAndLossAccountRegex
|
journalProfitAndLossAccountQuery _ = MatchAcct profitAndLossAccountRegex
|
||||||
|
|
||||||
-- Various kinds of filtering on journals. We do it differently depending
|
-- Various kinds of filtering on journals. We do it differently depending
|
||||||
-- on the command.
|
-- on the command.
|
||||||
|
|||||||
@ -49,7 +49,7 @@ journalToLedger fs j = nullledger{journal=j',accountnametree=t,accountmap=m}
|
|||||||
-- | Filter a journal's transactions as specified, and then process them
|
-- | Filter a journal's transactions as specified, and then process them
|
||||||
-- to derive a ledger containing all balances, the chart of accounts,
|
-- to derive a ledger containing all balances, the chart of accounts,
|
||||||
-- canonicalised commodities etc.
|
-- canonicalised commodities etc.
|
||||||
-- Like journalToLedger but uses the new matchers.
|
-- Like journalToLedger but uses the new queries.
|
||||||
journalToLedger2 :: Matcher -> Journal -> Ledger
|
journalToLedger2 :: Matcher -> Journal -> Ledger
|
||||||
journalToLedger2 m j = nullledger{journal=j',accountnametree=t,accountmap=amap}
|
journalToLedger2 m j = nullledger{journal=j',accountnametree=t,accountmap=amap}
|
||||||
where j' = filterJournalPostings2 m j
|
where j' = filterJournalPostings2 m j
|
||||||
|
|||||||
@ -7,13 +7,13 @@ Currently used only by hledger-web.
|
|||||||
|
|
||||||
module Hledger.Data.Query (
|
module Hledger.Data.Query (
|
||||||
Matcher(..),
|
Matcher(..),
|
||||||
matcherIsNull,
|
queryIsNull,
|
||||||
matcherIsStartDateOnly,
|
queryIsStartDateOnly,
|
||||||
matcherStartDate,
|
queryStartDate,
|
||||||
matchesTransaction,
|
matchesTransaction,
|
||||||
matchesPosting,
|
matchesPosting,
|
||||||
inAccount,
|
inAccount,
|
||||||
inAccountMatcher,
|
inAccountQuery,
|
||||||
tests_Hledger_Data_Query
|
tests_Hledger_Data_Query
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
@ -42,9 +42,8 @@ import Hledger.Data.Posting
|
|||||||
import Hledger.Data.Transaction
|
import Hledger.Data.Transaction
|
||||||
-- import Hledger.Data.TimeLog
|
-- import Hledger.Data.TimeLog
|
||||||
|
|
||||||
-- | A matcher is a single, or boolean composition of, search criteria,
|
-- | A query is a composition of search criteria, which can be used to
|
||||||
-- which can be used to match postings, transactions, accounts and more.
|
-- match postings, transactions, accounts and more.
|
||||||
-- Currently used by hledger-web, will likely replace FilterSpec at some point.
|
|
||||||
data Matcher = MatchAny -- ^ always match
|
data Matcher = MatchAny -- ^ always match
|
||||||
| MatchNone -- ^ never match
|
| MatchNone -- ^ never match
|
||||||
| MatchNot Matcher -- ^ negate this match
|
| MatchNot Matcher -- ^ negate this match
|
||||||
@ -77,21 +76,21 @@ inAccount [] = Nothing
|
|||||||
inAccount (QueryOptInAcctOnly a:_) = Just (a,False)
|
inAccount (QueryOptInAcctOnly a:_) = Just (a,False)
|
||||||
inAccount (QueryOptInAcct a:_) = Just (a,True)
|
inAccount (QueryOptInAcct a:_) = Just (a,True)
|
||||||
|
|
||||||
-- | A matcher for the account(s) we are currently focussed on, if any.
|
-- | A query for the account(s) we are currently focussed on, if any.
|
||||||
-- Just looks at the first query option.
|
-- Just looks at the first query option.
|
||||||
inAccountMatcher :: [QueryOpt] -> Maybe Matcher
|
inAccountQuery :: [QueryOpt] -> Maybe Matcher
|
||||||
inAccountMatcher [] = Nothing
|
inAccountQuery [] = Nothing
|
||||||
inAccountMatcher (QueryOptInAcctOnly a:_) = Just $ MatchAcct $ accountNameToAccountOnlyRegex a
|
inAccountQuery (QueryOptInAcctOnly a:_) = Just $ MatchAcct $ accountNameToAccountOnlyRegex a
|
||||||
inAccountMatcher (QueryOptInAcct a:_) = Just $ MatchAcct $ accountNameToAccountRegex a
|
inAccountQuery (QueryOptInAcct a:_) = Just $ MatchAcct $ accountNameToAccountRegex a
|
||||||
|
|
||||||
-- -- | A matcher restricting the account(s) to be shown in the sidebar, if any.
|
-- -- | A query restricting the account(s) to be shown in the sidebar, if any.
|
||||||
-- -- Just looks at the first query option.
|
-- -- Just looks at the first query option.
|
||||||
-- showAccountMatcher :: [QueryOpt] -> Maybe Matcher
|
-- showAccountMatcher :: [QueryOpt] -> Maybe Matcher
|
||||||
-- showAccountMatcher (QueryOptInAcctSubsOnly a:_) = Just $ MatchAcct True $ accountNameToAccountRegex a
|
-- showAccountMatcher (QueryOptInAcctSubsOnly a:_) = Just $ MatchAcct True $ accountNameToAccountRegex a
|
||||||
-- showAccountMatcher _ = Nothing
|
-- showAccountMatcher _ = Nothing
|
||||||
|
|
||||||
-- | Convert a query expression containing zero or more space-separated
|
-- | Convert a query expression containing zero or more space-separated
|
||||||
-- terms to a matcher and zero or more query options. A query term is either:
|
-- terms to a query and zero or more query options. A query term is either:
|
||||||
--
|
--
|
||||||
-- 1. a search criteria, used to match transactions. This is usually a prefixed pattern such as:
|
-- 1. a search criteria, used to match transactions. This is usually a prefixed pattern such as:
|
||||||
-- acct:REGEXP
|
-- acct:REGEXP
|
||||||
@ -109,10 +108,10 @@ parseQuery :: Day -> String -> (Matcher,[QueryOpt])
|
|||||||
parseQuery d s = (m,qopts)
|
parseQuery d s = (m,qopts)
|
||||||
where
|
where
|
||||||
terms = words'' prefixes s
|
terms = words'' prefixes s
|
||||||
(matchers, qopts) = partitionEithers $ map (parseMatcher d) terms
|
(queries, qopts) = partitionEithers $ map (parseQueryTerm d) terms
|
||||||
m = case matchers of [] -> MatchAny
|
m = case queries of [] -> MatchAny
|
||||||
(m':[]) -> m'
|
(m':[]) -> m'
|
||||||
ms -> MatchAnd ms
|
ms -> MatchAnd ms
|
||||||
|
|
||||||
-- | Quote-and-prefix-aware version of words - don't split on spaces which
|
-- | Quote-and-prefix-aware version of words - don't split on spaces which
|
||||||
-- are inside quotes, including quotes which may have one of the specified
|
-- are inside quotes, including quotes which may have one of the specified
|
||||||
@ -135,14 +134,14 @@ words'' prefixes = fromparse . parsewith maybeprefixedquotedphrases -- XXX
|
|||||||
pattern = many (noneOf " \n\r\"")
|
pattern = many (noneOf " \n\r\"")
|
||||||
|
|
||||||
-- -- | Parse the query string as a boolean tree of match patterns.
|
-- -- | Parse the query string as a boolean tree of match patterns.
|
||||||
-- parseMatcher :: String -> Matcher
|
-- parseQueryTerm :: String -> Matcher
|
||||||
-- parseMatcher s = either (const (MatchAny)) id $ runParser matcher () "" $ lexmatcher s
|
-- parseQueryTerm s = either (const (MatchAny)) id $ runParser query () "" $ lexmatcher s
|
||||||
|
|
||||||
-- lexmatcher :: String -> [String]
|
-- lexmatcher :: String -> [String]
|
||||||
-- lexmatcher s = words' s
|
-- lexmatcher s = words' s
|
||||||
|
|
||||||
-- matcher :: GenParser String () Matcher
|
-- query :: GenParser String () Matcher
|
||||||
-- matcher = undefined
|
-- query = undefined
|
||||||
|
|
||||||
-- keep synced with patterns below, excluding "not"
|
-- keep synced with patterns below, excluding "not"
|
||||||
prefixes = map (++":") [
|
prefixes = map (++":") [
|
||||||
@ -151,34 +150,34 @@ prefixes = map (++":") [
|
|||||||
]
|
]
|
||||||
defaultprefix = "acct"
|
defaultprefix = "acct"
|
||||||
|
|
||||||
-- | Parse a single query term as either a matcher or a query option.
|
-- | Parse a single query term as either a query or a query option.
|
||||||
parseMatcher :: Day -> String -> Either Matcher QueryOpt
|
parseQueryTerm :: Day -> String -> Either Matcher QueryOpt
|
||||||
parseMatcher _ ('i':'n':'a':'c':'c':'t':'o':'n':'l':'y':':':s) = Right $ QueryOptInAcctOnly s
|
parseQueryTerm _ ('i':'n':'a':'c':'c':'t':'o':'n':'l':'y':':':s) = Right $ QueryOptInAcctOnly s
|
||||||
parseMatcher _ ('i':'n':'a':'c':'c':'t':':':s) = Right $ QueryOptInAcct s
|
parseQueryTerm _ ('i':'n':'a':'c':'c':'t':':':s) = Right $ QueryOptInAcct s
|
||||||
parseMatcher d ('n':'o':'t':':':s) = case parseMatcher d s of
|
parseQueryTerm d ('n':'o':'t':':':s) = case parseQueryTerm d s of
|
||||||
Left m -> Left $ MatchNot m
|
Left m -> Left $ MatchNot m
|
||||||
Right _ -> Left MatchAny -- not:somequeryoption will be ignored
|
Right _ -> Left MatchAny -- not:somequeryoption will be ignored
|
||||||
parseMatcher _ ('d':'e':'s':'c':':':s) = Left $ MatchDesc s
|
parseQueryTerm _ ('d':'e':'s':'c':':':s) = Left $ MatchDesc s
|
||||||
parseMatcher _ ('a':'c':'c':'t':':':s) = Left $ MatchAcct s
|
parseQueryTerm _ ('a':'c':'c':'t':':':s) = Left $ MatchAcct s
|
||||||
parseMatcher d ('d':'a':'t':'e':':':s) =
|
parseQueryTerm d ('d':'a':'t':'e':':':s) =
|
||||||
case parsePeriodExpr d s of Left _ -> Left MatchNone -- XXX should warn
|
case parsePeriodExpr d s of Left _ -> Left MatchNone -- XXX should warn
|
||||||
Right (_,span) -> Left $ MatchDate span
|
Right (_,span) -> Left $ MatchDate span
|
||||||
parseMatcher d ('e':'d':'a':'t':'e':':':s) =
|
parseQueryTerm d ('e':'d':'a':'t':'e':':':s) =
|
||||||
case parsePeriodExpr d s of Left _ -> Left MatchNone -- XXX should warn
|
case parsePeriodExpr d s of Left _ -> Left MatchNone -- XXX should warn
|
||||||
Right (_,span) -> Left $ MatchEDate span
|
Right (_,span) -> Left $ MatchEDate span
|
||||||
parseMatcher _ ('s':'t':'a':'t':'u':'s':':':s) = Left $ MatchStatus $ parseStatus s
|
parseQueryTerm _ ('s':'t':'a':'t':'u':'s':':':s) = Left $ MatchStatus $ parseStatus s
|
||||||
parseMatcher _ ('r':'e':'a':'l':':':s) = Left $ MatchReal $ parseBool s
|
parseQueryTerm _ ('r':'e':'a':'l':':':s) = Left $ MatchReal $ parseBool s
|
||||||
parseMatcher _ ('e':'m':'p':'t':'y':':':s) = Left $ MatchEmpty $ parseBool s
|
parseQueryTerm _ ('e':'m':'p':'t':'y':':':s) = Left $ MatchEmpty $ parseBool s
|
||||||
parseMatcher _ ('d':'e':'p':'t':'h':':':s) = Left $ MatchDepth $ readDef 0 s
|
parseQueryTerm _ ('d':'e':'p':'t':'h':':':s) = Left $ MatchDepth $ readDef 0 s
|
||||||
parseMatcher _ "" = Left $ MatchAny
|
parseQueryTerm _ "" = Left $ MatchAny
|
||||||
parseMatcher d s = parseMatcher d $ defaultprefix++":"++s
|
parseQueryTerm d s = parseQueryTerm d $ defaultprefix++":"++s
|
||||||
|
|
||||||
-- | Parse the boolean value part of a "status:" matcher, allowing "*" as
|
-- | Parse the boolean value part of a "status:" query, allowing "*" as
|
||||||
-- another way to spell True, similar to the journal file format.
|
-- another way to spell True, similar to the journal file format.
|
||||||
parseStatus :: String -> Bool
|
parseStatus :: String -> Bool
|
||||||
parseStatus s = s `elem` (truestrings ++ ["*"])
|
parseStatus s = s `elem` (truestrings ++ ["*"])
|
||||||
|
|
||||||
-- | Parse the boolean value part of a "status:" matcher. A true value can
|
-- | Parse the boolean value part of a "status:" query. A true value can
|
||||||
-- be spelled as "1", "t" or "true".
|
-- be spelled as "1", "t" or "true".
|
||||||
parseBool :: String -> Bool
|
parseBool :: String -> Bool
|
||||||
parseBool s = s `elem` truestrings
|
parseBool s = s `elem` truestrings
|
||||||
@ -186,9 +185,9 @@ parseBool s = s `elem` truestrings
|
|||||||
truestrings :: [String]
|
truestrings :: [String]
|
||||||
truestrings = ["1","t","true"]
|
truestrings = ["1","t","true"]
|
||||||
|
|
||||||
-- -- | Convert a match expression to its inverse.
|
-- -- | Convert a query to its inverse.
|
||||||
-- negateMatcher :: Matcher -> Matcher
|
-- negateQuery :: Matcher -> Matcher
|
||||||
-- negateMatcher = MatchNot
|
-- negateQuery = MatchNot
|
||||||
|
|
||||||
-- | Does the match expression match this posting ?
|
-- | Does the match expression match this posting ?
|
||||||
matchesPosting :: Matcher -> Posting -> Bool
|
matchesPosting :: Matcher -> Posting -> Bool
|
||||||
@ -240,33 +239,33 @@ matchesAccount (MatchAnd ms) a = all (`matchesAccount` a) ms
|
|||||||
matchesAccount (MatchAcct r) a = regexMatchesCI r a
|
matchesAccount (MatchAcct r) a = regexMatchesCI r a
|
||||||
matchesAccount _ _ = False
|
matchesAccount _ _ = False
|
||||||
|
|
||||||
-- | What start date does this matcher specify, if any ?
|
-- | What start date does this query specify, if any ?
|
||||||
-- If the matcher is an OR expression, returns the earliest of the alternatives.
|
-- If the query is an OR expression, returns the earliest of the alternatives.
|
||||||
-- When the flag is true, look for a starting effective date instead.
|
-- When the flag is true, look for a starting effective date instead.
|
||||||
matcherStartDate :: Bool -> Matcher -> Maybe Day
|
queryStartDate :: Bool -> Matcher -> Maybe Day
|
||||||
matcherStartDate effective (MatchOr ms) = earliestMaybeDate $ map (matcherStartDate effective) ms
|
queryStartDate effective (MatchOr ms) = earliestMaybeDate $ map (queryStartDate effective) ms
|
||||||
matcherStartDate effective (MatchAnd ms) = latestMaybeDate $ map (matcherStartDate effective) ms
|
queryStartDate effective (MatchAnd ms) = latestMaybeDate $ map (queryStartDate effective) ms
|
||||||
matcherStartDate False (MatchDate (DateSpan (Just d) _)) = Just d
|
queryStartDate False (MatchDate (DateSpan (Just d) _)) = Just d
|
||||||
matcherStartDate True (MatchEDate (DateSpan (Just d) _)) = Just d
|
queryStartDate True (MatchEDate (DateSpan (Just d) _)) = Just d
|
||||||
matcherStartDate _ _ = Nothing
|
queryStartDate _ _ = Nothing
|
||||||
|
|
||||||
-- | Does this matcher specify a start date and nothing else (that would
|
-- | Does this query specify a start date and nothing else (that would
|
||||||
-- filter postings prior to the date) ?
|
-- filter postings prior to the date) ?
|
||||||
-- When the flag is true, look for a starting effective date instead.
|
-- When the flag is true, look for a starting effective date instead.
|
||||||
matcherIsStartDateOnly :: Bool -> Matcher -> Bool
|
queryIsStartDateOnly :: Bool -> Matcher -> Bool
|
||||||
matcherIsStartDateOnly _ MatchAny = False
|
queryIsStartDateOnly _ MatchAny = False
|
||||||
matcherIsStartDateOnly _ MatchNone = False
|
queryIsStartDateOnly _ MatchNone = False
|
||||||
matcherIsStartDateOnly effective (MatchOr ms) = and $ map (matcherIsStartDateOnly effective) ms
|
queryIsStartDateOnly effective (MatchOr ms) = and $ map (queryIsStartDateOnly effective) ms
|
||||||
matcherIsStartDateOnly effective (MatchAnd ms) = and $ map (matcherIsStartDateOnly effective) ms
|
queryIsStartDateOnly effective (MatchAnd ms) = and $ map (queryIsStartDateOnly effective) ms
|
||||||
matcherIsStartDateOnly False (MatchDate (DateSpan (Just _) _)) = True
|
queryIsStartDateOnly False (MatchDate (DateSpan (Just _) _)) = True
|
||||||
matcherIsStartDateOnly True (MatchEDate (DateSpan (Just _) _)) = True
|
queryIsStartDateOnly True (MatchEDate (DateSpan (Just _) _)) = True
|
||||||
matcherIsStartDateOnly _ _ = False
|
queryIsStartDateOnly _ _ = False
|
||||||
|
|
||||||
-- | Does this matcher match everything ?
|
-- | Does this query match everything ?
|
||||||
matcherIsNull MatchAny = True
|
queryIsNull MatchAny = True
|
||||||
matcherIsNull (MatchAnd []) = True
|
queryIsNull (MatchAnd []) = True
|
||||||
matcherIsNull (MatchNot (MatchOr [])) = True
|
queryIsNull (MatchNot (MatchOr [])) = True
|
||||||
matcherIsNull _ = False
|
queryIsNull _ = False
|
||||||
|
|
||||||
-- | What is the earliest of these dates, where Nothing is earliest ?
|
-- | What is the earliest of these dates, where Nothing is earliest ?
|
||||||
earliestMaybeDate :: [Maybe Day] -> Maybe Day
|
earliestMaybeDate :: [Maybe Day] -> Maybe Day
|
||||||
|
|||||||
@ -20,7 +20,7 @@ module Hledger.Reports (
|
|||||||
whichDateFromOpts,
|
whichDateFromOpts,
|
||||||
journalSelectingDateFromOpts,
|
journalSelectingDateFromOpts,
|
||||||
journalSelectingAmountFromOpts,
|
journalSelectingAmountFromOpts,
|
||||||
optsToFilterSpec,
|
filterSpecFromOpts,
|
||||||
-- * Entries report
|
-- * Entries report
|
||||||
EntriesReport,
|
EntriesReport,
|
||||||
EntriesReportItem,
|
EntriesReportItem,
|
||||||
@ -167,8 +167,8 @@ journalSelectingAmountFromOpts opts
|
|||||||
| otherwise = id
|
| otherwise = id
|
||||||
|
|
||||||
-- | Convert application options to the library's generic filter specification.
|
-- | Convert application options to the library's generic filter specification.
|
||||||
optsToFilterSpec :: ReportOpts -> Day -> FilterSpec
|
filterSpecFromOpts :: ReportOpts -> Day -> FilterSpec
|
||||||
optsToFilterSpec opts@ReportOpts{..} d = FilterSpec {
|
filterSpecFromOpts opts@ReportOpts{..} d = FilterSpec {
|
||||||
datespan=dateSpanFromOpts d opts
|
datespan=dateSpanFromOpts d opts
|
||||||
,cleared= clearedValueFromOpts opts
|
,cleared= clearedValueFromOpts opts
|
||||||
,real=real_
|
,real=real_
|
||||||
@ -384,7 +384,7 @@ triBalance (_,_,_,_,_,Mixed a) = case a of [] -> "0"
|
|||||||
|
|
||||||
-- | Select transactions from the whole journal for a transactions report,
|
-- | Select transactions from the whole journal for a transactions report,
|
||||||
-- with no \"current\" account. The end result is similar to
|
-- with no \"current\" account. The end result is similar to
|
||||||
-- "postingsReport" except it uses matchers and transaction-based report
|
-- "postingsReport" except it uses queries and transaction-based report
|
||||||
-- items and the items are most recent first. Used by eg hledger-web's
|
-- items and the items are most recent first. Used by eg hledger-web's
|
||||||
-- journal view.
|
-- journal view.
|
||||||
journalTransactionsReport :: ReportOpts -> Journal -> Matcher -> TransactionsReport
|
journalTransactionsReport :: ReportOpts -> Journal -> Matcher -> TransactionsReport
|
||||||
@ -411,43 +411,43 @@ journalTransactionsReport _ Journal{jtxns=ts} m = (totallabel, items)
|
|||||||
-- most recent first. Used by eg hledger-web's account register view.
|
-- most recent first. Used by eg hledger-web's account register view.
|
||||||
--
|
--
|
||||||
accountTransactionsReport :: ReportOpts -> Journal -> Matcher -> Matcher -> TransactionsReport
|
accountTransactionsReport :: ReportOpts -> Journal -> Matcher -> Matcher -> TransactionsReport
|
||||||
accountTransactionsReport opts j m thisacctmatcher = (label, items)
|
accountTransactionsReport opts j m thisacctquery = (label, items)
|
||||||
where
|
where
|
||||||
-- transactions affecting this account, in date order
|
-- transactions affecting this account, in date order
|
||||||
ts = sortBy (comparing tdate) $ filter (matchesTransaction thisacctmatcher) $ jtxns $
|
ts = sortBy (comparing tdate) $ filter (matchesTransaction thisacctquery) $ jtxns $
|
||||||
journalSelectingDateFromOpts opts $ journalSelectingAmountFromOpts opts j
|
journalSelectingDateFromOpts opts $ journalSelectingAmountFromOpts opts j
|
||||||
-- starting balance: if we are filtering by a start date and nothing else,
|
-- starting balance: if we are filtering by a start date and nothing else,
|
||||||
-- the sum of postings to this account before that date; otherwise zero.
|
-- the sum of postings to this account before that date; otherwise zero.
|
||||||
(startbal,label) | matcherIsNull m = (nullmixedamt, balancelabel)
|
(startbal,label) | queryIsNull m = (nullmixedamt, balancelabel)
|
||||||
| matcherIsStartDateOnly (effective_ opts) m = (sumPostings priorps, balancelabel)
|
| queryIsStartDateOnly (effective_ opts) m = (sumPostings priorps, balancelabel)
|
||||||
| otherwise = (nullmixedamt, totallabel)
|
| otherwise = (nullmixedamt, totallabel)
|
||||||
where
|
where
|
||||||
priorps = -- ltrace "priorps" $
|
priorps = -- ltrace "priorps" $
|
||||||
filter (matchesPosting
|
filter (matchesPosting
|
||||||
(-- ltrace "priormatcher" $
|
(-- ltrace "priormatcher" $
|
||||||
MatchAnd [thisacctmatcher, tostartdatematcher]))
|
MatchAnd [thisacctquery, tostartdatequery]))
|
||||||
$ transactionsPostings ts
|
$ transactionsPostings ts
|
||||||
tostartdatematcher = MatchDate (DateSpan Nothing startdate)
|
tostartdatequery = MatchDate (DateSpan Nothing startdate)
|
||||||
startdate = matcherStartDate (effective_ opts) m
|
startdate = queryStartDate (effective_ opts) m
|
||||||
items = reverse $ accountTransactionsReportItems m (Just thisacctmatcher) startbal negate ts
|
items = reverse $ accountTransactionsReportItems m (Just thisacctquery) startbal negate ts
|
||||||
|
|
||||||
-- | Generate transactions report items from a list of transactions,
|
-- | Generate transactions report items from a list of transactions,
|
||||||
-- using the provided query and current account matchers, starting balance,
|
-- using the provided query and current account queries, starting balance,
|
||||||
-- sign-setting function and balance-summing function.
|
-- sign-setting function and balance-summing function.
|
||||||
accountTransactionsReportItems :: Matcher -> Maybe Matcher -> MixedAmount -> (MixedAmount -> MixedAmount) -> [Transaction] -> [TransactionsReportItem]
|
accountTransactionsReportItems :: Matcher -> Maybe Matcher -> MixedAmount -> (MixedAmount -> MixedAmount) -> [Transaction] -> [TransactionsReportItem]
|
||||||
accountTransactionsReportItems _ _ _ _ [] = []
|
accountTransactionsReportItems _ _ _ _ [] = []
|
||||||
accountTransactionsReportItems matcher thisacctmatcher bal signfn (t:ts) =
|
accountTransactionsReportItems query thisacctquery bal signfn (t:ts) =
|
||||||
-- This is used for both accountTransactionsReport and journalTransactionsReport,
|
-- This is used for both accountTransactionsReport and journalTransactionsReport,
|
||||||
-- which makes it a bit overcomplicated
|
-- which makes it a bit overcomplicated
|
||||||
case i of Just i' -> i':is
|
case i of Just i' -> i':is
|
||||||
Nothing -> is
|
Nothing -> is
|
||||||
where
|
where
|
||||||
tmatched@Transaction{tpostings=psmatched} = filterTransactionPostings matcher t
|
tmatched@Transaction{tpostings=psmatched} = filterTransactionPostings query t
|
||||||
(psthisacct,psotheracct) = case thisacctmatcher of Just m -> partition (matchesPosting m) psmatched
|
(psthisacct,psotheracct) = case thisacctquery of Just m -> partition (matchesPosting m) psmatched
|
||||||
Nothing -> ([],psmatched)
|
Nothing -> ([],psmatched)
|
||||||
numotheraccts = length $ nub $ map paccount psotheracct
|
numotheraccts = length $ nub $ map paccount psotheracct
|
||||||
amt = negate $ sum $ map pamount psthisacct
|
amt = negate $ sum $ map pamount psthisacct
|
||||||
acct | isNothing thisacctmatcher = summarisePostings psmatched -- journal register
|
acct | isNothing thisacctquery = summarisePostings psmatched -- journal register
|
||||||
| numotheraccts == 0 = "transfer between " ++ summarisePostingAccounts psthisacct
|
| numotheraccts == 0 = "transfer between " ++ summarisePostingAccounts psthisacct
|
||||||
| otherwise = prefix ++ summarisePostingAccounts psotheracct
|
| otherwise = prefix ++ summarisePostingAccounts psotheracct
|
||||||
where prefix = maybe "" (\b -> if b then "from " else "to ") $ isNegativeMixedAmount amt
|
where prefix = maybe "" (\b -> if b then "from " else "to ") $ isNegativeMixedAmount amt
|
||||||
@ -457,7 +457,7 @@ accountTransactionsReportItems matcher thisacctmatcher bal signfn (t:ts) =
|
|||||||
where
|
where
|
||||||
a = signfn amt
|
a = signfn amt
|
||||||
b = bal + a
|
b = bal + a
|
||||||
is = accountTransactionsReportItems matcher thisacctmatcher bal' signfn ts
|
is = accountTransactionsReportItems query thisacctquery bal' signfn ts
|
||||||
|
|
||||||
-- | Generate a short readable summary of some postings, like
|
-- | Generate a short readable summary of some postings, like
|
||||||
-- "from (negatives) to (positives)".
|
-- "from (negatives) to (positives)".
|
||||||
@ -498,10 +498,10 @@ accountsReport opts filterspec j = accountsReport' opts j (journalToLedger filte
|
|||||||
|
|
||||||
-- | Select accounts, and get their balances at the end of the selected
|
-- | Select accounts, and get their balances at the end of the selected
|
||||||
-- period, and misc. display information, for an accounts report. Like
|
-- period, and misc. display information, for an accounts report. Like
|
||||||
-- "accountsReport" but uses the new matchers. Used by eg hledger-web's
|
-- "accountsReport" but uses the new queries. Used by eg hledger-web's
|
||||||
-- accounts sidebar.
|
-- accounts sidebar.
|
||||||
accountsReport2 :: ReportOpts -> Matcher -> Journal -> AccountsReport
|
accountsReport2 :: ReportOpts -> Matcher -> Journal -> AccountsReport
|
||||||
accountsReport2 opts matcher j = accountsReport' opts j (journalToLedger2 matcher)
|
accountsReport2 opts query j = accountsReport' opts j (journalToLedger2 query)
|
||||||
|
|
||||||
-- Accounts report helper.
|
-- Accounts report helper.
|
||||||
accountsReport' :: ReportOpts -> Journal -> (Journal -> Ledger) -> AccountsReport
|
accountsReport' :: ReportOpts -> Journal -> (Journal -> Ledger) -> AccountsReport
|
||||||
|
|||||||
@ -138,7 +138,7 @@ getRegisterR = do
|
|||||||
(a,subs) = fromMaybe ("all accounts",False) $ inAccount qopts
|
(a,subs) = fromMaybe ("all accounts",False) $ inAccount qopts
|
||||||
andsubs = if subs then " (and subaccounts)" else ""
|
andsubs = if subs then " (and subaccounts)" else ""
|
||||||
filter = if filtering then ", filtered" else ""
|
filter = if filtering then ", filtered" else ""
|
||||||
maincontent = registerReportHtml opts vd $ accountTransactionsReport (reportopts_ $ cliopts_ opts) j m $ fromMaybe MatchAny $ inAccountMatcher qopts
|
maincontent = registerReportHtml opts vd $ accountTransactionsReport (reportopts_ $ cliopts_ opts) j m $ fromMaybe MatchAny $ inAccountQuery qopts
|
||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle "hledger-web register"
|
setTitle "hledger-web register"
|
||||||
addHamlet [$hamlet|
|
addHamlet [$hamlet|
|
||||||
@ -163,7 +163,7 @@ getRegisterOnlyR = do
|
|||||||
defaultLayout $ do
|
defaultLayout $ do
|
||||||
setTitle "hledger-web register only"
|
setTitle "hledger-web register only"
|
||||||
addHamlet $
|
addHamlet $
|
||||||
case inAccountMatcher qopts of Just m' -> registerReportHtml opts vd $ accountTransactionsReport (reportopts_ $ cliopts_ opts) j m m'
|
case inAccountQuery qopts of Just m' -> registerReportHtml opts vd $ accountTransactionsReport (reportopts_ $ cliopts_ opts) j m m'
|
||||||
Nothing -> registerReportHtml opts vd $ journalTransactionsReport (reportopts_ $ cliopts_ opts) j m
|
Nothing -> registerReportHtml opts vd $ journalTransactionsReport (reportopts_ $ cliopts_ opts) j m
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
@ -237,7 +237,7 @@ accountsReportAsHtml _ vd@VD{..} (items',total) =
|
|||||||
|]
|
|]
|
||||||
where
|
where
|
||||||
l = journalToLedger nullfilterspec j
|
l = journalToLedger nullfilterspec j
|
||||||
inacctmatcher = inAccountMatcher qopts
|
inacctmatcher = inAccountQuery qopts
|
||||||
allaccts = isNothing inacctmatcher
|
allaccts = isNothing inacctmatcher
|
||||||
items = items' -- maybe items' (\m -> filter (matchesAccount m . \(a,_,_,_)->a) items') showacctmatcher
|
items = items' -- maybe items' (\m -> filter (matchesAccount m . \(a,_,_,_)->a) items') showacctmatcher
|
||||||
itemAsHtml :: ViewData -> AccountsReportItem -> HtmlUrl AppRoute
|
itemAsHtml :: ViewData -> AccountsReportItem -> HtmlUrl AppRoute
|
||||||
@ -850,9 +850,9 @@ data ViewData = VD {
|
|||||||
,today :: Day -- ^ today's date (for queries containing relative dates)
|
,today :: Day -- ^ today's date (for queries containing relative dates)
|
||||||
,j :: Journal -- ^ the up-to-date parsed unfiltered journal
|
,j :: Journal -- ^ the up-to-date parsed unfiltered journal
|
||||||
,q :: String -- ^ the current q parameter, the main query expression
|
,q :: String -- ^ the current q parameter, the main query expression
|
||||||
,m :: Matcher -- ^ a matcher parsed from the q parameter
|
,m :: Matcher -- ^ a query parsed from the q parameter
|
||||||
,qopts :: [QueryOpt] -- ^ query options parsed from the q parameter
|
,qopts :: [QueryOpt] -- ^ query options parsed from the q parameter
|
||||||
,am :: Matcher -- ^ a matcher parsed from the accounts sidebar query expr ("a" parameter)
|
,am :: Matcher -- ^ a query parsed from the accounts sidebar query expr ("a" parameter)
|
||||||
,aopts :: [QueryOpt] -- ^ query options parsed from the accounts sidebar query expr
|
,aopts :: [QueryOpt] -- ^ query options parsed from the accounts sidebar query expr
|
||||||
,showpostings :: Bool -- ^ current p parameter, 1 or 0 shows/hides all postings where applicable
|
,showpostings :: Bool -- ^ current p parameter, 1 or 0 shows/hides all postings where applicable
|
||||||
}
|
}
|
||||||
|
|||||||
@ -110,7 +110,7 @@ tests_Hledger_Cli = TestList
|
|||||||
let opts `gives` es = do
|
let opts `gives` es = do
|
||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
accountsReportAsText opts (accountsReport opts (optsToFilterSpec opts d) j) `is` es
|
accountsReportAsText opts (accountsReport opts (filterSpecFromOpts opts d) j) `is` es
|
||||||
in TestList
|
in TestList
|
||||||
[
|
[
|
||||||
"balance report with no args" ~:
|
"balance report with no args" ~:
|
||||||
@ -281,7 +281,7 @@ tests_Hledger_Cli = TestList
|
|||||||
let opts = defreportopts{patterns_=["expenses"]}
|
let opts = defreportopts{patterns_=["expenses"]}
|
||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
showTransactions opts (optsToFilterSpec opts d) j `is` unlines
|
showTransactions opts (filterSpecFromOpts opts d) j `is` unlines
|
||||||
["2008/06/03 * eat & shop"
|
["2008/06/03 * eat & shop"
|
||||||
," expenses:food $1"
|
," expenses:food $1"
|
||||||
," expenses:supplies $1"
|
," expenses:supplies $1"
|
||||||
@ -294,7 +294,7 @@ tests_Hledger_Cli = TestList
|
|||||||
let opts = defreportopts{depth_=Just 2}
|
let opts = defreportopts{depth_=Just 2}
|
||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
showTransactions opts (optsToFilterSpec opts d) j `is` unlines
|
showTransactions opts (filterSpecFromOpts opts d) j `is` unlines
|
||||||
["2008/01/01 income"
|
["2008/01/01 income"
|
||||||
," income:salary $-1"
|
," income:salary $-1"
|
||||||
,""
|
,""
|
||||||
@ -323,7 +323,7 @@ tests_Hledger_Cli = TestList
|
|||||||
do
|
do
|
||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
let opts = defreportopts
|
let opts = defreportopts
|
||||||
(postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` unlines
|
(postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` unlines
|
||||||
["2008/01/01 income assets:bank:checking $1 $1"
|
["2008/01/01 income assets:bank:checking $1 $1"
|
||||||
," income:salary $-1 0"
|
," income:salary $-1 0"
|
||||||
,"2008/06/01 gift assets:bank:checking $1 $1"
|
,"2008/06/01 gift assets:bank:checking $1 $1"
|
||||||
@ -341,7 +341,7 @@ tests_Hledger_Cli = TestList
|
|||||||
do
|
do
|
||||||
let opts = defreportopts{cleared_=True}
|
let opts = defreportopts{cleared_=True}
|
||||||
j <- readJournal' sample_journal_str
|
j <- readJournal' sample_journal_str
|
||||||
(postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` unlines
|
(postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` unlines
|
||||||
["2008/06/03 eat & shop expenses:food $1 $1"
|
["2008/06/03 eat & shop expenses:food $1 $1"
|
||||||
," expenses:supplies $1 $2"
|
," expenses:supplies $1 $2"
|
||||||
," assets:cash $-2 0"
|
," assets:cash $-2 0"
|
||||||
@ -353,7 +353,7 @@ tests_Hledger_Cli = TestList
|
|||||||
do
|
do
|
||||||
let opts = defreportopts{uncleared_=True}
|
let opts = defreportopts{uncleared_=True}
|
||||||
j <- readJournal' sample_journal_str
|
j <- readJournal' sample_journal_str
|
||||||
(postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` unlines
|
(postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` unlines
|
||||||
["2008/01/01 income assets:bank:checking $1 $1"
|
["2008/01/01 income assets:bank:checking $1 $1"
|
||||||
," income:salary $-1 0"
|
," income:salary $-1 0"
|
||||||
,"2008/06/01 gift assets:bank:checking $1 $1"
|
,"2008/06/01 gift assets:bank:checking $1 $1"
|
||||||
@ -374,13 +374,13 @@ tests_Hledger_Cli = TestList
|
|||||||
," f"
|
," f"
|
||||||
]
|
]
|
||||||
let opts = defreportopts
|
let opts = defreportopts
|
||||||
registerdates (postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` ["2008/01/01","2008/02/02"]
|
registerdates (postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` ["2008/01/01","2008/02/02"]
|
||||||
|
|
||||||
,"register report with account pattern" ~:
|
,"register report with account pattern" ~:
|
||||||
do
|
do
|
||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
let opts = defreportopts{patterns_=["cash"]}
|
let opts = defreportopts{patterns_=["cash"]}
|
||||||
(postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` unlines
|
(postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` unlines
|
||||||
["2008/06/03 eat & shop assets:cash $-2 $-2"
|
["2008/06/03 eat & shop assets:cash $-2 $-2"
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -388,7 +388,7 @@ tests_Hledger_Cli = TestList
|
|||||||
do
|
do
|
||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
let opts = defreportopts{patterns_=["cAsH"]}
|
let opts = defreportopts{patterns_=["cAsH"]}
|
||||||
(postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` unlines
|
(postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` unlines
|
||||||
["2008/06/03 eat & shop assets:cash $-2 $-2"
|
["2008/06/03 eat & shop assets:cash $-2 $-2"
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -396,7 +396,7 @@ tests_Hledger_Cli = TestList
|
|||||||
do
|
do
|
||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
let gives displayexpr =
|
let gives displayexpr =
|
||||||
(registerdates (postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is`)
|
(registerdates (postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is`)
|
||||||
where opts = defreportopts{display_=Just displayexpr}
|
where opts = defreportopts{display_=Just displayexpr}
|
||||||
"d<[2008/6/2]" `gives` ["2008/01/01","2008/06/01"]
|
"d<[2008/6/2]" `gives` ["2008/01/01","2008/06/01"]
|
||||||
"d<=[2008/6/2]" `gives` ["2008/01/01","2008/06/01","2008/06/02"]
|
"d<=[2008/6/2]" `gives` ["2008/01/01","2008/06/01","2008/06/02"]
|
||||||
@ -409,7 +409,7 @@ tests_Hledger_Cli = TestList
|
|||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
let periodexpr `gives` dates = do
|
let periodexpr `gives` dates = do
|
||||||
j' <- samplejournal
|
j' <- samplejournal
|
||||||
registerdates (postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j') `is` dates
|
registerdates (postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j') `is` dates
|
||||||
where opts = defreportopts{period_=maybePeriod date1 periodexpr}
|
where opts = defreportopts{period_=maybePeriod date1 periodexpr}
|
||||||
"" `gives` ["2008/01/01","2008/06/01","2008/06/02","2008/06/03","2008/12/31"]
|
"" `gives` ["2008/01/01","2008/06/01","2008/06/02","2008/06/03","2008/12/31"]
|
||||||
"2008" `gives` ["2008/01/01","2008/06/01","2008/06/02","2008/06/03","2008/12/31"]
|
"2008" `gives` ["2008/01/01","2008/06/01","2008/06/02","2008/06/03","2008/12/31"]
|
||||||
@ -418,7 +418,7 @@ tests_Hledger_Cli = TestList
|
|||||||
"monthly" `gives` ["2008/01/01","2008/06/01","2008/12/01"]
|
"monthly" `gives` ["2008/01/01","2008/06/01","2008/12/01"]
|
||||||
"quarterly" `gives` ["2008/01/01","2008/04/01","2008/10/01"]
|
"quarterly" `gives` ["2008/01/01","2008/04/01","2008/10/01"]
|
||||||
let opts = defreportopts{period_=maybePeriod date1 "yearly"}
|
let opts = defreportopts{period_=maybePeriod date1 "yearly"}
|
||||||
(postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` unlines
|
(postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` unlines
|
||||||
["2008/01/01 - 2008/12/31 assets:bank:saving $1 $1"
|
["2008/01/01 - 2008/12/31 assets:bank:saving $1 $1"
|
||||||
," assets:cash $-2 $-1"
|
," assets:cash $-2 $-1"
|
||||||
," expenses:food $1 0"
|
," expenses:food $1 0"
|
||||||
@ -428,9 +428,9 @@ tests_Hledger_Cli = TestList
|
|||||||
," liabilities:debts $1 0"
|
," liabilities:debts $1 0"
|
||||||
]
|
]
|
||||||
let opts = defreportopts{period_=maybePeriod date1 "quarterly"}
|
let opts = defreportopts{period_=maybePeriod date1 "quarterly"}
|
||||||
registerdates (postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` ["2008/01/01","2008/04/01","2008/10/01"]
|
registerdates (postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` ["2008/01/01","2008/04/01","2008/10/01"]
|
||||||
let opts = defreportopts{period_=maybePeriod date1 "quarterly",empty_=True}
|
let opts = defreportopts{period_=maybePeriod date1 "quarterly",empty_=True}
|
||||||
registerdates (postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` ["2008/01/01","2008/04/01","2008/07/01","2008/10/01"]
|
registerdates (postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` ["2008/01/01","2008/04/01","2008/07/01","2008/10/01"]
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -438,7 +438,7 @@ tests_Hledger_Cli = TestList
|
|||||||
do
|
do
|
||||||
j <- samplejournal
|
j <- samplejournal
|
||||||
let opts = defreportopts{depth_=Just 2}
|
let opts = defreportopts{depth_=Just 2}
|
||||||
(postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` unlines
|
(postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` unlines
|
||||||
["2008/01/01 income assets:bank $1 $1"
|
["2008/01/01 income assets:bank $1 $1"
|
||||||
," income:salary $-1 0"
|
," income:salary $-1 0"
|
||||||
,"2008/06/01 gift assets:bank $1 $1"
|
,"2008/06/01 gift assets:bank $1 $1"
|
||||||
@ -460,7 +460,7 @@ tests_Hledger_Cli = TestList
|
|||||||
j <- readJournal'
|
j <- readJournal'
|
||||||
"2009/01/01 * медвежья шкура\n расходы:покупки 100\n актив:наличные\n"
|
"2009/01/01 * медвежья шкура\n расходы:покупки 100\n актив:наличные\n"
|
||||||
let opts = defreportopts
|
let opts = defreportopts
|
||||||
accountsReportAsText opts (accountsReport opts (optsToFilterSpec opts date1) j) `is`
|
accountsReportAsText opts (accountsReport opts (filterSpecFromOpts opts date1) j) `is`
|
||||||
[" -100 актив:наличные"
|
[" -100 актив:наличные"
|
||||||
," 100 расходы:покупки"
|
," 100 расходы:покупки"
|
||||||
,"--------------------"
|
,"--------------------"
|
||||||
@ -471,7 +471,7 @@ tests_Hledger_Cli = TestList
|
|||||||
j <- readJournal'
|
j <- readJournal'
|
||||||
"2009/01/01 * медвежья шкура\n расходы:покупки 100\n актив:наличные\n"
|
"2009/01/01 * медвежья шкура\n расходы:покупки 100\n актив:наличные\n"
|
||||||
let opts = defreportopts
|
let opts = defreportopts
|
||||||
(postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts date1) j) `is` unlines
|
(postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts date1) j) `is` unlines
|
||||||
["2009/01/01 медвежья шкура расходы:покупки 100 100"
|
["2009/01/01 медвежья шкура расходы:покупки 100 100"
|
||||||
," актив:наличные -100 0"]
|
," актив:наличные -100 0"]
|
||||||
|
|
||||||
|
|||||||
@ -229,7 +229,7 @@ registerFromString :: String -> IO String
|
|||||||
registerFromString s = do
|
registerFromString s = do
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
j <- readJournal' s
|
j <- readJournal' s
|
||||||
return $ postingsReportAsText opts $ postingsReport opts (optsToFilterSpec opts d) j
|
return $ postingsReportAsText opts $ postingsReport opts (filterSpecFromOpts opts d) j
|
||||||
where opts = defreportopts{empty_=True}
|
where opts = defreportopts{empty_=True}
|
||||||
|
|
||||||
-- | Return a similarity measure, from 0 to 1, for two strings.
|
-- | Return a similarity measure, from 0 to 1, for two strings.
|
||||||
|
|||||||
@ -117,7 +117,7 @@ balance CliOpts{reportopts_=ropts} j = do
|
|||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
let lines = case formatFromOpts ropts of
|
let lines = case formatFromOpts ropts of
|
||||||
Left err -> [err]
|
Left err -> [err]
|
||||||
Right _ -> accountsReportAsText ropts $ accountsReport ropts (optsToFilterSpec ropts d) j
|
Right _ -> accountsReportAsText ropts $ accountsReport ropts (filterSpecFromOpts ropts d) j
|
||||||
putStr $ unlines lines
|
putStr $ unlines lines
|
||||||
|
|
||||||
-- | Render a balance report as plain text suitable for console output.
|
-- | Render a balance report as plain text suitable for console output.
|
||||||
|
|||||||
@ -24,7 +24,7 @@ balancesheet :: CliOpts -> Journal -> IO ()
|
|||||||
balancesheet CliOpts{reportopts_=ropts} j = do
|
balancesheet CliOpts{reportopts_=ropts} j = do
|
||||||
let lines = case formatFromOpts ropts of
|
let lines = case formatFromOpts ropts of
|
||||||
Left err -> [err]
|
Left err -> [err]
|
||||||
Right _ -> accountsReportAsText ropts $ accountsReport2 ropts (journalBalanceSheetAccountMatcher j) j
|
Right _ -> accountsReportAsText ropts $ accountsReport2 ropts (journalBalanceSheetAccountQuery j) j
|
||||||
putStr $ unlines lines
|
putStr $ unlines lines
|
||||||
|
|
||||||
tests_Hledger_Cli_Balancesheet = TestList
|
tests_Hledger_Cli_Balancesheet = TestList
|
||||||
|
|||||||
@ -30,8 +30,8 @@ cashflow :: CliOpts -> Journal -> IO ()
|
|||||||
cashflow CliOpts{reportopts_=ropts} j = do
|
cashflow CliOpts{reportopts_=ropts} j = do
|
||||||
-- let lines = case formatFromOpts ropts of Left err, Right ...
|
-- let lines = case formatFromOpts ropts of Left err, Right ...
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
let m = optsToMatcher (withoutBeginDate ropts) d
|
let m = queryFromOpts (withoutBeginDate ropts) d
|
||||||
cashreport@(_,total) = accountsReport2 ropts (MatchAnd [m, journalCashAccountMatcher j]) j
|
cashreport@(_,total) = accountsReport2 ropts (MatchAnd [m, journalCashAccountQuery j]) j
|
||||||
-- operatingreport@(_,operating) = accountsReport2 ropts (MatchAnd [m, journalOperatingAccountMatcher j]) j
|
-- operatingreport@(_,operating) = accountsReport2 ropts (MatchAnd [m, journalOperatingAccountMatcher j]) j
|
||||||
-- investingreport@(_,investing) = accountsReport2 ropts (MatchAnd [m, journalInvestingAccountMatcher j]) j
|
-- investingreport@(_,investing) = accountsReport2 ropts (MatchAnd [m, journalInvestingAccountMatcher j]) j
|
||||||
-- financingreport@(_,financing) = accountsReport2 ropts (MatchAnd [m, journalFinancingAccountMatcher j]) j
|
-- financingreport@(_,financing) = accountsReport2 ropts (MatchAnd [m, journalFinancingAccountMatcher j]) j
|
||||||
|
|||||||
@ -25,7 +25,7 @@ barchar = '*'
|
|||||||
histogram :: CliOpts -> Journal -> IO ()
|
histogram :: CliOpts -> Journal -> IO ()
|
||||||
histogram CliOpts{reportopts_=reportopts_} j = do
|
histogram CliOpts{reportopts_=reportopts_} j = do
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
putStr $ showHistogram reportopts_ (optsToFilterSpec reportopts_ d) j
|
putStr $ showHistogram reportopts_ (filterSpecFromOpts reportopts_ d) j
|
||||||
|
|
||||||
showHistogram :: ReportOpts -> FilterSpec -> Journal -> String
|
showHistogram :: ReportOpts -> FilterSpec -> Journal -> String
|
||||||
showHistogram opts filterspec j = concatMap (printDayWith countBar) spanps
|
showHistogram opts filterspec j = concatMap (printDayWith countBar) spanps
|
||||||
|
|||||||
@ -24,7 +24,7 @@ incomestatement :: CliOpts -> Journal -> IO ()
|
|||||||
incomestatement CliOpts{reportopts_=ropts} j = do
|
incomestatement CliOpts{reportopts_=ropts} j = do
|
||||||
let lines = case formatFromOpts ropts of
|
let lines = case formatFromOpts ropts of
|
||||||
Left err -> [err]
|
Left err -> [err]
|
||||||
Right _ -> accountsReportAsText ropts $ accountsReport2 ropts (journalProfitAndLossAccountMatcher j) j
|
Right _ -> accountsReportAsText ropts $ accountsReport2 ropts (journalProfitAndLossAccountQuery j) j
|
||||||
putStr $ unlines lines
|
putStr $ unlines lines
|
||||||
|
|
||||||
tests_Hledger_Cli_Incomestatement = TestList
|
tests_Hledger_Cli_Incomestatement = TestList
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import Hledger.Cli.Options
|
|||||||
print' :: CliOpts -> Journal -> IO ()
|
print' :: CliOpts -> Journal -> IO ()
|
||||||
print' CliOpts{reportopts_=ropts} j = do
|
print' CliOpts{reportopts_=ropts} j = do
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
putStr $ showTransactions ropts (optsToFilterSpec ropts d) j
|
putStr $ showTransactions ropts (filterSpecFromOpts ropts d) j
|
||||||
|
|
||||||
showTransactions :: ReportOpts -> FilterSpec -> Journal -> String
|
showTransactions :: ReportOpts -> FilterSpec -> Journal -> String
|
||||||
showTransactions opts fspec j = entriesReportAsText opts fspec $ entriesReport opts fspec j
|
showTransactions opts fspec j = entriesReportAsText opts fspec $ entriesReport opts fspec j
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import Hledger.Cli.Options
|
|||||||
register :: CliOpts -> Journal -> IO ()
|
register :: CliOpts -> Journal -> IO ()
|
||||||
register CliOpts{reportopts_=ropts} j = do
|
register CliOpts{reportopts_=ropts} j = do
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
putStr $ postingsReportAsText ropts $ postingsReport ropts (optsToFilterSpec ropts d) j
|
putStr $ postingsReportAsText ropts $ postingsReport ropts (filterSpecFromOpts ropts d) j
|
||||||
|
|
||||||
-- | Render a register report as plain text suitable for console output.
|
-- | Render a register report as plain text suitable for console output.
|
||||||
postingsReportAsText :: ReportOpts -> PostingsReport -> String
|
postingsReportAsText :: ReportOpts -> PostingsReport -> String
|
||||||
|
|||||||
@ -24,7 +24,7 @@ import Hledger.Utils.UTF8IOCompat (putStr)
|
|||||||
stats :: CliOpts -> Journal -> IO ()
|
stats :: CliOpts -> Journal -> IO ()
|
||||||
stats CliOpts{reportopts_=reportopts_} j = do
|
stats CliOpts{reportopts_=reportopts_} j = do
|
||||||
d <- getCurrentDay
|
d <- getCurrentDay
|
||||||
let filterspec = optsToFilterSpec reportopts_ d
|
let filterspec = filterSpecFromOpts reportopts_ d
|
||||||
l = journalToLedger filterspec j
|
l = journalToLedger filterspec j
|
||||||
reportspan = (ledgerDateSpan l) `orDatesFrom` (datespan filterspec)
|
reportspan = (ledgerDateSpan l) `orDatesFrom` (datespan filterspec)
|
||||||
intervalspans = splitSpan (intervalFromOpts reportopts_) reportspan
|
intervalspans = splitSpan (intervalFromOpts reportopts_) reportspan
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user