handle pending status correctly, add --pending (#250)

A transaction/posting status of ! (pending) was effectively equivalent
to * (cleared). Now it's a separate state, not matched by --cleared.
The new Ledger-compatible --pending flag matches it, and so does
--uncleared. The equivalent search queries are now status:*, status:!
and status: (the old status:1 and status:0 spellings are deprecated).

Since we interpret --uncleared and status: as "any state except cleared",
it's not currently possible to match things which are neither cleared
nor pending.
This commit is contained in:
Simon Michael 2015-05-16 11:51:35 -07:00
parent 6fb0910996
commit d1f63334ee
17 changed files with 141 additions and 90 deletions

View File

@ -840,7 +840,8 @@ General flags:
all at once (overrides the flags above) all at once (overrides the flags above)
--date2 --aux-date use postings/txns' secondary dates instead --date2 --aux-date use postings/txns' secondary dates instead
-C --cleared include only cleared postings/txns -C --cleared include only cleared postings/txns
-U --uncleared include only uncleared postings/txns --pending include only pending postings/txns
-U --uncleared include only uncleared (and pending) postings/txns
-R --real include only non-virtual postings -R --real include only non-virtual postings
--depth=N hide accounts/postings deeper than N --depth=N hide accounts/postings deeper than N
-E --empty show empty/zero things which are normally omitted -E --empty show empty/zero things which are normally omitted
@ -962,7 +963,7 @@ A query term can be any of the following:
- `date2:PERIODEXPR` - as above, but match secondary dates - `date2:PERIODEXPR` - as above, but match secondary dates
- `tag:NAME[=REGEX]` - match by (exact, case sensitive) [tag](#tags) name, and optionally match the tag value by regular expression. Note `tag:` will match a transaction if it or any its postings have the tag, and will match posting if it or its parent transaction has the tag. - `tag:NAME[=REGEX]` - match by (exact, case sensitive) [tag](#tags) name, and optionally match the tag value by regular expression. Note `tag:` will match a transaction if it or any its postings have the tag, and will match posting if it or its parent transaction has the tag.
- `depth:N` - match (or display, depending on command) accounts at or above this [depth](#depth-limiting) - `depth:N` - match (or display, depending on command) accounts at or above this [depth](#depth-limiting)
- `status:1` or `status:0` - match pending/cleared or uncleared transactions respectively - `status:*` or `status:!` or `status:` - match cleared, pending, or uncleared/pending transactions respectively
- `real:1` or `real:0` - match real/virtual-ness - `real:1` or `real:0` - match real/virtual-ness
- `empty:1` or `empty:0` - match if amount is/is not zero - `empty:1` or `empty:0` - match if amount is/is not zero
- `amt:N`, `amt:<N`, `amt:<=N`, `amt:>N`, `amt:>=N` - match postings with a single-commodity - `amt:N`, `amt:<N`, `amt:<=N`, `amt:>N`, `amt:>=N` - match postings with a single-commodity

View File

@ -674,7 +674,7 @@ Right samplejournal = journalBalanceTransactions $
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2008/01/01", tdate=parsedate "2008/01/01",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="", tcode="",
tdescription="income", tdescription="income",
tcomment="", tcomment="",
@ -690,7 +690,7 @@ Right samplejournal = journalBalanceTransactions $
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2008/06/01", tdate=parsedate "2008/06/01",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="", tcode="",
tdescription="gift", tdescription="gift",
tcomment="", tcomment="",
@ -706,7 +706,7 @@ Right samplejournal = journalBalanceTransactions $
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2008/06/02", tdate=parsedate "2008/06/02",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="", tcode="",
tdescription="save", tdescription="save",
tcomment="", tcomment="",
@ -722,7 +722,7 @@ Right samplejournal = journalBalanceTransactions $
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2008/06/03", tdate=parsedate "2008/06/03",
tdate2=Nothing, tdate2=Nothing,
tstatus=True, tstatus=Cleared,
tcode="", tcode="",
tdescription="eat & shop", tdescription="eat & shop",
tcomment="", tcomment="",
@ -738,7 +738,7 @@ Right samplejournal = journalBalanceTransactions $
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2008/12/31", tdate=parsedate "2008/12/31",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="", tcode="",
tdescription="pay off", tdescription="pay off",
tcomment="", tcomment="",

View File

@ -13,7 +13,7 @@ module Hledger.Data.Posting (
posting, posting,
post, post,
-- * operations -- * operations
postingCleared, postingStatus,
isReal, isReal,
isVirtual, isVirtual,
isBalancedVirtual, isBalancedVirtual,
@ -67,7 +67,7 @@ nullposting, posting :: Posting
nullposting = Posting nullposting = Posting
{pdate=Nothing {pdate=Nothing
,pdate2=Nothing ,pdate2=Nothing
,pstatus=False ,pstatus=Uncleared
,paccount="" ,paccount=""
,pamount=nullmixedamt ,pamount=nullmixedamt
,pcomment="" ,pcomment=""
@ -137,14 +137,28 @@ postingDate2 p = headDef nulldate $ catMaybes dates
,maybe Nothing (Just . tdate) $ ptransaction p ,maybe Nothing (Just . tdate) $ ptransaction p
] ]
-- |Is this posting cleared? If this posting was individually marked -- | Get a posting's cleared status: cleared or pending if explicitly set,
-- as cleared, returns True. Otherwise, return the parent -- otherwise the cleared status of its parent transaction, or uncleared
-- transaction's cleared status or, if there is no parent -- if there is no parent transaction.
-- transaction, return False. -- (Note Uncleared's ambiguity, can mean "uncleared" or "don't know".
postingCleared :: Posting -> Bool postingStatus :: Posting -> ClearedStatus
postingCleared p = if pstatus p postingStatus Posting{pstatus=s, ptransaction=mt}
then True | s == Uncleared = case mt of Just t -> tstatus t
else maybe False tstatus $ ptransaction p Nothing -> Uncleared
| otherwise = s
-- -- | Is this posting cleared? True if the posting is explicitly marked
-- -- cleared, false if it is marked pending, otherwise true if the
-- -- parent transaction is marked cleared or false if there is no parent
-- -- transaction.
-- -- (Note Uncleared's ambiguity, can mean "uncleared" or "don't know".
-- postingIsCleared :: Posting -> Bool
-- postingIsCleared p
-- | pstatus p == Cleared = True
-- | pstatus p == Pending = False
-- | otherwise = case ptransaction p of
-- Just t -> tstatus t == Cleared
-- Nothing -> False
-- | Tags for this posting including any inherited from its parent transaction. -- | Tags for this posting including any inherited from its parent transaction.
postingAllTags :: Posting -> [Tag] postingAllTags :: Posting -> [Tag]

View File

@ -82,7 +82,7 @@ entryFromTimeLogInOut i o
tsourcepos = tlsourcepos i, tsourcepos = tlsourcepos i,
tdate = idate, tdate = idate,
tdate2 = Nothing, tdate2 = Nothing,
tstatus = True, tstatus = Cleared,
tcode = "", tcode = "",
tdescription = desc, tdescription = desc,
tcomment = "", tcomment = "",

View File

@ -64,7 +64,7 @@ nulltransaction = Transaction {
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=nulldate, tdate=nulldate,
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="", tcode="",
tdescription="", tdescription="",
tcomment="", tcomment="",
@ -102,14 +102,14 @@ tests_showTransactionUnelided = [
nulltransaction{ nulltransaction{
tdate=parsedate "2012/05/14", tdate=parsedate "2012/05/14",
tdate2=Just $ parsedate "2012/05/15", tdate2=Just $ parsedate "2012/05/15",
tstatus=False, tstatus=Uncleared,
tcode="code", tcode="code",
tdescription="desc", tdescription="desc",
tcomment="tcomment1\ntcomment2\n", tcomment="tcomment1\ntcomment2\n",
ttags=[("ttag1","val1")], ttags=[("ttag1","val1")],
tpostings=[ tpostings=[
nullposting{ nullposting{
pstatus=True, pstatus=Cleared,
paccount="a", paccount="a",
pamount=Mixed [usd 1, hrs 2], pamount=Mixed [usd 1, hrs 2],
pcomment="\npcomment2\n", pcomment="\npcomment2\n",
@ -140,7 +140,9 @@ showTransaction' elide t =
date = showdate (tdate t) ++ maybe "" showedate (tdate2 t) date = showdate (tdate t) ++ maybe "" showedate (tdate2 t)
showdate = printf "%-10s" . showDate showdate = printf "%-10s" . showDate
showedate = printf "=%s" . showdate showedate = printf "=%s" . showdate
status = if tstatus t then " *" else "" status | tstatus t == Cleared = " *"
| tstatus t == Pending = " !"
| otherwise = ""
code = if length (tcode t) > 0 then printf " (%s)" $ tcode t else "" code = if length (tcode t) > 0 then printf " (%s)" $ tcode t else ""
desc = if null d then "" else " " ++ d where d = tdescription t desc = if null d then "" else " " ++ d where d = tdescription t
(samelinecomment, newlinecomments) = (samelinecomment, newlinecomments) =
@ -184,7 +186,7 @@ postingAsLines elideamount ps p =
showacct p = showacct p =
indent $ showstatus p ++ printf (printf "%%-%ds" w) (showAccountName Nothing (ptype p) (paccount p)) indent $ showstatus p ++ printf (printf "%%-%ds" w) (showAccountName Nothing (ptype p) (paccount p))
where where
showstatus p = if pstatus p then "* " else "" showstatus p = if pstatus p == Cleared then "* " else ""
w = maximum $ map (length . paccount) ps w = maximum $ map (length . paccount) ps
showamt = showamt =
padleft 12 . showMixedAmount padleft 12 . showMixedAmount
@ -194,7 +196,7 @@ tests_postingAsLines = [
let p `gives` ls = assertEqual "" ls (postingAsLines False [p] p) let p `gives` ls = assertEqual "" ls (postingAsLines False [p] p)
posting `gives` [" 0"] posting `gives` [" 0"]
posting{ posting{
pstatus=True, pstatus=Cleared,
paccount="a", paccount="a",
pamount=Mixed [usd 1, hrs 2], pamount=Mixed [usd 1, hrs 2],
pcomment="pcomment1\npcomment2\n tag3: val3 \n", pcomment="pcomment1\npcomment2\n tag3: val3 \n",
@ -382,7 +384,7 @@ tests_Hledger_Data_Transaction = TestList $ concat [
," assets:checking" ," assets:checking"
,"" ,""
]) ])
(let t = Transaction nullsourcepos (parsedate "2007/01/28") Nothing False "" "coopportunity" "" [] (let t = Transaction nullsourcepos (parsedate "2007/01/28") Nothing Uncleared "" "coopportunity" "" []
[posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18], ptransaction=Just t} [posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18], ptransaction=Just t}
,posting{paccount="assets:checking", pamount=Mixed [usd (-47.18)], ptransaction=Just t} ,posting{paccount="assets:checking", pamount=Mixed [usd (-47.18)], ptransaction=Just t}
] "" ] ""
@ -396,7 +398,7 @@ tests_Hledger_Data_Transaction = TestList $ concat [
," assets:checking $-47.18" ," assets:checking $-47.18"
,"" ,""
]) ])
(let t = Transaction nullsourcepos (parsedate "2007/01/28") Nothing False "" "coopportunity" "" [] (let t = Transaction nullsourcepos (parsedate "2007/01/28") Nothing Uncleared "" "coopportunity" "" []
[posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18], ptransaction=Just t} [posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18], ptransaction=Just t}
,posting{paccount="assets:checking", pamount=Mixed [usd (-47.18)], ptransaction=Just t} ,posting{paccount="assets:checking", pamount=Mixed [usd (-47.18)], ptransaction=Just t}
] "" ] ""
@ -412,7 +414,7 @@ tests_Hledger_Data_Transaction = TestList $ concat [
,"" ,""
]) ])
(showTransaction (showTransaction
(txnTieKnot $ Transaction nullsourcepos (parsedate "2007/01/28") Nothing False "" "coopportunity" "" [] (txnTieKnot $ Transaction nullsourcepos (parsedate "2007/01/28") Nothing Uncleared "" "coopportunity" "" []
[posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18]} [posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18]}
,posting{paccount="assets:checking", pamount=Mixed [usd (-47.19)]} ,posting{paccount="assets:checking", pamount=Mixed [usd (-47.19)]}
] "")) ] ""))
@ -425,7 +427,7 @@ tests_Hledger_Data_Transaction = TestList $ concat [
,"" ,""
]) ])
(showTransaction (showTransaction
(txnTieKnot $ Transaction nullsourcepos (parsedate "2007/01/28") Nothing False "" "coopportunity" "" [] (txnTieKnot $ Transaction nullsourcepos (parsedate "2007/01/28") Nothing Uncleared "" "coopportunity" "" []
[posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18]} [posting{paccount="expenses:food:groceries", pamount=Mixed [usd 47.18]}
] "")) ] ""))
@ -437,7 +439,7 @@ tests_Hledger_Data_Transaction = TestList $ concat [
,"" ,""
]) ])
(showTransaction (showTransaction
(txnTieKnot $ Transaction nullsourcepos (parsedate "2007/01/28") Nothing False "" "coopportunity" "" [] (txnTieKnot $ Transaction nullsourcepos (parsedate "2007/01/28") Nothing Uncleared "" "coopportunity" "" []
[posting{paccount="expenses:food:groceries", pamount=missingmixedamt} [posting{paccount="expenses:food:groceries", pamount=missingmixedamt}
] "")) ] ""))
@ -450,7 +452,7 @@ tests_Hledger_Data_Transaction = TestList $ concat [
,"" ,""
]) ])
(showTransaction (showTransaction
(txnTieKnot $ Transaction nullsourcepos (parsedate "2010/01/01") Nothing False "" "x" "" [] (txnTieKnot $ Transaction nullsourcepos (parsedate "2010/01/01") Nothing Uncleared "" "x" "" []
[posting{paccount="a", pamount=Mixed [num 1 `at` (usd 2 `withPrecision` 0)]} [posting{paccount="a", pamount=Mixed [num 1 `at` (usd 2 `withPrecision` 0)]}
,posting{paccount="b", pamount= missingmixedamt} ,posting{paccount="b", pamount= missingmixedamt}
] "")) ] ""))
@ -458,19 +460,19 @@ tests_Hledger_Data_Transaction = TestList $ concat [
,"balanceTransaction" ~: do ,"balanceTransaction" ~: do
assertBool "detect unbalanced entry, sign error" assertBool "detect unbalanced entry, sign error"
(isLeft $ balanceTransaction Nothing (isLeft $ balanceTransaction Nothing
(Transaction nullsourcepos (parsedate "2007/01/28") Nothing False "" "test" "" [] (Transaction nullsourcepos (parsedate "2007/01/28") Nothing Uncleared "" "test" "" []
[posting{paccount="a", pamount=Mixed [usd 1]} [posting{paccount="a", pamount=Mixed [usd 1]}
,posting{paccount="b", pamount=Mixed [usd 1]} ,posting{paccount="b", pamount=Mixed [usd 1]}
] "")) ] ""))
assertBool "detect unbalanced entry, multiple missing amounts" assertBool "detect unbalanced entry, multiple missing amounts"
(isLeft $ balanceTransaction Nothing (isLeft $ balanceTransaction Nothing
(Transaction nullsourcepos (parsedate "2007/01/28") Nothing False "" "test" "" [] (Transaction nullsourcepos (parsedate "2007/01/28") Nothing Uncleared "" "test" "" []
[posting{paccount="a", pamount=missingmixedamt} [posting{paccount="a", pamount=missingmixedamt}
,posting{paccount="b", pamount=missingmixedamt} ,posting{paccount="b", pamount=missingmixedamt}
] "")) ] ""))
let e = balanceTransaction Nothing (Transaction nullsourcepos (parsedate "2007/01/28") Nothing False "" "" "" [] let e = balanceTransaction Nothing (Transaction nullsourcepos (parsedate "2007/01/28") Nothing Uncleared "" "" "" []
[posting{paccount="a", pamount=Mixed [usd 1]} [posting{paccount="a", pamount=Mixed [usd 1]}
,posting{paccount="b", pamount=missingmixedamt} ,posting{paccount="b", pamount=missingmixedamt}
] "") ] "")
@ -481,7 +483,7 @@ tests_Hledger_Data_Transaction = TestList $ concat [
Right e' -> (pamount $ last $ tpostings e') Right e' -> (pamount $ last $ tpostings e')
Left _ -> error' "should not happen") Left _ -> error' "should not happen")
let e = balanceTransaction Nothing (Transaction nullsourcepos (parsedate "2011/01/01") Nothing False "" "" "" [] let e = balanceTransaction Nothing (Transaction nullsourcepos (parsedate "2011/01/01") Nothing Uncleared "" "" "" []
[posting{paccount="a", pamount=Mixed [usd 1.35]} [posting{paccount="a", pamount=Mixed [usd 1.35]}
,posting{paccount="b", pamount=Mixed [eur (-1)]} ,posting{paccount="b", pamount=Mixed [eur (-1)]}
] "") ] "")
@ -493,49 +495,49 @@ tests_Hledger_Data_Transaction = TestList $ concat [
Left _ -> error' "should not happen") Left _ -> error' "should not happen")
assertBool "balanceTransaction balances based on cost if there are unit prices" (isRight $ assertBool "balanceTransaction balances based on cost if there are unit prices" (isRight $
balanceTransaction Nothing (Transaction nullsourcepos (parsedate "2011/01/01") Nothing False "" "" "" [] balanceTransaction Nothing (Transaction nullsourcepos (parsedate "2011/01/01") Nothing Uncleared "" "" "" []
[posting{paccount="a", pamount=Mixed [usd 1 `at` eur 2]} [posting{paccount="a", pamount=Mixed [usd 1 `at` eur 2]}
,posting{paccount="a", pamount=Mixed [usd (-2) `at` eur 1]} ,posting{paccount="a", pamount=Mixed [usd (-2) `at` eur 1]}
] "")) ] ""))
assertBool "balanceTransaction balances based on cost if there are total prices" (isRight $ assertBool "balanceTransaction balances based on cost if there are total prices" (isRight $
balanceTransaction Nothing (Transaction nullsourcepos (parsedate "2011/01/01") Nothing False "" "" "" [] balanceTransaction Nothing (Transaction nullsourcepos (parsedate "2011/01/01") Nothing Uncleared "" "" "" []
[posting{paccount="a", pamount=Mixed [usd 1 @@ eur 1]} [posting{paccount="a", pamount=Mixed [usd 1 @@ eur 1]}
,posting{paccount="a", pamount=Mixed [usd (-2) @@ eur 1]} ,posting{paccount="a", pamount=Mixed [usd (-2) @@ eur 1]}
] "")) ] ""))
,"isTransactionBalanced" ~: do ,"isTransactionBalanced" ~: do
let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing False "" "a" "" [] let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing Uncleared "" "a" "" []
[posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t} [posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t}
,posting{paccount="c", pamount=Mixed [usd (-1.00)], ptransaction=Just t} ,posting{paccount="c", pamount=Mixed [usd (-1.00)], ptransaction=Just t}
] "" ] ""
assertBool "detect balanced" (isTransactionBalanced Nothing t) assertBool "detect balanced" (isTransactionBalanced Nothing t)
let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing False "" "a" "" [] let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing Uncleared "" "a" "" []
[posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t} [posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t}
,posting{paccount="c", pamount=Mixed [usd (-1.01)], ptransaction=Just t} ,posting{paccount="c", pamount=Mixed [usd (-1.01)], ptransaction=Just t}
] "" ] ""
assertBool "detect unbalanced" (not $ isTransactionBalanced Nothing t) assertBool "detect unbalanced" (not $ isTransactionBalanced Nothing t)
let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing False "" "a" "" [] let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing Uncleared "" "a" "" []
[posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t} [posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t}
] "" ] ""
assertBool "detect unbalanced, one posting" (not $ isTransactionBalanced Nothing t) assertBool "detect unbalanced, one posting" (not $ isTransactionBalanced Nothing t)
let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing False "" "a" "" [] let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing Uncleared "" "a" "" []
[posting{paccount="b", pamount=Mixed [usd 0], ptransaction=Just t} [posting{paccount="b", pamount=Mixed [usd 0], ptransaction=Just t}
] "" ] ""
assertBool "one zero posting is considered balanced for now" (isTransactionBalanced Nothing t) assertBool "one zero posting is considered balanced for now" (isTransactionBalanced Nothing t)
let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing False "" "a" "" [] let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing Uncleared "" "a" "" []
[posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t} [posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t}
,posting{paccount="c", pamount=Mixed [usd (-1.00)], ptransaction=Just t} ,posting{paccount="c", pamount=Mixed [usd (-1.00)], ptransaction=Just t}
,posting{paccount="d", pamount=Mixed [usd 100], ptype=VirtualPosting, ptransaction=Just t} ,posting{paccount="d", pamount=Mixed [usd 100], ptype=VirtualPosting, ptransaction=Just t}
] "" ] ""
assertBool "virtual postings don't need to balance" (isTransactionBalanced Nothing t) assertBool "virtual postings don't need to balance" (isTransactionBalanced Nothing t)
let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing False "" "a" "" [] let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing Uncleared "" "a" "" []
[posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t} [posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t}
,posting{paccount="c", pamount=Mixed [usd (-1.00)], ptransaction=Just t} ,posting{paccount="c", pamount=Mixed [usd (-1.00)], ptransaction=Just t}
,posting{paccount="d", pamount=Mixed [usd 100], ptype=BalancedVirtualPosting, ptransaction=Just t} ,posting{paccount="d", pamount=Mixed [usd 100], ptype=BalancedVirtualPosting, ptransaction=Just t}
] "" ] ""
assertBool "balanced virtual postings need to balance among themselves" (not $ isTransactionBalanced Nothing t) assertBool "balanced virtual postings need to balance among themselves" (not $ isTransactionBalanced Nothing t)
let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing False "" "a" "" [] let t = Transaction nullsourcepos (parsedate "2009/01/01") Nothing Uncleared "" "a" "" []
[posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t} [posting{paccount="b", pamount=Mixed [usd 1.00], ptransaction=Just t}
,posting{paccount="c", pamount=Mixed [usd (-1.00)], ptransaction=Just t} ,posting{paccount="c", pamount=Mixed [usd (-1.00)], ptransaction=Just t}
,posting{paccount="d", pamount=Mixed [usd 100], ptype=BalancedVirtualPosting, ptransaction=Just t} ,posting{paccount="d", pamount=Mixed [usd 100], ptype=BalancedVirtualPosting, ptransaction=Just t}

View File

@ -5,7 +5,7 @@ Most data types are defined here to avoid import cycles.
Here is an overview of the hledger data model: Here is an overview of the hledger data model:
> Journal -- a journal is read from one or more data files. It contains.. > Journal -- a journal is read from one or more data files. It contains..
> [Transaction] -- journal transactions (aka entries), which have date, status, code, description and.. > [Transaction] -- journal transactions (aka entries), which have date, cleared status, code, description and..
> [Posting] -- multiple account postings, which have account name and amount > [Posting] -- multiple account postings, which have account name and amount
> [HistoricalPrice] -- historical commodity prices > [HistoricalPrice] -- historical commodity prices
> >
@ -116,10 +116,18 @@ data PostingType = RegularPosting | VirtualPosting | BalancedVirtualPosting
type Tag = (String, String) -- ^ A tag name and (possibly empty) value. type Tag = (String, String) -- ^ A tag name and (possibly empty) value.
data ClearedStatus = Uncleared | Pending | Cleared
deriving (Eq,Ord,Typeable,Data)
instance Show ClearedStatus where -- custom show
show Uncleared = "" -- a bad idea
show Pending = "!" -- don't do it
show Cleared = "*"
data Posting = Posting { data Posting = Posting {
pdate :: Maybe Day, -- ^ this posting's date, if different from the transaction's pdate :: Maybe Day, -- ^ this posting's date, if different from the transaction's
pdate2 :: Maybe Day, -- ^ this posting's secondary date, if different from the transaction's pdate2 :: Maybe Day, -- ^ this posting's secondary date, if different from the transaction's
pstatus :: Bool, pstatus :: ClearedStatus,
paccount :: AccountName, paccount :: AccountName,
pamount :: MixedAmount, pamount :: MixedAmount,
pcomment :: String, -- ^ this posting's comment lines, as a single non-indented multi-line string pcomment :: String, -- ^ this posting's comment lines, as a single non-indented multi-line string
@ -139,7 +147,7 @@ data Transaction = Transaction {
tsourcepos :: SourcePos, tsourcepos :: SourcePos,
tdate :: Day, tdate :: Day,
tdate2 :: Maybe Day, tdate2 :: Maybe Day,
tstatus :: Bool, -- XXX tcleared ? tstatus :: ClearedStatus,
tcode :: String, tcode :: String,
tdescription :: String, tdescription :: String,
tcomment :: String, -- ^ this transaction's comment lines, as a single non-indented multi-line string tcomment :: String, -- ^ this transaction's comment lines, as a single non-indented multi-line string

View File

@ -73,7 +73,7 @@ data Query = Any -- ^ always match
| Acct String -- ^ match postings whose account matches this regexp | Acct String -- ^ match postings whose account matches this regexp
| Date DateSpan -- ^ match if primary date in this date span | Date DateSpan -- ^ match if primary date in this date span
| Date2 DateSpan -- ^ match if secondary date in this date span | Date2 DateSpan -- ^ match if secondary date in this date span
| Status Bool -- ^ match if cleared status has this value | Status ClearedStatus -- ^ match if cleared status has this value
| Real Bool -- ^ match if "realness" (involves a real non-virtual account ?) has this value | Real Bool -- ^ match if "realness" (involves a real non-virtual account ?) has this value
| Amt OrdPlus Quantity -- ^ match if the amount's numeric quantity is less than/greater than/equal to/unsignedly equal to some value | Amt OrdPlus Quantity -- ^ match if the amount's numeric quantity is less than/greater than/equal to/unsignedly equal to some value
| Sym String -- ^ match if the entire commodity symbol is matched by this regexp | Sym String -- ^ match if the entire commodity symbol is matched by this regexp
@ -265,9 +265,11 @@ tests_parseQueryTerm = [
"a" `gives` (Left $ Acct "a") "a" `gives` (Left $ Acct "a")
"acct:expenses:autres d\233penses" `gives` (Left $ Acct "expenses:autres d\233penses") "acct:expenses:autres d\233penses" `gives` (Left $ Acct "expenses:autres d\233penses")
"not:desc:a b" `gives` (Left $ Not $ Desc "a b") "not:desc:a b" `gives` (Left $ Not $ Desc "a b")
"status:1" `gives` (Left $ Status True) "status:1" `gives` (Left $ Status Cleared)
"status:0" `gives` (Left $ Status False) "status:*" `gives` (Left $ Status Cleared)
"status:" `gives` (Left $ Status False) "status:!" `gives` (Left $ Status Pending)
"status:0" `gives` (Left $ Status Uncleared)
"status:" `gives` (Left $ Status Uncleared)
"real:1" `gives` (Left $ Real True) "real:1" `gives` (Left $ Real True)
"date:2008" `gives` (Left $ Date $ DateSpan (Just $ parsedate "2008/01/01") (Just $ parsedate "2009/01/01")) "date:2008" `gives` (Left $ Date $ DateSpan (Just $ parsedate "2008/01/01") (Just $ parsedate "2009/01/01"))
"date:from 2012/5/17" `gives` (Left $ Date $ DateSpan (Just $ parsedate "2012/05/17") Nothing) "date:from 2012/5/17" `gives` (Left $ Date $ DateSpan (Just $ parsedate "2012/05/17") Nothing)
@ -333,8 +335,10 @@ parseTag s | '=' `elem` s = (n, Just $ tail v)
-- -- , treating "*" or "!" as synonyms for "1". -- -- , treating "*" or "!" as synonyms for "1".
-- | Parse the boolean value part of a "status:" query. -- | Parse the boolean value part of a "status:" query.
parseStatus :: String -> Bool parseStatus :: String -> ClearedStatus
parseStatus s = s `elem` (truestrings) -- ++ ["*","!"]) parseStatus s | s `elem` ["1","*"] = Cleared
| s == "!" = Pending
| otherwise = Uncleared
-- | Parse the boolean value part of a "status:" query. "1" means true, -- | Parse the boolean value part of a "status:" query. "1" means true,
-- anything else will be parsed as false without error. -- anything else will be parsed as false without error.
@ -399,7 +403,7 @@ tests_filterQuery = [
let (q,p) `gives` r = assertEqual "" r (filterQuery p q) let (q,p) `gives` r = assertEqual "" r (filterQuery p q)
(Any, queryIsDepth) `gives` Any (Any, queryIsDepth) `gives` Any
(Depth 1, queryIsDepth) `gives` Depth 1 (Depth 1, queryIsDepth) `gives` Depth 1
(And [And [Status True,Depth 1]], not . queryIsDepth) `gives` Status True (And [And [Status Cleared,Depth 1]], not . queryIsDepth) `gives` Status Cleared
-- (And [Date nulldatespan, Not (Or [Any, Depth 1])], queryIsDepth) `gives` And [Not (Or [Depth 1])] -- (And [Date nulldatespan, Not (Or [Any, Depth 1])], queryIsDepth) `gives` And [Not (Or [Depth 1])]
] ]
@ -643,7 +647,8 @@ matchesPosting (Desc r) p = regexMatchesCI r $ maybe "" tdescription $ ptransact
matchesPosting (Acct r) p = regexMatchesCI r $ paccount p matchesPosting (Acct r) p = regexMatchesCI r $ paccount p
matchesPosting (Date span) p = span `spanContainsDate` postingDate p matchesPosting (Date span) p = span `spanContainsDate` postingDate p
matchesPosting (Date2 span) p = span `spanContainsDate` postingDate2 p matchesPosting (Date2 span) p = span `spanContainsDate` postingDate2 p
matchesPosting (Status v) p = v == postingCleared p matchesPosting (Status Uncleared) p = postingStatus p /= Cleared
matchesPosting (Status s) p = postingStatus p == s
matchesPosting (Real v) p = v == isReal p matchesPosting (Real v) p = v == isReal p
matchesPosting q@(Depth _) Posting{paccount=a} = q `matchesAccount` a matchesPosting q@(Depth _) Posting{paccount=a} = q `matchesAccount` a
matchesPosting q@(Amt _ _) Posting{pamount=amt} = q `matchesMixedAmount` amt matchesPosting q@(Amt _ _) Posting{pamount=amt} = q `matchesMixedAmount` amt
@ -660,16 +665,16 @@ matchesPosting (Tag n (Just v)) p = isJust $ lookupTagByNameAndValue (n,v) $ pos
tests_matchesPosting = [ tests_matchesPosting = [
"matchesPosting" ~: do "matchesPosting" ~: do
-- matching posting status.. -- matching posting status..
assertBool "positive match on true posting status" $ assertBool "positive match on cleared posting status" $
(Status True) `matchesPosting` nullposting{pstatus=True} (Status Cleared) `matchesPosting` nullposting{pstatus=Cleared}
assertBool "negative match on true posting status" $ assertBool "negative match on cleared posting status" $
not $ (Not $ Status True) `matchesPosting` nullposting{pstatus=True} not $ (Not $ Status Cleared) `matchesPosting` nullposting{pstatus=Cleared}
assertBool "positive match on false posting status" $ assertBool "positive match on unclered posting status" $
(Status False) `matchesPosting` nullposting{pstatus=False} (Status Uncleared) `matchesPosting` nullposting{pstatus=Uncleared}
assertBool "negative match on false posting status" $ assertBool "negative match on unclered posting status" $
not $ (Not $ Status False) `matchesPosting` nullposting{pstatus=False} not $ (Not $ Status Uncleared) `matchesPosting` nullposting{pstatus=Uncleared}
assertBool "positive match on true posting status acquired from transaction" $ assertBool "positive match on true posting status acquired from transaction" $
(Status True) `matchesPosting` nullposting{pstatus=False,ptransaction=Just nulltransaction{tstatus=True}} (Status Cleared) `matchesPosting` nullposting{pstatus=Uncleared,ptransaction=Just nulltransaction{tstatus=Cleared}}
assertBool "real:1 on real posting" $ (Real True) `matchesPosting` nullposting{ptype=RegularPosting} assertBool "real:1 on real posting" $ (Real True) `matchesPosting` nullposting{ptype=RegularPosting}
assertBool "real:1 on virtual posting fails" $ not $ (Real True) `matchesPosting` nullposting{ptype=VirtualPosting} assertBool "real:1 on virtual posting fails" $ not $ (Real True) `matchesPosting` nullposting{ptype=VirtualPosting}
assertBool "real:1 on balanced virtual posting fails" $ not $ (Real True) `matchesPosting` nullposting{ptype=BalancedVirtualPosting} assertBool "real:1 on balanced virtual posting fails" $ not $ (Real True) `matchesPosting` nullposting{ptype=BalancedVirtualPosting}
@ -701,7 +706,8 @@ matchesTransaction (Desc r) t = regexMatchesCI r $ tdescription t
matchesTransaction q@(Acct _) t = any (q `matchesPosting`) $ tpostings t matchesTransaction q@(Acct _) t = any (q `matchesPosting`) $ tpostings t
matchesTransaction (Date span) t = spanContainsDate span $ tdate t matchesTransaction (Date span) t = spanContainsDate span $ tdate t
matchesTransaction (Date2 span) t = spanContainsDate span $ transactionDate2 t matchesTransaction (Date2 span) t = spanContainsDate span $ transactionDate2 t
matchesTransaction (Status v) t = v == tstatus t matchesTransaction (Status Uncleared) t = tstatus t /= Cleared
matchesTransaction (Status s) t = tstatus t == s
matchesTransaction (Real v) t = v == hasRealPostings t matchesTransaction (Real v) t = v == hasRealPostings t
matchesTransaction q@(Amt _ _) t = any (q `matchesPosting`) $ tpostings t matchesTransaction q@(Amt _ _) t = any (q `matchesPosting`) $ tpostings t
matchesTransaction (Empty _) _ = True matchesTransaction (Empty _) _ = True

View File

@ -51,7 +51,7 @@ import Text.Printf (hPrintf,printf)
import Hledger.Data import Hledger.Data
import Hledger.Utils.UTF8IOCompat (getContents) import Hledger.Utils.UTF8IOCompat (getContents)
import Hledger.Utils import Hledger.Utils
import Hledger.Read.JournalReader (amountp) import Hledger.Read.JournalReader (amountp, statusp)
reader :: Reader reader :: Reader
@ -602,7 +602,15 @@ transactionFromCsvRecord sourcepos rules record = t
++"or "++maybe "add a" (const "change your") mskip++" skip rule" ++"or "++maybe "add a" (const "change your") mskip++" skip rule"
,"for m/d/y or d/m/y dates, use date-format %-m/%-d/%Y or date-format %-d/%-m/%Y" ,"for m/d/y or d/m/y dates, use date-format %-m/%-d/%Y or date-format %-d/%-m/%Y"
] ]
status = maybe False ((=="*") . render) $ mfieldtemplate "status" status =
case mfieldtemplate "status" of
Nothing -> Uncleared
Just str -> either statuserror id $ runParser (statusp <* eof) nullctx "" $ render str
where
statuserror err = error' $ unlines
["error: could not parse \""++str++"\" as a cleared status (should be *, ! or empty)"
,"the parse error is: "++show err
]
code = maybe "" render $ mfieldtemplate "code" code = maybe "" render $ mfieldtemplate "code"
description = maybe "" render $ mfieldtemplate "description" description = maybe "" render $ mfieldtemplate "description"
comment = maybe "" render $ mfieldtemplate "comment" comment = maybe "" render $ mfieldtemplate "comment"

View File

@ -36,6 +36,7 @@ module Hledger.Read.JournalReader (
amountp', amountp',
mamountp', mamountp',
numberp, numberp,
statusp,
emptyorcommentlinep, emptyorcommentlinep,
followingcommentp, followingcommentp,
accountaliasp accountaliasp
@ -367,7 +368,7 @@ transaction = do
date <- datep <?> "transaction" date <- datep <?> "transaction"
edate <- optionMaybe (secondarydatep date) <?> "secondary date" edate <- optionMaybe (secondarydatep date) <?> "secondary date"
lookAhead (spacenonewline <|> newline) <?> "whitespace or newline" lookAhead (spacenonewline <|> newline) <?> "whitespace or newline"
status <- status <?> "cleared flag" status <- statusp <?> "cleared status"
code <- codep <?> "transaction code" code <- codep <?> "transaction code"
description <- descriptionp >>= return . strip description <- descriptionp >>= return . strip
comment <- try followingcommentp <|> (newline >> return "") comment <- try followingcommentp <|> (newline >> return "")
@ -407,14 +408,14 @@ test_transaction = do
nulltransaction{ nulltransaction{
tdate=parsedate "2012/05/14", tdate=parsedate "2012/05/14",
tdate2=Just $ parsedate "2012/05/15", tdate2=Just $ parsedate "2012/05/15",
tstatus=False, tstatus=Uncleared,
tcode="code", tcode="code",
tdescription="desc", tdescription="desc",
tcomment=" tcomment1\n tcomment2\n ttag1: val1\n", tcomment=" tcomment1\n tcomment2\n ttag1: val1\n",
ttags=[("ttag1","val1")], ttags=[("ttag1","val1")],
tpostings=[ tpostings=[
nullposting{ nullposting{
pstatus=True, pstatus=Cleared,
paccount="a", paccount="a",
pamount=Mixed [usd 1], pamount=Mixed [usd 1],
pcomment=" pcomment1\n pcomment2\n ptag1: val1\n ptag2: val2\n", pcomment=" pcomment1\n pcomment2\n ptag1: val1\n ptag2: val2\n",
@ -535,8 +536,14 @@ secondarydatep primarydate = do
edate <- withDefaultYear primarydate datep edate <- withDefaultYear primarydate datep
return edate return edate
status :: Stream [Char] m Char => ParsecT [Char] JournalContext m Bool statusp :: Stream [Char] m Char => ParsecT [Char] JournalContext m ClearedStatus
status = try (do { many spacenonewline; (char '*' <|> char '!') <?> "status"; return True } ) <|> return False statusp =
choice'
[ many spacenonewline >> char '*' >> return Cleared
, many spacenonewline >> char '!' >> return Pending
, return Uncleared
]
<?> "cleared status"
codep :: Stream [Char] m Char => ParsecT [Char] JournalContext m String codep :: Stream [Char] m Char => ParsecT [Char] JournalContext m String
codep = try (do { many1 spacenonewline; char '(' <?> "codep"; code <- anyChar `manyTill` char ')'; return code } ) <|> return "" codep = try (do { many1 spacenonewline; char '(' <?> "codep"; code <- anyChar `manyTill` char ')'; return code } ) <|> return ""
@ -555,7 +562,7 @@ postings = many1 (try postingp) <?> "postings"
postingp :: Stream [Char] m Char => ParsecT [Char] JournalContext m Posting postingp :: Stream [Char] m Char => ParsecT [Char] JournalContext m Posting
postingp = do postingp = do
many1 spacenonewline many1 spacenonewline
status <- status status <- statusp
many spacenonewline many spacenonewline
account <- modifiedaccountname account <- modifiedaccountname
let (ptype, account') = (accountNamePostingType account, unbracket account) let (ptype, account') = (accountNamePostingType account, unbracket account)

View File

@ -332,7 +332,7 @@ Right samplejournal2 = journalBalanceTransactions $
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2008/01/01", tdate=parsedate "2008/01/01",
tdate2=Just $ parsedate "2009/01/01", tdate2=Just $ parsedate "2009/01/01",
tstatus=False, tstatus=Uncleared,
tcode="", tcode="",
tdescription="income", tdescription="income",
tcomment="", tcomment="",

View File

@ -228,8 +228,8 @@ tests_postingsReport = [
(Any, samplejournal) `gives` 11 (Any, samplejournal) `gives` 11
-- register --depth just clips account names -- register --depth just clips account names
(Depth 2, samplejournal) `gives` 11 (Depth 2, samplejournal) `gives` 11
(And [Depth 1, Status True, Acct "expenses"], samplejournal) `gives` 2 (And [Depth 1, Status Cleared, Acct "expenses"], samplejournal) `gives` 2
(And [And [Depth 1, Status True], Acct "expenses"], samplejournal) `gives` 2 (And [And [Depth 1, Status Cleared], Acct "expenses"], samplejournal) `gives` 2
-- with query and/or command-line options -- with query and/or command-line options
assertEqual "" 11 (length $ snd $ postingsReport defreportopts Any samplejournal) assertEqual "" 11 (length $ snd $ postingsReport defreportopts Any samplejournal)

View File

@ -63,6 +63,7 @@ data ReportOpts = ReportOpts {
,end_ :: Maybe Day ,end_ :: Maybe Day
,period_ :: Maybe (Interval,DateSpan) ,period_ :: Maybe (Interval,DateSpan)
,cleared_ :: Bool ,cleared_ :: Bool
,pending_ :: Bool
,uncleared_ :: Bool ,uncleared_ :: Bool
,cost_ :: Bool ,cost_ :: Bool
,depth_ :: Maybe Int ,depth_ :: Maybe Int
@ -119,6 +120,7 @@ defreportopts = ReportOpts
def def
def def
def def
def
rawOptsToReportOpts :: RawOpts -> IO ReportOpts rawOptsToReportOpts :: RawOpts -> IO ReportOpts
rawOptsToReportOpts rawopts = do rawOptsToReportOpts rawopts = do
@ -128,6 +130,7 @@ rawOptsToReportOpts rawopts = do
,end_ = maybesmartdateopt d "end" rawopts ,end_ = maybesmartdateopt d "end" rawopts
,period_ = maybeperiodopt d rawopts ,period_ = maybeperiodopt d rawopts
,cleared_ = boolopt "cleared" rawopts ,cleared_ = boolopt "cleared" rawopts
,pending_ = boolopt "pending" rawopts
,uncleared_ = boolopt "uncleared" rawopts ,uncleared_ = boolopt "uncleared" rawopts
,cost_ = boolopt "cost" rawopts ,cost_ = boolopt "cost" rawopts
,depth_ = maybeintopt "depth" rawopts ,depth_ = maybeintopt "depth" rawopts
@ -226,9 +229,10 @@ intervalFromOpts ReportOpts{..} =
| otherwise = NoInterval | otherwise = NoInterval
-- | Get a maybe boolean representing the last cleared/uncleared option if any. -- | Get a maybe boolean representing the last cleared/uncleared option if any.
clearedValueFromOpts :: ReportOpts -> Maybe Bool clearedValueFromOpts :: ReportOpts -> Maybe ClearedStatus
clearedValueFromOpts ReportOpts{..} | cleared_ = Just True clearedValueFromOpts ReportOpts{..} | cleared_ = Just Cleared
| uncleared_ = Just False | pending_ = Just Pending
| uncleared_ = Just Uncleared
| otherwise = Nothing | otherwise = Nothing
-- depthFromOpts :: ReportOpts -> Int -- depthFromOpts :: ReportOpts -> Int

View File

@ -81,7 +81,7 @@ $newline never
<li> <b><tt>desc:REGEXP</tt></b> - filter on description <li> <b><tt>desc:REGEXP</tt></b> - filter on description
<li> <b><tt>date:PERIODEXP</tt></b>, <b><tt>date2:PERIODEXP</tt></b> - filter on date or secondary date <li> <b><tt>date:PERIODEXP</tt></b>, <b><tt>date2:PERIODEXP</tt></b> - filter on date or secondary date
<li> <b><tt>code:REGEXP</tt></b> - filter on transaction's code (eg check number) <li> <b><tt>code:REGEXP</tt></b> - filter on transaction's code (eg check number)
<li> <b><tt>status:*</tt></b>, <b><tt>status:!</tt></b>, <b><tt>status:</tt></b> - filter on transaction's status flag (eg cleared status) <li> <b><tt>status:*</tt></b>, <b><tt>status:!</tt></b>, <b><tt>status:</tt></b> - filter on transaction's cleared status (cleared, pending, uncleared)
<!-- <li> <b><tt>empty:BOOL</tt></b> - filter on whether amount is zero --> <!-- <li> <b><tt>empty:BOOL</tt></b> - filter on whether amount is zero -->
<li> <b><tt>amt:N</tt></b>, <b><tt>amt:&lt;N</tt></b>, <b><tt>amt:&gt;N</tt></b> - filter on the unsigned amount magnitude. Or with a sign before N, filter on the signed value. (Single-commodity amounts only.) <li> <b><tt>amt:N</tt></b>, <b><tt>amt:&lt;N</tt></b>, <b><tt>amt:&gt;N</tt></b> - filter on the unsigned amount magnitude. Or with a sign before N, filter on the signed value. (Single-commodity amounts only.)
<li> <b><tt>cur:REGEXP</tt></b> - filter on the currency/commodity symbol (must match all of it). Dollar sign must be written as <tt>\$</tt> <li> <b><tt>cur:REGEXP</tt></b> - filter on the currency/commodity symbol (must match all of it). Dollar sign must be written as <tt>\$</tt>

View File

@ -346,7 +346,7 @@ journal7 = nulljournal {jtxns =
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2007/01/01", tdate=parsedate "2007/01/01",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="*", tcode="*",
tdescription="opening balance", tdescription="opening balance",
tcomment="", tcomment="",
@ -362,7 +362,7 @@ journal7 = nulljournal {jtxns =
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2007/02/01", tdate=parsedate "2007/02/01",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="*", tcode="*",
tdescription="ayres suites", tdescription="ayres suites",
tcomment="", tcomment="",
@ -378,7 +378,7 @@ journal7 = nulljournal {jtxns =
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2007/01/02", tdate=parsedate "2007/01/02",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="*", tcode="*",
tdescription="auto transfer to savings", tdescription="auto transfer to savings",
tcomment="", tcomment="",
@ -394,7 +394,7 @@ journal7 = nulljournal {jtxns =
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2007/01/03", tdate=parsedate "2007/01/03",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="*", tcode="*",
tdescription="poquito mas", tdescription="poquito mas",
tcomment="", tcomment="",
@ -410,7 +410,7 @@ journal7 = nulljournal {jtxns =
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2007/01/03", tdate=parsedate "2007/01/03",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="*", tcode="*",
tdescription="verizon", tdescription="verizon",
tcomment="", tcomment="",
@ -426,7 +426,7 @@ journal7 = nulljournal {jtxns =
tsourcepos=nullsourcepos, tsourcepos=nullsourcepos,
tdate=parsedate "2007/01/03", tdate=parsedate "2007/01/03",
tdate2=Nothing, tdate2=Nothing,
tstatus=False, tstatus=Uncleared,
tcode="*", tcode="*",
tdescription="discover", tdescription="discover",
tcomment="", tcomment="",

View File

@ -147,7 +147,7 @@ transactionWizard es@EntryState{..} = do
balancedPostingsWizard = do balancedPostingsWizard = do
ps <- postingsWizard es2{esPostings=[]} ps <- postingsWizard es2{esPostings=[]}
let t = nulltransaction{tdate=date let t = nulltransaction{tdate=date
,tstatus=False ,tstatus=Uncleared
,tcode=code ,tcode=code
,tdescription=desc ,tdescription=desc
,tcomment=comment ,tcomment=comment

View File

@ -121,8 +121,9 @@ reportflags = [
,flagReq ["period","p"] (\s opts -> Right $ setopt "period" s opts) "PERIODEXP" "set start date, end date, and/or reporting interval all at once (overrides the flags above)" ,flagReq ["period","p"] (\s opts -> Right $ setopt "period" s opts) "PERIODEXP" "set start date, end date, and/or reporting interval all at once (overrides the flags above)"
,flagNone ["date2","aux-date"] (setboolopt "date2") "use postings/txns' secondary dates instead" ,flagNone ["date2","aux-date"] (setboolopt "date2") "use postings/txns' secondary dates instead"
,flagNone ["cleared","C"] (setboolopt "cleared") "include only pending/cleared postings/txns" ,flagNone ["cleared","C"] (setboolopt "cleared") "include only cleared postings/txns"
,flagNone ["uncleared","U"] (setboolopt "uncleared") "include only uncleared postings/txns" ,flagNone ["pending"] (setboolopt "pending") "include only pending postings/txns"
,flagNone ["uncleared","U"] (setboolopt "uncleared") "include only uncleared (and pending) postings/txns"
,flagNone ["real","R"] (setboolopt "real") "include only non-virtual postings" ,flagNone ["real","R"] (setboolopt "real") "include only non-virtual postings"
,flagReq ["depth"] (\s opts -> Right $ setopt "depth" s opts) "N" "hide accounts/postings deeper than N" ,flagReq ["depth"] (\s opts -> Right $ setopt "depth" s opts) "N" "hide accounts/postings deeper than N"
,flagNone ["empty","E"] (setboolopt "empty") "show empty/zero things which are normally omitted" ,flagNone ["empty","E"] (setboolopt "empty") "show empty/zero things which are normally omitted"

View File

@ -100,7 +100,7 @@ transactionToCSV n t =
description = tdescription t description = tdescription t
date = showDate (tdate t) date = showDate (tdate t)
date2 = maybe "" showDate (tdate2 t) date2 = maybe "" showDate (tdate2 t)
status = if tstatus t then "*" else "" status = show $ tstatus t
code = tcode t code = tcode t
comment = chomp $ strip $ tcomment t comment = chomp $ strip $ tcomment t
@ -116,7 +116,7 @@ postingToCSV p =
amounts amounts
where where
Mixed amounts = pamount p Mixed amounts = pamount p
status = if pstatus p then "*" else "" status = show $ pstatus p
account = showAccountName Nothing (ptype p) (paccount p) account = showAccountName Nothing (ptype p) (paccount p)
comment = chomp $ strip $ pcomment p comment = chomp $ strip $ pcomment p