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)
817 , "\"A\" = Right \"A\"" ~:
818 (Data.Either.rights $
820 (Format.Ledger.Read.account_name <* P.eof)
824 , "\"AA\" = Right \"AA\"" ~:
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)
866 , "\"A \" ^= Right" ~:
867 (Data.Either.rights $
869 (Format.Ledger.Read.account_name)
873 , "\"A A\" = Right \"A A\"" ~:
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)
887 , "\"A \\n\" = Left" ~:
888 (Data.Either.rights $
890 (Format.Ledger.Read.account_name <* P.eof)
891 () "" ("A \n"::Text)])
894 , "\"(A)A\" = Right \"(A)A\"" ~:
895 (Data.Either.rights $
897 (Format.Ledger.Read.account_name <* P.eof)
898 () "" ("(A)A"::Text)])
901 , "\"( )A\" = Right \"( )A\"" ~:
902 (Data.Either.rights $
904 (Format.Ledger.Read.account_name <* P.eof)
905 () "" ("( )A"::Text)])
908 , "\"(A) A\" = Right \"(A) A\"" ~:
909 (Data.Either.rights $
911 (Format.Ledger.Read.account_name <* P.eof)
912 () "" ("(A) A"::Text)])
915 , "\"[ ]A\" = Right \"[ ]A\"" ~:
916 (Data.Either.rights $
918 (Format.Ledger.Read.account_name <* P.eof)
919 () "" ("[ ]A"::Text)])
922 , "\"(A) \" = Left" ~:
923 (Data.Either.rights $
925 (Format.Ledger.Read.account_name <* P.eof)
926 () "" ("(A) "::Text)])
929 , "\"(A)\" = Left" ~:
930 (Data.Either.rights $
932 (Format.Ledger.Read.account_name <* P.eof)
933 () "" ("(A)"::Text)])
936 , "\"[A]A\" = Right \"(A)A\"" ~:
937 (Data.Either.rights $
939 (Format.Ledger.Read.account_name <* P.eof)
940 () "" ("[A]A"::Text)])
943 , "\"[A] A\" = Right \"[A] A\"" ~:
944 (Data.Either.rights $
946 (Format.Ledger.Read.account_name <* P.eof)
947 () "" ("[A] A"::Text)])
950 , "\"[A] \" = Left" ~:
951 (Data.Either.rights $
953 (Format.Ledger.Read.account_name <* P.eof)
954 () "" ("[A] "::Text)])
957 , "\"[A]\" = Left" ~:
958 (Data.Either.rights $
960 (Format.Ledger.Read.account_name <* P.eof)
961 () "" ("[A]"::Text)])
965 , "account" ~: TestList
967 (Data.Either.rights $
969 (Format.Ledger.Read.account <* P.eof)
973 , "\"A\" = Right [\"A\"]" ~:
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)
1001 , "\" A\" = Left" ~:
1002 (Data.Either.rights $
1004 (Format.Ledger.Read.account <* P.eof)
1005 () "" (" A"::Text)])
1008 , "\"A:B\" = Right [\"A\", \"B\"]" ~:
1009 (Data.Either.rights $
1011 (Format.Ledger.Read.account <* P.eof)
1012 () "" ("A:B"::Text)])
1015 , "\"A:B:C\" = Right [\"A\", \"B\", \"C\"]" ~:
1016 (Data.Either.rights $
1018 (Format.Ledger.Read.account <* P.eof)
1019 () "" ("A:B:C"::Text)])
1022 , "\"Aa:Bbb:Cccc\" = Right [\"Aa\", \"Bbb\", \":Cccc\"]" ~:
1023 (Data.Either.rights $
1025 (Format.Ledger.Read.account <* P.eof)
1026 () "" ("Aa:Bbb:Cccc"::Text)])
1028 ["Aa":|["Bbb", "Cccc"]]
1029 , "\"A a : B b b : C c c c\" = Right [\"A a \", \" B b b \", \": C c c c\"]" ~:
1030 (Data.Either.rights $
1032 (Format.Ledger.Read.account <* P.eof)
1033 () "" ("A a : B b b : C c c c"::Text)])
1035 ["A a ":|[" B b b ", " C c c c"]]
1036 , "\"A: :C\" = Right [\"A\", \" \", \"C\"]" ~:
1037 (Data.Either.rights $
1039 (Format.Ledger.Read.account <* P.eof)
1040 () "" ("A: :C"::Text)])
1043 , "\"A::C\" = Left" ~:
1044 (Data.Either.rights $
1046 (Format.Ledger.Read.account <* P.eof)
1047 () "" ("A::C"::Text)])
1051 , "amount" ~: TestList
1053 (Data.Either.rights $
1055 (Format.Ledger.Read.amount <* P.eof)
1059 , "\"0\" = Right 0" ~:
1060 (Data.Either.rights $
1062 (Format.Ledger.Read.amount <* P.eof)
1066 { Amount.quantity = Decimal 0 0
1068 , "\"00\" = Right 0" ~:
1069 (Data.Either.rights $
1071 (Format.Ledger.Read.amount <* P.eof)
1072 () "" ("00"::Text)])
1075 { Amount.quantity = Decimal 0 0
1077 , "\"0.\" = Right 0." ~:
1078 (Data.Either.rights $
1080 (Format.Ledger.Read.amount <* P.eof)
1081 () "" ("0."::Text)])
1084 { Amount.quantity = Decimal 0 0
1087 { Amount.Style.fractioning = Just '.'
1090 , "\".0\" = Right 0.0" ~:
1091 (Data.Either.rights $
1093 (Format.Ledger.Read.amount <* P.eof)
1094 () "" (".0"::Text)])
1097 { Amount.quantity = Decimal 0 0
1100 { Amount.Style.fractioning = Just '.'
1101 , Amount.Style.precision = 1
1104 , "\"0,\" = Right 0," ~:
1105 (Data.Either.rights $
1107 (Format.Ledger.Read.amount <* P.eof)
1108 () "" ("0,"::Text)])
1111 { Amount.quantity = Decimal 0 0
1114 { Amount.Style.fractioning = Just ','
1117 , "\",0\" = Right 0,0" ~:
1118 (Data.Either.rights $
1120 (Format.Ledger.Read.amount <* P.eof)
1121 () "" (",0"::Text)])
1124 { Amount.quantity = Decimal 0 0
1127 { Amount.Style.fractioning = Just ','
1128 , Amount.Style.precision = 1
1131 , "\"0_\" = Left" ~:
1132 (Data.Either.rights $
1134 (Format.Ledger.Read.amount <* P.eof)
1135 () "" ("0_"::Text)])
1138 , "\"_0\" = Left" ~:
1139 (Data.Either.rights $
1141 (Format.Ledger.Read.amount <* P.eof)
1142 () "" ("_0"::Text)])
1145 , "\"0.0\" = Right 0.0" ~:
1146 (Data.Either.rights $
1148 (Format.Ledger.Read.amount <* P.eof)
1149 () "" ("0.0"::Text)])
1152 { Amount.quantity = Decimal 0 0
1155 { Amount.Style.fractioning = Just '.'
1156 , Amount.Style.precision = 1
1159 , "\"00.00\" = Right 0.00" ~:
1160 (Data.Either.rights $
1162 (Format.Ledger.Read.amount <* P.eof)
1163 () "" ("00.00"::Text)])
1166 { Amount.quantity = Decimal 0 0
1169 { Amount.Style.fractioning = Just '.'
1170 , Amount.Style.precision = 2
1173 , "\"0,0\" = Right 0,0" ~:
1174 (Data.Either.rights $
1176 (Format.Ledger.Read.amount <* P.eof)
1177 () "" ("0,0"::Text)])
1180 { Amount.quantity = Decimal 0 0
1183 { Amount.Style.fractioning = Just ','
1184 , Amount.Style.precision = 1
1187 , "\"00,00\" = Right 0,00" ~:
1188 (Data.Either.rights $
1190 (Format.Ledger.Read.amount <* P.eof)
1191 () "" ("00,00"::Text)])
1194 { Amount.quantity = Decimal 0 0
1197 { Amount.Style.fractioning = Just ','
1198 , Amount.Style.precision = 2
1201 , "\"0_0\" = Right 0" ~:
1202 (Data.Either.rights $
1204 (Format.Ledger.Read.amount <* P.eof)
1205 () "" ("0_0"::Text)])
1208 { Amount.quantity = Decimal 0 0
1211 { Amount.Style.fractioning = Nothing
1212 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [1]
1213 , Amount.Style.precision = 0
1216 , "\"00_00\" = Right 0" ~:
1217 (Data.Either.rights $
1219 (Format.Ledger.Read.amount <* P.eof)
1220 () "" ("00_00"::Text)])
1223 { Amount.quantity = Decimal 0 0
1226 { Amount.Style.fractioning = Nothing
1227 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [2]
1228 , Amount.Style.precision = 0
1231 , "\"0,000.00\" = Right 0,000.00" ~:
1232 (Data.Either.rights $
1234 (Format.Ledger.Read.amount <* P.eof)
1235 () "" ("0,000.00"::Text)])
1238 { Amount.quantity = Decimal 0 0
1241 { Amount.Style.fractioning = Just '.'
1242 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
1243 , Amount.Style.precision = 2
1246 , "\"0.000,00\" = Right 0.000,00" ~:
1247 (Data.Either.rights $
1249 (Format.Ledger.Read.amount)
1250 () "" ("0.000,00"::Text)])
1253 { Amount.quantity = Decimal 0 0
1256 { Amount.Style.fractioning = Just ','
1257 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1258 , Amount.Style.precision = 2
1261 , "\"1,000.00\" = Right 1,000.00" ~:
1262 (Data.Either.rights $
1264 (Format.Ledger.Read.amount <* P.eof)
1265 () "" ("1,000.00"::Text)])
1268 { Amount.quantity = Decimal 0 1000
1271 { Amount.Style.fractioning = Just '.'
1272 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
1273 , Amount.Style.precision = 2
1276 , "\"1.000,00\" = Right 1.000,00" ~:
1277 (Data.Either.rights $
1279 (Format.Ledger.Read.amount)
1280 () "" ("1.000,00"::Text)])
1283 { Amount.quantity = Decimal 0 1000
1286 { Amount.Style.fractioning = Just ','
1287 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1288 , Amount.Style.precision = 2
1291 , "\"1,000.00.\" = Left" ~:
1292 (Data.Either.rights $
1294 (Format.Ledger.Read.amount)
1295 () "" ("1,000.00."::Text)])
1298 , "\"1.000,00,\" = Left" ~:
1299 (Data.Either.rights $
1301 (Format.Ledger.Read.amount)
1302 () "" ("1.000,00,"::Text)])
1305 , "\"1,000.00_\" = Left" ~:
1306 (Data.Either.rights $
1308 (Format.Ledger.Read.amount)
1309 () "" ("1,000.00_"::Text)])
1312 , "\"12\" = Right 12" ~:
1313 (Data.Either.rights $
1315 (Format.Ledger.Read.amount <* P.eof)
1316 () "" ("123"::Text)])
1319 { Amount.quantity = Decimal 0 123
1321 , "\"1.2\" = Right 1.2" ~:
1322 (Data.Either.rights $
1324 (Format.Ledger.Read.amount <* P.eof)
1325 () "" ("1.2"::Text)])
1328 { Amount.quantity = Decimal 1 12
1331 { Amount.Style.fractioning = Just '.'
1332 , Amount.Style.precision = 1
1335 , "\"1,2\" = Right 1,2" ~:
1336 (Data.Either.rights $
1338 (Format.Ledger.Read.amount <* P.eof)
1339 () "" ("1,2"::Text)])
1342 { Amount.quantity = Decimal 1 12
1345 { Amount.Style.fractioning = Just ','
1346 , Amount.Style.precision = 1
1349 , "\"12.23\" = Right 12.23" ~:
1350 (Data.Either.rights $
1352 (Format.Ledger.Read.amount <* P.eof)
1353 () "" ("12.34"::Text)])
1356 { Amount.quantity = Decimal 2 1234
1359 { Amount.Style.fractioning = Just '.'
1360 , Amount.Style.precision = 2
1363 , "\"12,23\" = Right 12,23" ~:
1364 (Data.Either.rights $
1366 (Format.Ledger.Read.amount <* P.eof)
1367 () "" ("12,34"::Text)])
1370 { Amount.quantity = Decimal 2 1234
1373 { Amount.Style.fractioning = Just ','
1374 , Amount.Style.precision = 2
1377 , "\"1_2\" = Right 1_2" ~:
1378 (Data.Either.rights $
1380 (Format.Ledger.Read.amount <* P.eof)
1381 () "" ("1_2"::Text)])
1384 { Amount.quantity = Decimal 0 12
1387 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [1]
1388 , Amount.Style.precision = 0
1391 , "\"1_23\" = Right 1_23" ~:
1392 (Data.Either.rights $
1394 (Format.Ledger.Read.amount <* P.eof)
1395 () "" ("1_23"::Text)])
1398 { Amount.quantity = Decimal 0 123
1401 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [2]
1402 , Amount.Style.precision = 0
1405 , "\"1_23_456\" = Right 1_23_456" ~:
1406 (Data.Either.rights $
1408 (Format.Ledger.Read.amount <* P.eof)
1409 () "" ("1_23_456"::Text)])
1412 { Amount.quantity = Decimal 0 123456
1415 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [3, 2]
1416 , Amount.Style.precision = 0
1419 , "\"1_23_456.7890_12345_678901\" = Right 1_23_456.7890_12345_678901" ~:
1420 (Data.Either.rights $
1422 (Format.Ledger.Read.amount <* P.eof)
1423 () "" ("1_23_456.7890_12345_678901"::Text)])
1426 { Amount.quantity = Decimal 15 123456789012345678901
1429 { Amount.Style.fractioning = Just '.'
1430 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [3, 2]
1431 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping '_' [4, 5, 6]
1432 , Amount.Style.precision = 15
1435 , "\"123456_78901_2345.678_90_1\" = Right 123456_78901_2345.678_90_1" ~:
1436 (Data.Either.rights $
1438 (Format.Ledger.Read.amount <* P.eof)
1439 () "" ("123456_78901_2345.678_90_1"::Text)])
1442 { Amount.quantity = Decimal 6 123456789012345678901
1445 { Amount.Style.fractioning = Just '.'
1446 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [4, 5, 6]
1447 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping '_' [3, 2]
1448 , Amount.Style.precision = 6
1451 , "\"$1\" = Right $1" ~:
1452 (Data.Either.rights $
1454 (Format.Ledger.Read.amount <* P.eof)
1455 () "" ("$1"::Text)])
1458 { Amount.quantity = Decimal 0 1
1461 { Amount.Style.fractioning = Nothing
1462 , Amount.Style.grouping_integral = Nothing
1463 , Amount.Style.grouping_fractional = Nothing
1464 , Amount.Style.precision = 0
1465 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1466 , Amount.Style.unit_spaced = Just False
1470 , "\"1$\" = Right 1$" ~:
1471 (Data.Either.rights $
1473 (Format.Ledger.Read.amount <* P.eof)
1474 () "" ("1$"::Text)])
1477 { Amount.quantity = Decimal 0 1
1480 { Amount.Style.fractioning = Nothing
1481 , Amount.Style.grouping_integral = Nothing
1482 , Amount.Style.grouping_fractional = Nothing
1483 , Amount.Style.precision = 0
1484 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1485 , Amount.Style.unit_spaced = Just False
1489 , "\"$ 1\" = Right $ 1" ~:
1490 (Data.Either.rights $
1492 (Format.Ledger.Read.amount <* P.eof)
1493 () "" ("$ 1"::Text)])
1496 { Amount.quantity = Decimal 0 1
1499 { Amount.Style.fractioning = Nothing
1500 , Amount.Style.grouping_integral = Nothing
1501 , Amount.Style.grouping_fractional = Nothing
1502 , Amount.Style.precision = 0
1503 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1504 , Amount.Style.unit_spaced = Just True
1508 , "\"1 $\" = Right 1 $" ~:
1509 (Data.Either.rights $
1511 (Format.Ledger.Read.amount <* P.eof)
1512 () "" ("1 $"::Text)])
1515 { Amount.quantity = Decimal 0 1
1518 { Amount.Style.fractioning = Nothing
1519 , Amount.Style.grouping_integral = Nothing
1520 , Amount.Style.grouping_fractional = Nothing
1521 , Amount.Style.precision = 0
1522 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1523 , Amount.Style.unit_spaced = Just True
1527 , "\"-$1\" = Right $-1" ~:
1528 (Data.Either.rights $
1530 (Format.Ledger.Read.amount <* P.eof)
1531 () "" ("-$1"::Text)])
1534 { Amount.quantity = Decimal 0 (-1)
1537 { Amount.Style.fractioning = Nothing
1538 , Amount.Style.grouping_integral = Nothing
1539 , Amount.Style.grouping_fractional = Nothing
1540 , Amount.Style.precision = 0
1541 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1542 , Amount.Style.unit_spaced = Just False
1546 , "\"\\\"4 2\\\"1\" = Right \\\"4 2\\\"1" ~:
1547 (Data.Either.rights $
1549 (Format.Ledger.Read.amount <* P.eof)
1550 () "" ("\"4 2\"1"::Text)])
1553 { Amount.quantity = Decimal 0 1
1556 { Amount.Style.fractioning = Nothing
1557 , Amount.Style.grouping_integral = Nothing
1558 , Amount.Style.grouping_fractional = Nothing
1559 , Amount.Style.precision = 0
1560 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1561 , Amount.Style.unit_spaced = Just False
1563 , Amount.unit = "4 2"
1565 , "\"1\\\"4 2\\\"\" = Right 1\\\"4 2\\\"" ~:
1566 (Data.Either.rights $
1568 (Format.Ledger.Read.amount <* P.eof)
1569 () "" ("1\"4 2\""::Text)])
1572 { Amount.quantity = Decimal 0 1
1575 { Amount.Style.fractioning = Nothing
1576 , Amount.Style.grouping_integral = Nothing
1577 , Amount.Style.grouping_fractional = Nothing
1578 , Amount.Style.precision = 0
1579 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1580 , Amount.Style.unit_spaced = Just False
1582 , Amount.unit = "4 2"
1584 , "\"$1.000,00\" = Right $1.000,00" ~:
1585 (Data.Either.rights $
1587 (Format.Ledger.Read.amount <* P.eof)
1588 () "" ("$1.000,00"::Text)])
1591 { Amount.quantity = Decimal 0 1000
1594 { Amount.Style.fractioning = Just ','
1595 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1596 , Amount.Style.grouping_fractional = Nothing
1597 , Amount.Style.precision = 2
1598 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1599 , Amount.Style.unit_spaced = Just False
1603 , "\"1.000,00$\" = Right 1.000,00$" ~:
1604 (Data.Either.rights $
1606 (Format.Ledger.Read.amount <* P.eof)
1607 () "" ("1.000,00$"::Text)])
1610 { Amount.quantity = Decimal 0 1000
1613 { Amount.Style.fractioning = Just ','
1614 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1615 , Amount.Style.grouping_fractional = Nothing
1616 , Amount.Style.precision = 2
1617 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1618 , Amount.Style.unit_spaced = Just False
1623 , "comment" ~: TestList
1624 [ "; some comment = Right \" some comment\"" ~:
1625 (Data.Either.rights $
1627 (Format.Ledger.Read.comment <* P.eof)
1628 () "" ("; some comment"::Text)])
1631 , "; some comment \\n = Right \" some comment \"" ~:
1632 (Data.Either.rights $
1634 (Format.Ledger.Read.comment <* P.newline <* P.eof)
1635 () "" ("; some comment \n"::Text)])
1637 [ " some comment " ]
1638 , "; some comment \\r\\n = Right \" some comment \"" ~:
1639 (Data.Either.rights $
1641 (Format.Ledger.Read.comment <* P.string "\r\n" <* P.eof)
1642 () "" ("; some comment \r\n"::Text)])
1644 [ " some comment " ]
1646 , "comments" ~: TestList
1647 [ "; some comment\\n ; some other comment = Right [\" some comment\", \" some other comment\"]" ~:
1648 (Data.Either.rights $
1650 (Format.Ledger.Read.comments <* P.eof)
1651 () "" ("; some comment\n ; some other comment"::Text)])
1653 [ [" some comment", " some other comment"] ]
1654 , "; some comment \\n = Right \" some comment \"" ~:
1655 (Data.Either.rights $
1657 (Format.Ledger.Read.comments <* P.string "\n" <* P.eof)
1658 () "" ("; some comment \n"::Text)])
1660 [ [" some comment "] ]
1662 , "date" ~: TestList
1664 (Data.Either.rights $
1666 (Format.Ledger.Read.date Nothing <* P.eof)
1667 () "" ("2000/01/01"::Text)])
1671 (Time.fromGregorian 2000 01 01)
1672 (Time.TimeOfDay 0 0 0))
1674 , "2000/01/01 some text" ~:
1675 (Data.Either.rights $
1677 (Format.Ledger.Read.date Nothing)
1678 () "" ("2000/01/01 some text"::Text)])
1682 (Time.fromGregorian 2000 01 01)
1683 (Time.TimeOfDay 0 0 0))
1685 , "2000/01/01 12:34" ~:
1686 (Data.Either.rights $
1688 (Format.Ledger.Read.date Nothing <* P.eof)
1689 () "" ("2000/01/01 12:34"::Text)])
1693 (Time.fromGregorian 2000 01 01)
1694 (Time.TimeOfDay 12 34 0))
1696 , "2000/01/01 12:34:56" ~:
1697 (Data.Either.rights $
1699 (Format.Ledger.Read.date Nothing <* P.eof)
1700 () "" ("2000/01/01 12:34:56"::Text)])
1704 (Time.fromGregorian 2000 01 01)
1705 (Time.TimeOfDay 12 34 56))
1707 , "2000/01/01 12:34 CET" ~:
1708 (Data.Either.rights $
1710 (Format.Ledger.Read.date Nothing <* P.eof)
1711 () "" ("2000/01/01 12:34 CET"::Text)])
1715 (Time.fromGregorian 2000 01 01)
1716 (Time.TimeOfDay 12 34 0))
1717 (Time.TimeZone 60 True "CET")]
1718 , "2000/01/01 12:34 +0130" ~:
1719 (Data.Either.rights $
1721 (Format.Ledger.Read.date Nothing <* P.eof)
1722 () "" ("2000/01/01 12:34 +0130"::Text)])
1726 (Time.fromGregorian 2000 01 01)
1727 (Time.TimeOfDay 12 34 0))
1728 (Time.TimeZone 90 False "+0130")]
1729 , "2000/01/01 12:34:56 CET" ~:
1730 (Data.Either.rights $
1732 (Format.Ledger.Read.date Nothing <* P.eof)
1733 () "" ("2000/01/01 12:34:56 CET"::Text)])
1737 (Time.fromGregorian 2000 01 01)
1738 (Time.TimeOfDay 12 34 56))
1739 (Time.TimeZone 60 True "CET")]
1741 (Data.Either.rights $
1743 (Format.Ledger.Read.date Nothing <* P.eof)
1744 () "" ("2001/02/29"::Text)])
1748 (Data.Either.rights $
1750 (Format.Ledger.Read.date (Just 2000) <* P.eof)
1751 () "" ("01/01"::Text)])
1755 (Time.fromGregorian 2000 01 01)
1756 (Time.TimeOfDay 0 0 0))
1759 , "tag_value" ~: TestList
1761 (Data.Either.rights $
1763 (Format.Ledger.Read.tag_value <* P.eof)
1768 (Data.Either.rights $
1770 (Format.Ledger.Read.tag_value <* P.char '\n' <* P.eof)
1771 () "" (",\n"::Text)])
1775 (Data.Either.rights $
1777 (Format.Ledger.Read.tag_value <* P.eof)
1778 () "" (",x"::Text)])
1782 (Data.Either.rights $
1784 (Format.Ledger.Read.tag_value <* P.string ",x:" <* P.eof)
1785 () "" (",x:"::Text)])
1789 (Data.Either.rights $
1791 (Format.Ledger.Read.tag_value <* P.string ", n:" <* P.eof)
1792 () "" ("v, v, n:"::Text)])
1798 (Data.Either.rights $
1800 (Format.Ledger.Read.tag <* P.eof)
1801 () "" ("Name:"::Text)])
1805 (Data.Either.rights $
1807 (Format.Ledger.Read.tag <* P.eof)
1808 () "" ("Name:Value"::Text)])
1811 , "Name:Value\\n" ~:
1812 (Data.Either.rights $
1814 (Format.Ledger.Read.tag <* P.string "\n" <* P.eof)
1815 () "" ("Name:Value\n"::Text)])
1819 (Data.Either.rights $
1821 (Format.Ledger.Read.tag <* P.eof)
1822 () "" ("Name:Val ue"::Text)])
1824 [("Name", "Val ue")]
1826 (Data.Either.rights $
1828 (Format.Ledger.Read.tag <* P.eof)
1829 () "" ("Name:,"::Text)])
1833 (Data.Either.rights $
1835 (Format.Ledger.Read.tag <* P.eof)
1836 () "" ("Name:Val,ue"::Text)])
1838 [("Name", "Val,ue")]
1840 (Data.Either.rights $
1842 (Format.Ledger.Read.tag <* P.string ",ue:" <* P.eof)
1843 () "" ("Name:Val,ue:"::Text)])
1847 , "tags" ~: TestList
1849 (Data.Either.rights $
1851 (Format.Ledger.Read.tags <* P.eof)
1852 () "" ("Name:"::Text)])
1859 (Data.Either.rights $
1861 (Format.Ledger.Read.tags <* P.eof)
1862 () "" ("Name:,"::Text)])
1869 (Data.Either.rights $
1871 (Format.Ledger.Read.tags <* P.eof)
1872 () "" ("Name:,Name:"::Text)])
1875 [ ("Name", ["", ""])
1879 (Data.Either.rights $
1881 (Format.Ledger.Read.tags <* P.eof)
1882 () "" ("Name:,Name2:"::Text)])
1889 , "Name: , Name2:" ~:
1890 (Data.Either.rights $
1892 (Format.Ledger.Read.tags <* P.eof)
1893 () "" ("Name: , Name2:"::Text)])
1900 , "Name:,Name2:,Name3:" ~:
1901 (Data.Either.rights $
1903 (Format.Ledger.Read.tags <* P.eof)
1904 () "" ("Name:,Name2:,Name3:"::Text)])
1912 , "Name:Val ue,Name2:V a l u e,Name3:V al ue" ~:
1913 (Data.Either.rights $
1915 (Format.Ledger.Read.tags <* P.eof)
1916 () "" ("Name:Val ue,Name2:V a l u e,Name3:V al ue"::Text)])
1919 [ ("Name", ["Val ue"])
1920 , ("Name2", ["V a l u e"])
1921 , ("Name3", ["V al ue"])
1925 , "posting" ~: TestList
1926 [ " A:B:C = Right A:B:C" ~:
1927 (Data.Either.rights $
1929 (Format.Ledger.Read.posting <* P.eof)
1930 Format.Ledger.Read.nil_Context "" (" A:B:C"::Text)])
1932 [ ( (Posting.nil ("A":|["B", "C"]))
1933 { Posting.sourcepos = P.newPos "" 1 1
1935 , Posting.Type_Regular
1938 , " !A:B:C = Right !A:B:C" ~:
1939 (Data.List.map fst $
1940 Data.Either.rights $
1942 (Format.Ledger.Read.posting <* P.eof)
1943 Format.Ledger.Read.nil_Context "" (" !A:B:C"::Text)])
1945 [ (Posting.nil ("A":|["B", "C"]))
1946 { Posting.sourcepos = P.newPos "" 1 1
1947 , Posting.status = True
1950 , " *A:B:C = Right *A:B:C" ~:
1951 (Data.List.map fst $
1952 Data.Either.rights $
1954 (Format.Ledger.Read.posting <* P.eof)
1955 Format.Ledger.Read.nil_Context "" (" *A:B:C"::Text)])
1957 [ (Posting.nil ("A":|["B", "C"]))
1958 { Posting.amounts = Data.Map.fromList []
1959 , Posting.comments = []
1960 , Posting.dates = []
1961 , Posting.status = True
1962 , Posting.sourcepos = P.newPos "" 1 1
1963 , Posting.tags = Data.Map.fromList []
1966 , " A:B:C $1 = Right A:B:C $1" ~:
1967 (Data.List.map fst $
1968 Data.Either.rights $
1970 (Format.Ledger.Read.posting <* P.eof)
1971 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
1973 [ (Posting.nil ("A":|["B","C $1"]))
1974 { Posting.sourcepos = P.newPos "" 1 1
1977 , " A:B:C $1 = Right A:B:C $1" ~:
1978 (Data.List.map fst $
1979 Data.Either.rights $
1981 (Format.Ledger.Read.posting <* P.eof)
1982 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
1984 [ (Posting.nil ("A":|["B", "C"]))
1985 { Posting.amounts = Data.Map.fromList
1987 { Amount.quantity = 1
1988 , Amount.style = Amount.Style.nil
1989 { Amount.Style.unit_side = Just Amount.Style.Side_Left
1990 , Amount.Style.unit_spaced = Just False
1995 , Posting.sourcepos = P.newPos "" 1 1
1998 , " A:B:C $1 + 1€ = Right A:B:C $1 + 1€" ~:
1999 (Data.List.map fst $
2000 Data.Either.rights $
2002 (Format.Ledger.Read.posting <* P.eof)
2003 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1€"::Text)])
2005 [ (Posting.nil ("A":|["B", "C"]))
2006 { Posting.amounts = Data.Map.fromList
2008 { Amount.quantity = 1
2009 , Amount.style = Amount.Style.nil
2010 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2011 , Amount.Style.unit_spaced = Just False
2016 { Amount.quantity = 1
2017 , Amount.style = Amount.Style.nil
2018 { Amount.Style.unit_side = Just Amount.Style.Side_Right
2019 , Amount.Style.unit_spaced = Just False
2024 , Posting.sourcepos = P.newPos "" 1 1
2027 , " A:B:C $1 + 1$ = Right A:B:C $2" ~:
2028 (Data.List.map fst $
2029 Data.Either.rights $
2031 (Format.Ledger.Read.posting <* P.eof)
2032 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$"::Text)])
2034 [ (Posting.nil ("A":|["B", "C"]))
2035 { Posting.amounts = Data.Map.fromList
2037 { Amount.quantity = 2
2038 , Amount.style = Amount.Style.nil
2039 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2040 , Amount.Style.unit_spaced = Just False
2045 , Posting.sourcepos = P.newPos "" 1 1
2048 , " A:B:C $1 + 1$ + 1$ = Right A:B:C $3" ~:
2049 (Data.List.map fst $
2050 Data.Either.rights $
2052 (Format.Ledger.Read.posting <* P.eof)
2053 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$ + 1$"::Text)])
2055 [ (Posting.nil ("A":|["B", "C"]))
2056 { Posting.amounts = Data.Map.fromList
2058 { Amount.quantity = 3
2059 , Amount.style = Amount.Style.nil
2060 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2061 , Amount.Style.unit_spaced = Just False
2066 , Posting.sourcepos = P.newPos "" 1 1
2069 , " A:B:C ; some comment = Right A:B:C ; some comment" ~:
2070 (Data.List.map fst $
2071 Data.Either.rights $
2073 (Format.Ledger.Read.posting <* P.eof)
2074 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment"::Text)])
2076 [ (Posting.nil ("A":|["B", "C"]))
2077 { Posting.amounts = Data.Map.fromList []
2078 , Posting.comments = [" some comment"]
2079 , Posting.sourcepos = P.newPos "" 1 1
2082 , " A:B:C ; some comment\\n ; some other comment = Right A:B:C ; some comment\\n ; some other comment" ~:
2083 (Data.List.map fst $
2084 Data.Either.rights $
2086 (Format.Ledger.Read.posting <* P.eof)
2087 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment\n ; some other comment"::Text)])
2089 [ (Posting.nil ("A":|["B", "C"]))
2090 { Posting.amounts = Data.Map.fromList []
2091 , Posting.comments = [" some comment", " some other comment"]
2092 , Posting.sourcepos = P.newPos "" 1 1
2095 , " A:B:C $1 ; some comment = Right A:B:C $1 ; some comment" ~:
2096 (Data.List.map fst $
2097 Data.Either.rights $
2099 (Format.Ledger.Read.posting)
2100 Format.Ledger.Read.nil_Context "" (" A:B:C $1 ; some comment"::Text)])
2102 [ (Posting.nil ("A":|["B", "C"]))
2103 { Posting.amounts = Data.Map.fromList
2105 { Amount.quantity = 1
2106 , Amount.style = Amount.Style.nil
2107 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2108 , Amount.Style.unit_spaced = Just False
2113 , Posting.comments = [" some comment"]
2114 , Posting.sourcepos = P.newPos "" 1 1
2117 , " A:B:C ; N:V = Right A:B:C ; N:V" ~:
2118 (Data.List.map fst $
2119 Data.Either.rights $
2121 (Format.Ledger.Read.posting <* P.eof)
2122 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V"::Text)])
2124 [ (Posting.nil ("A":|["B", "C"]))
2125 { Posting.comments = [" N:V"]
2126 , Posting.sourcepos = P.newPos "" 1 1
2127 , Posting.tags = Data.Map.fromList
2132 , " A:B:C ; some comment N:V = Right A:B:C ; some comment N:V" ~:
2133 (Data.List.map fst $
2134 Data.Either.rights $
2136 (Format.Ledger.Read.posting <* P.eof)
2137 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V"::Text)])
2139 [ (Posting.nil ("A":|["B", "C"]))
2140 { Posting.comments = [" some comment N:V"]
2141 , Posting.sourcepos = P.newPos "" 1 1
2142 , Posting.tags = Data.Map.fromList
2147 , " A:B:C ; some comment N:V v, N2:V2 v2 = Right A:B:C ; some comment N:V v, N2:V2 v2" ~:
2148 (Data.List.map fst $
2149 Data.Either.rights $
2151 (Format.Ledger.Read.posting )
2152 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V v, N2:V2 v2"::Text)])
2154 [ (Posting.nil ("A":|["B", "C"]))
2155 { Posting.comments = [" some comment N:V v, N2:V2 v2"]
2156 , Posting.sourcepos = P.newPos "" 1 1
2157 , Posting.tags = Data.Map.fromList
2163 , " A:B:C ; N:V\\n ; N:V2 = Right A:B:C ; N:V\\n ; N:V2" ~:
2164 (Data.List.map fst $
2165 Data.Either.rights $
2167 (Format.Ledger.Read.posting <* P.eof)
2168 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N:V2"::Text)])
2170 [ (Posting.nil ("A":|["B", "C"]))
2171 { Posting.comments = [" N:V", " N:V2"]
2172 , Posting.sourcepos = P.newPos "" 1 1
2173 , Posting.tags = Data.Map.fromList
2174 [ ("N", ["V", "V2"])
2178 , " A:B:C ; N:V\\n ; N2:V = Right A:B:C ; N:V\\n ; N2:V" ~:
2179 (Data.List.map fst $
2180 Data.Either.rights $
2182 (Format.Ledger.Read.posting <* P.eof)
2183 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N2:V"::Text)])
2185 [ (Posting.nil ("A":|["B", "C"]))
2186 { Posting.comments = [" N:V", " N2:V"]
2187 , Posting.sourcepos = P.newPos "" 1 1
2188 , Posting.tags = Data.Map.fromList
2194 , " A:B:C ; date:2001/01/01 = Right A:B:C ; date:2001/01/01" ~:
2195 (Data.List.map fst $
2196 Data.Either.rights $
2198 (Format.Ledger.Read.posting <* P.eof)
2199 Format.Ledger.Read.nil_Context "" (" A:B:C ; date:2001/01/01"::Text)])
2201 [ (Posting.nil ("A":|["B", "C"]))
2202 { Posting.comments = [" date:2001/01/01"]
2206 (Time.fromGregorian 2001 01 01)
2207 (Time.TimeOfDay 0 0 0))
2210 , Posting.sourcepos = P.newPos "" 1 1
2211 , Posting.tags = Data.Map.fromList
2212 [ ("date", ["2001/01/01"])
2216 , " (A:B:C) = Right (A:B:C)" ~:
2217 (Data.Either.rights $
2219 (Format.Ledger.Read.posting <* P.eof)
2220 Format.Ledger.Read.nil_Context "" (" (A:B:C)"::Text)])
2222 [ ( (Posting.nil ("A":|["B", "C"]))
2223 { Posting.sourcepos = P.newPos "" 1 1
2225 , Posting.Type_Virtual
2228 , " [A:B:C] = Right [A:B:C]" ~:
2229 (Data.Either.rights $
2231 (Format.Ledger.Read.posting <* P.eof)
2232 Format.Ledger.Read.nil_Context "" (" [A:B:C]"::Text)])
2234 [ ( (Posting.nil ("A":|["B", "C"]))
2235 { Posting.sourcepos = P.newPos "" 1 1
2237 , Posting.Type_Virtual_Balanced
2241 , "transaction" ~: TestList
2242 [ "2000/01/01 some description\\n A:B:C $1\\n a:b:c" ~:
2243 (Data.Either.rights $
2245 (Format.Ledger.Read.transaction <* P.eof)
2246 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c"::Text)])
2249 { Transaction.dates=
2252 (Time.fromGregorian 2000 01 01)
2253 (Time.TimeOfDay 0 0 0))
2256 , Transaction.description="some description"
2257 , Transaction.postings = Posting.from_List
2258 [ (Posting.nil ("A":|["B", "C"]))
2259 { Posting.amounts = Data.Map.fromList
2261 { Amount.quantity = 1
2262 , Amount.style = Amount.Style.nil
2263 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2264 , Amount.Style.unit_spaced = Just False
2269 , Posting.sourcepos = P.newPos "" 2 1
2271 , (Posting.nil ("a":|["b", "c"]))
2272 { Posting.sourcepos = P.newPos "" 3 1
2275 , Transaction.sourcepos = P.newPos "" 1 1
2278 , "2000/01/01 some description\\n A:B:C $1\\n a:b:c\\n" ~:
2279 (Data.Either.rights $
2281 (Format.Ledger.Read.transaction <* P.newline <* P.eof)
2282 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c\n"::Text)])
2285 { Transaction.dates=
2288 (Time.fromGregorian 2000 01 01)
2289 (Time.TimeOfDay 0 0 0))
2292 , Transaction.description="some description"
2293 , Transaction.postings = Posting.from_List
2294 [ (Posting.nil ("A":|["B", "C"]))
2295 { Posting.amounts = Data.Map.fromList
2297 { Amount.quantity = 1
2298 , Amount.style = Amount.Style.nil
2299 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2300 , Amount.Style.unit_spaced = Just False
2305 , Posting.sourcepos = P.newPos "" 2 1
2307 , (Posting.nil ("a":|["b", "c"]))
2308 { Posting.sourcepos = P.newPos "" 3 1
2311 , Transaction.sourcepos = P.newPos "" 1 1
2314 , "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" ~:
2315 (Data.Either.rights $
2317 (Format.Ledger.Read.transaction <* P.eof)
2318 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)])
2321 { Transaction.comments_after =
2323 , " some other;comment"
2325 , " some last comment"
2327 , Transaction.dates=
2330 (Time.fromGregorian 2000 01 01)
2331 (Time.TimeOfDay 0 0 0))
2334 , Transaction.description="some description"
2335 , Transaction.postings = Posting.from_List
2336 [ (Posting.nil ("A":|["B", "C"]))
2337 { Posting.amounts = Data.Map.fromList
2339 { Amount.quantity = 1
2340 , Amount.style = Amount.Style.nil
2341 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2342 , Amount.Style.unit_spaced = Just False
2347 , Posting.sourcepos = P.newPos "" 5 1
2349 , (Posting.nil ("a":|["b", "c"]))
2350 { Posting.sourcepos = P.newPos "" 6 1
2351 , Posting.tags = Data.Map.fromList []
2354 , Transaction.sourcepos = P.newPos "" 1 1
2355 , Transaction.tags = Data.Map.fromList
2361 , "journal" ~: TestList
2362 [ "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
2365 (Format.Ledger.Read.journal "" {-<* P.eof-})
2366 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)
2368 (\j -> j{Format.Ledger.Journal.last_read_time=
2369 Format.Ledger.Journal.last_read_time Format.Ledger.Journal.nil}) $
2370 Data.Either.rights [jnl])
2372 [ Format.Ledger.Journal.nil
2373 { Format.Ledger.Journal.transactions = Transaction.from_List
2375 { Transaction.dates=
2378 (Time.fromGregorian 2000 01 01)
2379 (Time.TimeOfDay 0 0 0))
2382 , Transaction.description="1° description"
2383 , Transaction.postings = Posting.from_List
2384 [ (Posting.nil ("A":|["B", "C"]))
2385 { Posting.amounts = Data.Map.fromList
2387 { Amount.quantity = 1
2388 , Amount.style = Amount.Style.nil
2389 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2390 , Amount.Style.unit_spaced = Just False
2395 , Posting.sourcepos = P.newPos "" 2 1
2397 , (Posting.nil ("a":|["b", "c"]))
2398 { Posting.sourcepos = P.newPos "" 3 1
2401 , Transaction.sourcepos = P.newPos "" 1 1
2404 { Transaction.dates=
2407 (Time.fromGregorian 2000 01 02)
2408 (Time.TimeOfDay 0 0 0))
2411 , Transaction.description="2° description"
2412 , Transaction.postings = Posting.from_List
2413 [ (Posting.nil ("A":|["B", "C"]))
2414 { Posting.amounts = Data.Map.fromList
2416 { Amount.quantity = 1
2417 , Amount.style = Amount.Style.nil
2418 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2419 , Amount.Style.unit_spaced = Just False
2424 , Posting.sourcepos = P.newPos "" 5 1
2426 , (Posting.nil ("x":|["y", "z"]))
2427 { Posting.sourcepos = P.newPos "" 6 1
2430 , Transaction.sourcepos = P.newPos "" 4 1
2437 , "Write" ~: TestList
2438 [ "account" ~: TestList
2440 ((Format.Ledger.Write.show False $
2441 Format.Ledger.Write.account Posting.Type_Regular $
2446 ((Format.Ledger.Write.show False $
2447 Format.Ledger.Write.account Posting.Type_Regular $
2452 ((Format.Ledger.Write.show False $
2453 Format.Ledger.Write.account Posting.Type_Virtual $
2458 ((Format.Ledger.Write.show False $
2459 Format.Ledger.Write.account Posting.Type_Virtual_Balanced $
2464 , "amount" ~: TestList
2466 ((Format.Ledger.Write.show False $
2467 Format.Ledger.Write.amount
2472 ((Format.Ledger.Write.show False $
2473 Format.Ledger.Write.amount
2475 { Amount.style = Amount.Style.nil
2476 { Amount.Style.precision = 2 }
2481 ((Format.Ledger.Write.show False $
2482 Format.Ledger.Write.amount
2484 { Amount.quantity = Decimal 0 123
2489 ((Format.Ledger.Write.show False $
2490 Format.Ledger.Write.amount
2492 { Amount.quantity = Decimal 0 (- 123)
2496 , "12.3 @ prec=0" ~:
2497 ((Format.Ledger.Write.show False $
2498 Format.Ledger.Write.amount
2500 { Amount.quantity = Decimal 1 123
2501 , Amount.style = Amount.Style.nil
2502 { Amount.Style.fractioning = Just '.'
2507 , "12.5 @ prec=0" ~:
2508 ((Format.Ledger.Write.show False $
2509 Format.Ledger.Write.amount
2511 { Amount.quantity = Decimal 1 125
2512 , Amount.style = Amount.Style.nil
2513 { Amount.Style.fractioning = Just '.'
2518 , "12.3 @ prec=1" ~:
2519 ((Format.Ledger.Write.show False $
2520 Format.Ledger.Write.amount
2522 { Amount.quantity = Decimal 1 123
2523 , Amount.style = Amount.Style.nil
2524 { Amount.Style.fractioning = Just '.'
2525 , Amount.Style.precision = 1
2530 , "1,234.56 @ prec=2" ~:
2531 ((Format.Ledger.Write.show False $
2532 Format.Ledger.Write.amount
2534 { Amount.quantity = Decimal 2 123456
2535 , Amount.style = Amount.Style.nil
2536 { Amount.Style.fractioning = Just '.'
2537 , Amount.Style.precision = 2
2538 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
2543 , "123,456,789,01,2.3456789 @ prec=7" ~:
2544 ((Format.Ledger.Write.show False $
2545 Format.Ledger.Write.amount
2547 { Amount.quantity = Decimal 7 1234567890123456789
2548 , Amount.style = Amount.Style.nil
2549 { Amount.Style.fractioning = Just '.'
2550 , Amount.Style.precision = 7
2551 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2555 "123,456,789,01,2.3456789")
2556 , "1234567.8,90,123,456,789 @ prec=12" ~:
2557 ((Format.Ledger.Write.show False $
2558 Format.Ledger.Write.amount
2560 { Amount.quantity = Decimal 12 1234567890123456789
2561 , Amount.style = Amount.Style.nil
2562 { Amount.Style.fractioning = Just '.'
2563 , Amount.Style.precision = 12
2564 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2568 "1234567.8,90,123,456,789")
2569 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
2570 ((Format.Ledger.Write.show False $
2571 Format.Ledger.Write.amount
2573 { Amount.quantity = Decimal 7 1234567890123456789
2574 , Amount.style = Amount.Style.nil
2575 { Amount.Style.fractioning = Just '.'
2576 , Amount.Style.precision = 7
2577 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2581 "1,2,3,4,5,6,7,89,012.3456789")
2582 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
2583 ((Format.Ledger.Write.show False $
2584 Format.Ledger.Write.amount
2586 { Amount.quantity = Decimal 12 1234567890123456789
2587 , Amount.style = Amount.Style.nil
2588 { Amount.Style.fractioning = Just '.'
2589 , Amount.Style.precision = 12
2590 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2594 "1234567.890,12,3,4,5,6,7,8,9")
2596 , "amount_length" ~: TestList
2598 ((Format.Ledger.Write.amount_length
2603 ((Format.Ledger.Write.amount_length
2605 { Amount.style = Amount.Style.nil
2606 { Amount.Style.precision = 2 }
2611 ((Format.Ledger.Write.amount_length
2613 { Amount.quantity = Decimal 0 123
2618 ((Format.Ledger.Write.amount_length
2620 { Amount.quantity = Decimal 0 (- 123)
2624 , "12.3 @ prec=0" ~:
2625 ((Format.Ledger.Write.amount_length
2627 { Amount.quantity = Decimal 1 123
2628 , Amount.style = Amount.Style.nil
2629 { Amount.Style.fractioning = Just '.'
2634 , "12.5 @ prec=0" ~:
2635 ((Format.Ledger.Write.amount_length
2637 { Amount.quantity = Decimal 1 125
2638 , Amount.style = Amount.Style.nil
2639 { Amount.Style.fractioning = Just '.'
2644 , "12.3 @ prec=1" ~:
2645 ((Format.Ledger.Write.amount_length
2647 { Amount.quantity = Decimal 1 123
2648 , Amount.style = Amount.Style.nil
2649 { Amount.Style.fractioning = Just '.'
2650 , Amount.Style.precision = 1
2655 , "1,234.56 @ prec=2" ~:
2656 ((Format.Ledger.Write.amount_length
2658 { Amount.quantity = Decimal 2 123456
2659 , Amount.style = Amount.Style.nil
2660 { Amount.Style.fractioning = Just '.'
2661 , Amount.Style.precision = 2
2662 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
2667 , "123,456,789,01,2.3456789 @ prec=7" ~:
2668 ((Format.Ledger.Write.amount_length
2670 { Amount.quantity = Decimal 7 1234567890123456789
2671 , Amount.style = Amount.Style.nil
2672 { Amount.Style.fractioning = Just '.'
2673 , Amount.Style.precision = 7
2674 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2679 , "1234567.8,90,123,456,789 @ prec=12" ~:
2680 ((Format.Ledger.Write.amount_length
2682 { Amount.quantity = Decimal 12 1234567890123456789
2683 , Amount.style = Amount.Style.nil
2684 { Amount.Style.fractioning = Just '.'
2685 , Amount.Style.precision = 12
2686 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2691 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
2692 ((Format.Ledger.Write.amount_length
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]
2703 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
2704 ((Format.Ledger.Write.amount_length
2706 { Amount.quantity = Decimal 12 1234567890123456789
2707 , Amount.style = Amount.Style.nil
2708 { Amount.Style.fractioning = Just '.'
2709 , Amount.Style.precision = 12
2710 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2716 , "date" ~: TestList
2718 ((Format.Ledger.Write.show False $
2719 Format.Ledger.Write.date
2723 , "2000/01/01 12:34:51 CET" ~:
2724 (Format.Ledger.Write.show False $
2725 Format.Ledger.Write.date $
2728 (Time.fromGregorian 2000 01 01)
2729 (Time.TimeOfDay 12 34 51))
2730 (Time.TimeZone 60 False "CET"))
2732 "2000/01/01 12:34:51 CET"
2733 , "2000/01/01 12:34:51 +0100" ~:
2734 (Format.Ledger.Write.show False $
2735 Format.Ledger.Write.date $
2738 (Time.fromGregorian 2000 01 01)
2739 (Time.TimeOfDay 12 34 51))
2740 (Time.TimeZone 60 False ""))
2742 "2000/01/01 12:34:51 +0100"
2743 , "2000/01/01 01:02:03" ~:
2744 (Format.Ledger.Write.show False $
2745 Format.Ledger.Write.date $
2748 (Time.fromGregorian 2000 01 01)
2749 (Time.TimeOfDay 1 2 3))
2752 "2000/01/01 01:02:03"
2754 (Format.Ledger.Write.show False $
2755 Format.Ledger.Write.date $
2758 (Time.fromGregorian 0 01 01)
2759 (Time.TimeOfDay 1 2 0))
2764 (Format.Ledger.Write.show False $
2765 Format.Ledger.Write.date $
2768 (Time.fromGregorian 0 01 01)
2769 (Time.TimeOfDay 1 0 0))
2774 (Format.Ledger.Write.show False $
2775 Format.Ledger.Write.date $
2778 (Time.fromGregorian 0 01 01)
2779 (Time.TimeOfDay 0 1 0))
2784 (Format.Ledger.Write.show False $
2785 Format.Ledger.Write.date $
2788 (Time.fromGregorian 0 01 01)
2789 (Time.TimeOfDay 0 0 0))
2794 , "transaction" ~: TestList
2796 ((Format.Ledger.Write.show False $
2797 Format.Ledger.Write.transaction
2801 , "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" ~:
2802 ((Format.Ledger.Write.show False $
2803 Format.Ledger.Write.transaction $
2805 { Transaction.dates=
2808 (Time.fromGregorian 2000 01 01)
2809 (Time.TimeOfDay 0 0 0))
2812 , Transaction.description="some description"
2813 , Transaction.postings = Posting.from_List
2814 [ (Posting.nil ("A":|["B", "C"]))
2815 { Posting.amounts = Data.Map.fromList
2817 { Amount.quantity = 1
2818 , Amount.style = Amount.Style.nil
2819 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2820 , Amount.Style.unit_spaced = Just False
2826 , (Posting.nil ("a":|["b", "c"]))
2827 { Posting.comments = ["first comment","second comment","third comment"]
2832 "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")
2833 , "2000/01/01 some description\\n\\tA:B:C $1\\n\\tAA:BB:CC $123" ~:
2834 ((Format.Ledger.Write.show False $
2835 Format.Ledger.Write.transaction $
2837 { Transaction.dates=
2840 (Time.fromGregorian 2000 01 01)
2841 (Time.TimeOfDay 0 0 0))
2844 , Transaction.description="some description"
2845 , Transaction.postings = Posting.from_List
2846 [ (Posting.nil ("A":|["B", "C"]))
2847 { Posting.amounts = Data.Map.fromList
2849 { Amount.quantity = 1
2850 , Amount.style = Amount.Style.nil
2851 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2852 , Amount.Style.unit_spaced = Just False
2858 , (Posting.nil ("AA":|["BB", "CC"]))
2859 { Posting.amounts = Data.Map.fromList
2861 { Amount.quantity = 123
2862 , Amount.style = Amount.Style.nil
2863 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2864 , Amount.Style.unit_spaced = Just False
2873 "2000/01/01 some description\n\tA:B:C $1\n\tAA:BB:CC $123")