reorganize tests
This commit is contained in:
		
							parent
							
								
									e03ada3bd3
								
							
						
					
					
						commit
						dd9e78a67a
					
				| @ -37,16 +37,16 @@ import Hledger.Data.Utils | |||||||
| 
 | 
 | ||||||
| tests_Hledger_Data = TestList | tests_Hledger_Data = TestList | ||||||
|     [ |     [ | ||||||
|     --  Hledger.Data.Account.tests_Account |      tests_Hledger_Data_Account | ||||||
|     -- ,Hledger.Data.AccountName.tests_AccountName |     ,tests_Hledger_Data_AccountName | ||||||
|      Hledger.Data.Amount.tests_Amount |     ,tests_Hledger_Data_Amount | ||||||
|     -- ,Hledger.Data.Commodity.tests_Commodity |     ,tests_Hledger_Data_Commodity | ||||||
|     ,Hledger.Data.Dates.tests_Dates |     ,tests_Hledger_Data_Dates | ||||||
|     ,Hledger.Data.Transaction.tests_Transaction |     ,tests_Hledger_Data_Journal | ||||||
|     -- ,Hledger.Data.Hledger.Data.tests_Hledger.Data |     ,tests_Hledger_Data_Ledger | ||||||
|     -- ,Hledger.Data.Journal.tests_Journal |     ,tests_Hledger_Data_Posting | ||||||
|     -- ,Hledger.Data.Posting.tests_Posting |     ,tests_Hledger_Data_TimeLog | ||||||
|     ,Hledger.Data.TimeLog.tests_TimeLog |     ,tests_Hledger_Data_Transaction | ||||||
|     -- ,Hledger.Data.Types.tests_Types |     -- ,tests_Hledger_Data_Types | ||||||
|     -- ,Hledger.Data.Utils.tests_Utils |     -- ,tests_Hledger_Data_Utils | ||||||
|     ] |     ] | ||||||
|  | |||||||
| @ -25,3 +25,6 @@ instance Eq Account where | |||||||
| 
 | 
 | ||||||
| nullacct = Account "" [] nullmixedamt | nullacct = Account "" [] nullmixedamt | ||||||
| 
 | 
 | ||||||
|  | tests_Hledger_Data_Account = TestList [ | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -173,3 +173,29 @@ elideAccountName width s = | |||||||
| clipAccountName :: Int -> AccountName -> AccountName | clipAccountName :: Int -> AccountName -> AccountName | ||||||
| clipAccountName n = accountNameFromComponents . take n . accountNameComponents | clipAccountName n = accountNameFromComponents . take n . accountNameComponents | ||||||
| 
 | 
 | ||||||
|  | tests_Hledger_Data_AccountName = TestList | ||||||
|  |  [ | ||||||
|  |   "accountNameTreeFrom" ~: do | ||||||
|  |     accountNameTreeFrom ["a"]       `is` Node "top" [Node "a" []] | ||||||
|  |     accountNameTreeFrom ["a","b"]   `is` Node "top" [Node "a" [], Node "b" []] | ||||||
|  |     accountNameTreeFrom ["a","a:b"] `is` Node "top" [Node "a" [Node "a:b" []]] | ||||||
|  |     accountNameTreeFrom ["a:b:c"]   `is` Node "top" [Node "a" [Node "a:b" [Node "a:b:c" []]]] | ||||||
|  | 
 | ||||||
|  |   ,"expandAccountNames" ~: | ||||||
|  |     expandAccountNames ["assets:cash","assets:checking","expenses:vacation"] `is` | ||||||
|  |      ["assets","assets:cash","assets:checking","expenses","expenses:vacation"] | ||||||
|  | 
 | ||||||
|  |   ,"isAccountNamePrefixOf" ~: do | ||||||
|  |     "assets" `isAccountNamePrefixOf` "assets" `is` False | ||||||
|  |     "assets" `isAccountNamePrefixOf` "assets:bank" `is` True | ||||||
|  |     "assets" `isAccountNamePrefixOf` "assets:bank:checking" `is` True | ||||||
|  |     "my assets" `isAccountNamePrefixOf` "assets:bank" `is` False | ||||||
|  | 
 | ||||||
|  |   ,"isSubAccountNameOf" ~: do | ||||||
|  |     "assets" `isSubAccountNameOf` "assets" `is` False | ||||||
|  |     "assets:bank" `isSubAccountNameOf` "assets" `is` True | ||||||
|  |     "assets:bank:checking" `isSubAccountNameOf` "assets" `is` False | ||||||
|  |     "assets:bank" `isSubAccountNameOf` "my assets" `is` False | ||||||
|  | 
 | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -38,7 +38,32 @@ price-discarding arithmetic which ignores and discards prices. | |||||||
| 
 | 
 | ||||||
| -} | -} | ||||||
| 
 | 
 | ||||||
| module Hledger.Data.Amount | module Hledger.Data.Amount ( | ||||||
|  |                             amounts, | ||||||
|  |                             canonicaliseAmount, | ||||||
|  |                             canonicaliseMixedAmount, | ||||||
|  |                             convertMixedAmountTo, | ||||||
|  |                             costOfAmount, | ||||||
|  |                             costOfMixedAmount, | ||||||
|  |                             isNegativeMixedAmount, | ||||||
|  |                             isReallyZeroMixedAmountCost, | ||||||
|  |                             isZeroMixedAmount, | ||||||
|  |                             maxprecision, | ||||||
|  |                             missingamt, | ||||||
|  |                             normaliseMixedAmount, | ||||||
|  |                             nullamt, | ||||||
|  |                             nullmixedamt, | ||||||
|  |                             punctuatethousands, | ||||||
|  |                             showMixedAmount, | ||||||
|  |                             showMixedAmountDebug, | ||||||
|  |                             showMixedAmountOrZero, | ||||||
|  |                             showMixedAmountOrZeroWithoutPrice, | ||||||
|  |                             showMixedAmountWithoutPrice, | ||||||
|  |                             showMixedAmountWithPrecision, | ||||||
|  |                             sumMixedAmountsPreservingHighestPrecision, | ||||||
|  |                             tests_Hledger_Data_Amount | ||||||
|  |                             -- Hledger.Data.Amount.tests_Hledger_Data_Amount | ||||||
|  |                            ) | ||||||
| where | where | ||||||
| import qualified Data.Map as Map | import qualified Data.Map as Map | ||||||
| import Data.Map (findWithDefault) | import Data.Map (findWithDefault) | ||||||
| @ -216,14 +241,14 @@ isNegativeMixedAmount m = case as of [a] -> Just $ isNegativeAmount a | |||||||
| isReallyZeroMixedAmountCost :: MixedAmount -> Bool | isReallyZeroMixedAmountCost :: MixedAmount -> Bool | ||||||
| isReallyZeroMixedAmountCost = isReallyZeroMixedAmount . costOfMixedAmount | isReallyZeroMixedAmountCost = isReallyZeroMixedAmount . costOfMixedAmount | ||||||
| 
 | 
 | ||||||
| -- | MixedAmount derives Eq in Types.hs, but that doesn't know that we | -- -- | MixedAmount derives Eq in Types.hs, but that doesn't know that we | ||||||
| -- want $0 = EUR0 = 0. Yet we don't want to drag all this code in there. | -- -- want $0 = EUR0 = 0. Yet we don't want to drag all this code in there. | ||||||
| -- When zero equality is important, use this, for now; should be used | -- -- When zero equality is important, use this, for now; should be used | ||||||
| -- everywhere. | -- -- everywhere. | ||||||
| mixedAmountEquals :: MixedAmount -> MixedAmount -> Bool | -- mixedAmountEquals :: MixedAmount -> MixedAmount -> Bool | ||||||
| mixedAmountEquals a b = amounts a' == amounts b' || (isZeroMixedAmount a' && isZeroMixedAmount b') | -- mixedAmountEquals a b = amounts a' == amounts b' || (isZeroMixedAmount a' && isZeroMixedAmount b') | ||||||
|     where a' = normaliseMixedAmount a | --     where a' = normaliseMixedAmount a | ||||||
|           b' = normaliseMixedAmount b | --           b' = normaliseMixedAmount b | ||||||
| 
 | 
 | ||||||
| -- | Get the string representation of a mixed amount, showing each of | -- | Get the string representation of a mixed amount, showing each of | ||||||
| -- its component amounts. NB a mixed amount can have an empty amounts | -- its component amounts. NB a mixed amount can have an empty amounts | ||||||
| @ -231,8 +256,8 @@ mixedAmountEquals a b = amounts a' == amounts b' || (isZeroMixedAmount a' && isZ | |||||||
| showMixedAmount :: MixedAmount -> String | showMixedAmount :: MixedAmount -> String | ||||||
| showMixedAmount m = vConcatRightAligned $ map show $ amounts $ normaliseMixedAmount m | showMixedAmount m = vConcatRightAligned $ map show $ amounts $ normaliseMixedAmount m | ||||||
| 
 | 
 | ||||||
| setMixedAmountPrecision :: Int -> MixedAmount -> MixedAmount | -- setMixedAmountPrecision :: Int -> MixedAmount -> MixedAmount | ||||||
| setMixedAmountPrecision p (Mixed as) = Mixed $ map (setAmountPrecision p) as | -- setMixedAmountPrecision p (Mixed as) = Mixed $ map (setAmountPrecision p) as | ||||||
| 
 | 
 | ||||||
| -- | Get the string representation of a mixed amount, showing each of its | -- | Get the string representation of a mixed amount, showing each of its | ||||||
| -- component amounts with the specified precision, ignoring their | -- component amounts with the specified precision, ignoring their | ||||||
| @ -382,7 +407,7 @@ missingamt :: MixedAmount | |||||||
| missingamt = Mixed [Amount Commodity {symbol="AUTO",side=L,spaced=False,comma=False,precision=0} 0 Nothing] | missingamt = Mixed [Amount Commodity {symbol="AUTO",side=L,spaced=False,comma=False,precision=0} 0 Nothing] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| tests_Amount = TestList [ | tests_Hledger_Data_Amount = TestList [ | ||||||
| 
 | 
 | ||||||
|    "showMixedAmount" ~: do |    "showMixedAmount" ~: do | ||||||
|      showMixedAmount (Mixed [Amount dollar 0 Nothing]) `is` "$0.00" |      showMixedAmount (Mixed [Amount dollar 0 Nothing]) `is` "$0.00" | ||||||
| @ -417,5 +442,13 @@ tests_Amount = TestList [ | |||||||
|               Amount dollar (-0.25) Nothing]) |               Amount dollar (-0.25) Nothing]) | ||||||
|       `is` Mixed [Amount dollar 0 Nothing] |       `is` Mixed [Amount dollar 0 Nothing] | ||||||
| 
 | 
 | ||||||
