1 {-# LANGUAGE TupleSections #-}
2 {-# LANGUAGE OverloadedStrings #-}
6 import Test.Framework.Providers.HUnit (hUnitTestToTests)
7 import Test.Framework.Runners.Console (defaultMain)
9 import Control.Applicative ((<*))
10 import Control.Monad.IO.Class (liftIO)
11 import Data.Decimal (DecimalRaw(..))
12 import qualified Data.Either
13 import qualified Data.List
14 import Data.List.NonEmpty (NonEmpty(..))
15 import qualified Data.Map.Strict as Data.Map
16 import Data.Text (Text)
17 import qualified Data.Time.Calendar as Time
18 import qualified Data.Time.LocalTime as Time
19 import qualified Text.Parsec as P
20 import qualified Text.Parsec.Pos as P
21 -- import qualified Text.PrettyPrint.Leijen.Text as PP
23 import qualified Hcompta.Model.Account as Account
24 import qualified Hcompta.Model.Amount as Amount
25 import qualified Hcompta.Model.Amount.Style as Amount.Style
26 import qualified Hcompta.Model.Date as Date
27 import qualified Hcompta.Model.Transaction as Transaction
28 import qualified Hcompta.Model.Transaction.Posting as Posting
29 import qualified Hcompta.Calc.Balance as Calc.Balance
30 import qualified Hcompta.Format.Ledger.Read as Format.Ledger.Read
31 import qualified Hcompta.Format.Ledger.Journal as Format.Ledger.Journal
32 import qualified Hcompta.Format.Ledger.Write as Format.Ledger.Write
33 import qualified Hcompta.Lib.TreeMap as Lib.TreeMap
35 --instance Eq Text.Parsec.ParseError where
36 -- (==) = const (const False)
39 main = defaultMain $ hUnitTestToTests test_Hcompta
45 [ "Account" ~: TestList
48 (reverse $ Account.foldr ("A":|[]) (:) []) ~?= ["A":|[]]
50 (reverse $ Account.foldr ("A":|["B"]) (:) []) ~?= ["A":|[], "A":|["B"]]
52 (reverse $ Account.foldr ("A":|["B", "C"]) (:) []) ~?= ["A":|[], "A":|["B"], "A":|["B", "C"]]
54 , "ascending" ~: TestList
56 Account.ascending ("A":|[]) ~?= Nothing
58 Account.ascending ("A":|["B"]) ~?= Just ("A":|[])
60 Account.ascending ("A":|["B", "C"]) ~?= Just ("A":|["B"])
63 , "Amount" ~: TestList
68 { Amount.quantity = Decimal 0 1
69 , Amount.style = Amount.Style.nil
70 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
75 { Amount.quantity = Decimal 0 1
76 , Amount.style = Amount.Style.nil
77 { Amount.Style.unit_side = Just $ Amount.Style.Side_Right
83 { Amount.quantity = Decimal 0 2
84 , Amount.style = Amount.Style.nil
85 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
90 , "from_List" ~: TestList
91 [ "from_List [$1, 1$] = $2" ~:
94 { Amount.quantity = Decimal 0 1
95 , Amount.style = Amount.Style.nil
96 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
101 { Amount.quantity = Decimal 0 1
102 , Amount.style = Amount.Style.nil
103 { Amount.Style.unit_side = Just $ Amount.Style.Side_Right
111 { Amount.quantity = Decimal 0 2
112 , Amount.style = Amount.Style.nil
113 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
122 [ "Balance" ~: TestList
123 [ "posting" ~: TestList
124 [ "[A+$1] = A+$1 & $+1" ~:
125 (Calc.Balance.posting
126 (Posting.nil ("A":|[]))
127 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
132 { Calc.Balance.by_account =
133 Lib.TreeMap.from_List const
134 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
135 , Calc.Balance.by_unit =
137 Data.List.map Calc.Balance.assoc_unit_sum $
138 [ Calc.Balance.Unit_Sum
139 { Calc.Balance.amount = Amount.usd $ 1
140 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
145 , "[A+$1, A-$1] = {A+$0, $+0}" ~:
147 (flip Calc.Balance.posting)
149 [ (Posting.nil ("A":|[]))
150 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
152 , (Posting.nil ("A":|[]))
153 { Posting.amounts=Amount.from_List [ Amount.usd $ -1 ]
158 { Calc.Balance.by_account =
159 Lib.TreeMap.from_List const
160 [ ("A":|[], Amount.from_List [ Amount.usd $ 0 ]) ]
161 , Calc.Balance.by_unit =
163 Data.List.map Calc.Balance.assoc_unit_sum $
164 [ Calc.Balance.Unit_Sum
165 { Calc.Balance.amount = Amount.usd $ 0
166 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
171 , "[A+$1, A-€1] = {A+$1-€1, $+1 €-1}" ~:
173 (flip Calc.Balance.posting)
175 [ (Posting.nil ("A":|[]))
176 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
178 , (Posting.nil ("A":|[]))
179 { Posting.amounts=Amount.from_List [ Amount.eur $ -1 ]
184 { Calc.Balance.by_account =
185 Lib.TreeMap.from_List const
186 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ -1 ]) ]
187 , Calc.Balance.by_unit =
189 Data.List.map Calc.Balance.assoc_unit_sum $
190 [ Calc.Balance.Unit_Sum
191 { Calc.Balance.amount = Amount.usd $ 1
192 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
195 , Calc.Balance.Unit_Sum
196 { Calc.Balance.amount = Amount.eur $ -1
197 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
202 , "[A+$1, B-$1] = {A+$1 B-$1, $+0}" ~:
204 (flip Calc.Balance.posting)
206 [ (Posting.nil ("A":|[]))
207 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
209 , (Posting.nil ("B":|[]))
210 { Posting.amounts=Amount.from_List [ Amount.usd $ -1 ]
215 { Calc.Balance.by_account =
216 Lib.TreeMap.from_List const
217 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
218 , ("B":|[], Amount.from_List [ Amount.usd $ -1 ])
220 , Calc.Balance.by_unit =
222 Data.List.map Calc.Balance.assoc_unit_sum $
223 [ Calc.Balance.Unit_Sum
224 { Calc.Balance.amount = Amount.usd $ 0
225 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
230 , "[A+$1+€2, A-$1-€2] = {A+$0+€0, $+0 €+0}" ~:
232 (flip Calc.Balance.posting)
234 [ (Posting.nil ("A":|[]))
235 { Posting.amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2 ]
237 , (Posting.nil ("A":|[]))
238 { Posting.amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2 ]
243 { Calc.Balance.by_account =
244 Lib.TreeMap.from_List const
245 [ ("A":|[], Amount.from_List [ Amount.usd $ 0, Amount.eur $ 0 ])
247 , Calc.Balance.by_unit =
249 Data.List.map Calc.Balance.assoc_unit_sum $
250 [ Calc.Balance.Unit_Sum
251 { Calc.Balance.amount = Amount.usd $ 0
252 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
255 , Calc.Balance.Unit_Sum
256 { Calc.Balance.amount = Amount.eur $ 0
257 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
262 , "[A+$1+€2+£3, B-$1-2€-£3] = {A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~:
264 (flip Calc.Balance.posting)
266 [ (Posting.nil ("A":|[]))
267 { Posting.amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ]
269 , (Posting.nil ("B":|[]))
270 { Posting.amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ]
275 { Calc.Balance.by_account =
276 Lib.TreeMap.from_List const
277 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
278 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
280 , Calc.Balance.by_unit =
282 Data.List.map Calc.Balance.assoc_unit_sum $
283 [ Calc.Balance.Unit_Sum
284 { Calc.Balance.amount = Amount.usd $ 0
285 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
288 , Calc.Balance.Unit_Sum
289 { Calc.Balance.amount = Amount.eur $ 0
290 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
293 , Calc.Balance.Unit_Sum
294 { Calc.Balance.amount = Amount.gbp $ 0
295 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
301 , "union" ~: TestList
308 , "{A+$1, $+1} {A+$1, $+1} = {A+$2, $+2}" ~:
310 (Calc.Balance.Balance
311 { Calc.Balance.by_account =
312 Lib.TreeMap.from_List const
313 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
314 , Calc.Balance.by_unit =
316 Data.List.map Calc.Balance.assoc_unit_sum $
317 [ Calc.Balance.Unit_Sum
318 { Calc.Balance.amount = Amount.usd $ 1
319 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
324 (Calc.Balance.Balance
325 { Calc.Balance.by_account =
326 Lib.TreeMap.from_List const
327 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
328 , Calc.Balance.by_unit =
330 Data.List.map Calc.Balance.assoc_unit_sum $
331 [ Calc.Balance.Unit_Sum
332 { Calc.Balance.amount = Amount.usd $ 1
333 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
340 { Calc.Balance.by_account =
341 Lib.TreeMap.from_List const
342 [ ("A":|[], Amount.from_List [ Amount.usd $ 2 ]) ]
343 , Calc.Balance.by_unit =
345 Data.List.map Calc.Balance.assoc_unit_sum $
346 [ Calc.Balance.Unit_Sum
347 { Calc.Balance.amount = Amount.usd $ 2
348 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
353 , "{A+$1, $+1} {B+$1, $+1} = {A+$1 B+$1, $+2}" ~:
355 (Calc.Balance.Balance
356 { Calc.Balance.by_account =
357 Lib.TreeMap.from_List const
358 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
359 , Calc.Balance.by_unit =
361 Data.List.map Calc.Balance.assoc_unit_sum $
362 [ Calc.Balance.Unit_Sum
363 { Calc.Balance.amount = Amount.usd $ 1
364 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
369 (Calc.Balance.Balance
370 { Calc.Balance.by_account =
371 Lib.TreeMap.from_List const
372 [ ("B":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
373 , Calc.Balance.by_unit =
375 Data.List.map Calc.Balance.assoc_unit_sum $
376 [ Calc.Balance.Unit_Sum
377 { Calc.Balance.amount = Amount.usd $ 1
378 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
385 { Calc.Balance.by_account =
386 Lib.TreeMap.from_List const
387 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
388 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
389 , Calc.Balance.by_unit =
391 Data.List.map Calc.Balance.assoc_unit_sum $
392 [ Calc.Balance.Unit_Sum
393 { Calc.Balance.amount = Amount.usd $ 2
394 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
399 , "{A+$1, $+1} {B+€1, €+1} = {A+$1 B+€1, $+1 €+1}" ~:
401 (Calc.Balance.Balance
402 { Calc.Balance.by_account =
403 Lib.TreeMap.from_List const
404 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
405 , Calc.Balance.by_unit =
407 Data.List.map Calc.Balance.assoc_unit_sum $
408 [ Calc.Balance.Unit_Sum
409 { Calc.Balance.amount = Amount.usd $ 1
410 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
415 (Calc.Balance.Balance
416 { Calc.Balance.by_account =
417 Lib.TreeMap.from_List const
418 [ ("B":|[], Amount.from_List [ Amount.eur $ 1 ]) ]
419 , Calc.Balance.by_unit =
421 Data.List.map Calc.Balance.assoc_unit_sum $
422 [ Calc.Balance.Unit_Sum
423 { Calc.Balance.amount = Amount.eur $ 1
424 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
431 { Calc.Balance.by_account =
432 Lib.TreeMap.from_List const
433 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
434 , ("B":|[], Amount.from_List [ Amount.eur $ 1 ]) ]
435 , Calc.Balance.by_unit =
437 Data.List.map Calc.Balance.assoc_unit_sum $
438 [ Calc.Balance.Unit_Sum
439 { Calc.Balance.amount = Amount.usd $ 1
440 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
443 , Calc.Balance.Unit_Sum
444 { Calc.Balance.amount = Amount.eur $ 1
445 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
451 , "expand" ~: TestList
452 [ "nil_By_Account" ~:
454 Calc.Balance.nil_By_Account
459 (Lib.TreeMap.from_List const
460 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ])
462 (Lib.TreeMap.from_List const
463 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
464 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
465 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
468 , "A/A+$1 = A+$1 A/A+$1" ~:
470 (Lib.TreeMap.from_List const
471 [ ("A":|["A"], Amount.from_List [ Amount.usd $ 1 ]) ])
473 (Lib.TreeMap.from_List const
474 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
475 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
476 , Calc.Balance.exclusive = Amount.from_List []
478 , ("A":|["A"], Calc.Balance.Account_Sum_Expanded
479 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
480 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
483 , "A/B+$1 = A+$1 A/B+$1" ~:
485 (Lib.TreeMap.from_List const
486 [ ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ]) ])
488 (Lib.TreeMap.from_List const
489 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
490 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
491 , Calc.Balance.exclusive = Amount.from_List []
493 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
494 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
495 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
498 , "A/B/C+$1 = A+$1 A/B+$1 A/B/C+$1" ~:
500 (Lib.TreeMap.from_List const
501 [ ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ]) ])
503 (Lib.TreeMap.from_List const
504 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
505 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
506 , Calc.Balance.exclusive = Amount.from_List []
508 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
509 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
510 , Calc.Balance.exclusive = Amount.from_List []
512 , ("A":|["B", "C"], Calc.Balance.Account_Sum_Expanded
513 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
514 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
517 , "A+$1 A/B+$1 = A+$2 A/B+$1" ~:
519 (Lib.TreeMap.from_List const
520 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
521 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
524 (Lib.TreeMap.from_List const
525 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
526 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 2 ]
527 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
529 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
530 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
531 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
534 , "A+$1 A/B+$1 A/B/C+$1 = A+$3 A/B+$2 A/B/C+$1" ~:
536 (Lib.TreeMap.from_List const
537 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
538 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
539 , ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ])
542 (Lib.TreeMap.from_List const
543 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
544 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 3 ]
545 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
547 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
548 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 2 ]
549 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
551 , ("A":|["B", "C"], Calc.Balance.Account_Sum_Expanded
552 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
553 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
556 , "A+$1 A/B+$1 A/B/C+$1 A/B/C/D+$1 = A+$4 A/B+$3 A/B/C+$2 A/B/C/D+$1" ~:
558 (Lib.TreeMap.from_List const
559 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
560 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
561 , ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ])
562 , ("A":|["B", "C", "D"], Amount.from_List [ Amount.usd $ 1 ])
565 (Lib.TreeMap.from_List const
566 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
567 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 4 ]
568 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
570 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
571 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 3 ]
572 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
574 , ("A":|["B", "C"], Calc.Balance.Account_Sum_Expanded
575 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 2 ]
576 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
578 , ("A":|["B", "C", "D"], Calc.Balance.Account_Sum_Expanded
579 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
580 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
583 , "A+$1 A/B+$1 A/BB+$1 AA/B+$1 = A+$3 A/B+$1 A/BB+$1 AA+$1 AA/B+$1" ~:
585 (Lib.TreeMap.from_List const
586 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
587 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
588 , ("A":|["BB"], Amount.from_List [ Amount.usd $ 1 ])
589 , ("AA":|["B"], Amount.from_List [ Amount.usd $ 1 ])
592 (Lib.TreeMap.from_List const
593 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
594 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 3 ]
595 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
597 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
598 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
599 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
601 , ("A":|["BB"], Calc.Balance.Account_Sum_Expanded
602 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
603 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
605 , ("AA":|[], Calc.Balance.Account_Sum_Expanded
606 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
607 , Calc.Balance.exclusive = Amount.from_List []
609 , ("AA":|["B"], Calc.Balance.Account_Sum_Expanded
610 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
611 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
615 , "is_equilibrable" ~: TestList
616 [ "nil" ~: TestCase $
618 Calc.Balance.is_equilibrable $
619 Calc.Balance.equilibre $
621 , "{A+$0, $+0}" ~: TestCase $
623 Calc.Balance.is_equilibrable $
624 Calc.Balance.equilibre $
626 { Calc.Balance.by_account =
627 Lib.TreeMap.from_List const
628 [ ("A":|[], Amount.from_List [ Amount.usd $ 0 ])
630 , Calc.Balance.by_unit =
632 Data.List.map Calc.Balance.assoc_unit_sum $
633 [ Calc.Balance.Unit_Sum
634 { Calc.Balance.amount = Amount.usd $ 0
635 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
640 , "{A+$1, $+1}" ~: TestCase $
642 Calc.Balance.is_equilibrable $
643 Calc.Balance.equilibre $
645 { Calc.Balance.by_account =
646 Lib.TreeMap.from_List const
647 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
649 , Calc.Balance.by_unit =
651 Data.List.map Calc.Balance.assoc_unit_sum $
652 [ Calc.Balance.Unit_Sum
653 { Calc.Balance.amount = Amount.usd $ 1
654 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
659 , "{A+$0+€0, $0 €+0}" ~: TestCase $
661 Calc.Balance.is_equilibrable $
662 Calc.Balance.equilibre $
664 { Calc.Balance.by_account =
665 Lib.TreeMap.from_List const
666 [ ("A":|[], Amount.from_List [ Amount.usd $ 0, Amount.eur $ 0 ])
668 , Calc.Balance.by_unit =
670 Data.List.map Calc.Balance.assoc_unit_sum $
671 [ Calc.Balance.Unit_Sum
672 { Calc.Balance.amount = Amount.usd $ 0
673 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
676 , Calc.Balance.Unit_Sum
677 { Calc.Balance.amount = Amount.eur $ 0
678 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
683 , "{A+$1, B-$1, $+0}" ~: TestCase $
685 Calc.Balance.is_equilibrable $
686 Calc.Balance.equilibre $
688 { Calc.Balance.by_account =
689 Lib.TreeMap.from_List const
690 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
691 , ("B":|[], Amount.from_List [ Amount.usd $ -1 ])
693 , Calc.Balance.by_unit =
695 Data.List.map Calc.Balance.assoc_unit_sum $
696 [ Calc.Balance.Unit_Sum
697 { Calc.Balance.amount = Amount.usd $ 0
698 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
703 , "{A+$1 B, $+1}" ~: TestCase $
705 Calc.Balance.is_equilibrable $
706 Calc.Balance.equilibre $
708 { Calc.Balance.by_account =
709 Lib.TreeMap.from_List const
710 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
711 , ("B":|[], Amount.from_List [])
713 , Calc.Balance.by_unit =
715 Data.List.map Calc.Balance.assoc_unit_sum $
716 [ Calc.Balance.Unit_Sum
717 { Calc.Balance.amount = Amount.usd $ 1
718 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
723 , "{A+$1 B+€1, $+1 €+1}" ~: TestCase $
725 Calc.Balance.is_equilibrable $
726 Calc.Balance.equilibre $
728 { Calc.Balance.by_account =
729 Lib.TreeMap.from_List const
730 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
731 , ("B":|[], Amount.from_List [ Amount.eur $ 1 ])
733 , Calc.Balance.by_unit =
735 Data.List.map Calc.Balance.assoc_unit_sum $
736 [ Calc.Balance.Unit_Sum
737 { Calc.Balance.amount = Amount.usd $ 1
738 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
741 , Calc.Balance.Unit_Sum
742 { Calc.Balance.amount = Amount.eur $ 1
743 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
748 , "{A+$1 B-$1+€1, $+0 €+1}" ~: TestCase $
750 Calc.Balance.is_equilibrable $
751 Calc.Balance.equilibre $
753 { Calc.Balance.by_account =
754 Lib.TreeMap.from_List const
755 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
756 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ 1 ])
758 , Calc.Balance.by_unit =
760 Data.List.map Calc.Balance.assoc_unit_sum $
761 [ Calc.Balance.Unit_Sum
762 { Calc.Balance.amount = Amount.usd $ 0
763 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
766 , Calc.Balance.Unit_Sum
767 { Calc.Balance.amount = Amount.eur $ 1
768 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
773 , "{A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~: TestCase $
775 Calc.Balance.is_equilibrable $
776 Calc.Balance.equilibre $
778 { Calc.Balance.by_account =
779 Lib.TreeMap.from_List const
780 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
781 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
783 , Calc.Balance.by_unit =
785 Data.List.map Calc.Balance.assoc_unit_sum $
786 [ Calc.Balance.Unit_Sum
787 { Calc.Balance.amount = Amount.usd $ 0
788 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
791 , Calc.Balance.Unit_Sum
792 { Calc.Balance.amount = Amount.eur $ 0
793 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
796 , Calc.Balance.Unit_Sum
797 { Calc.Balance.amount = Amount.gbp $ 0
798 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
806 , "Format" ~: TestList
807 [ "Ledger" ~: TestList
809 [ "account_name" ~: TestList
811 (Data.Either.rights $
813 (Format.Ledger.Read.account_name <* P.eof)
818 (Data.Either.rights $
820 (Format.Ledger.Read.account_name <* P.eof)
825 (Data.Either.rights $
827 (Format.Ledger.Read.account_name <* P.eof)
832 (Data.Either.rights $
834 (Format.Ledger.Read.account_name <* P.eof)
839 (Data.Either.rights $
841 (Format.Ledger.Read.account_name <* P.eof)
846 (Data.Either.rights $
848 (Format.Ledger.Read.account_name <* P.eof)
853 (Data.Either.rights $
855 (Format.Ledger.Read.account_name <* P.eof)
860 (Data.Either.rights $
862 (Format.Ledger.Read.account_name <* P.eof)
867 (Data.Either.rights $
869 (Format.Ledger.Read.account_name)
874 (Data.Either.rights $
876 (Format.Ledger.Read.account_name <* P.eof)
877 () "" ("A A"::Text)])
881 (Data.Either.rights $
883 (Format.Ledger.Read.account_name <* P.eof)
888 (Data.Either.rights $
890 (Format.Ledger.Read.account_name <* P.eof)
891 () "" ("A \n"::Text)])
895 (Data.Either.rights $
897 (Format.Ledger.Read.account_name <* P.eof)
898 () "" ("(A)A"::Text)])
902 (Data.Either.rights $
904 (Format.Ledger.Read.account_name <* P.eof)
905 () "" ("( )A"::Text)])
909 (Data.Either.rights $
911 (Format.Ledger.Read.account_name <* P.eof)
912 () "" ("(A) A"::Text)])
916 (Data.Either.rights $
918 (Format.Ledger.Read.account_name <* P.eof)
919 () "" ("[ ]A"::Text)])
923 (Data.Either.rights $
925 (Format.Ledger.Read.account_name <* P.eof)
926 () "" ("(A) "::Text)])
930 (Data.Either.rights $
932 (Format.Ledger.Read.account_name <* P.eof)
933 () "" ("(A)"::Text)])
937 (Data.Either.rights $
939 (Format.Ledger.Read.account_name <* P.eof)
940 () "" ("A(A)"::Text)])
944 (Data.Either.rights $
946 (Format.Ledger.Read.account_name <* P.eof)
947 () "" ("[A]A"::Text)])
951 (Data.Either.rights $
953 (Format.Ledger.Read.account_name <* P.eof)
954 () "" ("[A] A"::Text)])
958 (Data.Either.rights $
960 (Format.Ledger.Read.account_name <* P.eof)
961 () "" ("[A] "::Text)])
965 (Data.Either.rights $
967 (Format.Ledger.Read.account_name <* P.eof)
968 () "" ("[A]"::Text)])
972 , "account" ~: TestList
974 (Data.Either.rights $
976 (Format.Ledger.Read.account <* P.eof)
981 (Data.Either.rights $
983 (Format.Ledger.Read.account <* P.eof)
988 (Data.Either.rights $
990 (Format.Ledger.Read.account <* P.eof)
995 (Data.Either.rights $
997 (Format.Ledger.Read.account <* P.eof)
1002 (Data.Either.rights $
1004 (Format.Ledger.Read.account <* P.eof)
1005 () "" ("A "::Text)])
1009 (Data.Either.rights $
1011 (Format.Ledger.Read.account <* P.eof)
1012 () "" (" A"::Text)])
1016 (Data.Either.rights $
1018 (Format.Ledger.Read.account <* P.eof)
1019 () "" ("A:B"::Text)])
1023 (Data.Either.rights $
1025 (Format.Ledger.Read.account <* P.eof)
1026 () "" ("A:B:C"::Text)])
1029 , "\"Aa:Bbb:Cccc\"" ~:
1030 (Data.Either.rights $
1032 (Format.Ledger.Read.account <* P.eof)
1033 () "" ("Aa:Bbb:Cccc"::Text)])
1035 ["Aa":|["Bbb", "Cccc"]]
1036 , "\"A a : B b b : C c c c\"" ~:
1037 (Data.Either.rights $
1039 (Format.Ledger.Read.account <* P.eof)
1040 () "" ("A a : B b b : C c c c"::Text)])
1042 ["A a ":|[" B b b ", " C c c c"]]
1044 (Data.Either.rights $
1046 (Format.Ledger.Read.account <* P.eof)
1047 () "" ("A: :C"::Text)])
1051 (Data.Either.rights $
1053 (Format.Ledger.Read.account <* P.eof)
1054 () "" ("A::C"::Text)])
1058 (Data.Either.rights $
1060 (Format.Ledger.Read.account <* P.eof)
1061 () "" ("A:B:(C)"::Text)])
1065 , "posting_type" ~: TestList
1067 Format.Ledger.Read.posting_type
1070 (Posting.Type_Regular, "A":|[])
1072 Format.Ledger.Read.posting_type
1075 (Posting.Type_Regular, "(":|[])
1077 Format.Ledger.Read.posting_type
1080 (Posting.Type_Regular, ")":|[])
1082 Format.Ledger.Read.posting_type
1085 (Posting.Type_Regular, "()":|[])
1087 Format.Ledger.Read.posting_type
1090 (Posting.Type_Regular, "( )":|[])
1092 Format.Ledger.Read.posting_type
1095 (Posting.Type_Virtual, "A":|[])
1097 Format.Ledger.Read.posting_type
1100 (Posting.Type_Virtual, "A":|["B", "C"])
1102 Format.Ledger.Read.posting_type
1105 (Posting.Type_Regular, "A":|["B", "C"])
1107 Format.Ledger.Read.posting_type
1110 (Posting.Type_Regular, "(A)":|["B", "C"])
1112 Format.Ledger.Read.posting_type
1115 (Posting.Type_Regular, "A":|["(B)", "C"])
1117 Format.Ledger.Read.posting_type
1120 (Posting.Type_Regular, "A":|["B", "(C)"])
1122 Format.Ledger.Read.posting_type
1125 (Posting.Type_Regular, "[":|[])
1127 Format.Ledger.Read.posting_type
1130 (Posting.Type_Regular, "]":|[])
1132 Format.Ledger.Read.posting_type
1135 (Posting.Type_Regular, "[]":|[])
1137 Format.Ledger.Read.posting_type
1140 (Posting.Type_Regular, "[ ]":|[])
1142 Format.Ledger.Read.posting_type
1145 (Posting.Type_Virtual_Balanced, "A":|[])
1147 Format.Ledger.Read.posting_type
1150 (Posting.Type_Virtual_Balanced, "A":|["B", "C"])
1152 Format.Ledger.Read.posting_type
1155 (Posting.Type_Regular, "A":|["B", "C"])
1157 Format.Ledger.Read.posting_type
1160 (Posting.Type_Regular, "[A]":|["B", "C"])
1162 Format.Ledger.Read.posting_type
1165 (Posting.Type_Regular, "A":|["[B]", "C"])
1167 Format.Ledger.Read.posting_type
1170 (Posting.Type_Regular, "A":|["B", "[C]"])
1172 , "amount" ~: TestList
1174 (Data.Either.rights $
1176 (Format.Ledger.Read.amount <* P.eof)
1180 , "\"0\" = Right 0" ~:
1181 (Data.Either.rights $
1183 (Format.Ledger.Read.amount <* P.eof)
1187 { Amount.quantity = Decimal 0 0
1189 , "\"00\" = Right 0" ~:
1190 (Data.Either.rights $
1192 (Format.Ledger.Read.amount <* P.eof)
1193 () "" ("00"::Text)])
1196 { Amount.quantity = Decimal 0 0
1198 , "\"0.\" = Right 0." ~:
1199 (Data.Either.rights $
1201 (Format.Ledger.Read.amount <* P.eof)
1202 () "" ("0."::Text)])
1205 { Amount.quantity = Decimal 0 0
1208 { Amount.Style.fractioning = Just '.'
1211 , "\".0\" = Right 0.0" ~:
1212 (Data.Either.rights $
1214 (Format.Ledger.Read.amount <* P.eof)
1215 () "" (".0"::Text)])
1218 { Amount.quantity = Decimal 0 0
1221 { Amount.Style.fractioning = Just '.'
1222 , Amount.Style.precision = 1
1225 , "\"0,\" = Right 0," ~:
1226 (Data.Either.rights $
1228 (Format.Ledger.Read.amount <* P.eof)
1229 () "" ("0,"::Text)])
1232 { Amount.quantity = Decimal 0 0
1235 { Amount.Style.fractioning = Just ','
1238 , "\",0\" = Right 0,0" ~:
1239 (Data.Either.rights $
1241 (Format.Ledger.Read.amount <* P.eof)
1242 () "" (",0"::Text)])
1245 { Amount.quantity = Decimal 0 0
1248 { Amount.Style.fractioning = Just ','
1249 , Amount.Style.precision = 1
1252 , "\"0_\" = Left" ~:
1253 (Data.Either.rights $
1255 (Format.Ledger.Read.amount <* P.eof)
1256 () "" ("0_"::Text)])
1259 , "\"_0\" = Left" ~:
1260 (Data.Either.rights $
1262 (Format.Ledger.Read.amount <* P.eof)
1263 () "" ("_0"::Text)])
1266 , "\"0.0\" = Right 0.0" ~:
1267 (Data.Either.rights $
1269 (Format.Ledger.Read.amount <* P.eof)
1270 () "" ("0.0"::Text)])
1273 { Amount.quantity = Decimal 0 0
1276 { Amount.Style.fractioning = Just '.'
1277 , Amount.Style.precision = 1
1280 , "\"00.00\" = Right 0.00" ~:
1281 (Data.Either.rights $
1283 (Format.Ledger.Read.amount <* P.eof)
1284 () "" ("00.00"::Text)])
1287 { Amount.quantity = Decimal 0 0
1290 { Amount.Style.fractioning = Just '.'
1291 , Amount.Style.precision = 2
1294 , "\"0,0\" = Right 0,0" ~:
1295 (Data.Either.rights $
1297 (Format.Ledger.Read.amount <* P.eof)
1298 () "" ("0,0"::Text)])
1301 { Amount.quantity = Decimal 0 0
1304 { Amount.Style.fractioning = Just ','
1305 , Amount.Style.precision = 1
1308 , "\"00,00\" = Right 0,00" ~:
1309 (Data.Either.rights $
1311 (Format.Ledger.Read.amount <* P.eof)
1312 () "" ("00,00"::Text)])
1315 { Amount.quantity = Decimal 0 0
1318 { Amount.Style.fractioning = Just ','
1319 , Amount.Style.precision = 2
1322 , "\"0_0\" = Right 0" ~:
1323 (Data.Either.rights $
1325 (Format.Ledger.Read.amount <* P.eof)
1326 () "" ("0_0"::Text)])
1329 { Amount.quantity = Decimal 0 0
1332 { Amount.Style.fractioning = Nothing
1333 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [1]
1334 , Amount.Style.precision = 0
1337 , "\"00_00\" = Right 0" ~:
1338 (Data.Either.rights $
1340 (Format.Ledger.Read.amount <* P.eof)
1341 () "" ("00_00"::Text)])
1344 { Amount.quantity = Decimal 0 0
1347 { Amount.Style.fractioning = Nothing
1348 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [2]
1349 , Amount.Style.precision = 0
1352 , "\"0,000.00\" = Right 0,000.00" ~:
1353 (Data.Either.rights $
1355 (Format.Ledger.Read.amount <* P.eof)
1356 () "" ("0,000.00"::Text)])
1359 { Amount.quantity = Decimal 0 0
1362 { Amount.Style.fractioning = Just '.'
1363 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
1364 , Amount.Style.precision = 2
1367 , "\"0.000,00\" = Right 0.000,00" ~:
1368 (Data.Either.rights $
1370 (Format.Ledger.Read.amount)
1371 () "" ("0.000,00"::Text)])
1374 { Amount.quantity = Decimal 0 0
1377 { Amount.Style.fractioning = Just ','
1378 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1379 , Amount.Style.precision = 2
1382 , "\"1,000.00\" = Right 1,000.00" ~:
1383 (Data.Either.rights $
1385 (Format.Ledger.Read.amount <* P.eof)
1386 () "" ("1,000.00"::Text)])
1389 { Amount.quantity = Decimal 0 1000
1392 { Amount.Style.fractioning = Just '.'
1393 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
1394 , Amount.Style.precision = 2
1397 , "\"1.000,00\" = Right 1.000,00" ~:
1398 (Data.Either.rights $
1400 (Format.Ledger.Read.amount)
1401 () "" ("1.000,00"::Text)])
1404 { Amount.quantity = Decimal 0 1000
1407 { Amount.Style.fractioning = Just ','
1408 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1409 , Amount.Style.precision = 2
1412 , "\"1,000.00.\" = Left" ~:
1413 (Data.Either.rights $
1415 (Format.Ledger.Read.amount)
1416 () "" ("1,000.00."::Text)])
1419 , "\"1.000,00,\" = Left" ~:
1420 (Data.Either.rights $
1422 (Format.Ledger.Read.amount)
1423 () "" ("1.000,00,"::Text)])
1426 , "\"1,000.00_\" = Left" ~:
1427 (Data.Either.rights $
1429 (Format.Ledger.Read.amount)
1430 () "" ("1,000.00_"::Text)])
1433 , "\"12\" = Right 12" ~:
1434 (Data.Either.rights $
1436 (Format.Ledger.Read.amount <* P.eof)
1437 () "" ("123"::Text)])
1440 { Amount.quantity = Decimal 0 123
1442 , "\"1.2\" = Right 1.2" ~:
1443 (Data.Either.rights $
1445 (Format.Ledger.Read.amount <* P.eof)
1446 () "" ("1.2"::Text)])
1449 { Amount.quantity = Decimal 1 12
1452 { Amount.Style.fractioning = Just '.'
1453 , Amount.Style.precision = 1
1456 , "\"1,2\" = Right 1,2" ~:
1457 (Data.Either.rights $
1459 (Format.Ledger.Read.amount <* P.eof)
1460 () "" ("1,2"::Text)])
1463 { Amount.quantity = Decimal 1 12
1466 { Amount.Style.fractioning = Just ','
1467 , Amount.Style.precision = 1
1470 , "\"12.23\" = Right 12.23" ~:
1471 (Data.Either.rights $
1473 (Format.Ledger.Read.amount <* P.eof)
1474 () "" ("12.34"::Text)])
1477 { Amount.quantity = Decimal 2 1234
1480 { Amount.Style.fractioning = Just '.'
1481 , Amount.Style.precision = 2
1484 , "\"12,23\" = Right 12,23" ~:
1485 (Data.Either.rights $
1487 (Format.Ledger.Read.amount <* P.eof)
1488 () "" ("12,34"::Text)])
1491 { Amount.quantity = Decimal 2 1234
1494 { Amount.Style.fractioning = Just ','
1495 , Amount.Style.precision = 2
1498 , "\"1_2\" = Right 1_2" ~:
1499 (Data.Either.rights $
1501 (Format.Ledger.Read.amount <* P.eof)
1502 () "" ("1_2"::Text)])
1505 { Amount.quantity = Decimal 0 12
1508 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [1]
1509 , Amount.Style.precision = 0
1512 , "\"1_23\" = Right 1_23" ~:
1513 (Data.Either.rights $
1515 (Format.Ledger.Read.amount <* P.eof)
1516 () "" ("1_23"::Text)])
1519 { Amount.quantity = Decimal 0 123
1522 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [2]
1523 , Amount.Style.precision = 0
1526 , "\"1_23_456\" = Right 1_23_456" ~:
1527 (Data.Either.rights $
1529 (Format.Ledger.Read.amount <* P.eof)
1530 () "" ("1_23_456"::Text)])
1533 { Amount.quantity = Decimal 0 123456
1536 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [3, 2]
1537 , Amount.Style.precision = 0
1540 , "\"1_23_456.7890_12345_678901\" = Right 1_23_456.7890_12345_678901" ~:
1541 (Data.Either.rights $
1543 (Format.Ledger.Read.amount <* P.eof)
1544 () "" ("1_23_456.7890_12345_678901"::Text)])
1547 { Amount.quantity = Decimal 15 123456789012345678901
1550 { Amount.Style.fractioning = Just '.'
1551 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [3, 2]
1552 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping '_' [4, 5, 6]
1553 , Amount.Style.precision = 15
1556 , "\"123456_78901_2345.678_90_1\" = Right 123456_78901_2345.678_90_1" ~:
1557 (Data.Either.rights $
1559 (Format.Ledger.Read.amount <* P.eof)
1560 () "" ("123456_78901_2345.678_90_1"::Text)])
1563 { Amount.quantity = Decimal 6 123456789012345678901
1566 { Amount.Style.fractioning = Just '.'
1567 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [4, 5, 6]
1568 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping '_' [3, 2]
1569 , Amount.Style.precision = 6
1572 , "\"$1\" = Right $1" ~:
1573 (Data.Either.rights $
1575 (Format.Ledger.Read.amount <* P.eof)
1576 () "" ("$1"::Text)])
1579 { Amount.quantity = Decimal 0 1
1582 { Amount.Style.fractioning = Nothing
1583 , Amount.Style.grouping_integral = Nothing
1584 , Amount.Style.grouping_fractional = Nothing
1585 , Amount.Style.precision = 0
1586 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1587 , Amount.Style.unit_spaced = Just False
1591 , "\"1$\" = Right 1$" ~:
1592 (Data.Either.rights $
1594 (Format.Ledger.Read.amount <* P.eof)
1595 () "" ("1$"::Text)])
1598 { Amount.quantity = Decimal 0 1
1601 { Amount.Style.fractioning = Nothing
1602 , Amount.Style.grouping_integral = Nothing
1603 , Amount.Style.grouping_fractional = Nothing
1604 , Amount.Style.precision = 0
1605 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1606 , Amount.Style.unit_spaced = Just False
1610 , "\"$ 1\" = Right $ 1" ~:
1611 (Data.Either.rights $
1613 (Format.Ledger.Read.amount <* P.eof)
1614 () "" ("$ 1"::Text)])
1617 { Amount.quantity = Decimal 0 1
1620 { Amount.Style.fractioning = Nothing
1621 , Amount.Style.grouping_integral = Nothing
1622 , Amount.Style.grouping_fractional = Nothing
1623 , Amount.Style.precision = 0
1624 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1625 , Amount.Style.unit_spaced = Just True
1629 , "\"1 $\" = Right 1 $" ~:
1630 (Data.Either.rights $
1632 (Format.Ledger.Read.amount <* P.eof)
1633 () "" ("1 $"::Text)])
1636 { Amount.quantity = Decimal 0 1
1639 { Amount.Style.fractioning = Nothing
1640 , Amount.Style.grouping_integral = Nothing
1641 , Amount.Style.grouping_fractional = Nothing
1642 , Amount.Style.precision = 0
1643 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1644 , Amount.Style.unit_spaced = Just True
1648 , "\"-$1\" = Right $-1" ~:
1649 (Data.Either.rights $
1651 (Format.Ledger.Read.amount <* P.eof)
1652 () "" ("-$1"::Text)])
1655 { Amount.quantity = Decimal 0 (-1)
1658 { Amount.Style.fractioning = Nothing
1659 , Amount.Style.grouping_integral = Nothing
1660 , Amount.Style.grouping_fractional = Nothing
1661 , Amount.Style.precision = 0
1662 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1663 , Amount.Style.unit_spaced = Just False
1667 , "\"\\\"4 2\\\"1\" = Right \\\"4 2\\\"1" ~:
1668 (Data.Either.rights $
1670 (Format.Ledger.Read.amount <* P.eof)
1671 () "" ("\"4 2\"1"::Text)])
1674 { Amount.quantity = Decimal 0 1
1677 { Amount.Style.fractioning = Nothing
1678 , Amount.Style.grouping_integral = Nothing
1679 , Amount.Style.grouping_fractional = Nothing
1680 , Amount.Style.precision = 0
1681 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1682 , Amount.Style.unit_spaced = Just False
1684 , Amount.unit = "4 2"
1686 , "\"1\\\"4 2\\\"\" = Right 1\\\"4 2\\\"" ~:
1687 (Data.Either.rights $
1689 (Format.Ledger.Read.amount <* P.eof)
1690 () "" ("1\"4 2\""::Text)])
1693 { Amount.quantity = Decimal 0 1
1696 { Amount.Style.fractioning = Nothing
1697 , Amount.Style.grouping_integral = Nothing
1698 , Amount.Style.grouping_fractional = Nothing
1699 , Amount.Style.precision = 0
1700 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1701 , Amount.Style.unit_spaced = Just False
1703 , Amount.unit = "4 2"
1705 , "\"$1.000,00\" = Right $1.000,00" ~:
1706 (Data.Either.rights $
1708 (Format.Ledger.Read.amount <* P.eof)
1709 () "" ("$1.000,00"::Text)])
1712 { Amount.quantity = Decimal 0 1000
1715 { Amount.Style.fractioning = Just ','
1716 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1717 , Amount.Style.grouping_fractional = Nothing
1718 , Amount.Style.precision = 2
1719 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1720 , Amount.Style.unit_spaced = Just False
1724 , "\"1.000,00$\" = Right 1.000,00$" ~:
1725 (Data.Either.rights $
1727 (Format.Ledger.Read.amount <* P.eof)
1728 () "" ("1.000,00$"::Text)])
1731 { Amount.quantity = Decimal 0 1000
1734 { Amount.Style.fractioning = Just ','
1735 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1736 , Amount.Style.grouping_fractional = Nothing
1737 , Amount.Style.precision = 2
1738 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1739 , Amount.Style.unit_spaced = Just False
1744 , "comment" ~: TestList
1745 [ "; some comment = Right \" some comment\"" ~:
1746 (Data.Either.rights $
1748 (Format.Ledger.Read.comment <* P.eof)
1749 () "" ("; some comment"::Text)])
1752 , "; some comment \\n = Right \" some comment \"" ~:
1753 (Data.Either.rights $
1755 (Format.Ledger.Read.comment <* P.newline <* P.eof)
1756 () "" ("; some comment \n"::Text)])
1758 [ " some comment " ]
1759 , "; some comment \\r\\n = Right \" some comment \"" ~:
1760 (Data.Either.rights $
1762 (Format.Ledger.Read.comment <* P.string "\r\n" <* P.eof)
1763 () "" ("; some comment \r\n"::Text)])
1765 [ " some comment " ]
1767 , "comments" ~: TestList
1768 [ "; some comment\\n ; some other comment = Right [\" some comment\", \" some other comment\"]" ~:
1769 (Data.Either.rights $
1771 (Format.Ledger.Read.comments <* P.eof)
1772 () "" ("; some comment\n ; some other comment"::Text)])
1774 [ [" some comment", " some other comment"] ]
1775 , "; some comment \\n = Right \" some comment \"" ~:
1776 (Data.Either.rights $
1778 (Format.Ledger.Read.comments <* P.string "\n" <* P.eof)
1779 () "" ("; some comment \n"::Text)])
1781 [ [" some comment "] ]
1783 , "date" ~: TestList
1785 (Data.Either.rights $
1787 (Format.Ledger.Read.date Nothing <* P.eof)
1788 () "" ("2000/01/01"::Text)])
1792 (Time.fromGregorian 2000 01 01)
1793 (Time.TimeOfDay 0 0 0))
1795 , "2000/01/01 some text" ~:
1796 (Data.Either.rights $
1798 (Format.Ledger.Read.date Nothing)
1799 () "" ("2000/01/01 some text"::Text)])
1803 (Time.fromGregorian 2000 01 01)
1804 (Time.TimeOfDay 0 0 0))
1806 , "2000/01/01 12:34" ~:
1807 (Data.Either.rights $
1809 (Format.Ledger.Read.date Nothing <* P.eof)
1810 () "" ("2000/01/01 12:34"::Text)])
1814 (Time.fromGregorian 2000 01 01)
1815 (Time.TimeOfDay 12 34 0))
1817 , "2000/01/01 12:34:56" ~:
1818 (Data.Either.rights $
1820 (Format.Ledger.Read.date Nothing <* P.eof)
1821 () "" ("2000/01/01 12:34:56"::Text)])
1825 (Time.fromGregorian 2000 01 01)
1826 (Time.TimeOfDay 12 34 56))
1828 , "2000/01/01 12:34 CET" ~:
1829 (Data.Either.rights $
1831 (Format.Ledger.Read.date Nothing <* P.eof)
1832 () "" ("2000/01/01 12:34 CET"::Text)])
1836 (Time.fromGregorian 2000 01 01)
1837 (Time.TimeOfDay 12 34 0))
1838 (Time.TimeZone 60 True "CET")]
1839 , "2000/01/01 12:34 +0130" ~:
1840 (Data.Either.rights $
1842 (Format.Ledger.Read.date Nothing <* P.eof)
1843 () "" ("2000/01/01 12:34 +0130"::Text)])
1847 (Time.fromGregorian 2000 01 01)
1848 (Time.TimeOfDay 12 34 0))
1849 (Time.TimeZone 90 False "+0130")]
1850 , "2000/01/01 12:34:56 CET" ~:
1851 (Data.Either.rights $
1853 (Format.Ledger.Read.date Nothing <* P.eof)
1854 () "" ("2000/01/01 12:34:56 CET"::Text)])
1858 (Time.fromGregorian 2000 01 01)
1859 (Time.TimeOfDay 12 34 56))
1860 (Time.TimeZone 60 True "CET")]
1862 (Data.Either.rights $
1864 (Format.Ledger.Read.date Nothing <* P.eof)
1865 () "" ("2001/02/29"::Text)])
1869 (Data.Either.rights $
1871 (Format.Ledger.Read.date (Just 2000) <* P.eof)
1872 () "" ("01/01"::Text)])
1876 (Time.fromGregorian 2000 01 01)
1877 (Time.TimeOfDay 0 0 0))
1880 , "tag_value" ~: TestList
1882 (Data.Either.rights $
1884 (Format.Ledger.Read.tag_value <* P.eof)
1889 (Data.Either.rights $
1891 (Format.Ledger.Read.tag_value <* P.char '\n' <* P.eof)
1892 () "" (",\n"::Text)])
1896 (Data.Either.rights $
1898 (Format.Ledger.Read.tag_value <* P.eof)
1899 () "" (",x"::Text)])
1903 (Data.Either.rights $
1905 (Format.Ledger.Read.tag_value <* P.string ",x:" <* P.eof)
1906 () "" (",x:"::Text)])
1910 (Data.Either.rights $
1912 (Format.Ledger.Read.tag_value <* P.string ", n:" <* P.eof)
1913 () "" ("v, v, n:"::Text)])
1919 (Data.Either.rights $
1921 (Format.Ledger.Read.tag <* P.eof)
1922 () "" ("Name:"::Text)])
1926 (Data.Either.rights $
1928 (Format.Ledger.Read.tag <* P.eof)
1929 () "" ("Name:Value"::Text)])
1932 , "Name:Value\\n" ~:
1933 (Data.Either.rights $
1935 (Format.Ledger.Read.tag <* P.string "\n" <* P.eof)
1936 () "" ("Name:Value\n"::Text)])
1940 (Data.Either.rights $
1942 (Format.Ledger.Read.tag <* P.eof)
1943 () "" ("Name:Val ue"::Text)])
1945 [("Name", "Val ue")]
1947 (Data.Either.rights $
1949 (Format.Ledger.Read.tag <* P.eof)
1950 () "" ("Name:,"::Text)])
1954 (Data.Either.rights $
1956 (Format.Ledger.Read.tag <* P.eof)
1957 () "" ("Name:Val,ue"::Text)])
1959 [("Name", "Val,ue")]
1961 (Data.Either.rights $
1963 (Format.Ledger.Read.tag <* P.string ",ue:" <* P.eof)
1964 () "" ("Name:Val,ue:"::Text)])
1968 , "tags" ~: TestList
1970 (Data.Either.rights $
1972 (Format.Ledger.Read.tags <* P.eof)
1973 () "" ("Name:"::Text)])
1980 (Data.Either.rights $
1982 (Format.Ledger.Read.tags <* P.eof)
1983 () "" ("Name:,"::Text)])
1990 (Data.Either.rights $
1992 (Format.Ledger.Read.tags <* P.eof)
1993 () "" ("Name:,Name:"::Text)])
1996 [ ("Name", ["", ""])
2000 (Data.Either.rights $
2002 (Format.Ledger.Read.tags <* P.eof)
2003 () "" ("Name:,Name2:"::Text)])
2010 , "Name: , Name2:" ~:
2011 (Data.Either.rights $
2013 (Format.Ledger.Read.tags <* P.eof)
2014 () "" ("Name: , Name2:"::Text)])
2021 , "Name:,Name2:,Name3:" ~:
2022 (Data.Either.rights $
2024 (Format.Ledger.Read.tags <* P.eof)
2025 () "" ("Name:,Name2:,Name3:"::Text)])
2033 , "Name:Val ue,Name2:V a l u e,Name3:V al ue" ~:
2034 (Data.Either.rights $
2036 (Format.Ledger.Read.tags <* P.eof)
2037 () "" ("Name:Val ue,Name2:V a l u e,Name3:V al ue"::Text)])
2040 [ ("Name", ["Val ue"])
2041 , ("Name2", ["V a l u e"])
2042 , ("Name3", ["V al ue"])
2046 , "posting" ~: TestList
2047 [ " A:B:C = Right A:B:C" ~:
2048 (Data.Either.rights $
2050 (Format.Ledger.Read.posting <* P.eof)
2051 Format.Ledger.Read.nil_Context "" (" A:B:C"::Text)])
2053 [ ( (Posting.nil ("A":|["B", "C"]))
2054 { Posting.sourcepos = P.newPos "" 1 1
2056 , Posting.Type_Regular
2059 , " !A:B:C = Right !A:B:C" ~:
2060 (Data.List.map fst $
2061 Data.Either.rights $
2063 (Format.Ledger.Read.posting <* P.eof)
2064 Format.Ledger.Read.nil_Context "" (" !A:B:C"::Text)])
2066 [ (Posting.nil ("A":|["B", "C"]))
2067 { Posting.sourcepos = P.newPos "" 1 1
2068 , Posting.status = True
2071 , " *A:B:C = Right *A:B:C" ~:
2072 (Data.List.map fst $
2073 Data.Either.rights $
2075 (Format.Ledger.Read.posting <* P.eof)
2076 Format.Ledger.Read.nil_Context "" (" *A:B:C"::Text)])
2078 [ (Posting.nil ("A":|["B", "C"]))
2079 { Posting.amounts = Data.Map.fromList []
2080 , Posting.comments = []
2081 , Posting.dates = []
2082 , Posting.status = True
2083 , Posting.sourcepos = P.newPos "" 1 1
2084 , Posting.tags = Data.Map.fromList []
2087 , " A:B:C $1 = Right A:B:C $1" ~:
2088 (Data.List.map fst $
2089 Data.Either.rights $
2091 (Format.Ledger.Read.posting <* P.eof)
2092 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
2094 [ (Posting.nil ("A":|["B","C $1"]))
2095 { Posting.sourcepos = P.newPos "" 1 1
2098 , " A:B:C $1 = Right A:B:C $1" ~:
2099 (Data.List.map fst $
2100 Data.Either.rights $
2102 (Format.Ledger.Read.posting <* P.eof)
2103 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
2105 [ (Posting.nil ("A":|["B", "C"]))
2106 { Posting.amounts = Data.Map.fromList
2108 { Amount.quantity = 1
2109 , Amount.style = Amount.Style.nil
2110 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2111 , Amount.Style.unit_spaced = Just False
2116 , Posting.sourcepos = P.newPos "" 1 1
2119 , " A:B:C $1 + 1€ = Right A:B:C $1 + 1€" ~:
2120 (Data.List.map fst $
2121 Data.Either.rights $
2123 (Format.Ledger.Read.posting <* P.eof)
2124 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1€"::Text)])
2126 [ (Posting.nil ("A":|["B", "C"]))
2127 { Posting.amounts = Data.Map.fromList
2129 { Amount.quantity = 1
2130 , Amount.style = Amount.Style.nil
2131 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2132 , Amount.Style.unit_spaced = Just False
2137 { Amount.quantity = 1
2138 , Amount.style = Amount.Style.nil
2139 { Amount.Style.unit_side = Just Amount.Style.Side_Right
2140 , Amount.Style.unit_spaced = Just False
2145 , Posting.sourcepos = P.newPos "" 1 1
2148 , " A:B:C $1 + 1$ = Right A:B:C $2" ~:
2149 (Data.List.map fst $
2150 Data.Either.rights $
2152 (Format.Ledger.Read.posting <* P.eof)
2153 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$"::Text)])
2155 [ (Posting.nil ("A":|["B", "C"]))
2156 { Posting.amounts = Data.Map.fromList
2158 { Amount.quantity = 2
2159 , Amount.style = Amount.Style.nil
2160 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2161 , Amount.Style.unit_spaced = Just False
2166 , Posting.sourcepos = P.newPos "" 1 1
2169 , " A:B:C $1 + 1$ + 1$ = Right A:B:C $3" ~:
2170 (Data.List.map fst $
2171 Data.Either.rights $
2173 (Format.Ledger.Read.posting <* P.eof)
2174 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$ + 1$"::Text)])
2176 [ (Posting.nil ("A":|["B", "C"]))
2177 { Posting.amounts = Data.Map.fromList
2179 { Amount.quantity = 3
2180 , Amount.style = Amount.Style.nil
2181 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2182 , Amount.Style.unit_spaced = Just False
2187 , Posting.sourcepos = P.newPos "" 1 1
2190 , " A:B:C ; some comment = Right A:B:C ; some comment" ~:
2191 (Data.List.map fst $
2192 Data.Either.rights $
2194 (Format.Ledger.Read.posting <* P.eof)
2195 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment"::Text)])
2197 [ (Posting.nil ("A":|["B", "C"]))
2198 { Posting.amounts = Data.Map.fromList []
2199 , Posting.comments = [" some comment"]
2200 , Posting.sourcepos = P.newPos "" 1 1
2203 , " A:B:C ; some comment\\n ; some other comment = Right A:B:C ; some comment\\n ; some other comment" ~:
2204 (Data.List.map fst $
2205 Data.Either.rights $
2207 (Format.Ledger.Read.posting <* P.eof)
2208 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment\n ; some other comment"::Text)])
2210 [ (Posting.nil ("A":|["B", "C"]))
2211 { Posting.amounts = Data.Map.fromList []
2212 , Posting.comments = [" some comment", " some other comment"]
2213 , Posting.sourcepos = P.newPos "" 1 1
2216 , " A:B:C $1 ; some comment = Right A:B:C $1 ; some comment" ~:
2217 (Data.List.map fst $
2218 Data.Either.rights $
2220 (Format.Ledger.Read.posting)
2221 Format.Ledger.Read.nil_Context "" (" A:B:C $1 ; some comment"::Text)])
2223 [ (Posting.nil ("A":|["B", "C"]))
2224 { Posting.amounts = Data.Map.fromList
2226 { Amount.quantity = 1
2227 , Amount.style = Amount.Style.nil
2228 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2229 , Amount.Style.unit_spaced = Just False
2234 , Posting.comments = [" some comment"]
2235 , Posting.sourcepos = P.newPos "" 1 1
2238 , " A:B:C ; N:V = Right A:B:C ; N:V" ~:
2239 (Data.List.map fst $
2240 Data.Either.rights $
2242 (Format.Ledger.Read.posting <* P.eof)
2243 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V"::Text)])
2245 [ (Posting.nil ("A":|["B", "C"]))
2246 { Posting.comments = [" N:V"]
2247 , Posting.sourcepos = P.newPos "" 1 1
2248 , Posting.tags = Data.Map.fromList
2253 , " A:B:C ; some comment N:V = Right A:B:C ; some comment N:V" ~:
2254 (Data.List.map fst $
2255 Data.Either.rights $
2257 (Format.Ledger.Read.posting <* P.eof)
2258 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V"::Text)])
2260 [ (Posting.nil ("A":|["B", "C"]))
2261 { Posting.comments = [" some comment N:V"]
2262 , Posting.sourcepos = P.newPos "" 1 1
2263 , Posting.tags = Data.Map.fromList
2268 , " A:B:C ; some comment N:V v, N2:V2 v2 = Right A:B:C ; some comment N:V v, N2:V2 v2" ~:
2269 (Data.List.map fst $
2270 Data.Either.rights $
2272 (Format.Ledger.Read.posting )
2273 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V v, N2:V2 v2"::Text)])
2275 [ (Posting.nil ("A":|["B", "C"]))
2276 { Posting.comments = [" some comment N:V v, N2:V2 v2"]
2277 , Posting.sourcepos = P.newPos "" 1 1
2278 , Posting.tags = Data.Map.fromList
2284 , " A:B:C ; N:V\\n ; N:V2 = Right A:B:C ; N:V\\n ; N:V2" ~:
2285 (Data.List.map fst $
2286 Data.Either.rights $
2288 (Format.Ledger.Read.posting <* P.eof)
2289 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N:V2"::Text)])
2291 [ (Posting.nil ("A":|["B", "C"]))
2292 { Posting.comments = [" N:V", " N:V2"]
2293 , Posting.sourcepos = P.newPos "" 1 1
2294 , Posting.tags = Data.Map.fromList
2295 [ ("N", ["V", "V2"])
2299 , " A:B:C ; N:V\\n ; N2:V = Right A:B:C ; N:V\\n ; N2:V" ~:
2300 (Data.List.map fst $
2301 Data.Either.rights $
2303 (Format.Ledger.Read.posting <* P.eof)
2304 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N2:V"::Text)])
2306 [ (Posting.nil ("A":|["B", "C"]))
2307 { Posting.comments = [" N:V", " N2:V"]
2308 , Posting.sourcepos = P.newPos "" 1 1
2309 , Posting.tags = Data.Map.fromList
2315 , " A:B:C ; date:2001/01/01 = Right A:B:C ; date:2001/01/01" ~:
2316 (Data.List.map fst $
2317 Data.Either.rights $
2319 (Format.Ledger.Read.posting <* P.eof)
2320 Format.Ledger.Read.nil_Context "" (" A:B:C ; date:2001/01/01"::Text)])
2322 [ (Posting.nil ("A":|["B", "C"]))
2323 { Posting.comments = [" date:2001/01/01"]
2327 (Time.fromGregorian 2001 01 01)
2328 (Time.TimeOfDay 0 0 0))
2331 , Posting.sourcepos = P.newPos "" 1 1
2332 , Posting.tags = Data.Map.fromList
2333 [ ("date", ["2001/01/01"])
2337 , " (A:B:C) = Right (A:B:C)" ~:
2338 (Data.Either.rights $
2340 (Format.Ledger.Read.posting <* P.eof)
2341 Format.Ledger.Read.nil_Context "" (" (A:B:C)"::Text)])
2343 [ ( (Posting.nil ("A":|["B", "C"]))
2344 { Posting.sourcepos = P.newPos "" 1 1
2346 , Posting.Type_Virtual
2349 , " [A:B:C] = Right [A:B:C]" ~:
2350 (Data.Either.rights $
2352 (Format.Ledger.Read.posting <* P.eof)
2353 Format.Ledger.Read.nil_Context "" (" [A:B:C]"::Text)])
2355 [ ( (Posting.nil ("A":|["B", "C"]))
2356 { Posting.sourcepos = P.newPos "" 1 1
2358 , Posting.Type_Virtual_Balanced
2362 , "transaction" ~: TestList
2363 [ "2000/01/01 some description\\n A:B:C $1\\n a:b:c" ~:
2364 (Data.Either.rights $
2366 (Format.Ledger.Read.transaction <* P.eof)
2367 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c"::Text)])
2370 { Transaction.dates=
2373 (Time.fromGregorian 2000 01 01)
2374 (Time.TimeOfDay 0 0 0))
2377 , Transaction.description="some description"
2378 , Transaction.postings = Posting.from_List
2379 [ (Posting.nil ("A":|["B", "C"]))
2380 { Posting.amounts = Data.Map.fromList
2382 { Amount.quantity = 1
2383 , Amount.style = Amount.Style.nil
2384 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2385 , Amount.Style.unit_spaced = Just False
2390 , Posting.sourcepos = P.newPos "" 2 1
2392 , (Posting.nil ("a":|["b", "c"]))
2393 { Posting.sourcepos = P.newPos "" 3 1
2396 , Transaction.sourcepos = P.newPos "" 1 1
2399 , "2000/01/01 some description\\n A:B:C $1\\n a:b:c\\n" ~:
2400 (Data.Either.rights $
2402 (Format.Ledger.Read.transaction <* P.newline <* P.eof)
2403 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c\n"::Text)])
2406 { Transaction.dates=
2409 (Time.fromGregorian 2000 01 01)
2410 (Time.TimeOfDay 0 0 0))
2413 , Transaction.description="some description"
2414 , Transaction.postings = Posting.from_List
2415 [ (Posting.nil ("A":|["B", "C"]))
2416 { Posting.amounts = Data.Map.fromList
2418 { Amount.quantity = 1
2419 , Amount.style = Amount.Style.nil
2420 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2421 , Amount.Style.unit_spaced = Just False
2426 , Posting.sourcepos = P.newPos "" 2 1
2428 , (Posting.nil ("a":|["b", "c"]))
2429 { Posting.sourcepos = P.newPos "" 3 1
2432 , Transaction.sourcepos = P.newPos "" 1 1
2435 , "2000/01/01 some description ; some comment\\n ; some other;comment\\n ; some Tag:\\n ; some last comment\\n A:B:C $1\\n a:b:c" ~:
2436 (Data.Either.rights $
2438 (Format.Ledger.Read.transaction <* P.eof)
2439 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description ; some comment\n ; some other;comment\n ; some Tag:\n ; some last comment\n A:B:C $1\n a:b:c"::Text)])
2442 { Transaction.comments_after =
2444 , " some other;comment"
2446 , " some last comment"
2448 , Transaction.dates=
2451 (Time.fromGregorian 2000 01 01)
2452 (Time.TimeOfDay 0 0 0))
2455 , Transaction.description="some description"
2456 , Transaction.postings = Posting.from_List
2457 [ (Posting.nil ("A":|["B", "C"]))
2458 { Posting.amounts = Data.Map.fromList
2460 { Amount.quantity = 1
2461 , Amount.style = Amount.Style.nil
2462 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2463 , Amount.Style.unit_spaced = Just False
2468 , Posting.sourcepos = P.newPos "" 5 1
2470 , (Posting.nil ("a":|["b", "c"]))
2471 { Posting.sourcepos = P.newPos "" 6 1
2472 , Posting.tags = Data.Map.fromList []
2475 , Transaction.sourcepos = P.newPos "" 1 1
2476 , Transaction.tags = Data.Map.fromList
2482 , "journal" ~: TestList
2483 [ "2000/01/01 1° description\\n A:B:C $1\\n a:b:c\\n2000/01/02 2° description\\n A:B:C $1\\n x:y:z" ~: TestCase $ do
2486 (Format.Ledger.Read.journal "" {-<* P.eof-})
2487 Format.Ledger.Read.nil_Context "" ("2000/01/01 1° description\n A:B:C $1\n a:b:c\n2000/01/02 2° description\n A:B:C $1\n x:y:z"::Text)
2489 (\j -> j{Format.Ledger.Journal.last_read_time=
2490 Format.Ledger.Journal.last_read_time Format.Ledger.Journal.nil}) $
2491 Data.Either.rights [jnl])
2493 [ Format.Ledger.Journal.nil
2494 { Format.Ledger.Journal.transactions = Transaction.from_List
2496 { Transaction.dates=
2499 (Time.fromGregorian 2000 01 01)
2500 (Time.TimeOfDay 0 0 0))
2503 , Transaction.description="1° description"
2504 , Transaction.postings = Posting.from_List
2505 [ (Posting.nil ("A":|["B", "C"]))
2506 { Posting.amounts = Data.Map.fromList
2508 { Amount.quantity = 1
2509 , Amount.style = Amount.Style.nil
2510 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2511 , Amount.Style.unit_spaced = Just False
2516 , Posting.sourcepos = P.newPos "" 2 1
2518 , (Posting.nil ("a":|["b", "c"]))
2519 { Posting.sourcepos = P.newPos "" 3 1
2522 , Transaction.sourcepos = P.newPos "" 1 1
2525 { Transaction.dates=
2528 (Time.fromGregorian 2000 01 02)
2529 (Time.TimeOfDay 0 0 0))
2532 , Transaction.description="2° description"
2533 , Transaction.postings = Posting.from_List
2534 [ (Posting.nil ("A":|["B", "C"]))
2535 { Posting.amounts = Data.Map.fromList
2537 { Amount.quantity = 1
2538 , Amount.style = Amount.Style.nil
2539 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2540 , Amount.Style.unit_spaced = Just False
2545 , Posting.sourcepos = P.newPos "" 5 1
2547 , (Posting.nil ("x":|["y", "z"]))
2548 { Posting.sourcepos = P.newPos "" 6 1
2551 , Transaction.sourcepos = P.newPos "" 4 1
2558 , "Write" ~: TestList
2559 [ "account" ~: TestList
2561 ((Format.Ledger.Write.show False $
2562 Format.Ledger.Write.account Posting.Type_Regular $
2567 ((Format.Ledger.Write.show False $
2568 Format.Ledger.Write.account Posting.Type_Regular $
2573 ((Format.Ledger.Write.show False $
2574 Format.Ledger.Write.account Posting.Type_Virtual $
2579 ((Format.Ledger.Write.show False $
2580 Format.Ledger.Write.account Posting.Type_Virtual_Balanced $
2585 , "amount" ~: TestList
2587 ((Format.Ledger.Write.show False $
2588 Format.Ledger.Write.amount
2593 ((Format.Ledger.Write.show False $
2594 Format.Ledger.Write.amount
2596 { Amount.style = Amount.Style.nil
2597 { Amount.Style.precision = 2 }
2602 ((Format.Ledger.Write.show False $
2603 Format.Ledger.Write.amount
2605 { Amount.quantity = Decimal 0 123
2610 ((Format.Ledger.Write.show False $
2611 Format.Ledger.Write.amount
2613 { Amount.quantity = Decimal 0 (- 123)
2617 , "12.3 @ prec=0" ~:
2618 ((Format.Ledger.Write.show False $
2619 Format.Ledger.Write.amount
2621 { Amount.quantity = Decimal 1 123
2622 , Amount.style = Amount.Style.nil
2623 { Amount.Style.fractioning = Just '.'
2628 , "12.5 @ prec=0" ~:
2629 ((Format.Ledger.Write.show False $
2630 Format.Ledger.Write.amount
2632 { Amount.quantity = Decimal 1 125
2633 , Amount.style = Amount.Style.nil
2634 { Amount.Style.fractioning = Just '.'
2639 , "12.3 @ prec=1" ~:
2640 ((Format.Ledger.Write.show False $
2641 Format.Ledger.Write.amount
2643 { Amount.quantity = Decimal 1 123
2644 , Amount.style = Amount.Style.nil
2645 { Amount.Style.fractioning = Just '.'
2646 , Amount.Style.precision = 1
2651 , "1,234.56 @ prec=2" ~:
2652 ((Format.Ledger.Write.show False $
2653 Format.Ledger.Write.amount
2655 { Amount.quantity = Decimal 2 123456
2656 , Amount.style = Amount.Style.nil
2657 { Amount.Style.fractioning = Just '.'
2658 , Amount.Style.precision = 2
2659 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
2664 , "123,456,789,01,2.3456789 @ prec=7" ~:
2665 ((Format.Ledger.Write.show False $
2666 Format.Ledger.Write.amount
2668 { Amount.quantity = Decimal 7 1234567890123456789
2669 , Amount.style = Amount.Style.nil
2670 { Amount.Style.fractioning = Just '.'
2671 , Amount.Style.precision = 7
2672 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2676 "123,456,789,01,2.3456789")
2677 , "1234567.8,90,123,456,789 @ prec=12" ~:
2678 ((Format.Ledger.Write.show False $
2679 Format.Ledger.Write.amount
2681 { Amount.quantity = Decimal 12 1234567890123456789
2682 , Amount.style = Amount.Style.nil
2683 { Amount.Style.fractioning = Just '.'
2684 , Amount.Style.precision = 12
2685 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2689 "1234567.8,90,123,456,789")
2690 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
2691 ((Format.Ledger.Write.show False $
2692 Format.Ledger.Write.amount
2694 { Amount.quantity = Decimal 7 1234567890123456789
2695 , Amount.style = Amount.Style.nil
2696 { Amount.Style.fractioning = Just '.'
2697 , Amount.Style.precision = 7
2698 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2702 "1,2,3,4,5,6,7,89,012.3456789")
2703 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
2704 ((Format.Ledger.Write.show False $
2705 Format.Ledger.Write.amount
2707 { Amount.quantity = Decimal 12 1234567890123456789
2708 , Amount.style = Amount.Style.nil
2709 { Amount.Style.fractioning = Just '.'
2710 , Amount.Style.precision = 12
2711 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2715 "1234567.890,12,3,4,5,6,7,8,9")
2717 , "amount_length" ~: TestList
2719 ((Format.Ledger.Write.amount_length
2724 ((Format.Ledger.Write.amount_length
2726 { Amount.style = Amount.Style.nil
2727 { Amount.Style.precision = 2 }
2732 ((Format.Ledger.Write.amount_length
2734 { Amount.quantity = Decimal 0 123
2739 ((Format.Ledger.Write.amount_length
2741 { Amount.quantity = Decimal 0 (- 123)
2745 , "12.3 @ prec=0" ~:
2746 ((Format.Ledger.Write.amount_length
2748 { Amount.quantity = Decimal 1 123
2749 , Amount.style = Amount.Style.nil
2750 { Amount.Style.fractioning = Just '.'
2755 , "12.5 @ prec=0" ~:
2756 ((Format.Ledger.Write.amount_length
2758 { Amount.quantity = Decimal 1 125
2759 , Amount.style = Amount.Style.nil
2760 { Amount.Style.fractioning = Just '.'
2765 , "12.3 @ prec=1" ~:
2766 ((Format.Ledger.Write.amount_length
2768 { Amount.quantity = Decimal 1 123
2769 , Amount.style = Amount.Style.nil
2770 { Amount.Style.fractioning = Just '.'
2771 , Amount.Style.precision = 1
2776 , "1,234.56 @ prec=2" ~:
2777 ((Format.Ledger.Write.amount_length
2779 { Amount.quantity = Decimal 2 123456
2780 , Amount.style = Amount.Style.nil
2781 { Amount.Style.fractioning = Just '.'
2782 , Amount.Style.precision = 2
2783 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
2788 , "123,456,789,01,2.3456789 @ prec=7" ~:
2789 ((Format.Ledger.Write.amount_length
2791 { Amount.quantity = Decimal 7 1234567890123456789
2792 , Amount.style = Amount.Style.nil
2793 { Amount.Style.fractioning = Just '.'
2794 , Amount.Style.precision = 7
2795 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2800 , "1234567.8,90,123,456,789 @ prec=12" ~:
2801 ((Format.Ledger.Write.amount_length
2803 { Amount.quantity = Decimal 12 1234567890123456789
2804 , Amount.style = Amount.Style.nil
2805 { Amount.Style.fractioning = Just '.'
2806 , Amount.Style.precision = 12
2807 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2812 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
2813 ((Format.Ledger.Write.amount_length
2815 { Amount.quantity = Decimal 7 1234567890123456789
2816 , Amount.style = Amount.Style.nil
2817 { Amount.Style.fractioning = Just '.'
2818 , Amount.Style.precision = 7
2819 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2824 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
2825 ((Format.Ledger.Write.amount_length
2827 { Amount.quantity = Decimal 12 1234567890123456789
2828 , Amount.style = Amount.Style.nil
2829 { Amount.Style.fractioning = Just '.'
2830 , Amount.Style.precision = 12
2831 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2837 , "date" ~: TestList
2839 ((Format.Ledger.Write.show False $
2840 Format.Ledger.Write.date
2844 , "2000/01/01 12:34:51 CET" ~:
2845 (Format.Ledger.Write.show False $
2846 Format.Ledger.Write.date $
2849 (Time.fromGregorian 2000 01 01)
2850 (Time.TimeOfDay 12 34 51))
2851 (Time.TimeZone 60 False "CET"))
2853 "2000/01/01 12:34:51 CET"
2854 , "2000/01/01 12:34:51 +0100" ~:
2855 (Format.Ledger.Write.show False $
2856 Format.Ledger.Write.date $
2859 (Time.fromGregorian 2000 01 01)
2860 (Time.TimeOfDay 12 34 51))
2861 (Time.TimeZone 60 False ""))
2863 "2000/01/01 12:34:51 +0100"
2864 , "2000/01/01 01:02:03" ~:
2865 (Format.Ledger.Write.show False $
2866 Format.Ledger.Write.date $
2869 (Time.fromGregorian 2000 01 01)
2870 (Time.TimeOfDay 1 2 3))
2873 "2000/01/01 01:02:03"
2875 (Format.Ledger.Write.show False $
2876 Format.Ledger.Write.date $
2879 (Time.fromGregorian 0 01 01)
2880 (Time.TimeOfDay 1 2 0))
2885 (Format.Ledger.Write.show False $
2886 Format.Ledger.Write.date $
2889 (Time.fromGregorian 0 01 01)
2890 (Time.TimeOfDay 1 0 0))
2895 (Format.Ledger.Write.show False $
2896 Format.Ledger.Write.date $
2899 (Time.fromGregorian 0 01 01)
2900 (Time.TimeOfDay 0 1 0))
2905 (Format.Ledger.Write.show False $
2906 Format.Ledger.Write.date $
2909 (Time.fromGregorian 0 01 01)
2910 (Time.TimeOfDay 0 0 0))
2915 , "transaction" ~: TestList
2917 ((Format.Ledger.Write.show False $
2918 Format.Ledger.Write.transaction
2922 , "2000/01/01 some description\\n\\ta:b:c\\n\\t\\t; first comment\\n\\t\\t; second comment\\n\\t\\t; third comment\\n\\tA:B:C $1" ~:
2923 ((Format.Ledger.Write.show False $
2924 Format.Ledger.Write.transaction $
2926 { Transaction.dates=
2929 (Time.fromGregorian 2000 01 01)
2930 (Time.TimeOfDay 0 0 0))
2933 , Transaction.description="some description"
2934 , Transaction.postings = Posting.from_List
2935 [ (Posting.nil ("A":|["B", "C"]))
2936 { Posting.amounts = Data.Map.fromList
2938 { Amount.quantity = 1
2939 , Amount.style = Amount.Style.nil
2940 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2941 , Amount.Style.unit_spaced = Just False
2947 , (Posting.nil ("a":|["b", "c"]))
2948 { Posting.comments = ["first comment","second comment","third comment"]
2953 "2000/01/01 some description\n\ta:b:c\n\t\t; first comment\n\t\t; second comment\n\t\t; third comment\n\tA:B:C $1")
2954 , "2000/01/01 some description\\n\\tA:B:C $1\\n\\tAA:BB:CC $123" ~:
2955 ((Format.Ledger.Write.show False $
2956 Format.Ledger.Write.transaction $
2958 { Transaction.dates=
2961 (Time.fromGregorian 2000 01 01)
2962 (Time.TimeOfDay 0 0 0))
2965 , Transaction.description="some description"
2966 , Transaction.postings = Posting.from_List
2967 [ (Posting.nil ("A":|["B", "C"]))
2968 { Posting.amounts = Data.Map.fromList
2970 { Amount.quantity = 1
2971 , Amount.style = Amount.Style.nil
2972 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2973 , Amount.Style.unit_spaced = Just False
2979 , (Posting.nil ("AA":|["BB", "CC"]))
2980 { Posting.amounts = Data.Map.fromList
2982 { Amount.quantity = 123
2983 , Amount.style = Amount.Style.nil
2984 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2985 , Amount.Style.unit_spaced = Just False
2994 "2000/01/01 some description\n\tA:B:C $1\n\tAA:BB:CC $123")