|  |   ,"normaliseMixedAmount" ~: do | ||||||
|  |      normaliseMixedAmount (Mixed []) ~?= Mixed [nullamt] | ||||||
|  | 
 | ||||||
|  |   ,"punctuatethousands 1" ~: punctuatethousands "" `is` "" | ||||||
|  | 
 | ||||||
|  |   ,"punctuatethousands 2" ~: punctuatethousands "1234567.8901" `is` "1,234,567.8901" | ||||||
|  | 
 | ||||||
|  |   ,"punctuatethousands 3" ~: punctuatethousands "-100" `is` "-100" | ||||||
| 
 | 
 | ||||||
|   ] |   ] | ||||||
|  | |||||||
| @ -57,3 +57,7 @@ canonicaliseCommodities cs = | |||||||
|     commoditymap = Map.fromList [(s, commoditieswithsymbol s) | s <- symbols] |     commoditymap = Map.fromList [(s, commoditieswithsymbol s) | s <- symbols] | ||||||
|     commoditieswithsymbol s = filter ((s==) . symbol) cs |     commoditieswithsymbol s = filter ((s==) . symbol) cs | ||||||
|     symbols = nub $ map symbol cs |     symbols = nub $ map symbol cs | ||||||
|  | 
 | ||||||
|  | tests_Hledger_Data_Commodity = TestList [ | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -470,7 +470,8 @@ nulldatespan = DateSpan Nothing Nothing | |||||||
| 
 | 
 | ||||||
| nulldate = parsedate "1900/01/01" | nulldate = parsedate "1900/01/01" | ||||||
| 
 | 
 | ||||||
| tests_Dates = TestList [ | tests_Hledger_Data_Dates = TestList | ||||||
|  |  [ | ||||||
| 
 | 
 | ||||||
|    "splitSpan" ~: do |    "splitSpan" ~: do | ||||||
|     let gives (interval, span) = (splitSpan interval span `is`) |     let gives (interval, span) = (splitSpan interval span `is`) | ||||||
| @ -489,4 +490,53 @@ tests_Dates = TestList [ | |||||||
|     (Quarterly,mkdatespan "2008/01/01" "2008/01/01") `gives` |     (Quarterly,mkdatespan "2008/01/01" "2008/01/01") `gives` | ||||||
|      [mkdatespan "2008/01/01" "2008/01/01"] |      [mkdatespan "2008/01/01" "2008/01/01"] | ||||||
| 
 | 
 | ||||||
|  |   ,"parsedate" ~: do | ||||||
|  |     let date1 = parsedate "2008/11/26" | ||||||
|  |     parsedate "2008/02/03" `is` parsetimewith "%Y/%m/%d" "2008/02/03" date1 | ||||||
|  |     parsedate "2008-02-03" `is` parsetimewith "%Y/%m/%d" "2008/02/03" date1 | ||||||
|  | 
 | ||||||
|  |   ,"period expressions" ~: do | ||||||
|  |     let todaysdate = parsedate "2008/11/26" | ||||||
|  |     let str `gives` result = show (parsewith (periodexpr todaysdate) str) `is` ("Right " ++ result) | ||||||
|  |     "from aug to oct"           `gives` "(NoInterval,DateSpan (Just 2008-08-01) (Just 2008-10-01))" | ||||||
|  |     "aug to oct"                `gives` "(NoInterval,DateSpan (Just 2008-08-01) (Just 2008-10-01))" | ||||||
|  |     "every day from aug to oct" `gives` "(Daily,DateSpan (Just 2008-08-01) (Just 2008-10-01))" | ||||||
|  |     "daily from aug"            `gives` "(Daily,DateSpan (Just 2008-08-01) Nothing)" | ||||||
|  |     "every week to 2009"        `gives` "(Weekly,DateSpan Nothing (Just 2009-01-01))" | ||||||
|  | 
 | ||||||
|  |   ,"fixSmartDateStr" ~: do | ||||||
|  |     let gives = is . fixSmartDateStr (parsedate "2008/11/26") | ||||||
|  |     "1999-12-02"   `gives` "1999/12/02" | ||||||
|  |     "1999.12.02"   `gives` "1999/12/02" | ||||||
|  |     "1999/3/2"     `gives` "1999/03/02" | ||||||
|  |     "19990302"     `gives` "1999/03/02" | ||||||
|  |     "2008/2"       `gives` "2008/02/01" | ||||||
|  |     "0020/2"       `gives` "0020/02/01" | ||||||
|  |     "1000"         `gives` "1000/01/01" | ||||||
|  |     "4/2"          `gives` "2008/04/02" | ||||||
|  |     "2"            `gives` "2008/11/02" | ||||||
|  |     "January"      `gives` "2008/01/01" | ||||||
|  |     "feb"          `gives` "2008/02/01" | ||||||
|  |     "today"        `gives` "2008/11/26" | ||||||
|  |     "yesterday"    `gives` "2008/11/25" | ||||||
|  |     "tomorrow"     `gives` "2008/11/27" | ||||||
|  |     "this day"     `gives` "2008/11/26" | ||||||
|  |     "last day"     `gives` "2008/11/25" | ||||||
|  |     "next day"     `gives` "2008/11/27" | ||||||
|  |     "this week"    `gives` "2008/11/24" -- last monday | ||||||
|  |     "last week"    `gives` "2008/11/17" -- previous monday | ||||||
|  |     "next week"    `gives` "2008/12/01" -- next monday | ||||||
|  |     "this month"   `gives` "2008/11/01" | ||||||
|  |     "last month"   `gives` "2008/10/01" | ||||||
|  |     "next month"   `gives` "2008/12/01" | ||||||
|  |     "this quarter" `gives` "2008/10/01" | ||||||
|  |     "last quarter" `gives` "2008/07/01" | ||||||
|  |     "next quarter" `gives` "2009/01/01" | ||||||
|  |     "this year"    `gives` "2008/01/01" | ||||||
|  |     "last year"    `gives` "2007/01/01" | ||||||
|  |     "next year"    `gives` "2009/01/01" | ||||||
|  | --     "last wed"     `gives` "2008/11/19" | ||||||
|  | --     "next friday"  `gives` "2008/11/28" | ||||||
|  | --     "next january" `gives` "2009/01/01" | ||||||
|  | 
 | ||||||
|  ] |  ] | ||||||
|  | |||||||
| @ -389,3 +389,7 @@ postingsByAccount ps = m' | |||||||
|       sortedps = sortBy (comparing paccount) ps |       sortedps = sortBy (comparing paccount) ps | ||||||
|       groupedps = groupBy (\p1 p2 -> paccount p1 == paccount p2) sortedps |       groupedps = groupBy (\p1 p2 -> paccount p1 == paccount p2) sortedps | ||||||
|       m' = Map.fromList [(paccount $ head g, g) | g <- groupedps] |       m' = Map.fromList [(paccount $ head g, g) | g <- groupedps] | ||||||
|  | 
 | ||||||
|  | tests_Hledger_Data_Journal = TestList [ | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -122,3 +122,8 @@ rawdatespan = journalDateSpan . journal | |||||||
| 
 | 
 | ||||||
| ledgeramounts :: Ledger -> [MixedAmount] | ledgeramounts :: Ledger -> [MixedAmount] | ||||||
| ledgeramounts = journalAmounts . journal | ledgeramounts = journalAmounts . journal | ||||||
|  | 
 | ||||||
|  | tests_Hledger_Data_Ledger = TestList | ||||||
|  |  [ | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -91,3 +91,6 @@ postingsDateSpan [] = DateSpan Nothing Nothing | |||||||
| postingsDateSpan ps = DateSpan (Just $ postingDate $ head ps') (Just $ addDays 1 $ postingDate $ last ps') | postingsDateSpan ps = DateSpan (Just $ postingDate $ head ps') (Just $ addDays 1 $ postingDate $ last ps') | ||||||
|     where ps' = sortBy (comparing postingDate) ps |     where ps' = sortBy (comparing postingDate) ps | ||||||
| 
 | 
 | ||||||
|  | tests_Hledger_Data_Posting = TestList [ | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -90,7 +90,7 @@ entryFromTimeLogInOut i o | |||||||
|       ps       = [Posting{pstatus=False,paccount=acctname,pamount=amount, |       ps       = [Posting{pstatus=False,paccount=acctname,pamount=amount, | ||||||
|                           pcomment="",ptype=VirtualPosting,pmetadata=[],ptransaction=Just t}] |                           pcomment="",ptype=VirtualPosting,pmetadata=[],ptransaction=Just t}] | ||||||
| 
 | 
 | ||||||
| tests_TimeLog = TestList [ | tests_Hledger_Data_TimeLog = TestList [ | ||||||
| 
 | 
 | ||||||
|    "timeLogEntriesToTransactions" ~: do |    "timeLogEntriesToTransactions" ~: do | ||||||
|      today <- getCurrentDay |      today <- getCurrentDay | ||||||
|  | |||||||
| @ -182,7 +182,7 @@ txnTieKnot t@Transaction{tpostings=ps} = t{tpostings=map (settxn t) ps} | |||||||
| settxn :: Transaction -> Posting -> Posting | settxn :: Transaction -> Posting -> Posting | ||||||
| settxn t p = p{ptransaction=Just t} | settxn t p = p{ptransaction=Just t} | ||||||
| 
 | 
 | ||||||
| tests_Transaction = TestList [ | tests_Hledger_Data_Transaction = TestList [ | ||||||
|   "showTransaction" ~: do |   "showTransaction" ~: do | ||||||
|      assertEqual "show a balanced transaction, eliding last amount" |      assertEqual "show a balanced transaction, eliding last amount" | ||||||
|        (unlines |        (unlines | ||||||
| @ -264,4 +264,67 @@ tests_Transaction = TestList [ | |||||||
|          ,Posting False "b" missingamt "" RegularPosting [] Nothing |          ,Posting False "b" missingamt "" RegularPosting [] Nothing | ||||||
|          ] "")) |          ] "")) | ||||||
| 
 | 
 | ||||||
|  |   ,"balanceTransaction" ~: do | ||||||
|  |      assertBool "detect unbalanced entry, sign error" | ||||||
|  |                     (isLeft $ balanceTransaction Nothing | ||||||
|  |                            (Transaction (parsedate "2007/01/28") Nothing False "" "test" "" [] | ||||||
|  |                             [Posting False "a" (Mixed [dollars 1]) "" RegularPosting [] Nothing,  | ||||||
|  |                              Posting False "b" (Mixed [dollars 1]) "" RegularPosting [] Nothing | ||||||
|  |                             ] "")) | ||||||
|  |      assertBool "detect unbalanced entry, multiple missing amounts" | ||||||
|  |                     (isLeft $ balanceTransaction Nothing | ||||||
|  |                            (Transaction (parsedate "2007/01/28") Nothing False "" "test" "" [] | ||||||
|  |                             [Posting False "a" missingamt "" RegularPosting [] Nothing,  | ||||||
|  |                              Posting False "b" missingamt "" RegularPosting [] Nothing | ||||||
|  |                             ] "")) | ||||||
|  |      let e = balanceTransaction Nothing (Transaction (parsedate "2007/01/28") Nothing False "" "test" "" [] | ||||||
|  |                            [Posting False "a" (Mixed [dollars 1]) "" RegularPosting [] Nothing,  | ||||||
|  |                             Posting False "b" missingamt "" RegularPosting [] Nothing | ||||||
|  |                            ] "") | ||||||
|  |      assertBool "one missing amount should be ok" (isRight e) | ||||||
|  |      assertEqual "balancing amount is added"  | ||||||
|  |                      (Mixed [dollars (-1)]) | ||||||
|  |                      (case e of | ||||||
|  |                         Right e' -> (pamount $ last $ tpostings e') | ||||||
|  |                         Left _ -> error' "should not happen") | ||||||
|  | 
 | ||||||
|  |   ,"isTransactionBalanced" ~: do | ||||||
|  |      let t = Transaction (parsedate "2009/01/01") Nothing False "" "a" "" [] | ||||||
|  |              [Posting False "b" (Mixed [dollars 1.00]) "" RegularPosting [] (Just t) | ||||||
|  |              ,Posting False "c" (Mixed [dollars (-1.00)]) "" RegularPosting [] (Just t) | ||||||
|  |              ] "" | ||||||
|  |      assertBool "detect balanced" (isTransactionBalanced Nothing t) | ||||||
|  |      let t = Transaction (parsedate "2009/01/01") Nothing False "" "a" "" [] | ||||||
|  |              [Posting False "b" (Mixed [dollars 1.00]) "" RegularPosting [] (Just t) | ||||||
|  |              ,Posting False "c" (Mixed [dollars (-1.01)]) "" RegularPosting [] (Just t) | ||||||
|  |              ] "" | ||||||
|  |      assertBool "detect unbalanced" (not $ isTransactionBalanced Nothing t) | ||||||
|  |      let t = Transaction (parsedate "2009/01/01") Nothing False "" "a" "" [] | ||||||
|  |              [Posting False "b" (Mixed [dollars 1.00]) "" RegularPosting [] (Just t) | ||||||
|  |              ] "" | ||||||
|  |      assertBool "detect unbalanced, one posting" (not $ isTransactionBalanced Nothing t) | ||||||
|  |      let t = Transaction (parsedate "2009/01/01") Nothing False "" "a" "" [] | ||||||
|  |              [Posting False "b" (Mixed [dollars 0]) "" RegularPosting [] (Just t) | ||||||
|  |              ] "" | ||||||
|  |      assertBool "one zero posting is considered balanced for now" (isTransactionBalanced Nothing t) | ||||||
|  |      let t = Transaction (parsedate "2009/01/01") Nothing False "" "a" "" [] | ||||||
|  |              [Posting False "b" (Mixed [dollars 1.00]) "" RegularPosting [] (Just t) | ||||||
|  |              ,Posting False "c" (Mixed [dollars (-1.00)]) "" RegularPosting [] (Just t) | ||||||
|  |              ,Posting False "d" (Mixed [dollars 100]) "" VirtualPosting [] (Just t) | ||||||
|  |              ] "" | ||||||
|  |      assertBool "virtual postings don't need to balance" (isTransactionBalanced Nothing t) | ||||||
|  |      let t = Transaction (parsedate "2009/01/01") Nothing False "" "a" "" [] | ||||||
|  |              [Posting False "b" (Mixed [dollars 1.00]) "" RegularPosting [] (Just t) | ||||||
|  |              ,Posting False "c" (Mixed [dollars (-1.00)]) "" RegularPosting [] (Just t) | ||||||
|  |              ,Posting False "d" (Mixed [dollars 100]) "" BalancedVirtualPosting [] (Just t) | ||||||
|  |              ] "" | ||||||
|  |      assertBool "balanced virtual postings need to balance among themselves" (not $ isTransactionBalanced Nothing t) | ||||||
|  |      let t = Transaction (parsedate "2009/01/01") Nothing False "" "a" "" [] | ||||||
|  |              [Posting False "b" (Mixed [dollars 1.00]) "" RegularPosting [] (Just t) | ||||||
|  |              ,Posting False "c" (Mixed [dollars (-1.00)]) "" RegularPosting [] (Just t) | ||||||
|  |              ,Posting False "d" (Mixed [dollars 100]) "" BalancedVirtualPosting [] (Just t) | ||||||
|  |              ,Posting False "e" (Mixed [dollars (-100)]) "" BalancedVirtualPosting [] (Just t) | ||||||
|  |              ] "" | ||||||
|  |      assertBool "balanced virtual postings need to balance among themselves (2)" (isTransactionBalanced Nothing t) | ||||||
|  | 
 | ||||||
|   ] |   ] | ||||||
|  | |||||||
| @ -137,12 +137,12 @@ myTimelog = myTimelogPath >>= readJournalFile Nothing >>= either error' return | |||||||
| 
 | 
 | ||||||
| tests_Hledger_Read = TestList | tests_Hledger_Read = TestList | ||||||
|   [ |   [ | ||||||
|  |    tests_Hledger_Read_JournalReader, | ||||||
|  |    tests_Hledger_Read_TimelogReader, | ||||||
| 
 | 
 | ||||||
|    "journalFile" ~: do |    "journalFile" ~: do | ||||||
|     assertBool "journalFile should parse an empty file" (isRight $ parseWithCtx nullctx JournalReader.journalFile "") |     assertBool "journalFile should parse an empty file" (isRight $ parseWithCtx nullctx JournalReader.journalFile "") | ||||||
|     jE <- readJournal Nothing "" -- don't know how to get it from journalFile |     jE <- readJournal Nothing "" -- don't know how to get it from journalFile | ||||||
|     either error' (assertBool "journalFile parsing an empty file should give an empty journal" . null . jtxns) jE |     either error' (assertBool "journalFile parsing an empty file should give an empty journal" . null . jtxns) jE | ||||||
| 
 | 
 | ||||||
|   ,JournalReader.tests_JournalReader |  | ||||||
|   ,TimelogReader.tests_TimelogReader |  | ||||||
|   ] |   ] | ||||||
|  | |||||||
| @ -104,17 +104,17 @@ i, o, b, h | |||||||
| -} | -} | ||||||
| 
 | 
 | ||||||
| module Hledger.Read.JournalReader ( | module Hledger.Read.JournalReader ( | ||||||
|        tests_JournalReader, |        emptyLine, | ||||||
|        reader, |  | ||||||
|        journalFile, |  | ||||||
|        journalAddFile, |        journalAddFile, | ||||||
|        someamount, |        journalFile, | ||||||
|        ledgeraccountname, |        ledgeraccountname, | ||||||
|  |        ledgerdatetime, | ||||||
|  |        ledgerDefaultYear, | ||||||
|        ledgerExclamationDirective, |        ledgerExclamationDirective, | ||||||
|        ledgerHistoricalPrice, |        ledgerHistoricalPrice, | ||||||
|        ledgerDefaultYear, |        reader, | ||||||
|        emptyLine, |        someamount, | ||||||
|        ledgerdatetime, |        tests_Hledger_Read_JournalReader | ||||||
| ) | ) | ||||||
| where | where | ||||||
| import Control.Monad.Error (ErrorT(..), throwError, catchError) | import Control.Monad.Error (ErrorT(..), throwError, catchError) | ||||||
| @ -590,7 +590,7 @@ numberpartsstartingwithpoint = do | |||||||
|   return ("",frac) |   return ("",frac) | ||||||
|                       |                       | ||||||
| 
 | 
 | ||||||
| tests_JournalReader = TestList [ | tests_Hledger_Read_JournalReader = TestList [ | ||||||
| 
 | 
 | ||||||
|    "ledgerTransaction" ~: do |    "ledgerTransaction" ~: do | ||||||
|     assertParseEqual (parseWithCtx nullctx ledgerTransaction entry1_str) entry1 |     assertParseEqual (parseWithCtx nullctx ledgerTransaction entry1_str) entry1 | ||||||
|  | |||||||
| @ -43,8 +43,8 @@ o 2007/03/10 17:26:02 | |||||||
| -} | -} | ||||||
| 
 | 
 | ||||||
| module Hledger.Read.TimelogReader ( | module Hledger.Read.TimelogReader ( | ||||||
|        tests_TimelogReader, |  | ||||||
|        reader, |        reader, | ||||||
|  |        tests_Hledger_Read_TimelogReader | ||||||
| ) | ) | ||||||
| where | where | ||||||
| import Control.Monad.Error (ErrorT(..)) | import Control.Monad.Error (ErrorT(..)) | ||||||
| @ -96,6 +96,6 @@ timelogentry = do | |||||||
|   comment <- optionMaybe (many1 spacenonewline >> liftM2 (++) getParentAccount restofline) |   comment <- optionMaybe (many1 spacenonewline >> liftM2 (++) getParentAccount restofline) | ||||||
|   return $ TimeLogEntry (read [code]) datetime (maybe "" rstrip comment) |   return $ TimeLogEntry (read [code]) datetime (maybe "" rstrip comment) | ||||||
| 
 | 
 | ||||||
| tests_TimelogReader = TestList [ | tests_Hledger_Read_TimelogReader = TestList [ | ||||||
|  ] |  ] | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										909
									
								
								hledger/Hledger/Cli.hs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										909
									
								
								hledger/Hledger/Cli.hs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,909 @@ | |||||||
|  | {-|  | ||||||
|  | Hledger.Cli re-exports the options, utilities and commands provided by the | ||||||
|  | hledger command-line program. | ||||||
|  | -} | ||||||
|  | 
 | ||||||
|  | module Hledger.Cli ( | ||||||
|  |                      module Hledger.Cli.Add, | ||||||
|  |                      module Hledger.Cli.Balance, | ||||||
|  |                      module Hledger.Cli.Convert, | ||||||
|  |                      module Hledger.Cli.Histogram, | ||||||
|  |                      module Hledger.Cli.Print, | ||||||
|  |                      module Hledger.Cli.Register, | ||||||
|  |                      module Hledger.Cli.Stats, | ||||||
|  |                      module Hledger.Cli.Options, | ||||||
|  |                      module Hledger.Cli.Utils, | ||||||
|  |                      tests_Hledger_Cli | ||||||
|  |               ) | ||||||
|  | where | ||||||
|  | import Hledger.Cli.Add | ||||||
|  | import Hledger.Cli.Balance | ||||||
|  | import Hledger.Cli.Convert | ||||||
|  | import Hledger.Cli.Histogram | ||||||
|  | import Hledger.Cli.Print | ||||||
|  | import Hledger.Cli.Register | ||||||
|  | import Hledger.Cli.Stats | ||||||
|  | import Hledger.Cli.Options | ||||||
|  | import Hledger.Cli.Utils | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | import qualified Data.Map as Map | ||||||
|  | import System.Time (ClockTime(TOD)) | ||||||
|  | 
 | ||||||
|  | import Hledger.Data  -- including testing utils in Hledger.Data.Utils | ||||||
|  | import Hledger.Read | ||||||
|  | import Hledger.Read.JournalReader (someamount) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | -- | hledger and hledger-lib's unit tests aggregated from all modules | ||||||
|  | -- plus some more which are easier to define here for now. | ||||||
|  | -- tests_Hledger_Cli1 :: Test | ||||||
|  | tests_Hledger_Cli = TestList | ||||||
|  |  [ | ||||||
|  |     tests_Hledger_Data | ||||||
|  |    ,tests_Hledger_Read | ||||||
|  |    -- ,tests_Hledger_Cli_Add | ||||||
|  |    -- ,tests_Hledger_Cli_Balance | ||||||
|  |    ,tests_Hledger_Cli_Convert | ||||||
|  |    -- ,tests_Hledger_Cli_Histogram | ||||||
|  |    ,tests_Hledger_Cli_Options | ||||||
|  |    -- ,tests_Hledger_Cli_Print | ||||||
|  |    ,tests_Hledger_Cli_Register | ||||||
|  |    -- ,tests_Hledger_Cli_Stats | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |    ,"account directive" ~: | ||||||
|  |    let sameParse str1 str2 = do j1 <- readJournal Nothing str1 >>= either error' return | ||||||
|  |                                 j2 <- readJournal Nothing str2 >>= either error' return | ||||||
|  |                                 j1 `is` j2{filereadtime=filereadtime j1, files=files j1, jContext=jContext j1} | ||||||
|  |    in TestList | ||||||
|  |    [ | ||||||
|  |     "account directive 1" ~: sameParse  | ||||||
|  |                           "2008/12/07 One\n  test:from  $-1\n  test:to  $1\n" | ||||||
|  |                           "!account test\n2008/12/07 One\n  from  $-1\n  to  $1\n" | ||||||
|  | 
 | ||||||
|  |    ,"account directive 2" ~: sameParse  | ||||||
|  |                            "2008/12/07 One\n  test:foo:from  $-1\n  test:foo:to  $1\n" | ||||||
|  |                            "!account test\n!account foo\n2008/12/07 One\n  from  $-1\n  to  $1\n" | ||||||
|  | 
 | ||||||
|  |    ,"account directive 3" ~: sameParse  | ||||||
|  |                            "2008/12/07 One\n  test:from  $-1\n  test:to  $1\n" | ||||||
|  |                            "!account test\n!account foo\n!end\n2008/12/07 One\n  from  $-1\n  to  $1\n" | ||||||
|  | 
 | ||||||
|  |    ,"account directive 4" ~: sameParse  | ||||||
|  |                            ("2008/12/07 One\n  alpha  $-1\n  beta  $1\n" ++ | ||||||
|  |                             "!account outer\n2008/12/07 Two\n  aigh  $-2\n  bee  $2\n" ++ | ||||||
|  |                             "!account inner\n2008/12/07 Three\n  gamma  $-3\n  delta  $3\n" ++ | ||||||
|  |                             "!end\n2008/12/07 Four\n  why  $-4\n  zed  $4\n" ++ | ||||||
|  |                             "!end\n2008/12/07 Five\n  foo  $-5\n  bar  $5\n" | ||||||
|  |                            ) | ||||||
|  |                            ("2008/12/07 One\n  alpha  $-1\n  beta  $1\n" ++ | ||||||
|  |                             "2008/12/07 Two\n  outer:aigh  $-2\n  outer:bee  $2\n" ++ | ||||||
|  |                             "2008/12/07 Three\n  outer:inner:gamma  $-3\n  outer:inner:delta  $3\n" ++ | ||||||
|  |                             "2008/12/07 Four\n  outer:why  $-4\n  outer:zed  $4\n" ++ | ||||||
|  |                             "2008/12/07 Five\n  foo  $-5\n  bar  $5\n" | ||||||
|  |                            ) | ||||||
|  |    ] | ||||||
|  | 
 | ||||||
|  |   ,"ledgerAccountNames" ~: | ||||||
|  |     ledgerAccountNames ledger7 `is` | ||||||
|  |      ["assets","assets:cash","assets:checking","assets:saving","equity","equity:opening balances", | ||||||
|  |       "expenses","expenses:food","expenses:food:dining","expenses:phone","expenses:vacation", | ||||||
|  |       "liabilities","liabilities:credit cards","liabilities:credit cards:discover"] | ||||||
|  | 
 | ||||||
|  |   ,"balance report tests" ~: | ||||||
|  |    let (opts,args) `gives` es = do  | ||||||
|  |         l <- samplejournalwithopts opts args | ||||||
|  |         t <- getCurrentLocalTime | ||||||
|  |         balanceReportAsText opts (balanceReport opts (optsToFilterSpec opts args t) l) `is` unlines es | ||||||
|  |    in TestList | ||||||
|  |    [ | ||||||
|  | 
 | ||||||
|  |     "balance report with no args" ~: | ||||||
|  |     ([], []) `gives` | ||||||
|  |     ["                 $-1  assets" | ||||||
|  |     ,"                  $1    bank:saving" | ||||||
|  |     ,"                 $-2    cash" | ||||||
|  |     ,"                  $2  expenses" | ||||||
|  |     ,"                  $1    food" | ||||||
|  |     ,"                  $1    supplies" | ||||||
|  |     ,"                 $-2  income" | ||||||
|  |     ,"                 $-1    gifts" | ||||||
|  |     ,"                 $-1    salary" | ||||||
|  |     ,"                  $1  liabilities:debts" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                  $0" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report can be limited with --depth" ~: | ||||||
|  |     ([Depth "1"], []) `gives` | ||||||
|  |     ["                 $-1  assets" | ||||||
|  |     ,"                  $2  expenses" | ||||||
|  |     ,"                 $-2  income" | ||||||
|  |     ,"                  $1  liabilities" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                  $0" | ||||||
|  |     ] | ||||||
|  |      | ||||||
|  |    ,"balance report with account pattern o" ~: | ||||||
|  |     ([SubTotal], ["o"]) `gives` | ||||||
|  |     ["                  $1  expenses:food" | ||||||
|  |     ,"                 $-2  income" | ||||||
|  |     ,"                 $-1    gifts" | ||||||
|  |     ,"                 $-1    salary" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                 $-1" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report with account pattern o and --depth 1" ~: | ||||||
|  |     ([Depth "1"], ["o"]) `gives` | ||||||
|  |     ["                  $1  expenses" | ||||||
|  |     ,"                 $-2  income" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                 $-1" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report with account pattern a" ~: | ||||||
|  |     ([], ["a"]) `gives` | ||||||
|  |     ["                 $-1  assets" | ||||||
|  |     ,"                  $1    bank:saving" | ||||||
|  |     ,"                 $-2    cash" | ||||||
|  |     ,"                 $-1  income:salary" | ||||||
|  |     ,"                  $1  liabilities:debts" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                 $-1" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report with account pattern e" ~: | ||||||
|  |     ([], ["e"]) `gives` | ||||||
|  |     ["                 $-1  assets" | ||||||
|  |     ,"                  $1    bank:saving" | ||||||
|  |     ,"                 $-2    cash" | ||||||
|  |     ,"                  $2  expenses" | ||||||
|  |     ,"                  $1    food" | ||||||
|  |     ,"                  $1    supplies" | ||||||
|  |     ,"                 $-2  income" | ||||||
|  |     ,"                 $-1    gifts" | ||||||
|  |     ,"                 $-1    salary" | ||||||
|  |     ,"                  $1  liabilities:debts" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                  $0" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report with unmatched parent of two matched subaccounts" ~:  | ||||||
|  |     ([], ["cash","saving"]) `gives` | ||||||
|  |     ["                 $-1  assets" | ||||||
|  |     ,"                  $1    bank:saving" | ||||||
|  |     ,"                 $-2    cash" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                 $-1" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report with multi-part account name" ~:  | ||||||
|  |     ([], ["expenses:food"]) `gives` | ||||||
|  |     ["                  $1  expenses:food" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                  $1" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report with negative account pattern" ~: | ||||||
|  |     ([], ["not:assets"]) `gives` | ||||||
|  |     ["                  $2  expenses" | ||||||
|  |     ,"                  $1    food" | ||||||
|  |     ,"                  $1    supplies" | ||||||
|  |     ,"                 $-2  income" | ||||||
|  |     ,"                 $-1    gifts" | ||||||
|  |     ,"                 $-1    salary" | ||||||
|  |     ,"                  $1  liabilities:debts" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                  $1" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report negative account pattern always matches full name" ~:  | ||||||
|  |     ([], ["not:e"]) `gives` | ||||||
|  |     ["--------------------" | ||||||
|  |     ,"                   0" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report negative patterns affect totals" ~:  | ||||||
|  |     ([], ["expenses","not:food"]) `gives` | ||||||
|  |     ["                  $1  expenses:supplies" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                  $1" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report with -E shows zero-balance accounts" ~: | ||||||
|  |     ([SubTotal,Empty], ["assets"]) `gives` | ||||||
|  |     ["                 $-1  assets" | ||||||
|  |     ,"                  $1    bank" | ||||||
|  |     ,"                  $0      checking" | ||||||
|  |     ,"                  $1      saving" | ||||||
|  |     ,"                 $-2    cash" | ||||||
|  |     ,"--------------------" | ||||||
|  |     ,"                 $-1" | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report with cost basis" ~: do | ||||||
|  |       j <- (readJournal Nothing $ unlines | ||||||
|  |              ["" | ||||||
|  |              ,"2008/1/1 test           " | ||||||
|  |              ,"  a:b          10h @ $50" | ||||||
|  |              ,"  c:d                   " | ||||||
|  |              ]) >>= either error' return | ||||||
|  |       let j' = journalCanonicaliseAmounts $ journalConvertAmountsToCost j -- enable cost basis adjustment | ||||||
|  |       balanceReportAsText [] (balanceReport [] nullfilterspec j') `is` | ||||||
|  |        unlines | ||||||
|  |         ["                $500  a:b" | ||||||
|  |         ,"               $-500  c:d" | ||||||
|  |         ,"--------------------" | ||||||
|  |         ,"                  $0" | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  |    ,"balance report elides zero-balance root account(s)" ~: do | ||||||
|  |       l <- readJournalWithOpts [] | ||||||
|  |              (unlines | ||||||
|  |               ["2008/1/1 one" | ||||||
|  |               ,"  test:a  1" | ||||||
|  |               ,"  test:b" | ||||||
|  |               ]) | ||||||
|  |       balanceReportAsText [] (balanceReport [] nullfilterspec l) `is` | ||||||
|  |        unlines | ||||||
|  |         ["                   1  test:a" | ||||||
|  |         ,"                  -1  test:b" | ||||||
|  |         ,"--------------------" | ||||||
|  |         ,"                   0" | ||||||
|  |         ] | ||||||
|  | 
 | ||||||
|  |    ] | ||||||
|  | 
 | ||||||
|  |   ,"journalCanonicaliseAmounts" ~: | ||||||
|  |    "use the greatest precision" ~: | ||||||
|  |     (map precision $ journalAmountAndPriceCommodities $ journalCanonicaliseAmounts $ journalWithAmounts ["1","2.00"]) `is` [2,2] | ||||||
|  | 
 | ||||||
|  |   ,"commodities" ~: | ||||||
|  |     Map.elems (commodities ledger7) `is` [Commodity {symbol="$", side=L, spaced=False, comma=False, precision=2}] | ||||||
|  | 
 | ||||||
|  |   -- don't know what this should do | ||||||
|  |   -- ,"elideAccountName" ~: do | ||||||
|  |   --    (elideAccountName 50 "aaaaaaaaaaaaaaaaaaaa:aaaaaaaaaaaaaaaaaaaa:aaaaaaaaaaaaaaaaaaaa" | ||||||
|  |   --     `is` "aa:aaaaaaaaaaaaaaaaaaaa:aaaaaaaaaaaaaaaaaaaa") | ||||||
|  |   --    (elideAccountName 20 "aaaaaaaaaaaaaaaaaaaa:aaaaaaaaaaaaaaaaaaaa:aaaaaaaaaaaaaaaaaaaa" | ||||||
|  |   --     `is` "aa:aa:aaaaaaaaaaaaaa") | ||||||
|  | 
 | ||||||
|  |   ,"default year" ~: do | ||||||
|  |     rl <- readJournal Nothing defaultyear_journal_str >>= either error' return | ||||||
|  |     tdate (head $ jtxns rl) `is` fromGregorian 2009 1 1 | ||||||
|  |     return () | ||||||
|  | 
 | ||||||
|  |   ,"print report tests" ~: TestList | ||||||
|  |   [ | ||||||
|  | 
 | ||||||
|  |    "print expenses" ~: | ||||||
|  |    do  | ||||||
|  |     let args = ["expenses"] | ||||||
|  |     l <- samplejournalwithopts [] args | ||||||
|  |     t <- getCurrentLocalTime | ||||||
|  |     showTransactions (optsToFilterSpec [] args t) l `is` unlines | ||||||
|  |      ["2008/06/03 * eat & shop" | ||||||
|  |      ,"    expenses:food                $1" | ||||||
|  |      ,"    expenses:supplies            $1" | ||||||
|  |      ,"    assets:cash                 $-2" | ||||||
|  |      ,"" | ||||||
|  |      ] | ||||||
|  | 
 | ||||||
|  |   , "print report with depth arg" ~: | ||||||
|  |    do  | ||||||
|  |     l <- samplejournal | ||||||
|  |     t <- getCurrentLocalTime | ||||||
|  |     showTransactions (optsToFilterSpec [Depth "2"] [] t) l `is` unlines | ||||||
|  |       ["2008/01/01 income" | ||||||
|  |       ,"    income:salary           $-1" | ||||||
|  |       ,"" | ||||||
|  |       ,"2008/06/01 gift" | ||||||
|  |       ,"    income:gifts           $-1" | ||||||
|  |       ,"" | ||||||
|  |       ,"2008/06/03 * eat & shop" | ||||||
|  |       ,"    expenses:food                $1" | ||||||
|  |       ,"    expenses:supplies            $1" | ||||||
|  |       ,"    assets:cash                 $-2" | ||||||
|  |       ,"" | ||||||
|  |       ,"2008/12/31 * pay off" | ||||||
|  |       ,"    liabilities:debts            $1" | ||||||
|  |       ,"" | ||||||
|  |       ] | ||||||
|  | 
 | ||||||
|  |   ] | ||||||
|  | 
 | ||||||
|  |   ,"register report tests" ~: | ||||||
|  |   let registerdates = filter (not . null) .  map (strip . take 10) . lines | ||||||
|  |   in | ||||||
|  |   TestList | ||||||
|  |   [ | ||||||
|  | 
 | ||||||
|  |    "register report with no args" ~: | ||||||
|  |    do  | ||||||
|  |     l <- samplejournal | ||||||
|  |     (registerReportAsText [] $ registerReport [] (optsToFilterSpec [] [] t1) l) `is` unlines | ||||||
|  |      ["2008/01/01 income               assets:bank:checking             $1           $1" | ||||||
|  |      ,"                                income:salary                   $-1            0" | ||||||
|  |      ,"2008/06/01 gift                 assets:bank:checking             $1           $1" | ||||||
|  |      ,"                                income:gifts                    $-1            0" | ||||||
|  |      ,"2008/06/02 save                 assets:bank:saving               $1           $1" | ||||||
|  |      ,"                                assets:bank:checking            $-1            0" | ||||||
|  |      ,"2008/06/03 eat & shop           expenses:food                    $1           $1" | ||||||
|  |      ,"                                expenses:supplies                $1           $2" | ||||||
|  |      ,"                                assets:cash                     $-2            0" | ||||||
|  |      ,"2008/12/31 pay off              liabilities:debts                $1           $1" | ||||||
|  |      ,"                                assets:bank:checking            $-1            0" | ||||||
|  |      ] | ||||||
|  | 
 | ||||||
|  |   ,"register report with cleared option" ~: | ||||||
|  |    do  | ||||||
|  |     let opts = [Cleared] | ||||||
|  |     l <- readJournalWithOpts opts sample_journal_str | ||||||
|  |     (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is` unlines | ||||||
|  |      ["2008/06/03 eat & shop           expenses:food                    $1           $1" | ||||||
|  |      ,"                                expenses:supplies                $1           $2" | ||||||
|  |      ,"                                assets:cash                     $-2            0" | ||||||
|  |      ,"2008/12/31 pay off              liabilities:debts                $1           $1" | ||||||
|  |      ,"                                assets:bank:checking            $-1            0" | ||||||
|  |      ] | ||||||
|  | 
 | ||||||
|  |   ,"register report with uncleared option" ~: | ||||||
|  |    do  | ||||||
|  |     let opts = [UnCleared] | ||||||
|  |     l <- readJournalWithOpts opts sample_journal_str | ||||||
|  |     (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is` unlines | ||||||
|  |      ["2008/01/01 income               assets:bank:checking             $1           $1" | ||||||
|  |      ,"                                income:salary                   $-1            0" | ||||||
|  |      ,"2008/06/01 gift                 assets:bank:checking             $1           $1" | ||||||
|  |      ,"                                income:gifts                    $-1            0" | ||||||
|  |      ,"2008/06/02 save                 assets:bank:saving               $1           $1" | ||||||
|  |      ,"                                assets:bank:checking            $-1            0" | ||||||
|  |      ] | ||||||
|  | 
 | ||||||
|  |   ,"register report sorts by date" ~: | ||||||
|  |    do  | ||||||
|  |     l <- readJournalWithOpts [] $ unlines | ||||||
|  |         ["2008/02/02 a" | ||||||
|  |         ,"  b  1" | ||||||
|  |         ,"  c" | ||||||
|  |         ,"" | ||||||
|  |         ,"2008/01/01 d" | ||||||
|  |         ,"  e  1" | ||||||
|  |         ,"  f" | ||||||
|  |         ] | ||||||
|  |     registerdates (registerReportAsText [] $ registerReport [] (optsToFilterSpec [] [] t1) l) `is` ["2008/01/01","2008/02/02"] | ||||||
|  | 
 | ||||||
|  |   ,"register report with account pattern" ~: | ||||||
|  |    do | ||||||
|  |     l <- samplejournal | ||||||
|  |     (registerReportAsText [] $ registerReport [] (optsToFilterSpec [] ["cash"] t1) l) `is` unlines | ||||||
|  |      ["2008/06/03 eat & shop           assets:cash                     $-2          $-2" | ||||||
|  |      ] | ||||||
|  | 
 | ||||||
|  |   ,"register report with account pattern, case insensitive" ~: | ||||||
|  |    do  | ||||||
|  |     l <- samplejournal | ||||||
|  |     (registerReportAsText [] $ registerReport [] (optsToFilterSpec [] ["cAsH"] t1) l) `is` unlines | ||||||
|  |      ["2008/06/03 eat & shop           assets:cash                     $-2          $-2" | ||||||
|  |      ] | ||||||
|  | 
 | ||||||
|  |   ,"register report with display expression" ~: | ||||||
|  |    do  | ||||||
|  |     l <- samplejournal | ||||||
|  |     let gives displayexpr =  | ||||||
|  |             (registerdates (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is`) | ||||||
|  |                 where opts = [Display displayexpr] | ||||||
|  |     "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/06/02"] | ||||||
|  |     "d>=[2008/6/2]" `gives` ["2008/06/02","2008/06/03","2008/12/31"] | ||||||
|  |     "d>[2008/6/2]"  `gives` ["2008/06/03","2008/12/31"] | ||||||
|  | 
 | ||||||
|  |   ,"register report with period expression" ~: | ||||||
|  |    do  | ||||||
|  |     l <- samplejournal | ||||||
|  |     let periodexpr `gives` dates = do | ||||||
|  |           l' <- samplejournalwithopts opts [] | ||||||
|  |           registerdates (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l') `is` dates | ||||||
|  |               where opts = [Period periodexpr] | ||||||
|  |     ""     `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"] | ||||||
|  |     "2007" `gives` [] | ||||||
|  |     "june" `gives` ["2008/06/01","2008/06/02","2008/06/03"] | ||||||
|  |     "monthly" `gives` ["2008/01/01","2008/06/01","2008/12/01"] | ||||||
|  |     "quarterly" `gives` ["2008/01/01","2008/04/01","2008/10/01"] | ||||||
|  |     let opts = [Period "yearly"] | ||||||
|  |     (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is` unlines | ||||||
|  |      ["2008/01/01 - 2008/12/31         assets:bank:saving               $1           $1" | ||||||
|  |      ,"                                assets:cash                     $-2          $-1" | ||||||
|  |      ,"                                expenses:food                    $1            0" | ||||||
|  |      ,"                                expenses:supplies                $1           $1" | ||||||
|  |      ,"                                income:gifts                    $-1            0" | ||||||
|  |      ,"                                income:salary                   $-1          $-1" | ||||||
|  |      ,"                                liabilities:debts                $1            0" | ||||||
|  |      ] | ||||||
|  |     let opts = [Period "quarterly"] | ||||||
|  |     registerdates (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is` ["2008/01/01","2008/04/01","2008/10/01"] | ||||||
|  |     let opts = [Period "quarterly",Empty] | ||||||
|  |     registerdates (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is` ["2008/01/01","2008/04/01","2008/07/01","2008/10/01"] | ||||||
|  | 
 | ||||||
|  |   ] | ||||||
|  | 
 | ||||||
|  |   , "register report with depth arg" ~: | ||||||
|  |    do  | ||||||
|  |     l <- samplejournal | ||||||
|  |     let opts = [Depth "2"] | ||||||
|  |     (registerReportAsText opts $ registerReport opts (optsToFilterSpec opts [] t1) l) `is` unlines | ||||||
|  |      ["2008/01/01 income               assets:bank                      $1           $1" | ||||||
|  |      ,"                                income:salary                   $-1            0" | ||||||
|  |      ,"2008/06/01 gift                 assets:bank                      $1           $1" | ||||||
|  |      ,"                                income:gifts                    $-1            0" | ||||||
|  |      ,"2008/06/02 save                 assets:bank                      $1           $1" | ||||||
|  |      ,"                                assets:bank                     $-1            0" | ||||||
|  |      ,"2008/06/03 eat & shop           expenses:food                    $1           $1" | ||||||
|  |      ,"                                expenses:supplies                $1           $2" | ||||||
|  |      ,"                                assets:cash                     $-2            0" | ||||||
|  |      ,"2008/12/31 pay off              liabilities:debts                $1           $1" | ||||||
|  |      ,"                                assets:bank                     $-1            0" | ||||||
|  |      ] | ||||||
|  | 
 | ||||||
|  |   ,"show dollars" ~: show (dollars 1) ~?= "$1.00" | ||||||
|  | 
 | ||||||
|  |   ,"show hours" ~: show (hours 1) ~?= "1.0h" | ||||||
|  | 
 | ||||||
|  |   ,"unicode in balance layout" ~: do | ||||||
|  |     l <- readJournalWithOpts [] | ||||||
|  |       "2009/01/01 * медвежья шкура\n  расходы:покупки  100\n  актив:наличные\n" | ||||||
|  |     balanceReportAsText [] (balanceReport [] (optsToFilterSpec [] [] t1) l) `is` unlines | ||||||
|  |       ["                -100  актив:наличные" | ||||||
|  |       ,"                 100  расходы:покупки" | ||||||
|  |       ,"--------------------" | ||||||
|  |       ,"                   0" | ||||||
|  |       ] | ||||||
|  | 
 | ||||||
|  |   ,"unicode in register layout" ~: do | ||||||
|  |     l <- readJournalWithOpts [] | ||||||
|  |       "2009/01/01 * медвежья шкура\n  расходы:покупки  100\n  актив:наличные\n" | ||||||
|  |     (registerReportAsText [] $ registerReport [] (optsToFilterSpec [] [] t1) l) `is` unlines | ||||||
|  |       ["2009/01/01 медвежья шкура       расходы:покупки                 100          100" | ||||||
|  |       ,"                                актив:наличные                 -100            0"] | ||||||
|  | 
 | ||||||
|  |   ,"subAccounts" ~: do | ||||||
|  |     l <- liftM (journalToLedger nullfilterspec) samplejournal | ||||||
|  |     let a = ledgerAccount l "assets" | ||||||
|  |     map aname (ledgerSubAccounts l a) `is` ["assets:bank","assets:cash"] | ||||||
|  | 
 | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  |    | ||||||
|  | -- fixtures/test data | ||||||
|  | 
 | ||||||
|  | t1 = LocalTime date1 midday where date1 = parsedate "2008/11/26" | ||||||
|  | 
 | ||||||
|  | samplejournal = readJournalWithOpts [] sample_journal_str | ||||||
|  | samplejournalwithopts opts _ = readJournalWithOpts opts sample_journal_str | ||||||
|  | 
 | ||||||
|  | sample_journal_str = unlines | ||||||
|  |  ["; A sample journal file." | ||||||
|  |  ,";" | ||||||
|  |  ,"; Sets up this account tree:" | ||||||
|  |  ,"; assets" | ||||||
|  |  ,";   bank" | ||||||
|  |  ,";     checking" | ||||||
|  |  ,";     saving" | ||||||
|  |  ,";   cash" | ||||||
|  |  ,"; expenses" | ||||||
|  |  ,";   food" | ||||||
|  |  ,";   supplies" | ||||||
|  |  ,"; income" | ||||||
|  |  ,";   gifts" | ||||||
|  |  ,";   salary" | ||||||
|  |  ,"; liabilities" | ||||||
|  |  ,";   debts" | ||||||
|  |  ,"" | ||||||
|  |  ,"2008/01/01 income" | ||||||
|  |  ,"    assets:bank:checking  $1" | ||||||
|  |  ,"    income:salary" | ||||||
|  |  ,"" | ||||||
|  |  ,"2008/06/01 gift" | ||||||
|  |  ,"    assets:bank:checking  $1" | ||||||
|  |  ,"    income:gifts" | ||||||
|  |  ,"" | ||||||
|  |  ,"2008/06/02 save" | ||||||
|  |  ,"    assets:bank:saving  $1" | ||||||
|  |  ,"    assets:bank:checking" | ||||||
|  |  ,"" | ||||||
|  |  ,"2008/06/03 * eat & shop" | ||||||
|  |  ,"    expenses:food      $1" | ||||||
|  |  ,"    expenses:supplies  $1" | ||||||
|  |  ,"    assets:cash" | ||||||
|  |  ,"" | ||||||
|  |  ,"2008/12/31 * pay off" | ||||||
|  |  ,"    liabilities:debts  $1" | ||||||
|  |  ,"    assets:bank:checking" | ||||||
|  |  ,"" | ||||||
|  |  ,"" | ||||||
|  |  ,";final comment" | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  | defaultyear_journal_str = unlines | ||||||
|  |  ["Y2009" | ||||||
|  |  ,"" | ||||||
|  |  ,"01/01 A" | ||||||
|  |  ,"    a  $1" | ||||||
|  |  ,"    b" | ||||||
|  |  ] | ||||||
|  | 
 | ||||||
|  | -- write_sample_journal = writeFile "sample.journal" sample_journal_str | ||||||
|  | 
 | ||||||
|  | -- entry2_str = unlines | ||||||
|  | --  ["2007/01/27 * joes diner" | ||||||
|  | --  ,"    expenses:food:dining                      $10.00" | ||||||
|  | --  ,"    expenses:gifts                            $10.00" | ||||||
|  | --  ,"    assets:checking                          $-20.00" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- entry3_str = unlines | ||||||
|  | --  ["2007/01/01 * opening balance" | ||||||
|  | --  ,"    assets:cash                                $4.82" | ||||||
|  | --  ,"    equity:opening balances" | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/01 * opening balance" | ||||||
|  | --  ,"    assets:cash                                $4.82" | ||||||
|  | --  ,"    equity:opening balances" | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/28 coopportunity" | ||||||
|  | --  ,"  expenses:food:groceries                 $47.18" | ||||||
|  | --  ,"  assets:checking" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- periodic_entry1_str = unlines | ||||||
|  | --  ["~ monthly from 2007/2/2" | ||||||
|  | --  ,"  assets:saving            $200.00" | ||||||
|  | --  ,"  assets:checking" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- periodic_entry2_str = unlines | ||||||
|  | --  ["~ monthly from 2007/2/2" | ||||||
|  | --  ,"  assets:saving            $200.00         ;auto savings" | ||||||
|  | --  ,"  assets:checking" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- periodic_entry3_str = unlines | ||||||
|  | --  ["~ monthly from 2007/01/01" | ||||||
|  | --  ,"    assets:cash                                $4.82" | ||||||
|  | --  ,"    equity:opening balances" | ||||||
|  | --  ,"" | ||||||
|  | --  ,"~ monthly from 2007/01/01" | ||||||
|  | --  ,"    assets:cash                                $4.82" | ||||||
|  | --  ,"    equity:opening balances" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- journal1_str = unlines | ||||||
|  | --  ["" | ||||||
|  | --  ,"2007/01/27 * joes diner" | ||||||
|  | --  ,"  expenses:food:dining                    $10.00" | ||||||
|  | --  ,"  expenses:gifts                          $10.00" | ||||||
|  | --  ,"  assets:checking                        $-20.00" | ||||||
|  | --  ,"" | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/28 coopportunity" | ||||||
|  | --  ,"  expenses:food:groceries                 $47.18" | ||||||
|  | --  ,"  assets:checking                        $-47.18" | ||||||
|  | --  ,"" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- journal2_str = unlines | ||||||
|  | --  [";comment" | ||||||
|  | --  ,"2007/01/27 * joes diner" | ||||||
|  | --  ,"  expenses:food:dining                    $10.00" | ||||||
|  | --  ,"  assets:checking                        $-47.18" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- journal3_str = unlines | ||||||
|  | --  ["2007/01/27 * joes diner" | ||||||
|  | --  ,"  expenses:food:dining                    $10.00" | ||||||
|  | --  ,";intra-entry comment" | ||||||
|  | --  ,"  assets:checking                        $-47.18" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- journal4_str = unlines | ||||||
|  | --  ["!include \"somefile\"" | ||||||
|  | --  ,"2007/01/27 * joes diner" | ||||||
|  | --  ,"  expenses:food:dining                    $10.00" | ||||||
|  | --  ,"  assets:checking                        $-47.18" | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- journal5_str = "" | ||||||
|  | 
 | ||||||
|  | -- journal6_str = unlines | ||||||
|  | --  ["~ monthly from 2007/1/21" | ||||||
|  | --  ,"    expenses:entertainment  $16.23        ;netflix" | ||||||
|  | --  ,"    assets:checking" | ||||||
|  | --  ,"" | ||||||
|  | --  ,"; 2007/01/01 * opening balance" | ||||||
|  | --  ,";     assets:saving                            $200.04" | ||||||
|  | --  ,";     equity:opening balances                         " | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- journal7_str = unlines | ||||||
|  | --  ["2007/01/01 * opening balance" | ||||||
|  | --  ,"    assets:cash                                $4.82" | ||||||
|  | --  ,"    equity:opening balances                         " | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/01 * opening balance" | ||||||
|  | --  ,"    income:interest                                $-4.82" | ||||||
|  | --  ,"    equity:opening balances                         " | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/02 * ayres suites" | ||||||
|  | --  ,"    expenses:vacation                        $179.92" | ||||||
|  | --  ,"    assets:checking                                 " | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/02 * auto transfer to savings" | ||||||
|  | --  ,"    assets:saving                            $200.00" | ||||||
|  | --  ,"    assets:checking                                 " | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/03 * poquito mas" | ||||||
|  | --  ,"    expenses:food:dining                       $4.82" | ||||||
|  | --  ,"    assets:cash                                     " | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/03 * verizon" | ||||||
|  | --  ,"    expenses:phone                            $95.11" | ||||||
|  | --  ,"    assets:checking                                 " | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/03 * discover" | ||||||
|  | --  ,"    liabilities:credit cards:discover         $80.00" | ||||||
|  | --  ,"    assets:checking                                 " | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/04 * blue cross" | ||||||
|  | --  ,"    expenses:health:insurance                 $90.00" | ||||||
|  | --  ,"    assets:checking                                 " | ||||||
|  | --  ,"" | ||||||
|  | --  ,"2007/01/05 * village market liquor" | ||||||
|  | --  ,"    expenses:food:dining                       $6.48" | ||||||
|  | --  ,"    assets:checking                                 " | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | journal7 = Journal | ||||||
|  |           []  | ||||||
|  |           []  | ||||||
|  |           [ | ||||||
|  |            txnTieKnot $ Transaction { | ||||||
|  |              tdate=parsedate "2007/01/01", | ||||||
|  |              teffectivedate=Nothing, | ||||||
|  |              tstatus=False, | ||||||
|  |              tcode="*", | ||||||
|  |              tdescription="opening balance", | ||||||
|  |              tcomment="", | ||||||
|  |              tmetadata=[], | ||||||
|  |              tpostings=[ | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="assets:cash", | ||||||
|  |                 pamount=(Mixed [dollars 4.82]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               }, | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="equity:opening balances", | ||||||
|  |                 pamount=(Mixed [dollars (-4.82)]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               } | ||||||
|  |              ], | ||||||
|  |              tpreceding_comment_lines="" | ||||||
|  |            } | ||||||
|  |           , | ||||||
|  |            txnTieKnot $ Transaction { | ||||||
|  |              tdate=parsedate "2007/02/01", | ||||||
|  |              teffectivedate=Nothing, | ||||||
|  |              tstatus=False, | ||||||
|  |              tcode="*", | ||||||
|  |              tdescription="ayres suites", | ||||||
|  |              tcomment="", | ||||||
|  |              tmetadata=[], | ||||||
|  |              tpostings=[ | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="expenses:vacation", | ||||||
|  |                 pamount=(Mixed [dollars 179.92]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               }, | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="assets:checking", | ||||||
|  |                 pamount=(Mixed [dollars (-179.92)]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               } | ||||||
|  |              ], | ||||||
|  |              tpreceding_comment_lines="" | ||||||
|  |            } | ||||||
|  |           , | ||||||
|  |            txnTieKnot $ Transaction { | ||||||
|  |              tdate=parsedate "2007/01/02", | ||||||
|  |              teffectivedate=Nothing, | ||||||
|  |              tstatus=False, | ||||||
|  |              tcode="*", | ||||||
|  |              tdescription="auto transfer to savings", | ||||||
|  |              tcomment="", | ||||||
|  |              tmetadata=[], | ||||||
|  |              tpostings=[ | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="assets:saving", | ||||||
|  |                 pamount=(Mixed [dollars 200]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               }, | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="assets:checking", | ||||||
|  |                 pamount=(Mixed [dollars (-200)]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               } | ||||||
|  |              ], | ||||||
|  |              tpreceding_comment_lines="" | ||||||
|  |            } | ||||||
|  |           , | ||||||
|  |            txnTieKnot $ Transaction { | ||||||
|  |              tdate=parsedate "2007/01/03", | ||||||
|  |              teffectivedate=Nothing, | ||||||
|  |              tstatus=False, | ||||||
|  |              tcode="*", | ||||||
|  |              tdescription="poquito mas", | ||||||
|  |              tcomment="", | ||||||
|  |              tmetadata=[], | ||||||
|  |              tpostings=[ | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="expenses:food:dining", | ||||||
|  |                 pamount=(Mixed [dollars 4.82]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               }, | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="assets:cash", | ||||||
|  |                 pamount=(Mixed [dollars (-4.82)]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               } | ||||||
|  |              ], | ||||||
|  |              tpreceding_comment_lines="" | ||||||
|  |            } | ||||||
|  |           , | ||||||
|  |            txnTieKnot $ Transaction { | ||||||
|  |              tdate=parsedate "2007/01/03", | ||||||
|  |              teffectivedate=Nothing, | ||||||
|  |              tstatus=False, | ||||||
|  |              tcode="*", | ||||||
|  |              tdescription="verizon", | ||||||
|  |              tcomment="", | ||||||
|  |              tmetadata=[], | ||||||
|  |              tpostings=[ | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="expenses:phone", | ||||||
|  |                 pamount=(Mixed [dollars 95.11]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               }, | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="assets:checking", | ||||||
|  |                 pamount=(Mixed [dollars (-95.11)]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               } | ||||||
|  |              ], | ||||||
|  |              tpreceding_comment_lines="" | ||||||
|  |            } | ||||||
|  |           , | ||||||
|  |            txnTieKnot $ Transaction { | ||||||
|  |              tdate=parsedate "2007/01/03", | ||||||
|  |              teffectivedate=Nothing, | ||||||
|  |              tstatus=False, | ||||||
|  |              tcode="*", | ||||||
|  |              tdescription="discover", | ||||||
|  |              tcomment="", | ||||||
|  |              tmetadata=[], | ||||||
|  |              tpostings=[ | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="liabilities:credit cards:discover", | ||||||
|  |                 pamount=(Mixed [dollars 80]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               }, | ||||||
|  |               Posting { | ||||||
|  |                 pstatus=False, | ||||||
|  |                 paccount="assets:checking", | ||||||
|  |                 pamount=(Mixed [dollars (-80)]), | ||||||
|  |                 pcomment="", | ||||||
|  |                 ptype=RegularPosting, | ||||||
|  |                 pmetadata=[], | ||||||
|  |                 ptransaction=Nothing | ||||||
|  |               } | ||||||
|  |              ], | ||||||
|  |              tpreceding_comment_lines="" | ||||||
|  |            } | ||||||
|  |           ] | ||||||
|  |           [] | ||||||
|  |           [] | ||||||
|  |           "" | ||||||
|  |           nullctx | ||||||
|  |           [] | ||||||
|  |           (TOD 0 0) | ||||||
|  | 
 | ||||||
|  | ledger7 = journalToLedger nullfilterspec journal7 | ||||||
|  | 
 | ||||||
|  | -- journal8_str = unlines | ||||||
|  | --  ["2008/1/1 test           " | ||||||
|  | --  ,"  a:b          10h @ $40" | ||||||
|  | --  ,"  c:d                   " | ||||||
|  | --  ,"" | ||||||
|  | --  ] | ||||||
|  | 
 | ||||||
|  | -- timelogentry1_str  = "i 2007/03/11 16:19:00 hledger\n" | ||||||
|  | -- timelogentry1 = TimeLogEntry In (parsedatetime "2007/03/11 16:19:00") "hledger" | ||||||
|  | 
 | ||||||
|  | -- timelogentry2_str  = "o 2007/03/11 16:30:00\n" | ||||||
|  | -- timelogentry2 = TimeLogEntry Out (parsedatetime "2007/03/11 16:30:00") "" | ||||||
|  | 
 | ||||||
|  | -- a1 = Mixed [(hours 1){price=Just $ Mixed [Amount (comm "$") 10 Nothing]}] | ||||||
|  | -- a2 = Mixed [(hours 2){price=Just $ Mixed [Amount (comm "EUR") 10 Nothing]}] | ||||||
|  | -- a3 = Mixed $ amounts a1 ++ amounts a2 | ||||||
|  | 
 | ||||||
|  | journalWithAmounts :: [String] -> Journal | ||||||
|  | journalWithAmounts as = | ||||||
|  |         Journal | ||||||
|  |         [] | ||||||
|  |         [] | ||||||
|  |         [t | a <- as, let t = nulltransaction{tdescription=a,tpostings=[nullposting{pamount=parse a,ptransaction=Just t}]}] | ||||||
|  |         [] | ||||||
|  |         [] | ||||||
|  |         "" | ||||||
|  |         nullctx | ||||||
|  |         [] | ||||||
|  |         (TOD 0 0) | ||||||
|  |     where parse = fromparse . parseWithCtx nullctx someamount | ||||||
|  | 
 | ||||||
| @ -101,6 +101,7 @@ module Hledger.Cli.Balance ( | |||||||
|  ,balance |  ,balance | ||||||
|  ,balanceReport |  ,balanceReport | ||||||
|  ,balanceReportAsText |  ,balanceReportAsText | ||||||
|  |  ,tests_Hledger_Cli_Balance | ||||||
|  -- ,tests_Balance |  -- ,tests_Balance | ||||||
| ) where | ) where | ||||||
| import Hledger.Data.Utils | import Hledger.Data.Utils | ||||||
| @ -211,3 +212,6 @@ isInterestingIndented opts l a | |||||||
|             isInterestingTree = treeany (isInteresting opts l . aname) |             isInterestingTree = treeany (isInteresting opts l . aname) | ||||||
|             subtrees = map (fromJust . ledgerAccountTreeAt l) $ ledgerSubAccounts l $ ledgerAccount l a |             subtrees = map (fromJust . ledgerAccountTreeAt l) $ ledgerSubAccounts l $ ledgerAccount l a | ||||||
| 
 | 
 | ||||||
|  | tests_Hledger_Cli_Balance = TestList | ||||||
|  |  [ | ||||||
|  |  ] | ||||||
|  | |||||||
| @ -1,40 +0,0 @@ | |||||||
| {-# LANGUAGE CPP #-} |  | ||||||
| {-|  |  | ||||||
| 
 |  | ||||||
| The Commands package defines all the commands offered by the hledger |  | ||||||
| application, like \"register\" and \"balance\".  This module exports all |  | ||||||
| the commands; you can also import individual modules if you prefer. |  | ||||||
| 
 |  | ||||||
| -} |  | ||||||
| 
 |  | ||||||
| module Hledger.Cli.Commands ( |  | ||||||
|                      module Hledger.Cli.Add, |  | ||||||
|                      module Hledger.Cli.Balance, |  | ||||||
|                      module Hledger.Cli.Convert, |  | ||||||
|                      module Hledger.Cli.Histogram, |  | ||||||
|                      module Hledger.Cli.Print, |  | ||||||
|                      module Hledger.Cli.Register, |  | ||||||
|                      module Hledger.Cli.Stats, |  | ||||||
|                      tests_Hledger_Commands |  | ||||||
|               ) |  | ||||||
| where |  | ||||||
| import Hledger.Cli.Add |  | ||||||
| import Hledger.Cli.Balance |  | ||||||
| import Hledger.Cli.Convert |  | ||||||
| import Hledger.Cli.Histogram |  | ||||||
| import Hledger.Cli.Print |  | ||||||
| import Hledger.Cli.Register |  | ||||||
| import Hledger.Cli.Stats |  | ||||||
| import Test.HUnit (Test(TestList)) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| tests_Hledger_Commands = TestList |  | ||||||
|     [ |  | ||||||
| --      Hledger.Cli.Add.tests_Add |  | ||||||
| --     ,Hledger.Cli.Balance.tests_Balance |  | ||||||
|      Hledger.Cli.Convert.tests_Convert |  | ||||||
| --     ,Hledger.Cli.Histogram.tests_Histogram |  | ||||||
| --     ,Hledger.Cli.Print.tests_Print |  | ||||||
|     ,Hledger.Cli.Register.tests_Register |  | ||||||
| --     ,Hledger.Cli.Stats.tests_Stats |  | ||||||
|     ] |  | ||||||
| @ -350,7 +350,7 @@ identify rules defacct desc | null matchingrules = (defacct,desc) | |||||||
| 
 | 
 | ||||||
| caseinsensitive = ("(?i)"++) | caseinsensitive = ("(?i)"++) | ||||||
| 
 | 
 | ||||||
| tests_Convert = TestList [ | tests_Hledger_Cli_Convert = TestList [ | ||||||
| 
 | 
 | ||||||
|    "convert rules parsing: empty file" ~: do |    "convert rules parsing: empty file" ~: do | ||||||
|      -- let assertMixedAmountParse parseresult mixedamount = |      -- let assertMixedAmountParse parseresult mixedamount = | ||||||
|  | |||||||
| @ -295,3 +295,28 @@ optsToFilterSpec opts args t = FilterSpec { | |||||||
| --     where | --     where | ||||||
| --       listtomaybe [] = Nothing | --       listtomaybe [] = Nothing | ||||||
| --       listtomaybe vs = Just $ last vs | --       listtomaybe vs = Just $ last vs | ||||||
|  | 
 | ||||||
|  | tests_Hledger_Cli_Options = TestList | ||||||
|  |  [ | ||||||
|  |   "dateSpanFromOpts" ~: do | ||||||
|  |     let todaysdate = parsedate "2008/11/26" | ||||||
|  |     let gives = is . show . dateSpanFromOpts todaysdate | ||||||
|  |     [] `gives` "DateSpan Nothing Nothing" | ||||||
|  |     [Begin "2008", End "2009"] `gives` "DateSpan (Just 2008-01-01) (Just 2009-01-01)" | ||||||
|  |     [Period "in 2008"] `gives` "DateSpan (Just 2008-01-01) (Just 2009-01-01)" | ||||||
|  |     [Begin "2005", End "2007",Period "in 2008"] `gives` "DateSpan (Just 2008-01-01) (Just 2009-01-01)" | ||||||
|  | 
 | ||||||
|  |   ,"intervalFromOpts" ~: do | ||||||
|  |     let gives = is . intervalFromOpts | ||||||
|  |     [] `gives` NoInterval | ||||||
|  |     [DailyOpt] `gives` Daily | ||||||
|  |     [WeeklyOpt] `gives` Weekly | ||||||
|  |     [MonthlyOpt] `gives` Monthly | ||||||
|  |     [QuarterlyOpt] `gives` Quarterly | ||||||
|  |     [YearlyOpt] `gives` Yearly | ||||||
|  |     [Period "weekly"] `gives` Weekly | ||||||
|  |     [Period "monthly"] `gives` Monthly | ||||||
|  |     [Period "quarterly"] `gives` Quarterly | ||||||
|  |     [WeeklyOpt, Period "yearly"] `gives` Yearly | ||||||
|  | 
 | ||||||
|  |  ] | ||||||
| @ -12,7 +12,7 @@ module Hledger.Cli.Register ( | |||||||
|  ,registerReport |  ,registerReport | ||||||
|  ,registerReportAsText |  ,registerReportAsText | ||||||
|  ,showPostingWithBalanceForVty |  ,showPostingWithBalanceForVty | ||||||
|  ,tests_Register |  ,tests_Hledger_Cli_Register | ||||||
| ) where | ) where | ||||||
| 
 | 
 | ||||||
| import Safe (headMay, lastMay) | import Safe (headMay, lastMay) | ||||||
| @ -198,10 +198,46 @@ depthClipPosting Nothing p = p | |||||||
| depthClipPosting (Just d) p@Posting{paccount=a} = p{paccount=clipAccountName d a} | depthClipPosting (Just d) p@Posting{paccount=a} = p{paccount=clipAccountName d a} | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| tests_Register :: Test | tests_Hledger_Cli_Register :: Test | ||||||
| tests_Register = TestList [ | tests_Hledger_Cli_Register = TestList | ||||||
|  |  [ | ||||||
| 
 | 
 | ||||||
|   "summarisePostingsByInterval" ~: do |   "summarisePostingsByInterval" ~: do | ||||||
|     summarisePostingsByInterval Quarterly Nothing False (DateSpan Nothing Nothing) [] ~?= [] |     summarisePostingsByInterval Quarterly Nothing False (DateSpan Nothing Nothing) [] ~?= [] | ||||||
| 
 | 
 | ||||||
|  |   -- ,"summarisePostingsInDateSpan" ~: do | ||||||
|  |   --   let gives (b,e,depth,showempty,ps) = | ||||||
|  |   --           (summarisePostingsInDateSpan (mkdatespan b e) depth showempty ps `is`) | ||||||
|  |   --   let ps = | ||||||
|  |   --           [ | ||||||
|  |   --            nullposting{lpdescription="desc",lpaccount="expenses:food:groceries",lpamount=Mixed [dollars 1]} | ||||||
|  |   --           ,nullposting{lpdescription="desc",lpaccount="expenses:food:dining",   lpamount=Mixed [dollars 2]} | ||||||
|  |   --           ,nullposting{lpdescription="desc",lpaccount="expenses:food",          lpamount=Mixed [dollars 4]} | ||||||
|  |   --           ,nullposting{lpdescription="desc",lpaccount="expenses:food:dining",   lpamount=Mixed [dollars 8]} | ||||||
|  |   --           ] | ||||||
|  |   --   ("2008/01/01","2009/01/01",0,9999,False,[]) `gives`  | ||||||
|  |   --    [] | ||||||
|  |   --   ("2008/01/01","2009/01/01",0,9999,True,[]) `gives`  | ||||||
|  |   --    [ | ||||||
|  |   --     nullposting{lpdate=parsedate "2008/01/01",lpdescription="- 2008/12/31"} | ||||||
|  |   --    ] | ||||||
|  |   --   ("2008/01/01","2009/01/01",0,9999,False,ts) `gives`  | ||||||
|  |   --    [ | ||||||
|  |   --     nullposting{lpdate=parsedate "2008/01/01",lpdescription="- 2008/12/31",lpaccount="expenses:food",          lpamount=Mixed [dollars 4]} | ||||||
|  |   --    ,nullposting{lpdate=parsedate "2008/01/01",lpdescription="- 2008/12/31",lpaccount="expenses:food:dining",   lpamount=Mixed [dollars 10]} | ||||||
|  |   --    ,nullposting{lpdate=parsedate "2008/01/01",lpdescription="- 2008/12/31",lpaccount="expenses:food:groceries",lpamount=Mixed [dollars 1]} | ||||||
|  |   --    ] | ||||||
|  |   --   ("2008/01/01","2009/01/01",0,2,False,ts) `gives`  | ||||||
|  |   --    [ | ||||||
|  |   --     nullposting{lpdate=parsedate "2008/01/01",lpdescription="- 2008/12/31",lpaccount="expenses:food",lpamount=Mixed [dollars 15]} | ||||||
|  |   --    ] | ||||||
|  |   --   ("2008/01/01","2009/01/01",0,1,False,ts) `gives`  | ||||||
|  |   --    [ | ||||||
|  |   --     nullposting{lpdate=parsedate "2008/01/01",lpdescription="- 2008/12/31",lpaccount="expenses",lpamount=Mixed [dollars 15]} | ||||||
|  |   --    ] | ||||||
|  |   --   ("2008/01/01","2009/01/01",0,0,False,ts) `gives`  | ||||||
|  |   --    [ | ||||||
|  |   --     nullposting{lpdate=parsedate "2008/01/01",lpdescription="- 2008/12/31",lpaccount="",lpamount=Mixed [dollars 15]} | ||||||
|  |   --    ] | ||||||
|  | 
 | ||||||
|  ] |  ] | ||||||
|  | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -19,6 +19,7 @@ module Hledger.Cli.Utils | |||||||
|      writeFileWithBackup, |      writeFileWithBackup, | ||||||
|      writeFileWithBackupIfChanged, |      writeFileWithBackupIfChanged, | ||||||
|      readFileStrictly, |      readFileStrictly, | ||||||
|  |      Test(TestList), | ||||||
|     ) |     ) | ||||||
| where | where | ||||||
| import Hledger.Data | import Hledger.Data | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user