]> Git — Sourcephile - comptalang.git/blob - lib/Test/Main.hs
Modif : aplatit Hcompta.{Format => } et Hcompta.{Calc => }.
[comptalang.git] / lib / Test / Main.hs
1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE TupleSections #-}
3
4 import Prelude
5 import Test.HUnit hiding ((~?))
6 import Test.Framework.Providers.HUnit (hUnitTestToTests)
7 import Test.Framework.Runners.Console (defaultMain)
8
9 import Control.Applicative ((<*))
10 import Control.Arrow ((***))
11 import Control.Monad.IO.Class (liftIO)
12 import Data.Decimal (DecimalRaw(..))
13 import qualified Data.Either
14 import qualified Data.List
15 import Data.List.NonEmpty (NonEmpty(..))
16 import qualified Data.Map.Strict as Data.Map
17 import Data.Text (Text)
18 import qualified Data.Time.Calendar as Time
19 import qualified Data.Time.LocalTime as Time
20 import qualified Text.Parsec as P hiding (char, space, spaces, string)
21 import qualified Text.Parsec.Pos as P
22 -- import qualified Text.PrettyPrint.Leijen.Text as PP
23
24 import qualified Hcompta.Account as Account
25 import Hcompta.Account (Account)
26 import qualified Hcompta.Amount as Amount
27 import Hcompta.Amount (Amount)
28 import qualified Hcompta.Amount.Read as Amount.Read
29 import qualified Hcompta.Amount.Style as Amount.Style
30 import qualified Hcompta.Date as Date
31 import qualified Hcompta.Date.Read as Date.Read
32 import qualified Hcompta.Filter as Filter
33 import qualified Hcompta.Filter.Read as Filter.Read
34 import qualified Hcompta.Balance as Balance
35 import qualified Hcompta.Format.Ledger as Format.Ledger
36 import qualified Hcompta.Format.Ledger.Read as Format.Ledger.Read
37 import qualified Hcompta.Format.Ledger.Write as Format.Ledger.Write
38 import qualified Hcompta.Lib.TreeMap as Lib.TreeMap
39 import qualified Hcompta.Lib.Parsec as P
40 import qualified Hcompta.Lib.Foldable as Lib.Foldable
41
42 main :: IO ()
43 main = defaultMain $ hUnitTestToTests test_Hcompta
44
45 (~?) :: String -> Bool -> Test
46 (~?) s b = s ~: (b ~?= True)
47
48 test_Hcompta :: Test
49 test_Hcompta =
50 TestList
51 [ "Lib" ~: TestList
52 [ "TreeMap" ~: TestList
53 [ "insert" ~: TestList
54 [ "[] 0" ~:
55 (Lib.TreeMap.insert const ((0::Int):|[]) () Lib.TreeMap.empty)
56 ~?=
57 (Lib.TreeMap.TreeMap $
58 Data.Map.fromList
59 [ ((0::Int), Lib.TreeMap.leaf ())
60 ])
61 , "[] 0/1" ~:
62 (Lib.TreeMap.insert const ((0::Int):|1:[]) () Lib.TreeMap.empty)
63 ~?=
64 (Lib.TreeMap.TreeMap $
65 Data.Map.fromList
66 [ ((0::Int), Lib.TreeMap.Node
67 { Lib.TreeMap.node_value = Nothing
68 , Lib.TreeMap.node_size = 1
69 , Lib.TreeMap.node_descendants =
70 Lib.TreeMap.singleton ((1::Int):|[]) ()
71 })
72 ])
73 ]
74 , "union" ~: TestList
75 [
76 ]
77 , "map_by_depth_first" ~: TestList
78 [
79 ]
80 , "flatten" ~: TestList
81 [ "[0, 0/1, 0/1/2]" ~:
82 (Lib.TreeMap.flatten id $
83 Lib.TreeMap.from_List const
84 [ (((0::Integer):|[]), ())
85 , ((0:|1:[]), ())
86 , ((0:|1:2:[]), ())
87 ]
88 )
89 ~?=
90 (Data.Map.fromList
91 [ ((0:|[]), ())
92 , ((0:|1:[]), ())
93 , ((0:|1:2:[]), ())
94 ])
95 , "[1, 1/2, 1/22, 1/2/3, 1/2/33, 11, 11/2, 11/2/3, 11/2/33]" ~:
96 (Lib.TreeMap.flatten id $
97 Lib.TreeMap.from_List const
98 [ ((1:|[]), ())
99 , ((1:|2:[]), ())
100 , ((1:|22:[]), ())
101 , ((1:|2:3:[]), ())
102 , ((1:|2:33:[]), ())
103 , ((11:|[]), ())
104 , ((11:|2:[]), ())
105 , ((11:|2:3:[]), ())
106 , ((11:|2:33:[]), ())
107 ]
108 )
109 ~?=
110 (Data.Map.fromList
111 [ (((1::Integer):|[]), ())
112 , ((1:|2:[]), ())
113 , ((1:|22:[]), ())
114 , ((1:|2:3:[]), ())
115 , ((1:|2:33:[]), ())
116 , ((11:|[]), ())
117 , ((11:|2:[]), ())
118 , ((11:|2:3:[]), ())
119 , ((11:|2:33:[]), ())
120 ])
121 ]
122 ]
123 , "Foldable" ~: TestList
124 [ "accumLeftsAndFoldrRights" ~: TestList
125 [ "Left" ~:
126 (Lib.Foldable.accumLeftsAndFoldrRights (++) [""] $
127 [Left [0]])
128 ~?=
129 (([(0::Integer)], [(""::String)]))
130 , "repeat Left" ~:
131 ((take 1 *** take 0) $
132 Lib.Foldable.accumLeftsAndFoldrRights (++) [""] $
133 ( repeat (Left [0]) ))
134 ~?=
135 ([(0::Integer)], ([]::[String]))
136 , "Right:Left:Right:Left" ~:
137 (Lib.Foldable.accumLeftsAndFoldrRights (++) ["0"] $
138 ( Right ["2"]:Left [1]:Right ["1"]:Left [0]:[] ))
139 ~?=
140 (([1, 0]::[Integer]), (["2", "1", "0"]::[String]))
141 , "Right:Left:Right:repeat Left" ~:
142 ((take 1 *** take 2) $
143 Lib.Foldable.accumLeftsAndFoldrRights (++) ["0"] $
144 ( Right ["2"]:Left [1]:Right ["1"]:repeat (Left [0]) ))
145 ~?=
146 (([1]::[Integer]), (["2", "1"]::[String]))
147 ]
148 ]
149 ]
150 , "Account" ~: TestList
151 [ "foldr" ~: TestList
152 [ "[A]" ~:
153 (reverse $ Account.foldr ("A":|[]) (:) []) ~?= ["A":|[]]
154 , "[A, B]" ~:
155 (reverse $ Account.foldr ("A":|["B"]) (:) []) ~?= ["A":|[], "A":|["B"]]
156 , "[A, B, C]" ~:
157 (reverse $ Account.foldr ("A":|["B", "C"]) (:) []) ~?= ["A":|[], "A":|["B"], "A":|["B", "C"]]
158 ]
159 , "ascending" ~: TestList
160 [ "[A]" ~:
161 Account.ascending ("A":|[]) ~?= Nothing
162 , "[A, B]" ~:
163 Account.ascending ("A":|["B"]) ~?= Just ("A":|[])
164 , "[A, B, C]" ~:
165 Account.ascending ("A":|["B", "C"]) ~?= Just ("A":|["B"])
166 ]
167 ]
168 , "Amount" ~: TestList
169 [ "+" ~: TestList
170 [ "$1 + 1$ = $2" ~:
171 (+)
172 (Amount.nil
173 { Amount.quantity = Decimal 0 1
174 , Amount.style = Amount.Style.nil
175 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
176 }
177 , Amount.unit = "$"
178 })
179 (Amount.nil
180 { Amount.quantity = Decimal 0 1
181 , Amount.style = Amount.Style.nil
182 { Amount.Style.unit_side = Just $ Amount.Style.Side_Right
183 }
184 , Amount.unit = "$"
185 })
186 ~?=
187 (Amount.nil
188 { Amount.quantity = Decimal 0 2
189 , Amount.style = Amount.Style.nil
190 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
191 }
192 , Amount.unit = "$"
193 })
194 ]
195 , "from_List" ~: TestList
196 [ "from_List [$1, 1$] = $2" ~:
197 Amount.from_List
198 [ Amount.nil
199 { Amount.quantity = Decimal 0 1
200 , Amount.style = Amount.Style.nil
201 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
202 }
203 , Amount.unit = "$"
204 }
205 , Amount.nil
206 { Amount.quantity = Decimal 0 1
207 , Amount.style = Amount.Style.nil
208 { Amount.Style.unit_side = Just $ Amount.Style.Side_Right
209 }
210 , Amount.unit = "$"
211 }
212 ]
213 ~?=
214 Data.Map.fromList
215 [ ("$", Amount.nil
216 { Amount.quantity = Decimal 0 2
217 , Amount.style = Amount.Style.nil
218 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
219 }
220 , Amount.unit = "$"
221 })
222 ]
223 ]
224 , "Read" ~: TestList
225 [ "amount" ~: TestList
226 [ "\"\" = Left" ~:
227 (Data.Either.rights $
228 [P.runParser
229 (Amount.Read.amount <* P.eof)
230 () "" (""::Text)])
231 ~?=
232 []
233 , "\"0\" = Right 0" ~:
234 (Data.Either.rights $
235 [P.runParser
236 (Amount.Read.amount <* P.eof)
237 () "" ("0"::Text)])
238 ~?=
239 [Amount.nil
240 { Amount.quantity = Decimal 0 0
241 }]
242 , "\"00\" = Right 0" ~:
243 (Data.Either.rights $
244 [P.runParser
245 (Amount.Read.amount <* P.eof)
246 () "" ("00"::Text)])
247 ~?=
248 [Amount.nil
249 { Amount.quantity = Decimal 0 0
250 }]
251 , "\"0.\" = Right 0." ~:
252 (Data.Either.rights $
253 [P.runParser
254 (Amount.Read.amount <* P.eof)
255 () "" ("0."::Text)])
256 ~?=
257 [Amount.nil
258 { Amount.quantity = Decimal 0 0
259 , Amount.style =
260 Amount.Style.nil
261 { Amount.Style.fractioning = Just '.'
262 }
263 }]
264 , "\".0\" = Right 0.0" ~:
265 (Data.Either.rights $
266 [P.runParser
267 (Amount.Read.amount <* P.eof)
268 () "" (".0"::Text)])
269 ~?=
270 [Amount.nil
271 { Amount.quantity = Decimal 0 0
272 , Amount.style =
273 Amount.Style.nil
274 { Amount.Style.fractioning = Just '.'
275 , Amount.Style.precision = 1
276 }
277 }]
278 , "\"0,\" = Right 0," ~:
279 (Data.Either.rights $
280 [P.runParser
281 (Amount.Read.amount <* P.eof)
282 () "" ("0,"::Text)])
283 ~?=
284 [Amount.nil
285 { Amount.quantity = Decimal 0 0
286 , Amount.style =
287 Amount.Style.nil
288 { Amount.Style.fractioning = Just ','
289 }
290 }]
291 , "\",0\" = Right 0,0" ~:
292 (Data.Either.rights $
293 [P.runParser
294 (Amount.Read.amount <* P.eof)
295 () "" (",0"::Text)])
296 ~?=
297 [Amount.nil
298 { Amount.quantity = Decimal 0 0
299 , Amount.style =
300 Amount.Style.nil
301 { Amount.Style.fractioning = Just ','
302 , Amount.Style.precision = 1
303 }
304 }]
305 , "\"0_\" = Left" ~:
306 (Data.Either.rights $
307 [P.runParser
308 (Amount.Read.amount <* P.eof)
309 () "" ("0_"::Text)])
310 ~?=
311 []
312 , "\"_0\" = Left" ~:
313 (Data.Either.rights $
314 [P.runParser
315 (Amount.Read.amount <* P.eof)
316 () "" ("_0"::Text)])
317 ~?=
318 []
319 , "\"0.0\" = Right 0.0" ~:
320 (Data.Either.rights $
321 [P.runParser
322 (Amount.Read.amount <* P.eof)
323 () "" ("0.0"::Text)])
324 ~?=
325 [Amount.nil
326 { Amount.quantity = Decimal 0 0
327 , Amount.style =
328 Amount.Style.nil
329 { Amount.Style.fractioning = Just '.'
330 , Amount.Style.precision = 1
331 }
332 }]
333 , "\"00.00\" = Right 0.00" ~:
334 (Data.Either.rights $
335 [P.runParser
336 (Amount.Read.amount <* P.eof)
337 () "" ("00.00"::Text)])
338 ~?=
339 [Amount.nil
340 { Amount.quantity = Decimal 0 0
341 , Amount.style =
342 Amount.Style.nil
343 { Amount.Style.fractioning = Just '.'
344 , Amount.Style.precision = 2
345 }
346 }]
347 , "\"0,0\" = Right 0,0" ~:
348 (Data.Either.rights $
349 [P.runParser
350 (Amount.Read.amount <* P.eof)
351 () "" ("0,0"::Text)])
352 ~?=
353 [Amount.nil
354 { Amount.quantity = Decimal 0 0
355 , Amount.style =
356 Amount.Style.nil
357 { Amount.Style.fractioning = Just ','
358 , Amount.Style.precision = 1
359 }
360 }]
361 , "\"00,00\" = Right 0,00" ~:
362 (Data.Either.rights $
363 [P.runParser
364 (Amount.Read.amount <* P.eof)
365 () "" ("00,00"::Text)])
366 ~?=
367 [Amount.nil
368 { Amount.quantity = Decimal 0 0
369 , Amount.style =
370 Amount.Style.nil
371 { Amount.Style.fractioning = Just ','
372 , Amount.Style.precision = 2
373 }
374 }]
375 , "\"0_0\" = Right 0" ~:
376 (Data.Either.rights $
377 [P.runParser
378 (Amount.Read.amount <* P.eof)
379 () "" ("0_0"::Text)])
380 ~?=
381 [Amount.nil
382 { Amount.quantity = Decimal 0 0
383 , Amount.style =
384 Amount.Style.nil
385 { Amount.Style.fractioning = Nothing
386 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [1]
387 , Amount.Style.precision = 0
388 }
389 }]
390 , "\"00_00\" = Right 0" ~:
391 (Data.Either.rights $
392 [P.runParser
393 (Amount.Read.amount <* P.eof)
394 () "" ("00_00"::Text)])
395 ~?=
396 [Amount.nil
397 { Amount.quantity = Decimal 0 0
398 , Amount.style =
399 Amount.Style.nil
400 { Amount.Style.fractioning = Nothing
401 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [2]
402 , Amount.Style.precision = 0
403 }
404 }]
405 , "\"0,000.00\" = Right 0,000.00" ~:
406 (Data.Either.rights $
407 [P.runParser
408 (Amount.Read.amount <* P.eof)
409 () "" ("0,000.00"::Text)])
410 ~?=
411 [Amount.nil
412 { Amount.quantity = Decimal 0 0
413 , Amount.style =
414 Amount.Style.nil
415 { Amount.Style.fractioning = Just '.'
416 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
417 , Amount.Style.precision = 2
418 }
419 }]
420 , "\"0.000,00\" = Right 0.000,00" ~:
421 (Data.Either.rights $
422 [P.runParser
423 (Amount.Read.amount)
424 () "" ("0.000,00"::Text)])
425 ~?=
426 [Amount.nil
427 { Amount.quantity = Decimal 0 0
428 , Amount.style =
429 Amount.Style.nil
430 { Amount.Style.fractioning = Just ','
431 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
432 , Amount.Style.precision = 2
433 }
434 }]
435 , "\"1,000.00\" = Right 1,000.00" ~:
436 (Data.Either.rights $
437 [P.runParser
438 (Amount.Read.amount <* P.eof)
439 () "" ("1,000.00"::Text)])
440 ~?=
441 [Amount.nil
442 { Amount.quantity = Decimal 0 1000
443 , Amount.style =
444 Amount.Style.nil
445 { Amount.Style.fractioning = Just '.'
446 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
447 , Amount.Style.precision = 2
448 }
449 }]
450 , "\"1.000,00\" = Right 1.000,00" ~:
451 (Data.Either.rights $
452 [P.runParser
453 (Amount.Read.amount)
454 () "" ("1.000,00"::Text)])
455 ~?=
456 [Amount.nil
457 { Amount.quantity = Decimal 0 1000
458 , Amount.style =
459 Amount.Style.nil
460 { Amount.Style.fractioning = Just ','
461 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
462 , Amount.Style.precision = 2
463 }
464 }]
465 , "\"1,000.00.\" = Left" ~:
466 (Data.Either.rights $
467 [P.runParser
468 (Amount.Read.amount)
469 () "" ("1,000.00."::Text)])
470 ~?=
471 []
472 , "\"1.000,00,\" = Left" ~:
473 (Data.Either.rights $
474 [P.runParser
475 (Amount.Read.amount)
476 () "" ("1.000,00,"::Text)])
477 ~?=
478 []
479 , "\"1,000.00_\" = Left" ~:
480 (Data.Either.rights $
481 [P.runParser
482 (Amount.Read.amount)
483 () "" ("1,000.00_"::Text)])
484 ~?=
485 []
486 , "\"12\" = Right 12" ~:
487 (Data.Either.rights $
488 [P.runParser
489 (Amount.Read.amount <* P.eof)
490 () "" ("123"::Text)])
491 ~?=
492 [Amount.nil
493 { Amount.quantity = Decimal 0 123
494 }]
495 , "\"1.2\" = Right 1.2" ~:
496 (Data.Either.rights $
497 [P.runParser
498 (Amount.Read.amount <* P.eof)
499 () "" ("1.2"::Text)])
500 ~?=
501 [Amount.nil
502 { Amount.quantity = Decimal 1 12
503 , Amount.style =
504 Amount.Style.nil
505 { Amount.Style.fractioning = Just '.'
506 , Amount.Style.precision = 1
507 }
508 }]
509 , "\"1,2\" = Right 1,2" ~:
510 (Data.Either.rights $
511 [P.runParser
512 (Amount.Read.amount <* P.eof)
513 () "" ("1,2"::Text)])
514 ~?=
515 [Amount.nil
516 { Amount.quantity = Decimal 1 12
517 , Amount.style =
518 Amount.Style.nil
519 { Amount.Style.fractioning = Just ','
520 , Amount.Style.precision = 1
521 }
522 }]
523 , "\"12.23\" = Right 12.23" ~:
524 (Data.Either.rights $
525 [P.runParser
526 (Amount.Read.amount <* P.eof)
527 () "" ("12.34"::Text)])
528 ~?=
529 [Amount.nil
530 { Amount.quantity = Decimal 2 1234
531 , Amount.style =
532 Amount.Style.nil
533 { Amount.Style.fractioning = Just '.'
534 , Amount.Style.precision = 2
535 }
536 }]
537 , "\"12,23\" = Right 12,23" ~:
538 (Data.Either.rights $
539 [P.runParser
540 (Amount.Read.amount <* P.eof)
541 () "" ("12,34"::Text)])
542 ~?=
543 [Amount.nil
544 { Amount.quantity = Decimal 2 1234
545 , Amount.style =
546 Amount.Style.nil
547 { Amount.Style.fractioning = Just ','
548 , Amount.Style.precision = 2
549 }
550 }]
551 , "\"1_2\" = Right 1_2" ~:
552 (Data.Either.rights $
553 [P.runParser
554 (Amount.Read.amount <* P.eof)
555 () "" ("1_2"::Text)])
556 ~?=
557 [Amount.nil
558 { Amount.quantity = Decimal 0 12
559 , Amount.style =
560 Amount.Style.nil
561 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [1]
562 , Amount.Style.precision = 0
563 }
564 }]
565 , "\"1_23\" = Right 1_23" ~:
566 (Data.Either.rights $
567 [P.runParser
568 (Amount.Read.amount <* P.eof)
569 () "" ("1_23"::Text)])
570 ~?=
571 [Amount.nil
572 { Amount.quantity = Decimal 0 123
573 , Amount.style =
574 Amount.Style.nil
575 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [2]
576 , Amount.Style.precision = 0
577 }
578 }]
579 , "\"1_23_456\" = Right 1_23_456" ~:
580 (Data.Either.rights $
581 [P.runParser
582 (Amount.Read.amount <* P.eof)
583 () "" ("1_23_456"::Text)])
584 ~?=
585 [Amount.nil
586 { Amount.quantity = Decimal 0 123456
587 , Amount.style =
588 Amount.Style.nil
589 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [3, 2]
590 , Amount.Style.precision = 0
591 }
592 }]
593 , "\"1_23_456.7890_12345_678901\" = Right 1_23_456.7890_12345_678901" ~:
594 (Data.Either.rights $
595 [P.runParser
596 (Amount.Read.amount <* P.eof)
597 () "" ("1_23_456.7890_12345_678901"::Text)])
598 ~?=
599 [Amount.nil
600 { Amount.quantity = Decimal 15 123456789012345678901
601 , Amount.style =
602 Amount.Style.nil
603 { Amount.Style.fractioning = Just '.'
604 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [3, 2]
605 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping '_' [4, 5, 6]
606 , Amount.Style.precision = 15
607 }
608 }]
609 , "\"123456_78901_2345.678_90_1\" = Right 123456_78901_2345.678_90_1" ~:
610 (Data.Either.rights $
611 [P.runParser
612 (Amount.Read.amount <* P.eof)
613 () "" ("123456_78901_2345.678_90_1"::Text)])
614 ~?=
615 [Amount.nil
616 { Amount.quantity = Decimal 6 123456789012345678901
617 , Amount.style =
618 Amount.Style.nil
619 { Amount.Style.fractioning = Just '.'
620 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [4, 5, 6]
621 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping '_' [3, 2]
622 , Amount.Style.precision = 6
623 }
624 }]
625 , "\"$1\" = Right $1" ~:
626 (Data.Either.rights $
627 [P.runParser
628 (Amount.Read.amount <* P.eof)
629 () "" ("$1"::Text)])
630 ~?=
631 [Amount.nil
632 { Amount.quantity = Decimal 0 1
633 , Amount.style =
634 Amount.Style.nil
635 { Amount.Style.fractioning = Nothing
636 , Amount.Style.grouping_integral = Nothing
637 , Amount.Style.grouping_fractional = Nothing
638 , Amount.Style.precision = 0
639 , Amount.Style.unit_side = Just Amount.Style.Side_Left
640 , Amount.Style.unit_spaced = Just False
641 }
642 , Amount.unit = "$"
643 }]
644 , "\"1$\" = Right 1$" ~:
645 (Data.Either.rights $
646 [P.runParser
647 (Amount.Read.amount <* P.eof)
648 () "" ("1$"::Text)])
649 ~?=
650 [Amount.nil
651 { Amount.quantity = Decimal 0 1
652 , Amount.style =
653 Amount.Style.nil
654 { Amount.Style.fractioning = Nothing
655 , Amount.Style.grouping_integral = Nothing
656 , Amount.Style.grouping_fractional = Nothing
657 , Amount.Style.precision = 0
658 , Amount.Style.unit_side = Just Amount.Style.Side_Right
659 , Amount.Style.unit_spaced = Just False
660 }
661 , Amount.unit = "$"
662 }]
663 , "\"$ 1\" = Right $ 1" ~:
664 (Data.Either.rights $
665 [P.runParser
666 (Amount.Read.amount <* P.eof)
667 () "" ("$ 1"::Text)])
668 ~?=
669 [Amount.nil
670 { Amount.quantity = Decimal 0 1
671 , Amount.style =
672 Amount.Style.nil
673 { Amount.Style.fractioning = Nothing
674 , Amount.Style.grouping_integral = Nothing
675 , Amount.Style.grouping_fractional = Nothing
676 , Amount.Style.precision = 0
677 , Amount.Style.unit_side = Just Amount.Style.Side_Left
678 , Amount.Style.unit_spaced = Just True
679 }
680 , Amount.unit = "$"
681 }]
682 , "\"1 $\" = Right 1 $" ~:
683 (Data.Either.rights $
684 [P.runParser
685 (Amount.Read.amount <* P.eof)
686 () "" ("1 $"::Text)])
687 ~?=
688 [Amount.nil
689 { Amount.quantity = Decimal 0 1
690 , Amount.style =
691 Amount.Style.nil
692 { Amount.Style.fractioning = Nothing
693 , Amount.Style.grouping_integral = Nothing
694 , Amount.Style.grouping_fractional = Nothing
695 , Amount.Style.precision = 0
696 , Amount.Style.unit_side = Just Amount.Style.Side_Right
697 , Amount.Style.unit_spaced = Just True
698 }
699 , Amount.unit = "$"
700 }]
701 , "\"-$1\" = Right $-1" ~:
702 (Data.Either.rights $
703 [P.runParser
704 (Amount.Read.amount <* P.eof)
705 () "" ("-$1"::Text)])
706 ~?=
707 [Amount.nil
708 { Amount.quantity = Decimal 0 (-1)
709 , Amount.style =
710 Amount.Style.nil
711 { Amount.Style.fractioning = Nothing
712 , Amount.Style.grouping_integral = Nothing
713 , Amount.Style.grouping_fractional = Nothing
714 , Amount.Style.precision = 0
715 , Amount.Style.unit_side = Just Amount.Style.Side_Left
716 , Amount.Style.unit_spaced = Just False
717 }
718 , Amount.unit = "$"
719 }]
720 , "\"\\\"4 2\\\"1\" = Right \\\"4 2\\\"1" ~:
721 (Data.Either.rights $
722 [P.runParser
723 (Amount.Read.amount <* P.eof)
724 () "" ("\"4 2\"1"::Text)])
725 ~?=
726 [Amount.nil
727 { Amount.quantity = Decimal 0 1
728 , Amount.style =
729 Amount.Style.nil
730 { Amount.Style.fractioning = Nothing
731 , Amount.Style.grouping_integral = Nothing
732 , Amount.Style.grouping_fractional = Nothing
733 , Amount.Style.precision = 0
734 , Amount.Style.unit_side = Just Amount.Style.Side_Left
735 , Amount.Style.unit_spaced = Just False
736 }
737 , Amount.unit = "4 2"
738 }]
739 , "\"1\\\"4 2\\\"\" = Right 1\\\"4 2\\\"" ~:
740 (Data.Either.rights $
741 [P.runParser
742 (Amount.Read.amount <* P.eof)
743 () "" ("1\"4 2\""::Text)])
744 ~?=
745 [Amount.nil
746 { Amount.quantity = Decimal 0 1
747 , Amount.style =
748 Amount.Style.nil
749 { Amount.Style.fractioning = Nothing
750 , Amount.Style.grouping_integral = Nothing
751 , Amount.Style.grouping_fractional = Nothing
752 , Amount.Style.precision = 0
753 , Amount.Style.unit_side = Just Amount.Style.Side_Right
754 , Amount.Style.unit_spaced = Just False
755 }
756 , Amount.unit = "4 2"
757 }]
758 , "\"$1.000,00\" = Right $1.000,00" ~:
759 (Data.Either.rights $
760 [P.runParser
761 (Amount.Read.amount <* P.eof)
762 () "" ("$1.000,00"::Text)])
763 ~?=
764 [Amount.nil
765 { Amount.quantity = Decimal 0 1000
766 , Amount.style =
767 Amount.Style.nil
768 { Amount.Style.fractioning = Just ','
769 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
770 , Amount.Style.grouping_fractional = Nothing
771 , Amount.Style.precision = 2
772 , Amount.Style.unit_side = Just Amount.Style.Side_Left
773 , Amount.Style.unit_spaced = Just False
774 }
775 , Amount.unit = "$"
776 }]
777 , "\"1.000,00$\" = Right 1.000,00$" ~:
778 (Data.Either.rights $
779 [P.runParser
780 (Amount.Read.amount <* P.eof)
781 () "" ("1.000,00$"::Text)])
782 ~?=
783 [Amount.nil
784 { Amount.quantity = Decimal 0 1000
785 , Amount.style =
786 Amount.Style.nil
787 { Amount.Style.fractioning = Just ','
788 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
789 , Amount.Style.grouping_fractional = Nothing
790 , Amount.Style.precision = 2
791 , Amount.Style.unit_side = Just Amount.Style.Side_Right
792 , Amount.Style.unit_spaced = Just False
793 }
794 , Amount.unit = "$"
795 }]
796 ]
797 ]
798 ]
799 , "Date" ~: TestList
800 [ "Read" ~: TestList
801 [ "date" ~: TestList
802 [ "2000/01/01" ~:
803 (Data.Either.rights $
804 [P.runParser_with_Error
805 (Date.Read.date id Nothing <* P.eof)
806 () "" ("2000/01/01"::Text)])
807 ~?=
808 [ Time.zonedTimeToUTC $
809 Time.ZonedTime
810 (Time.LocalTime
811 (Time.fromGregorian 2000 01 01)
812 (Time.TimeOfDay 0 0 0))
813 (Time.utc)]
814 , "2000/01/01 some text" ~:
815 (Data.Either.rights $
816 [P.runParser_with_Error
817 (Date.Read.date id Nothing)
818 () "" ("2000/01/01 some text"::Text)])
819 ~?=
820 [ Time.zonedTimeToUTC $
821 Time.ZonedTime
822 (Time.LocalTime
823 (Time.fromGregorian 2000 01 01)
824 (Time.TimeOfDay 0 0 0))
825 (Time.utc)]
826 , "2000/01/01 12:34" ~:
827 (Data.Either.rights $
828 [P.runParser_with_Error
829 (Date.Read.date id Nothing <* P.eof)
830 () "" ("2000/01/01 12:34"::Text)])
831 ~?=
832 [ Time.zonedTimeToUTC $
833 Time.ZonedTime
834 (Time.LocalTime
835 (Time.fromGregorian 2000 01 01)
836 (Time.TimeOfDay 12 34 0))
837 (Time.utc)]
838 , "2000/01/01 12:34:56" ~:
839 (Data.Either.rights $
840 [P.runParser_with_Error
841 (Date.Read.date id Nothing <* P.eof)
842 () "" ("2000/01/01 12:34:56"::Text)])
843 ~?=
844 [ Time.zonedTimeToUTC $
845 Time.ZonedTime
846 (Time.LocalTime
847 (Time.fromGregorian 2000 01 01)
848 (Time.TimeOfDay 12 34 56))
849 (Time.utc)]
850 , "2000/01/01 12:34 CET" ~:
851 (Data.Either.rights $
852 [P.runParser_with_Error
853 (Date.Read.date id Nothing <* P.eof)
854 () "" ("2000/01/01 12:34 CET"::Text)])
855 ~?=
856 [ Time.zonedTimeToUTC $
857 Time.ZonedTime
858 (Time.LocalTime
859 (Time.fromGregorian 2000 01 01)
860 (Time.TimeOfDay 12 34 0))
861 (Time.TimeZone 60 True "CET")]
862 , "2000/01/01 12:34 +0130" ~:
863 (Data.Either.rights $
864 [P.runParser_with_Error
865 (Date.Read.date id Nothing <* P.eof)
866 () "" ("2000/01/01 12:34 +0130"::Text)])
867 ~?=
868 [ Time.zonedTimeToUTC $
869 Time.ZonedTime
870 (Time.LocalTime
871 (Time.fromGregorian 2000 01 01)
872 (Time.TimeOfDay 12 34 0))
873 (Time.TimeZone 90 False "+0130")]
874 , "2000/01/01 12:34:56 CET" ~:
875 (Data.Either.rights $
876 [P.runParser_with_Error
877 (Date.Read.date id Nothing <* P.eof)
878 () "" ("2000/01/01 12:34:56 CET"::Text)])
879 ~?=
880 [ Time.zonedTimeToUTC $
881 Time.ZonedTime
882 (Time.LocalTime
883 (Time.fromGregorian 2000 01 01)
884 (Time.TimeOfDay 12 34 56))
885 (Time.TimeZone 60 True "CET")]
886 , "2001/02/29" ~:
887 (Data.Either.rights $
888 [P.runParser_with_Error
889 (Date.Read.date id Nothing <* P.eof)
890 () "" ("2001/02/29"::Text)])
891 ~?=
892 []
893 , "01/01" ~:
894 (Data.Either.rights $
895 [P.runParser_with_Error
896 (Date.Read.date id (Just 2000) <* P.eof)
897 () "" ("01/01"::Text)])
898 ~?=
899 [ Time.zonedTimeToUTC $
900 Time.ZonedTime
901 (Time.LocalTime
902 (Time.fromGregorian 2000 01 01)
903 (Time.TimeOfDay 0 0 0))
904 (Time.utc)]
905 ]
906 ]
907 ]
908 , "Filter" ~: TestList
909 [ "test" ~: TestList
910 [ "Test_Account" ~: TestList
911 [ "A A" ~?
912 Filter.test
913 [ Filter.Test_Account_Section_Text
914 (Filter.Test_Text_Exact "A")
915 ]
916 (("A":|[]::Account))
917 , "* A" ~?
918 Filter.test
919 [ Filter.Test_Account_Section_Any
920 ]
921 (("A":|[]::Account))
922 , ": A" ~?
923 Filter.test
924 [ Filter.Test_Account_Section_Many
925 ]
926 (("A":|[]::Account))
927 , ":A A" ~?
928 Filter.test
929 [ Filter.Test_Account_Section_Many
930 , Filter.Test_Account_Section_Text
931 (Filter.Test_Text_Exact "A")
932 ]
933 (("A":|[]::Account))
934 , "A: A" ~?
935 Filter.test
936 [ Filter.Test_Account_Section_Text
937 (Filter.Test_Text_Exact "A")
938 , Filter.Test_Account_Section_Many
939 ]
940 (("A":|[]::Account))
941 , "A: A:B" ~?
942 Filter.test
943 [ Filter.Test_Account_Section_Text
944 (Filter.Test_Text_Exact "A")
945 , Filter.Test_Account_Section_Many
946 ]
947 (("A":|"B":[]::Account))
948 , "A:B A:B" ~?
949 Filter.test
950 [ Filter.Test_Account_Section_Text
951 (Filter.Test_Text_Exact "A")
952 , Filter.Test_Account_Section_Text
953 (Filter.Test_Text_Exact "B")
954 ]
955 (("A":|"B":[]::Account))
956 , "A::B A:B" ~?
957 Filter.test
958 [ Filter.Test_Account_Section_Text
959 (Filter.Test_Text_Exact "A")
960 , Filter.Test_Account_Section_Many
961 , Filter.Test_Account_Section_Text
962 (Filter.Test_Text_Exact "B")
963 ]
964 (("A":|"B":[]::Account))
965 , ":B: A:B:C" ~?
966 Filter.test
967 [ Filter.Test_Account_Section_Many
968 , Filter.Test_Account_Section_Text
969 (Filter.Test_Text_Exact "B")
970 , Filter.Test_Account_Section_Many
971 ]
972 (("A":|"B":"C":[]::Account))
973 , ":C A:B:C" ~?
974 Filter.test
975 [ Filter.Test_Account_Section_Many
976 , Filter.Test_Account_Section_Text
977 (Filter.Test_Text_Exact "C")
978 ]
979 (("A":|"B":"C":[]::Account))
980 ]
981 , "Test_Bool" ~: TestList
982 [ "Any A" ~?
983 Filter.test
984 (Filter.Any::Filter.Test_Bool Filter.Test_Account)
985 (("A":|[]::Account))
986 ]
987 ]
988 , "Read" ~: TestList
989 [ "test_account_section" ~: TestList
990 [ "*" ~:
991 (Data.Either.rights $
992 [P.runParser
993 (Filter.Read.test_account <* P.eof)
994 () "" ("*"::Text)])
995 ~?=
996 [ [Filter.Test_Account_Section_Any]
997 ]
998 , "A" ~:
999 (Data.Either.rights $
1000 [P.runParser
1001 (Filter.Read.test_account <* P.eof)
1002 () "" ("A"::Text)])
1003 ~?=
1004 [ [Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")]
1005 ]
1006 , "AA" ~:
1007 (Data.Either.rights $
1008 [P.runParser
1009 (Filter.Read.test_account <* P.eof)
1010 () "" ("AA"::Text)])
1011 ~?=
1012 [ [Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "AA")]
1013 ]
1014 , "::A" ~:
1015 (Data.Either.rights $
1016 [P.runParser
1017 (Filter.Read.test_account <* P.eof)
1018 () "" ("::A"::Text)])
1019 ~?=
1020 [ [ Filter.Test_Account_Section_Many
1021 , Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")
1022 ]
1023 ]
1024 , ":A" ~:
1025 (Data.Either.rights $
1026 [P.runParser
1027 (Filter.Read.test_account <* P.eof)
1028 () "" (":A"::Text)])
1029 ~?=
1030 [ [ Filter.Test_Account_Section_Many
1031 , Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")
1032 ]
1033 ]
1034 , "A:" ~:
1035 (Data.Either.rights $
1036 [P.runParser
1037 (Filter.Read.test_account <* P.eof)
1038 () "" ("A:"::Text)])
1039 ~?=
1040 [ [ Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")
1041 , Filter.Test_Account_Section_Many
1042 ]
1043 ]
1044 , "A::" ~:
1045 (Data.Either.rights $
1046 [P.runParser
1047 (Filter.Read.test_account <* P.eof)
1048 () "" ("A::"::Text)])
1049 ~?=
1050 [ [ Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")
1051 , Filter.Test_Account_Section_Many
1052 ]
1053 ]
1054 , "A:B" ~:
1055 (Data.Either.rights $
1056 [P.runParser
1057 (Filter.Read.test_account <* P.eof)
1058 () "" ("A:B"::Text)])
1059 ~?=
1060 [ [ Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")
1061 , Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "B") ]
1062 ]
1063 , "A::B" ~:
1064 (Data.Either.rights $
1065 [P.runParser
1066 (Filter.Read.test_account <* P.eof)
1067 () "" ("A::B"::Text)])
1068 ~?=
1069 [ [ Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")
1070 , Filter.Test_Account_Section_Many
1071 , Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "B")
1072 ]
1073 ]
1074 , "A:::B" ~:
1075 (Data.Either.rights $
1076 [P.runParser
1077 (Filter.Read.test_account <* P.eof)
1078 () "" ("A:::B"::Text)])
1079 ~?=
1080 [ [ Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")
1081 , Filter.Test_Account_Section_Many
1082 , Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "B")
1083 ]
1084 ]
1085 , "A: " ~:
1086 (Data.Either.rights $
1087 [P.runParser
1088 (Filter.Read.test_account <* P.char ' ' <* P.eof)
1089 () "" ("A: "::Text)])
1090 ~?=
1091 [ [ Filter.Test_Account_Section_Text (Filter.Test_Text_Exact "A")
1092 , Filter.Test_Account_Section_Many
1093 ]
1094 ]
1095 ]
1096 , "test_bool" ~: TestList
1097 [ "( E )" ~:
1098 (Data.Either.rights $
1099 [P.runParser
1100 (Filter.Read.test_bool
1101 [ P.char 'E' >> return (return True) ]
1102 <* P.eof)
1103 () "" ("( E )"::Text)])
1104 ~?=
1105 [ Filter.And (Filter.Bool True) Filter.Any
1106 ]
1107 , "( ( E ) )" ~:
1108 (Data.Either.rights $
1109 [P.runParser
1110 (Filter.Read.test_bool
1111 [ P.char 'E' >> return (return True) ]
1112 <* P.eof)
1113 () "" ("( ( E ) )"::Text)])
1114 ~?=
1115 [ Filter.And (Filter.And (Filter.Bool True) Filter.Any) Filter.Any
1116 ]
1117 , "( E ) & ( E )" ~:
1118 (Data.Either.rights $
1119 [P.runParser
1120 (Filter.Read.test_bool
1121 [ P.char 'E' >> return (return True) ]
1122 <* P.eof)
1123 () "" ("( E ) & ( E )"::Text)])
1124 ~?=
1125 [ Filter.And
1126 (Filter.And (Filter.Bool True) Filter.Any)
1127 (Filter.And (Filter.Bool True) Filter.Any)
1128 ]
1129 , "( E ) + ( E )" ~:
1130 (Data.Either.rights $
1131 [P.runParser
1132 (Filter.Read.test_bool
1133 [ P.char 'E' >> return (return True) ]
1134 <* P.eof)
1135 () "" ("( E ) + ( E )"::Text)])
1136 ~?=
1137 [ Filter.Or
1138 (Filter.And (Filter.Bool True) Filter.Any)
1139 (Filter.And (Filter.Bool True) Filter.Any)
1140 ]
1141 , "( E ) - ( E )" ~:
1142 (Data.Either.rights $
1143 [P.runParser
1144 (Filter.Read.test_bool
1145 [ P.char 'E' >> return (return True) ]
1146 <* P.eof)
1147 () "" ("( E ) - ( E )"::Text)])
1148 ~?=
1149 [ Filter.And
1150 (Filter.And (Filter.Bool True) Filter.Any)
1151 (Filter.Not (Filter.And (Filter.Bool True) Filter.Any))
1152 ]
1153 , "(- E )" ~:
1154 (Data.Either.rights $
1155 [P.runParser
1156 (Filter.Read.test_bool
1157 [ P.char 'E' >> return (return True) ]
1158 <* P.eof)
1159 () "" ("(- E )"::Text)])
1160 ~?=
1161 [ Filter.And (Filter.Not (Filter.Bool True)) Filter.Any
1162 ]
1163 ]
1164 ]
1165 ]
1166 , "Balance" ~: TestList
1167 [ "balance" ~: TestList
1168 [ "[A+$1] = A+$1 & $+1" ~:
1169 (Balance.balance
1170 (Format.Ledger.posting ("A":|[]))
1171 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1172 }
1173 Balance.nil)
1174 ~?=
1175 Balance.Balance
1176 { Balance.balance_by_account =
1177 Lib.TreeMap.from_List const $
1178 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1179 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1180 , Balance.balance_by_unit =
1181 Data.Map.fromList $
1182 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1183 [ Balance.Unit_Sum
1184 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1185 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1186 ["A":|[]]
1187 }
1188 ]
1189 }
1190 , "[A+$1, A-$1] = {A+$0, $+0}" ~:
1191 (Data.List.foldl
1192 (flip Balance.balance)
1193 Balance.nil
1194 [ (Format.Ledger.posting ("A":|[]))
1195 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1196 }
1197 , (Format.Ledger.posting ("A":|[]))
1198 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1 ]
1199 }
1200 ])
1201 ~?=
1202 Balance.Balance
1203 { Balance.balance_by_account =
1204 Lib.TreeMap.from_List const $
1205 [ ( "A":|[]
1206 , Data.Map.fromListWith const $
1207 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance s, s))
1208 [ Balance.Amount_Sum
1209 { Balance.amount_sum_negative = Just $ Amount.usd $ -1
1210 , Balance.amount_sum_positive = Just $ Amount.usd $ 1
1211 , Balance.amount_sum_balance = Amount.usd $ 0
1212 }
1213 ]
1214 ) ]
1215 , Balance.balance_by_unit =
1216 Data.Map.fromList $
1217 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1218 [ Balance.Unit_Sum
1219 { Balance.unit_sum_amount = Balance.Amount_Sum
1220 { Balance.amount_sum_negative = Just $ Amount.usd $ -1
1221 , Balance.amount_sum_positive = Just $ Amount.usd $ 1
1222 , Balance.amount_sum_balance = Amount.usd $ 0
1223 }
1224 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1225 ["A":|[]]
1226 }
1227 ]
1228 }
1229 , "[A+$1, A-€1] = {A+$1-€1, $+1 €-1}" ~:
1230 (Data.List.foldl
1231 (flip Balance.balance)
1232 Balance.nil
1233 [ (Format.Ledger.posting ("A":|[]))
1234 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1235 }
1236 , (Format.Ledger.posting ("A":|[]))
1237 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.eur $ -1 ]
1238 }
1239 ])
1240 ~?=
1241 Balance.Balance
1242 { Balance.balance_by_account =
1243 Lib.TreeMap.from_List const $
1244 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1245 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ -1 ]) ]
1246 , Balance.balance_by_unit =
1247 Data.Map.fromList $
1248 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1249 [ Balance.Unit_Sum
1250 { Balance.unit_sum_amount = Balance.Amount_Sum
1251 { Balance.amount_sum_negative = Nothing
1252 , Balance.amount_sum_positive = Just $ Amount.usd $ 1
1253 , Balance.amount_sum_balance = Amount.usd $ 1
1254 }
1255 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1256 ["A":|[]]
1257 }
1258 , Balance.Unit_Sum
1259 { Balance.unit_sum_amount = Balance.Amount_Sum
1260 { Balance.amount_sum_negative = Just $ Amount.eur $ -1
1261 , Balance.amount_sum_positive = Nothing
1262 , Balance.amount_sum_balance = Amount.eur $ -1
1263 }
1264 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1265 ["A":|[]]
1266 }
1267 ]
1268 }
1269 , "[A+$1, B-$1] = {A+$1 B-$1, $+0}" ~:
1270 (Data.List.foldl
1271 (flip Balance.balance)
1272 Balance.nil
1273 [ (Format.Ledger.posting ("A":|[]))
1274 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1275 }
1276 , (Format.Ledger.posting ("B":|[]))
1277 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1 ]
1278 }
1279 ])
1280 ~?=
1281 Balance.Balance
1282 { Balance.balance_by_account =
1283 Lib.TreeMap.from_List const $
1284 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1285 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1286 , ("B":|[], Amount.from_List [ Amount.usd $ -1 ])
1287 ]
1288 , Balance.balance_by_unit =
1289 Data.Map.fromList $
1290 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1291 [ Balance.Unit_Sum
1292 { Balance.unit_sum_amount = Balance.Amount_Sum
1293 { Balance.amount_sum_negative = Just $ Amount.usd $ -1
1294 , Balance.amount_sum_positive = Just $ Amount.usd $ 1
1295 , Balance.amount_sum_balance = Amount.usd $ 0
1296 }
1297 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1298 ["A":|[], "B":|[]]
1299 }
1300 ]
1301 }
1302 , "[A+$1, B+$1]" ~:
1303 (Data.List.foldl
1304 (flip Balance.balance)
1305 Balance.nil
1306 [ (Format.Ledger.posting ("A":|[]))
1307 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1308 }
1309 , (Format.Ledger.posting ("B":|[]))
1310 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1311 }
1312 ])
1313 ~?=
1314 Balance.Balance
1315 { Balance.balance_by_account =
1316 Lib.TreeMap.from_List const $
1317 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1318 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1319 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ])
1320 ]
1321 , Balance.balance_by_unit =
1322 Data.Map.fromList $
1323 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1324 [ Balance.Unit_Sum
1325 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1326 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1327 ["A":|[], "B":|[]]
1328 }
1329 ]
1330 }
1331 , "[A+$1+€2, A-$1-€2] = {A+$0+€0, $+0 €+0}" ~:
1332 (Data.List.foldl
1333 (flip Balance.balance)
1334 Balance.nil
1335 [ (Format.Ledger.posting ("A":|[]))
1336 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2 ]
1337 }
1338 , (Format.Ledger.posting ("A":|[]))
1339 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2 ]
1340 }
1341 ])
1342 ~?=
1343 Balance.Balance
1344 { Balance.balance_by_account =
1345 Lib.TreeMap.from_List const $
1346 [ ("A":|[]
1347 , Data.Map.fromListWith const $
1348 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance s, s))
1349 [ Balance.Amount_Sum
1350 { Balance.amount_sum_negative = Just $ Amount.usd $ -1
1351 , Balance.amount_sum_positive = Just $ Amount.usd $ 1
1352 , Balance.amount_sum_balance = Amount.usd $ 0
1353 }
1354 , Balance.Amount_Sum
1355 { Balance.amount_sum_negative = Just $ Amount.eur $ -2
1356 , Balance.amount_sum_positive = Just $ Amount.eur $ 2
1357 , Balance.amount_sum_balance = Amount.eur $ 0
1358 }
1359 ]
1360 )
1361 ]
1362 , Balance.balance_by_unit =
1363 Data.Map.fromList $
1364 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1365 [ Balance.Unit_Sum
1366 { Balance.unit_sum_amount = Balance.Amount_Sum
1367 { Balance.amount_sum_negative = Just $ Amount.usd $ -1
1368 , Balance.amount_sum_positive = Just $ Amount.usd $ 1
1369 , Balance.amount_sum_balance = Amount.usd $ 0
1370 }
1371 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1372 ["A":|[]]
1373 }
1374 , Balance.Unit_Sum
1375 { Balance.unit_sum_amount = Balance.Amount_Sum
1376 { Balance.amount_sum_negative = Just $ Amount.eur $ -2
1377 , Balance.amount_sum_positive = Just $ Amount.eur $ 2
1378 , Balance.amount_sum_balance = Amount.eur $ 0
1379 }
1380 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1381 ["A":|[]]
1382 }
1383 ]
1384 }
1385 , "[A+$1+€2+£3, B-$1-2€-£3] = {A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~:
1386 (Data.List.foldl
1387 (flip Balance.balance)
1388 Balance.nil
1389 [ (Format.Ledger.posting ("A":|[]))
1390 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ]
1391 }
1392 , (Format.Ledger.posting ("B":|[]))
1393 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ]
1394 }
1395 ])
1396 ~?=
1397 Balance.Balance
1398 { Balance.balance_by_account =
1399 Lib.TreeMap.from_List const $
1400 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1401 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
1402 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
1403 ]
1404 , Balance.balance_by_unit =
1405 Data.Map.fromList $
1406 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1407 [ Balance.Unit_Sum
1408 { Balance.unit_sum_amount = Balance.Amount_Sum
1409 { Balance.amount_sum_negative = Just $ Amount.usd $ -1
1410 , Balance.amount_sum_positive = Just $ Amount.usd $ 1
1411 , Balance.amount_sum_balance = Amount.usd $ 0
1412 }
1413 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1414 ["A":|[], "B":|[]]
1415 }
1416 , Balance.Unit_Sum
1417 { Balance.unit_sum_amount = Balance.Amount_Sum
1418 { Balance.amount_sum_negative = Just $ Amount.eur $ -2
1419 , Balance.amount_sum_positive = Just $ Amount.eur $ 2
1420 , Balance.amount_sum_balance = Amount.eur $ 0
1421 }
1422 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1423 ["A":|[], "B":|[]]
1424 }
1425 , Balance.Unit_Sum
1426 { Balance.unit_sum_amount = Balance.Amount_Sum
1427 { Balance.amount_sum_negative = Just $ Amount.gbp $ -3
1428 , Balance.amount_sum_positive = Just $ Amount.gbp $ 3
1429 , Balance.amount_sum_balance = Amount.gbp $ 0
1430 }
1431 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1432 ["A":|[], "B":|[]]
1433 }
1434 ]
1435 }
1436 ]
1437 , "union" ~: TestList
1438 [ "nil nil = nil" ~:
1439 Balance.union Balance.nil Balance.nil
1440 ~?=
1441 (Balance.nil::Balance.Balance Amount)
1442 , "{A+$1, $+1} {A+$1, $+1} = {A+$2, $+2}" ~:
1443 Balance.union
1444 (Balance.Balance
1445 { Balance.balance_by_account =
1446 Lib.TreeMap.from_List const $
1447 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1448 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1449 , Balance.balance_by_unit =
1450 Data.Map.fromList $
1451 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1452 [ Balance.Unit_Sum
1453 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1454 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1455 ["A":|[]]
1456 }
1457 ]
1458 })
1459 (Balance.Balance
1460 { Balance.balance_by_account =
1461 Lib.TreeMap.from_List const $
1462 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1463 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1464 , Balance.balance_by_unit =
1465 Data.Map.fromList $
1466 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1467 [ Balance.Unit_Sum
1468 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1469 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1470 ["A":|[]]
1471 }
1472 ]
1473 })
1474 ~?=
1475 Balance.Balance
1476 { Balance.balance_by_account =
1477 Lib.TreeMap.from_List const $
1478 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1479 [ ("A":|[], Amount.from_List [ Amount.usd $ 2 ]) ]
1480 , Balance.balance_by_unit =
1481 Data.Map.fromList $
1482 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1483 [ Balance.Unit_Sum
1484 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1485 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1486 ["A":|[]]
1487 }
1488 ]
1489 }
1490 , "{A+$1, $+1} {B+$1, $+1} = {A+$1 B+$1, $+2}" ~:
1491 Balance.union
1492 (Balance.Balance
1493 { Balance.balance_by_account =
1494 Lib.TreeMap.from_List const $
1495 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1496 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1497 , Balance.balance_by_unit =
1498 Data.Map.fromList $
1499 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1500 [ Balance.Unit_Sum
1501 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1502 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1503 ["A":|[]]
1504 }
1505 ]
1506 })
1507 (Balance.Balance
1508 { Balance.balance_by_account =
1509 Lib.TreeMap.from_List const $
1510 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1511 [ ("B":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1512 , Balance.balance_by_unit =
1513 Data.Map.fromList $
1514 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1515 [ Balance.Unit_Sum
1516 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1517 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1518 ["B":|[]]
1519 }
1520 ]
1521 })
1522 ~?=
1523 Balance.Balance
1524 { Balance.balance_by_account =
1525 Lib.TreeMap.from_List const $
1526 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1527 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1528 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1529 , Balance.balance_by_unit =
1530 Data.Map.fromList $
1531 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1532 [ Balance.Unit_Sum
1533 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1534 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1535 ["A":|[], "B":|[]]
1536 }
1537 ]
1538 }
1539 , "{A+$1, $+1} {B+€1, €+1} = {A+$1 B+€1, $+1 €+1}" ~:
1540 Balance.union
1541 (Balance.Balance
1542 { Balance.balance_by_account =
1543 Lib.TreeMap.from_List const $
1544 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1545 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1546 , Balance.balance_by_unit =
1547 Data.Map.fromList $
1548 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1549 [ Balance.Unit_Sum
1550 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1551 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1552 ["A":|[]]
1553 }
1554 ]
1555 })
1556 (Balance.Balance
1557 { Balance.balance_by_account =
1558 Lib.TreeMap.from_List const $
1559 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1560 [ ("B":|[], Amount.from_List [ Amount.eur $ 1 ]) ]
1561 , Balance.balance_by_unit =
1562 Data.Map.fromList $
1563 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1564 [ Balance.Unit_Sum
1565 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 1
1566 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1567 ["B":|[]]
1568 }
1569 ]
1570 })
1571 ~?=
1572 Balance.Balance
1573 { Balance.balance_by_account =
1574 Lib.TreeMap.from_List const $
1575 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1576 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1577 , ("B":|[], Amount.from_List [ Amount.eur $ 1 ]) ]
1578 , Balance.balance_by_unit =
1579 Data.Map.fromList $
1580 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1581 [ Balance.Unit_Sum
1582 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1583 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1584 ["A":|[]]
1585 }
1586 , Balance.Unit_Sum
1587 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 1
1588 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1589 ["B":|[]]
1590 }
1591 ]
1592 }
1593 ]
1594 , "expanded" ~: TestList
1595 [ "nil_By_Account" ~:
1596 Balance.expanded
1597 Lib.TreeMap.empty
1598 ~?=
1599 (Lib.TreeMap.empty::Balance.Expanded Amount)
1600 , "A+$1 = A+$1" ~:
1601 Balance.expanded
1602 (Lib.TreeMap.from_List const $
1603 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1604 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ])
1605 ~?=
1606 (Lib.TreeMap.from_List const $
1607 [ ("A":|[], Balance.Account_Sum_Expanded
1608 { Balance.inclusive =
1609 Data.Map.map Balance.amount_sum $
1610 Amount.from_List [ Amount.usd $ 1 ]
1611 , Balance.exclusive =
1612 Data.Map.map Balance.amount_sum $
1613 Amount.from_List [ Amount.usd $ 1 ]
1614 })
1615 ])
1616 , "A/A+$1 = A+$1 A/A+$1" ~:
1617 Balance.expanded
1618 (Lib.TreeMap.from_List const $
1619 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1620 [ ("A":|["A"], Amount.from_List [ Amount.usd $ 1 ]) ])
1621 ~?=
1622 (Lib.TreeMap.from_List const
1623 [ ("A":|[], Balance.Account_Sum_Expanded
1624 { Balance.inclusive =
1625 Data.Map.map Balance.amount_sum $
1626 Amount.from_List [ Amount.usd $ 1 ]
1627 , Balance.exclusive =
1628 Data.Map.map Balance.amount_sum $
1629 Amount.from_List []
1630 })
1631 , ("A":|["A"], Balance.Account_Sum_Expanded
1632 { Balance.inclusive =
1633 Data.Map.map Balance.amount_sum $
1634 Amount.from_List [ Amount.usd $ 1 ]
1635 , Balance.exclusive =
1636 Data.Map.map Balance.amount_sum $
1637 Amount.from_List [ Amount.usd $ 1 ]
1638 })
1639 ])
1640 , "A/B+$1 = A+$1 A/B+$1" ~:
1641 Balance.expanded
1642 (Lib.TreeMap.from_List const $
1643 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1644 [ ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ]) ])
1645 ~?=
1646 (Lib.TreeMap.from_List const
1647 [ ("A":|[], Balance.Account_Sum_Expanded
1648 { Balance.inclusive =
1649 Data.Map.map Balance.amount_sum $
1650 Amount.from_List [ Amount.usd $ 1 ]
1651 , Balance.exclusive =
1652 Data.Map.map Balance.amount_sum $
1653 Amount.from_List []
1654 })
1655 , ("A":|["B"], Balance.Account_Sum_Expanded
1656 { Balance.inclusive =
1657 Data.Map.map Balance.amount_sum $
1658 Amount.from_List [ Amount.usd $ 1 ]
1659 , Balance.exclusive =
1660 Data.Map.map Balance.amount_sum $
1661 Amount.from_List [ Amount.usd $ 1 ]
1662 })
1663 ])
1664 , "A/B/C+$1 = A+$1 A/B+$1 A/B/C+$1" ~:
1665 Balance.expanded
1666 (Lib.TreeMap.from_List const $
1667 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1668 [ ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ]) ])
1669 ~?=
1670 (Lib.TreeMap.from_List const $
1671 [ ("A":|[], Balance.Account_Sum_Expanded
1672 { Balance.inclusive =
1673 Data.Map.map Balance.amount_sum $
1674 Amount.from_List [ Amount.usd $ 1 ]
1675 , Balance.exclusive =
1676 Data.Map.map Balance.amount_sum $
1677 Amount.from_List []
1678 })
1679 , ("A":|["B"], Balance.Account_Sum_Expanded
1680 { Balance.inclusive =
1681 Data.Map.map Balance.amount_sum $
1682 Amount.from_List [ Amount.usd $ 1 ]
1683 , Balance.exclusive =
1684 Data.Map.map Balance.amount_sum $
1685 Amount.from_List []
1686 })
1687 , ("A":|["B", "C"], Balance.Account_Sum_Expanded
1688 { Balance.inclusive =
1689 Data.Map.map Balance.amount_sum $
1690 Amount.from_List [ Amount.usd $ 1 ]
1691 , Balance.exclusive =
1692 Data.Map.map Balance.amount_sum $
1693 Amount.from_List [ Amount.usd $ 1 ]
1694 })
1695 ])
1696 , "A+$1 A/B+$1 = A+$2 A/B+$1" ~:
1697 Balance.expanded
1698 (Lib.TreeMap.from_List const $
1699 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1700 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1701 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1702 ])
1703 ~?=
1704 (Lib.TreeMap.from_List const
1705 [ ("A":|[], Balance.Account_Sum_Expanded
1706 { Balance.inclusive =
1707 Data.Map.map Balance.amount_sum $
1708 Amount.from_List [ Amount.usd $ 2 ]
1709 , Balance.exclusive =
1710 Data.Map.map Balance.amount_sum $
1711 Amount.from_List [ Amount.usd $ 1 ]
1712 })
1713 , ("A":|["B"], Balance.Account_Sum_Expanded
1714 { Balance.inclusive =
1715 Data.Map.map Balance.amount_sum $
1716 Amount.from_List [ Amount.usd $ 1 ]
1717 , Balance.exclusive =
1718 Data.Map.map Balance.amount_sum $
1719 Amount.from_List [ Amount.usd $ 1 ]
1720 })
1721 ])
1722 , "A+$1 A/B+$1 A/B/C+$1 = A+$3 A/B+$2 A/B/C+$1" ~:
1723 Balance.expanded
1724 (Lib.TreeMap.from_List const $
1725 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1726 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1727 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1728 , ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ])
1729 ])
1730 ~?=
1731 (Lib.TreeMap.from_List const
1732 [ ("A":|[], Balance.Account_Sum_Expanded
1733 { Balance.inclusive =
1734 Data.Map.map Balance.amount_sum $
1735 Amount.from_List [ Amount.usd $ 3 ]
1736 , Balance.exclusive =
1737 Data.Map.map Balance.amount_sum $
1738 Amount.from_List [ Amount.usd $ 1 ]
1739 })
1740 , ("A":|["B"], Balance.Account_Sum_Expanded
1741 { Balance.inclusive =
1742 Data.Map.map Balance.amount_sum $
1743 Amount.from_List [ Amount.usd $ 2 ]
1744 , Balance.exclusive =
1745 Data.Map.map Balance.amount_sum $
1746 Amount.from_List [ Amount.usd $ 1 ]
1747 })
1748 , ("A":|["B", "C"], Balance.Account_Sum_Expanded
1749 { Balance.inclusive =
1750 Data.Map.map Balance.amount_sum $
1751 Amount.from_List [ Amount.usd $ 1 ]
1752 , Balance.exclusive =
1753 Data.Map.map Balance.amount_sum $
1754 Amount.from_List [ Amount.usd $ 1 ]
1755 })
1756 ])
1757 , "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" ~:
1758 Balance.expanded
1759 (Lib.TreeMap.from_List const $
1760 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1761 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1762 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1763 , ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ])
1764 , ("A":|["B", "C", "D"], Amount.from_List [ Amount.usd $ 1 ])
1765 ])
1766 ~?=
1767 (Lib.TreeMap.from_List const
1768 [ ("A":|[], Balance.Account_Sum_Expanded
1769 { Balance.inclusive =
1770 Data.Map.map Balance.amount_sum $
1771 Amount.from_List [ Amount.usd $ 4 ]
1772 , Balance.exclusive =
1773 Data.Map.map Balance.amount_sum $
1774 Amount.from_List [ Amount.usd $ 1 ]
1775 })
1776 , ("A":|["B"], Balance.Account_Sum_Expanded
1777 { Balance.inclusive =
1778 Data.Map.map Balance.amount_sum $
1779 Amount.from_List [ Amount.usd $ 3 ]
1780 , Balance.exclusive =
1781 Data.Map.map Balance.amount_sum $
1782 Amount.from_List [ Amount.usd $ 1 ]
1783 })
1784 , ("A":|["B", "C"], Balance.Account_Sum_Expanded
1785 { Balance.inclusive =
1786 Data.Map.map Balance.amount_sum $
1787 Amount.from_List [ Amount.usd $ 2 ]
1788 , Balance.exclusive =
1789 Data.Map.map Balance.amount_sum $
1790 Amount.from_List [ Amount.usd $ 1 ]
1791 })
1792 , ("A":|["B", "C", "D"], Balance.Account_Sum_Expanded
1793 { Balance.inclusive =
1794 Data.Map.map Balance.amount_sum $
1795 Amount.from_List [ Amount.usd $ 1 ]
1796 , Balance.exclusive =
1797 Data.Map.map Balance.amount_sum $
1798 Amount.from_List [ Amount.usd $ 1 ]
1799 })
1800 ])
1801 , "A+$1 A/B+$1 A/BB+$1 AA/B+$1 = A+$3 A/B+$1 A/BB+$1 AA+$1 AA/B+$1" ~:
1802 Balance.expanded
1803 (Lib.TreeMap.from_List const $
1804 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1805 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1806 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1807 , ("A":|["BB"], Amount.from_List [ Amount.usd $ 1 ])
1808 , ("AA":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1809 ])
1810 ~?=
1811 (Lib.TreeMap.from_List const
1812 [ ("A":|[], Balance.Account_Sum_Expanded
1813 { Balance.inclusive =
1814 Data.Map.map Balance.amount_sum $
1815 Amount.from_List [ Amount.usd $ 3 ]
1816 , Balance.exclusive =
1817 Data.Map.map Balance.amount_sum $
1818 Amount.from_List [ Amount.usd $ 1 ]
1819 })
1820 , ("A":|["B"], Balance.Account_Sum_Expanded
1821 { Balance.inclusive =
1822 Data.Map.map Balance.amount_sum $
1823 Amount.from_List [ Amount.usd $ 1 ]
1824 , Balance.exclusive =
1825 Data.Map.map Balance.amount_sum $
1826 Amount.from_List [ Amount.usd $ 1 ]
1827 })
1828 , ("A":|["BB"], Balance.Account_Sum_Expanded
1829 { Balance.inclusive =
1830 Data.Map.map Balance.amount_sum $
1831 Amount.from_List [ Amount.usd $ 1 ]
1832 , Balance.exclusive =
1833 Data.Map.map Balance.amount_sum $
1834 Amount.from_List [ Amount.usd $ 1 ]
1835 })
1836 , ("AA":|[], Balance.Account_Sum_Expanded
1837 { Balance.inclusive =
1838 Data.Map.map Balance.amount_sum $
1839 Amount.from_List [ Amount.usd $ 1 ]
1840 , Balance.exclusive =
1841 Data.Map.map Balance.amount_sum $
1842 Amount.from_List []
1843 })
1844 , ("AA":|["B"], Balance.Account_Sum_Expanded
1845 { Balance.inclusive =
1846 Data.Map.map Balance.amount_sum $
1847 Amount.from_List [ Amount.usd $ 1 ]
1848 , Balance.exclusive =
1849 Data.Map.map Balance.amount_sum $
1850 Amount.from_List [ Amount.usd $ 1 ]
1851 })
1852 ])
1853 ]
1854 , "deviation" ~: TestList
1855 [ "{A+$1, $1}" ~:
1856 (Balance.deviation $
1857 Balance.Balance
1858 { Balance.balance_by_account =
1859 Lib.TreeMap.from_List const $
1860 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1861 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1862 , ("B":|[], Amount.from_List [])
1863 ]
1864 , Balance.balance_by_unit =
1865 Data.Map.fromList $
1866 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1867 [ Balance.Unit_Sum
1868 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1869 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1870 ["A":|[]]
1871 }
1872 ]
1873 })
1874 ~?=
1875 (Balance.Deviation $
1876 Data.Map.fromList $
1877 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1878 [ Balance.Unit_Sum
1879 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1880 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1881 ["B":|[]]
1882 }
1883 ])
1884 , "{A+$1 B+$1, $2}" ~:
1885 (Balance.deviation $
1886 Balance.Balance
1887 { Balance.balance_by_account =
1888 Lib.TreeMap.from_List const $
1889 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1890 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1891 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ])
1892 ]
1893 , Balance.balance_by_unit =
1894 Data.Map.fromList $
1895 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1896 [ Balance.Unit_Sum
1897 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1898 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1899 [ "A":|[]
1900 , "B":|[]
1901 ]
1902 }
1903 ]
1904 })
1905 ~?=
1906 (Balance.Deviation $
1907 Data.Map.fromList $
1908 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1909 [ Balance.Unit_Sum
1910 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1911 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1912 [
1913 ]
1914 }
1915 ])
1916 ]
1917 , "is_equilibrium_inferrable" ~: TestList
1918 [ "nil" ~: TestCase $
1919 (@=?) True $
1920 Balance.is_equilibrium_inferrable $
1921 Balance.deviation $
1922 (Balance.nil::Balance.Balance Amount.Amount)
1923 , "{A+$0, $+0}" ~: TestCase $
1924 (@=?) True $
1925 Balance.is_equilibrium_inferrable $
1926 Balance.deviation $
1927 Balance.Balance
1928 { Balance.balance_by_account =
1929 Lib.TreeMap.from_List const $
1930 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1931 [ ("A":|[], Amount.from_List [ Amount.usd $ 0 ])
1932 ]
1933 , Balance.balance_by_unit =
1934 Data.Map.fromList $
1935 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1936 [ Balance.Unit_Sum
1937 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
1938 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1939 ["A":|[]]
1940 }
1941 ]
1942 }
1943 , "{A+$1, $+1}" ~: TestCase $
1944 (@=?) False $
1945 Balance.is_equilibrium_inferrable $
1946 Balance.deviation $
1947 Balance.Balance
1948 { Balance.balance_by_account =
1949 Lib.TreeMap.from_List const $
1950 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1951 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1952 ]
1953 , Balance.balance_by_unit =
1954 Data.Map.fromList $
1955 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1956 [ Balance.Unit_Sum
1957 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1958 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1959 ["A":|[]]
1960 }
1961 ]
1962 }
1963 , "{A+$0+€0, $0 €+0}" ~: TestCase $
1964 (@=?) True $
1965 Balance.is_equilibrium_inferrable $
1966 Balance.deviation $
1967 Balance.Balance
1968 { Balance.balance_by_account =
1969 Lib.TreeMap.from_List const $
1970 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1971 [ ("A":|[], Amount.from_List [ Amount.usd $ 0, Amount.eur $ 0 ])
1972 ]
1973 , Balance.balance_by_unit =
1974 Data.Map.fromList $
1975 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1976 [ Balance.Unit_Sum
1977 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
1978 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1979 ["A":|[]]
1980 }
1981 , Balance.Unit_Sum
1982 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 0
1983 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1984 ["A":|[]]
1985 }
1986 ]
1987 }
1988 , "{A+$1, B-$1, $+0}" ~: TestCase $
1989 (@=?) True $
1990 Balance.is_equilibrium_inferrable $
1991 Balance.deviation $
1992 Balance.Balance
1993 { Balance.balance_by_account =
1994 Lib.TreeMap.from_List const $
1995 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1996 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1997 , ("B":|[], Amount.from_List [ Amount.usd $ -1 ])
1998 ]
1999 , Balance.balance_by_unit =
2000 Data.Map.fromList $
2001 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
2002 [ Balance.Unit_Sum
2003 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
2004 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2005 ["A":|[], "B":|[]]
2006 }
2007 ]
2008 }
2009 , "{A+$1 B, $+1}" ~: TestCase $
2010 (@=?) True $
2011 Balance.is_equilibrium_inferrable $
2012 Balance.deviation $
2013 Balance.Balance
2014 { Balance.balance_by_account =
2015 Lib.TreeMap.from_List const $
2016 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
2017 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
2018 , ("B":|[], Amount.from_List [])
2019 ]
2020 , Balance.balance_by_unit =
2021 Data.Map.fromList $
2022 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
2023 [ Balance.Unit_Sum
2024 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
2025 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2026 ["A":|[]]
2027 }
2028 ]
2029 }
2030 , "{A+$1 B+€1, $+1 €+1}" ~: TestCase $
2031 (@=?) True $
2032 Balance.is_equilibrium_inferrable $
2033 Balance.deviation $
2034 Balance.Balance
2035 { Balance.balance_by_account =
2036 Lib.TreeMap.from_List const $
2037 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
2038 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
2039 , ("B":|[], Amount.from_List [ Amount.eur $ 1 ])
2040 ]
2041 , Balance.balance_by_unit =
2042 Data.Map.fromList $
2043 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
2044 [ Balance.Unit_Sum
2045 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
2046 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2047 ["A":|[]]
2048 }
2049 , Balance.Unit_Sum
2050 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 1
2051 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2052 ["B":|[]]
2053 }
2054 ]
2055 }
2056 , "{A+$1 B-$1+€1, $+0 €+1}" ~: TestCase $
2057 (@=?) True $
2058 Balance.is_equilibrium_inferrable $
2059 Balance.deviation $
2060 Balance.Balance
2061 { Balance.balance_by_account =
2062 Lib.TreeMap.from_List const $
2063 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
2064 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
2065 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ 1 ])
2066 ]
2067 , Balance.balance_by_unit =
2068 Data.Map.fromList $
2069 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
2070 [ Balance.Unit_Sum
2071 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
2072 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2073 ["A":|[], "B":|[]]
2074 }
2075 , Balance.Unit_Sum
2076 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 1
2077 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2078 ["B":|[]]
2079 }
2080 ]
2081 }
2082 , "{A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~: TestCase $
2083 (@=?) True $
2084 Balance.is_equilibrium_inferrable $
2085 Balance.deviation $
2086 Balance.Balance
2087 { Balance.balance_by_account =
2088 Lib.TreeMap.from_List const $
2089 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
2090 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
2091 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
2092 ]
2093 , Balance.balance_by_unit =
2094 Data.Map.fromList $
2095 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
2096 [ Balance.Unit_Sum
2097 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
2098 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2099 ["A":|[], "B":|[]]
2100 }
2101 , Balance.Unit_Sum
2102 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 0
2103 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2104 ["A":|[], "B":|[]]
2105 }
2106 , Balance.Unit_Sum
2107 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.gbp $ 0
2108 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2109 ["A":|[], "B":|[]]
2110 }
2111 ]
2112 }
2113 ]
2114 , "infer_equilibrium" ~: TestList
2115 [ "{A+$1 B}" ~:
2116 (snd $ Balance.infer_equilibrium $
2117 Format.Ledger.posting_by_Account
2118 [ (Format.Ledger.posting ("A":|[]))
2119 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2120 , (Format.Ledger.posting ("B":|[]))
2121 { Format.Ledger.posting_amounts=Amount.from_List [] }
2122 ])
2123 ~?=
2124 (Right $
2125 Format.Ledger.posting_by_Account
2126 [ (Format.Ledger.posting ("A":|[]))
2127 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2128 , (Format.Ledger.posting ("B":|[]))
2129 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1 ] }
2130 ])
2131 , "{A+$1 B-1€}" ~:
2132 (snd $ Balance.infer_equilibrium $
2133 Format.Ledger.posting_by_Account
2134 [ (Format.Ledger.posting ("A":|[]))
2135 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2136 , (Format.Ledger.posting ("B":|[]))
2137 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.eur $ -1 ] }
2138 ])
2139 ~?=
2140 (Right $
2141 Format.Ledger.posting_by_Account
2142 [ (Format.Ledger.posting ("A":|[]))
2143 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 1] }
2144 , (Format.Ledger.posting ("B":|[]))
2145 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.eur $ -1, Amount.usd $ -1 ] }
2146 ])
2147 , "{A+$1 B+$1}" ~:
2148 (snd $ Balance.infer_equilibrium $
2149 Format.Ledger.posting_by_Account
2150 [ (Format.Ledger.posting ("A":|[]))
2151 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2152 , (Format.Ledger.posting ("B":|[]))
2153 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2154 ])
2155 ~?=
2156 (Left
2157 [ Balance.Unit_Sum
2158 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
2159 , Balance.unit_sum_accounts = Data.Map.fromList []}
2160 ])
2161 , "{A+$1 B-$1 B-1€}" ~:
2162 (snd $ Balance.infer_equilibrium $
2163 Format.Ledger.posting_by_Account
2164 [ (Format.Ledger.posting ("A":|[]))
2165 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2166 , (Format.Ledger.posting ("B":|[]))
2167 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -1 ] }
2168 ])
2169 ~?=
2170 (Right $
2171 Format.Ledger.posting_by_Account
2172 [ (Format.Ledger.posting ("A":|[]))
2173 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 1 ] }
2174 , (Format.Ledger.posting ("B":|[]))
2175 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -1 ] }
2176 ])
2177 ]
2178 ]
2179 , "Format" ~: TestList
2180 [ "Ledger" ~: TestList
2181 [ "Read" ~: TestList
2182 [ "account_name" ~: TestList
2183 [ "\"\"" ~:
2184 (Data.Either.rights $
2185 [P.runParser
2186 (Format.Ledger.Read.account_name <* P.eof)
2187 () "" (""::Text)])
2188 ~?=
2189 []
2190 , "\"A\"" ~:
2191 (Data.Either.rights $
2192 [P.runParser
2193 (Format.Ledger.Read.account_name <* P.eof)
2194 () "" ("A"::Text)])
2195 ~?=
2196 ["A"]
2197 , "\"AA\"" ~:
2198 (Data.Either.rights $
2199 [P.runParser
2200 (Format.Ledger.Read.account_name <* P.eof)
2201 () "" ("AA"::Text)])
2202 ~?=
2203 ["AA"]
2204 , "\" \"" ~:
2205 (Data.Either.rights $
2206 [P.runParser
2207 (Format.Ledger.Read.account_name <* P.eof)
2208 () "" (" "::Text)])
2209 ~?=
2210 []
2211 , "\":\"" ~:
2212 (Data.Either.rights $
2213 [P.runParser
2214 (Format.Ledger.Read.account_name <* P.eof)
2215 () "" (":"::Text)])
2216 ~?=
2217 []
2218 , "\"A:\"" ~:
2219 (Data.Either.rights $
2220 [P.runParser
2221 (Format.Ledger.Read.account_name <* P.eof)
2222 () "" ("A:"::Text)])
2223 ~?=
2224 []
2225 , "\":A\"" ~:
2226 (Data.Either.rights $
2227 [P.runParser
2228 (Format.Ledger.Read.account_name <* P.eof)
2229 () "" (":A"::Text)])
2230 ~?=
2231 []
2232 , "\"A \"" ~:
2233 (Data.Either.rights $
2234 [P.runParser
2235 (Format.Ledger.Read.account_name <* P.eof)
2236 () "" ("A "::Text)])
2237 ~?=
2238 []
2239 , "\"A \"" ~:
2240 (Data.Either.rights $
2241 [P.runParser
2242 (Format.Ledger.Read.account_name)
2243 () "" ("A "::Text)])
2244 ~?=
2245 ["A"]
2246 , "\"A A\"" ~:
2247 (Data.Either.rights $
2248 [P.runParser
2249 (Format.Ledger.Read.account_name <* P.eof)
2250 () "" ("A A"::Text)])
2251 ~?=
2252 ["A A"]
2253 , "\"A \"" ~:
2254 (Data.Either.rights $
2255 [P.runParser
2256 (Format.Ledger.Read.account_name <* P.eof)
2257 () "" ("A "::Text)])
2258 ~?=
2259 []
2260 , "\"A \\n\"" ~:
2261 (Data.Either.rights $
2262 [P.runParser
2263 (Format.Ledger.Read.account_name <* P.eof)
2264 () "" ("A \n"::Text)])
2265 ~?=
2266 []
2267 , "\"(A)A\"" ~:
2268 (Data.Either.rights $
2269 [P.runParser
2270 (Format.Ledger.Read.account_name <* P.eof)
2271 () "" ("(A)A"::Text)])
2272 ~?=
2273 ["(A)A"]
2274 , "\"( )A\"" ~:
2275 (Data.Either.rights $
2276 [P.runParser
2277 (Format.Ledger.Read.account_name <* P.eof)
2278 () "" ("( )A"::Text)])
2279 ~?=
2280 ["( )A"]
2281 , "\"(A) A\"" ~:
2282 (Data.Either.rights $
2283 [P.runParser
2284 (Format.Ledger.Read.account_name <* P.eof)
2285 () "" ("(A) A"::Text)])
2286 ~?=
2287 ["(A) A"]
2288 , "\"[ ]A\"" ~:
2289 (Data.Either.rights $
2290 [P.runParser
2291 (Format.Ledger.Read.account_name <* P.eof)
2292 () "" ("[ ]A"::Text)])
2293 ~?=
2294 ["[ ]A"]
2295 , "\"(A) \"" ~:
2296 (Data.Either.rights $
2297 [P.runParser
2298 (Format.Ledger.Read.account_name <* P.eof)
2299 () "" ("(A) "::Text)])
2300 ~?=
2301 []
2302 , "\"(A)\"" ~:
2303 (Data.Either.rights $
2304 [P.runParser
2305 (Format.Ledger.Read.account_name <* P.eof)
2306 () "" ("(A)"::Text)])
2307 ~?=
2308 ["(A)"]
2309 , "\"A(A)\"" ~:
2310 (Data.Either.rights $
2311 [P.runParser
2312 (Format.Ledger.Read.account_name <* P.eof)
2313 () "" ("A(A)"::Text)])
2314 ~?=
2315 [("A(A)"::Text)]
2316 , "\"[A]A\"" ~:
2317 (Data.Either.rights $
2318 [P.runParser
2319 (Format.Ledger.Read.account_name <* P.eof)
2320 () "" ("[A]A"::Text)])
2321 ~?=
2322 ["[A]A"]
2323 , "\"[A] A\"" ~:
2324 (Data.Either.rights $
2325 [P.runParser
2326 (Format.Ledger.Read.account_name <* P.eof)
2327 () "" ("[A] A"::Text)])
2328 ~?=
2329 ["[A] A"]
2330 , "\"[A] \"" ~:
2331 (Data.Either.rights $
2332 [P.runParser
2333 (Format.Ledger.Read.account_name <* P.eof)
2334 () "" ("[A] "::Text)])
2335 ~?=
2336 []
2337 , "\"[A]\"" ~:
2338 (Data.Either.rights $
2339 [P.runParser
2340 (Format.Ledger.Read.account_name <* P.eof)
2341 () "" ("[A]"::Text)])
2342 ~?=
2343 ["[A]"]
2344 ]
2345 , "account" ~: TestList
2346 [ "\"\"" ~:
2347 (Data.Either.rights $
2348 [P.runParser
2349 (Format.Ledger.Read.account <* P.eof)
2350 () "" (""::Text)])
2351 ~?=
2352 []
2353 , "\"A\"" ~:
2354 (Data.Either.rights $
2355 [P.runParser
2356 (Format.Ledger.Read.account <* P.eof)
2357 () "" ("A"::Text)])
2358 ~?=
2359 ["A":|[]]
2360 , "\"A:\"" ~:
2361 (Data.Either.rights $
2362 [P.runParser
2363 (Format.Ledger.Read.account <* P.eof)
2364 () "" ("A:"::Text)])
2365 ~?=
2366 []
2367 , "\":A\"" ~:
2368 (Data.Either.rights $
2369 [P.runParser
2370 (Format.Ledger.Read.account <* P.eof)
2371 () "" (":A"::Text)])
2372 ~?=
2373 []
2374 , "\"A \"" ~:
2375 (Data.Either.rights $
2376 [P.runParser
2377 (Format.Ledger.Read.account <* P.eof)
2378 () "" ("A "::Text)])
2379 ~?=
2380 []
2381 , "\" A\"" ~:
2382 (Data.Either.rights $
2383 [P.runParser
2384 (Format.Ledger.Read.account <* P.eof)
2385 () "" (" A"::Text)])
2386 ~?=
2387 []
2388 , "\"A:B\"" ~:
2389 (Data.Either.rights $
2390 [P.runParser
2391 (Format.Ledger.Read.account <* P.eof)
2392 () "" ("A:B"::Text)])
2393 ~?=
2394 ["A":|["B"]]
2395 , "\"A:B:C\"" ~:
2396 (Data.Either.rights $
2397 [P.runParser
2398 (Format.Ledger.Read.account <* P.eof)
2399 () "" ("A:B:C"::Text)])
2400 ~?=
2401 ["A":|["B", "C"]]
2402 , "\"Aa:Bbb:Cccc\"" ~:
2403 (Data.Either.rights $
2404 [P.runParser
2405 (Format.Ledger.Read.account <* P.eof)
2406 () "" ("Aa:Bbb:Cccc"::Text)])
2407 ~?=
2408 ["Aa":|["Bbb", "Cccc"]]
2409 , "\"A a : B b b : C c c c\"" ~:
2410 (Data.Either.rights $
2411 [P.runParser
2412 (Format.Ledger.Read.account <* P.eof)
2413 () "" ("A a : B b b : C c c c"::Text)])
2414 ~?=
2415 ["A a ":|[" B b b ", " C c c c"]]
2416 , "\"A: :C\"" ~:
2417 (Data.Either.rights $
2418 [P.runParser
2419 (Format.Ledger.Read.account <* P.eof)
2420 () "" ("A: :C"::Text)])
2421 ~?=
2422 ["A":|[" ", "C"]]
2423 , "\"A::C\"" ~:
2424 (Data.Either.rights $
2425 [P.runParser
2426 (Format.Ledger.Read.account <* P.eof)
2427 () "" ("A::C"::Text)])
2428 ~?=
2429 []
2430 , "\"A:B:(C)\"" ~:
2431 (Data.Either.rights $
2432 [P.runParser
2433 (Format.Ledger.Read.account <* P.eof)
2434 () "" ("A:B:(C)"::Text)])
2435 ~?=
2436 ["A":|["B", "(C)"]]
2437 ]
2438 , "posting_type" ~: TestList
2439 [ "A" ~:
2440 Format.Ledger.Read.posting_type
2441 ("A":|[])
2442 ~?=
2443 (Format.Ledger.Posting_Type_Regular, "A":|[])
2444 , "(" ~:
2445 Format.Ledger.Read.posting_type
2446 ("(":|[])
2447 ~?=
2448 (Format.Ledger.Posting_Type_Regular, "(":|[])
2449 , ")" ~:
2450 Format.Ledger.Read.posting_type
2451 (")":|[])
2452 ~?=
2453 (Format.Ledger.Posting_Type_Regular, ")":|[])
2454 , "()" ~:
2455 Format.Ledger.Read.posting_type
2456 ("()":|[])
2457 ~?=
2458 (Format.Ledger.Posting_Type_Regular, "()":|[])
2459 , "( )" ~:
2460 Format.Ledger.Read.posting_type
2461 ("( )":|[])
2462 ~?=
2463 (Format.Ledger.Posting_Type_Regular, "( )":|[])
2464 , "(A)" ~:
2465 Format.Ledger.Read.posting_type
2466 ("(A)":|[])
2467 ~?=
2468 (Format.Ledger.Posting_Type_Virtual, "A":|[])
2469 , "(A:B:C)" ~:
2470 Format.Ledger.Read.posting_type
2471 ("(A":|["B", "C)"])
2472 ~?=
2473 (Format.Ledger.Posting_Type_Virtual, "A":|["B", "C"])
2474 , "A:B:C" ~:
2475 Format.Ledger.Read.posting_type
2476 ("A":|["B", "C"])
2477 ~?=
2478 (Format.Ledger.Posting_Type_Regular, "A":|["B", "C"])
2479 , "(A):B:C" ~:
2480 Format.Ledger.Read.posting_type
2481 ("(A)":|["B", "C"])
2482 ~?=
2483 (Format.Ledger.Posting_Type_Regular, "(A)":|["B", "C"])
2484 , "A:(B):C" ~:
2485 Format.Ledger.Read.posting_type
2486 ("A":|["(B)", "C"])
2487 ~?=
2488 (Format.Ledger.Posting_Type_Regular, "A":|["(B)", "C"])
2489 , "A:B:(C)" ~:
2490 Format.Ledger.Read.posting_type
2491 ("A":|["B", "(C)"])
2492 ~?=
2493 (Format.Ledger.Posting_Type_Regular, "A":|["B", "(C)"])
2494 , "[" ~:
2495 Format.Ledger.Read.posting_type
2496 ("[":|[])
2497 ~?=
2498 (Format.Ledger.Posting_Type_Regular, "[":|[])
2499 , "]" ~:
2500 Format.Ledger.Read.posting_type
2501 ("]":|[])
2502 ~?=
2503 (Format.Ledger.Posting_Type_Regular, "]":|[])
2504 , "[]" ~:
2505 Format.Ledger.Read.posting_type
2506 ("[]":|[])
2507 ~?=
2508 (Format.Ledger.Posting_Type_Regular, "[]":|[])
2509 , "[ ]" ~:
2510 Format.Ledger.Read.posting_type
2511 ("[ ]":|[])
2512 ~?=
2513 (Format.Ledger.Posting_Type_Regular, "[ ]":|[])
2514 , "[A]" ~:
2515 Format.Ledger.Read.posting_type
2516 ("[A]":|[])
2517 ~?=
2518 (Format.Ledger.Posting_Type_Virtual_Balanced, "A":|[])
2519 , "[A:B:C]" ~:
2520 Format.Ledger.Read.posting_type
2521 ("[A":|["B", "C]"])
2522 ~?=
2523 (Format.Ledger.Posting_Type_Virtual_Balanced, "A":|["B", "C"])
2524 , "A:B:C" ~:
2525 Format.Ledger.Read.posting_type
2526 ("A":|["B", "C"])
2527 ~?=
2528 (Format.Ledger.Posting_Type_Regular, "A":|["B", "C"])
2529 , "[A]:B:C" ~:
2530 Format.Ledger.Read.posting_type
2531 ("[A]":|["B", "C"])
2532 ~?=
2533 (Format.Ledger.Posting_Type_Regular, "[A]":|["B", "C"])
2534 , "A:[B]:C" ~:
2535 Format.Ledger.Read.posting_type
2536 ("A":|["[B]", "C"])
2537 ~?=
2538 (Format.Ledger.Posting_Type_Regular, "A":|["[B]", "C"])
2539 , "A:B:[C]" ~:
2540 Format.Ledger.Read.posting_type
2541 ("A":|["B", "[C]"])
2542 ~?=
2543 (Format.Ledger.Posting_Type_Regular, "A":|["B", "[C]"])
2544 ]
2545 , "comment" ~: TestList
2546 [ "; some comment = Right \" some comment\"" ~:
2547 (Data.Either.rights $
2548 [P.runParser
2549 (Format.Ledger.Read.comment <* P.eof)
2550 () "" ("; some comment"::Text)])
2551 ~?=
2552 [ " some comment" ]
2553 , "; some comment \\n = Right \" some comment \"" ~:
2554 (Data.Either.rights $
2555 [P.runParser
2556 (Format.Ledger.Read.comment <* P.newline <* P.eof)
2557 () "" ("; some comment \n"::Text)])
2558 ~?=
2559 [ " some comment " ]
2560 , "; some comment \\r\\n = Right \" some comment \"" ~:
2561 (Data.Either.rights $
2562 [P.runParser
2563 (Format.Ledger.Read.comment <* P.string "\r\n" <* P.eof)
2564 () "" ("; some comment \r\n"::Text)])
2565 ~?=
2566 [ " some comment " ]
2567 ]
2568 , "comments" ~: TestList
2569 [ "; some comment\\n ; some other comment = Right [\" some comment\", \" some other comment\"]" ~:
2570 (Data.Either.rights $
2571 [P.runParser
2572 (Format.Ledger.Read.comments <* P.eof)
2573 () "" ("; some comment\n ; some other comment"::Text)])
2574 ~?=
2575 [ [" some comment", " some other comment"] ]
2576 , "; some comment \\n = Right \" some comment \"" ~:
2577 (Data.Either.rights $
2578 [P.runParser
2579 (Format.Ledger.Read.comments <* P.string "\n" <* P.eof)
2580 () "" ("; some comment \n"::Text)])
2581 ~?=
2582 [ [" some comment "] ]
2583 ]
2584 , "tag_value" ~: TestList
2585 [ "," ~:
2586 (Data.Either.rights $
2587 [P.runParser
2588 (Format.Ledger.Read.tag_value <* P.eof)
2589 () "" (","::Text)])
2590 ~?=
2591 [","]
2592 , ",\\n" ~:
2593 (Data.Either.rights $
2594 [P.runParser
2595 (Format.Ledger.Read.tag_value <* P.char '\n' <* P.eof)
2596 () "" (",\n"::Text)])
2597 ~?=
2598 [","]
2599 , ",x" ~:
2600 (Data.Either.rights $
2601 [P.runParser
2602 (Format.Ledger.Read.tag_value <* P.eof)
2603 () "" (",x"::Text)])
2604 ~?=
2605 [",x"]
2606 , ",x:" ~:
2607 (Data.Either.rights $
2608 [P.runParser
2609 (Format.Ledger.Read.tag_value <* P.string ",x:" <* P.eof)
2610 () "" (",x:"::Text)])
2611 ~?=
2612 [""]
2613 , "v, v, n:" ~:
2614 (Data.Either.rights $
2615 [P.runParser
2616 (Format.Ledger.Read.tag_value <* P.string ", n:" <* P.eof)
2617 () "" ("v, v, n:"::Text)])
2618 ~?=
2619 ["v, v"]
2620 ]
2621 , "tag" ~: TestList
2622 [ "Name:" ~:
2623 (Data.Either.rights $
2624 [P.runParser
2625 (Format.Ledger.Read.tag <* P.eof)
2626 () "" ("Name:"::Text)])
2627 ~?=
2628 [("Name", "")]
2629 , "Name:Value" ~:
2630 (Data.Either.rights $
2631 [P.runParser
2632 (Format.Ledger.Read.tag <* P.eof)
2633 () "" ("Name:Value"::Text)])
2634 ~?=
2635 [("Name", "Value")]
2636 , "Name:Value\\n" ~:
2637 (Data.Either.rights $
2638 [P.runParser
2639 (Format.Ledger.Read.tag <* P.string "\n" <* P.eof)
2640 () "" ("Name:Value\n"::Text)])
2641 ~?=
2642 [("Name", "Value")]
2643 , "Name:Val ue" ~:
2644 (Data.Either.rights $
2645 [P.runParser
2646 (Format.Ledger.Read.tag <* P.eof)
2647 () "" ("Name:Val ue"::Text)])
2648 ~?=
2649 [("Name", "Val ue")]
2650 , "Name:," ~:
2651 (Data.Either.rights $
2652 [P.runParser
2653 (Format.Ledger.Read.tag <* P.eof)
2654 () "" ("Name:,"::Text)])
2655 ~?=
2656 [("Name", ",")]
2657 , "Name:Val,ue" ~:
2658 (Data.Either.rights $
2659 [P.runParser
2660 (Format.Ledger.Read.tag <* P.eof)
2661 () "" ("Name:Val,ue"::Text)])
2662 ~?=
2663 [("Name", "Val,ue")]
2664 , "Name:Val,ue:" ~:
2665 (Data.Either.rights $
2666 [P.runParser
2667 (Format.Ledger.Read.tag <* P.string ",ue:" <* P.eof)
2668 () "" ("Name:Val,ue:"::Text)])
2669 ~?=
2670 [("Name", "Val")]
2671 ]
2672 , "tags" ~: TestList
2673 [ "Name:" ~:
2674 (Data.Either.rights $
2675 [P.runParser
2676 (Format.Ledger.Read.tags <* P.eof)
2677 () "" ("Name:"::Text)])
2678 ~?=
2679 [Data.Map.fromList
2680 [ ("Name", [""])
2681 ]
2682 ]
2683 , "Name:," ~:
2684 (Data.Either.rights $
2685 [P.runParser
2686 (Format.Ledger.Read.tags <* P.eof)
2687 () "" ("Name:,"::Text)])
2688 ~?=
2689 [Data.Map.fromList
2690 [ ("Name", [","])
2691 ]
2692 ]
2693 , "Name:,Name:" ~:
2694 (Data.Either.rights $
2695 [P.runParser
2696 (Format.Ledger.Read.tags <* P.eof)
2697 () "" ("Name:,Name:"::Text)])
2698 ~?=
2699 [Data.Map.fromList
2700 [ ("Name", ["", ""])
2701 ]
2702 ]
2703 , "Name:,Name2:" ~:
2704 (Data.Either.rights $
2705 [P.runParser
2706 (Format.Ledger.Read.tags <* P.eof)
2707 () "" ("Name:,Name2:"::Text)])
2708 ~?=
2709 [Data.Map.fromList
2710 [ ("Name", [""])
2711 , ("Name2", [""])
2712 ]
2713 ]
2714 , "Name: , Name2:" ~:
2715 (Data.Either.rights $
2716 [P.runParser
2717 (Format.Ledger.Read.tags <* P.eof)
2718 () "" ("Name: , Name2:"::Text)])
2719 ~?=
2720 [Data.Map.fromList
2721 [ ("Name", [" "])
2722 , ("Name2", [""])
2723 ]
2724 ]
2725 , "Name:,Name2:,Name3:" ~:
2726 (Data.Either.rights $
2727 [P.runParser
2728 (Format.Ledger.Read.tags <* P.eof)
2729 () "" ("Name:,Name2:,Name3:"::Text)])
2730 ~?=
2731 [Data.Map.fromList
2732 [ ("Name", [""])
2733 , ("Name2", [""])
2734 , ("Name3", [""])
2735 ]
2736 ]
2737 , "Name:Val ue,Name2:V a l u e,Name3:V al ue" ~:
2738 (Data.Either.rights $
2739 [P.runParser
2740 (Format.Ledger.Read.tags <* P.eof)
2741 () "" ("Name:Val ue,Name2:V a l u e,Name3:V al ue"::Text)])
2742 ~?=
2743 [Data.Map.fromList
2744 [ ("Name", ["Val ue"])
2745 , ("Name2", ["V a l u e"])
2746 , ("Name3", ["V al ue"])
2747 ]
2748 ]
2749 ]
2750 , "posting" ~: TestList
2751 [ " A:B:C = Right A:B:C" ~:
2752 (Data.Either.rights $
2753 [P.runParser_with_Error
2754 (Format.Ledger.Read.posting <* P.eof)
2755 Format.Ledger.Read.nil_Context "" (" A:B:C"::Text)])
2756 ~?=
2757 [ ( (Format.Ledger.posting ("A":|["B", "C"]))
2758 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2759 }
2760 , Format.Ledger.Posting_Type_Regular
2761 )
2762 ]
2763 , " !A:B:C = Right !A:B:C" ~:
2764 (Data.List.map fst $
2765 Data.Either.rights $
2766 [P.runParser_with_Error
2767 (Format.Ledger.Read.posting <* P.eof)
2768 Format.Ledger.Read.nil_Context "" (" !A:B:C"::Text)])
2769 ~?=
2770 [ (Format.Ledger.posting ("A":|["B", "C"]))
2771 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2772 , Format.Ledger.posting_status = True
2773 }
2774 ]
2775 , " *A:B:C = Right *A:B:C" ~:
2776 (Data.List.map fst $
2777 Data.Either.rights $
2778 [P.runParser_with_Error
2779 (Format.Ledger.Read.posting <* P.eof)
2780 Format.Ledger.Read.nil_Context "" (" *A:B:C"::Text)])
2781 ~?=
2782 [ (Format.Ledger.posting ("A":|["B", "C"]))
2783 { Format.Ledger.posting_amounts = Data.Map.fromList []
2784 , Format.Ledger.posting_comments = []
2785 , Format.Ledger.posting_dates = []
2786 , Format.Ledger.posting_status = True
2787 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2788 , Format.Ledger.posting_tags = Data.Map.fromList []
2789 }
2790 ]
2791 , " A:B:C $1 = Right A:B:C $1" ~:
2792 (Data.List.map fst $
2793 Data.Either.rights $
2794 [P.runParser_with_Error
2795 (Format.Ledger.Read.posting <* P.eof)
2796 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
2797 ~?=
2798 [ (Format.Ledger.posting ("A":|["B","C $1"]))
2799 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2800 }
2801 ]
2802 , " A:B:C $1 = Right A:B:C $1" ~:
2803 (Data.List.map fst $
2804 Data.Either.rights $
2805 [P.runParser_with_Error
2806 (Format.Ledger.Read.posting <* P.eof)
2807 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
2808 ~?=
2809 [ (Format.Ledger.posting ("A":|["B", "C"]))
2810 { Format.Ledger.posting_amounts = Data.Map.fromList
2811 [ ("$", Amount.nil
2812 { Amount.quantity = 1
2813 , Amount.style = Amount.Style.nil
2814 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2815 , Amount.Style.unit_spaced = Just False
2816 }
2817 , Amount.unit = "$"
2818 })
2819 ]
2820 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2821 }
2822 ]
2823 , " A:B:C $1 + 1€ = Right A:B:C $1 + 1€" ~:
2824 (Data.List.map fst $
2825 Data.Either.rights $
2826 [P.runParser_with_Error
2827 (Format.Ledger.Read.posting <* P.eof)
2828 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1€"::Text)])
2829 ~?=
2830 [ (Format.Ledger.posting ("A":|["B", "C"]))
2831 { Format.Ledger.posting_amounts = Data.Map.fromList
2832 [ ("$", Amount.nil
2833 { Amount.quantity = 1
2834 , Amount.style = Amount.Style.nil
2835 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2836 , Amount.Style.unit_spaced = Just False
2837 }
2838 , Amount.unit = "$"
2839 })
2840 , ("€", Amount.nil
2841 { Amount.quantity = 1
2842 , Amount.style = Amount.Style.nil
2843 { Amount.Style.unit_side = Just Amount.Style.Side_Right
2844 , Amount.Style.unit_spaced = Just False
2845 }
2846 , Amount.unit = "€"
2847 })
2848 ]
2849 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2850 }
2851 ]
2852 , " A:B:C $1 + 1$ = Right A:B:C $2" ~:
2853 (Data.List.map fst $
2854 Data.Either.rights $
2855 [P.runParser_with_Error
2856 (Format.Ledger.Read.posting <* P.eof)
2857 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$"::Text)])
2858 ~?=
2859 [ (Format.Ledger.posting ("A":|["B", "C"]))
2860 { Format.Ledger.posting_amounts = Data.Map.fromList
2861 [ ("$", Amount.nil
2862 { Amount.quantity = 2
2863 , Amount.style = Amount.Style.nil
2864 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2865 , Amount.Style.unit_spaced = Just False
2866 }
2867 , Amount.unit = "$"
2868 })
2869 ]
2870 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2871 }
2872 ]
2873 , " A:B:C $1 + 1$ + 1$ = Right A:B:C $3" ~:
2874 (Data.List.map fst $
2875 Data.Either.rights $
2876 [P.runParser_with_Error
2877 (Format.Ledger.Read.posting <* P.eof)
2878 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$ + 1$"::Text)])
2879 ~?=
2880 [ (Format.Ledger.posting ("A":|["B", "C"]))
2881 { Format.Ledger.posting_amounts = Data.Map.fromList
2882 [ ("$", Amount.nil
2883 { Amount.quantity = 3
2884 , Amount.style = Amount.Style.nil
2885 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2886 , Amount.Style.unit_spaced = Just False
2887 }
2888 , Amount.unit = "$"
2889 })
2890 ]
2891 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2892 }
2893 ]
2894 , " A:B:C ; some comment = Right A:B:C ; some comment" ~:
2895 (Data.List.map fst $
2896 Data.Either.rights $
2897 [P.runParser_with_Error
2898 (Format.Ledger.Read.posting <* P.eof)
2899 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment"::Text)])
2900 ~?=
2901 [ (Format.Ledger.posting ("A":|["B", "C"]))
2902 { Format.Ledger.posting_amounts = Data.Map.fromList []
2903 , Format.Ledger.posting_comments = [" some comment"]
2904 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2905 }
2906 ]
2907 , " A:B:C ; some comment\\n ; some other comment = Right A:B:C ; some comment\\n ; some other comment" ~:
2908 (Data.List.map fst $
2909 Data.Either.rights $
2910 [P.runParser_with_Error
2911 (Format.Ledger.Read.posting <* P.eof)
2912 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment\n ; some other comment"::Text)])
2913 ~?=
2914 [ (Format.Ledger.posting ("A":|["B", "C"]))
2915 { Format.Ledger.posting_amounts = Data.Map.fromList []
2916 , Format.Ledger.posting_comments = [" some comment", " some other comment"]
2917 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2918 }
2919 ]
2920 , " A:B:C $1 ; some comment = Right A:B:C $1 ; some comment" ~:
2921 (Data.List.map fst $
2922 Data.Either.rights $
2923 [P.runParser_with_Error
2924 (Format.Ledger.Read.posting)
2925 Format.Ledger.Read.nil_Context "" (" A:B:C $1 ; some comment"::Text)])
2926 ~?=
2927 [ (Format.Ledger.posting ("A":|["B", "C"]))
2928 { Format.Ledger.posting_amounts = Data.Map.fromList
2929 [ ("$", Amount.nil
2930 { Amount.quantity = 1
2931 , Amount.style = Amount.Style.nil
2932 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2933 , Amount.Style.unit_spaced = Just False
2934 }
2935 , Amount.unit = "$"
2936 })
2937 ]
2938 , Format.Ledger.posting_comments = [" some comment"]
2939 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2940 }
2941 ]
2942 , " A:B:C ; N:V = Right A:B:C ; N:V" ~:
2943 (Data.List.map fst $
2944 Data.Either.rights $
2945 [P.runParser_with_Error
2946 (Format.Ledger.Read.posting <* P.eof)
2947 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V"::Text)])
2948 ~?=
2949 [ (Format.Ledger.posting ("A":|["B", "C"]))
2950 { Format.Ledger.posting_comments = [" N:V"]
2951 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2952 , Format.Ledger.posting_tags = Data.Map.fromList
2953 [ ("N", ["V"])
2954 ]
2955 }
2956 ]
2957 , " A:B:C ; some comment N:V = Right A:B:C ; some comment N:V" ~:
2958 (Data.List.map fst $
2959 Data.Either.rights $
2960 [P.runParser_with_Error
2961 (Format.Ledger.Read.posting <* P.eof)
2962 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V"::Text)])
2963 ~?=
2964 [ (Format.Ledger.posting ("A":|["B", "C"]))
2965 { Format.Ledger.posting_comments = [" some comment N:V"]
2966 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2967 , Format.Ledger.posting_tags = Data.Map.fromList
2968 [ ("N", ["V"])
2969 ]
2970 }
2971 ]
2972 , " A:B:C ; some comment N:V v, N2:V2 v2 = Right A:B:C ; some comment N:V v, N2:V2 v2" ~:
2973 (Data.List.map fst $
2974 Data.Either.rights $
2975 [P.runParser_with_Error
2976 (Format.Ledger.Read.posting )
2977 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V v, N2:V2 v2"::Text)])
2978 ~?=
2979 [ (Format.Ledger.posting ("A":|["B", "C"]))
2980 { Format.Ledger.posting_comments = [" some comment N:V v, N2:V2 v2"]
2981 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2982 , Format.Ledger.posting_tags = Data.Map.fromList
2983 [ ("N", ["V v"])
2984 , ("N2", ["V2 v2"])
2985 ]
2986 }
2987 ]
2988 , " A:B:C ; N:V\\n ; N:V2 = Right A:B:C ; N:V\\n ; N:V2" ~:
2989 (Data.List.map fst $
2990 Data.Either.rights $
2991 [P.runParser_with_Error
2992 (Format.Ledger.Read.posting <* P.eof)
2993 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N:V2"::Text)])
2994 ~?=
2995 [ (Format.Ledger.posting ("A":|["B", "C"]))
2996 { Format.Ledger.posting_comments = [" N:V", " N:V2"]
2997 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2998 , Format.Ledger.posting_tags = Data.Map.fromList
2999 [ ("N", ["V", "V2"])
3000 ]
3001 }
3002 ]
3003 , " A:B:C ; N:V\\n ; N2:V = Right A:B:C ; N:V\\n ; N2:V" ~:
3004 (Data.List.map fst $
3005 Data.Either.rights $
3006 [P.runParser_with_Error
3007 (Format.Ledger.Read.posting <* P.eof)
3008 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N2:V"::Text)])
3009 ~?=
3010 [ (Format.Ledger.posting ("A":|["B", "C"]))
3011 { Format.Ledger.posting_comments = [" N:V", " N2:V"]
3012 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
3013 , Format.Ledger.posting_tags = Data.Map.fromList
3014 [ ("N", ["V"])
3015 , ("N2", ["V"])
3016 ]
3017 }
3018 ]
3019 , " A:B:C ; date:2001/01/01 = Right A:B:C ; date:2001/01/01" ~:
3020 (Data.List.map fst $
3021 Data.Either.rights $
3022 [P.runParser_with_Error
3023 (Format.Ledger.Read.posting <* P.eof)
3024 Format.Ledger.Read.nil_Context "" (" A:B:C ; date:2001/01/01"::Text)])
3025 ~?=
3026 [ (Format.Ledger.posting ("A":|["B", "C"]))
3027 { Format.Ledger.posting_comments = [" date:2001/01/01"]
3028 , Format.Ledger.posting_dates =
3029 [ Time.zonedTimeToUTC $
3030 Time.ZonedTime
3031 (Time.LocalTime
3032 (Time.fromGregorian 2001 01 01)
3033 (Time.TimeOfDay 0 0 0))
3034 Time.utc
3035 ]
3036 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
3037 , Format.Ledger.posting_tags = Data.Map.fromList
3038 [ ("date", ["2001/01/01"])
3039 ]
3040 }
3041 ]
3042 , " (A:B:C) = Right (A:B:C)" ~:
3043 (Data.Either.rights $
3044 [P.runParser_with_Error
3045 (Format.Ledger.Read.posting <* P.eof)
3046 Format.Ledger.Read.nil_Context "" (" (A:B:C)"::Text)])
3047 ~?=
3048 [ ( (Format.Ledger.posting ("A":|["B", "C"]))
3049 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
3050 }
3051 , Format.Ledger.Posting_Type_Virtual
3052 )
3053 ]
3054 , " [A:B:C] = Right [A:B:C]" ~:
3055 (Data.Either.rights $
3056 [P.runParser_with_Error
3057 (Format.Ledger.Read.posting <* P.eof)
3058 Format.Ledger.Read.nil_Context "" (" [A:B:C]"::Text)])
3059 ~?=
3060 [ ( (Format.Ledger.posting ("A":|["B", "C"]))
3061 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
3062 }
3063 , Format.Ledger.Posting_Type_Virtual_Balanced
3064 )
3065 ]
3066 ]
3067 , "transaction" ~: TestList
3068 [ "2000/01/01 some description\\n A:B:C $1\\n a:b:c" ~:
3069 (Data.Either.rights $
3070 [P.runParser_with_Error
3071 (Format.Ledger.Read.transaction <* P.eof)
3072 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c"::Text)])
3073 ~?=
3074 [ Format.Ledger.transaction
3075 { Format.Ledger.transaction_dates=
3076 ( Time.zonedTimeToUTC $
3077 Time.ZonedTime
3078 (Time.LocalTime
3079 (Time.fromGregorian 2000 01 01)
3080 (Time.TimeOfDay 0 0 0))
3081 (Time.utc)
3082 , [] )
3083 , Format.Ledger.transaction_description="some description"
3084 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3085 [ (Format.Ledger.posting ("A":|["B", "C"]))
3086 { Format.Ledger.posting_amounts = Data.Map.fromList
3087 [ ("$", Amount.nil
3088 { Amount.quantity = 1
3089 , Amount.style = Amount.Style.nil
3090 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3091 , Amount.Style.unit_spaced = Just False
3092 }
3093 , Amount.unit = "$"
3094 })
3095 ]
3096 , Format.Ledger.posting_sourcepos = P.newPos "" 2 1
3097 }
3098 , (Format.Ledger.posting ("a":|["b", "c"]))
3099 { Format.Ledger.posting_amounts = Data.Map.fromList
3100 [ ("$", Amount.nil
3101 { Amount.quantity = -1
3102 , Amount.style = Amount.Style.nil
3103 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3104 , Amount.Style.unit_spaced = Just False
3105 }
3106 , Amount.unit = "$"
3107 })
3108 ]
3109 , Format.Ledger.posting_sourcepos = P.newPos "" 3 1
3110 }
3111 ]
3112 , Format.Ledger.transaction_sourcepos = P.newPos "" 1 1
3113 }
3114 ]
3115 , "2000/01/01 some description\\n A:B:C $1\\n a:b:c\\n" ~:
3116 (Data.Either.rights $
3117 [P.runParser_with_Error
3118 (Format.Ledger.Read.transaction <* P.newline <* P.eof)
3119 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c\n"::Text)])
3120 ~?=
3121 [ Format.Ledger.transaction
3122 { Format.Ledger.transaction_dates=
3123 ( Time.zonedTimeToUTC $
3124 Time.ZonedTime
3125 (Time.LocalTime
3126 (Time.fromGregorian 2000 01 01)
3127 (Time.TimeOfDay 0 0 0))
3128 (Time.utc)
3129 , [] )
3130 , Format.Ledger.transaction_description="some description"
3131 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3132 [ (Format.Ledger.posting ("A":|["B", "C"]))
3133 { Format.Ledger.posting_amounts = Data.Map.fromList
3134 [ ("$", Amount.nil
3135 { Amount.quantity = 1
3136 , Amount.style = Amount.Style.nil
3137 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3138 , Amount.Style.unit_spaced = Just False
3139 }
3140 , Amount.unit = "$"
3141 })
3142 ]
3143 , Format.Ledger.posting_sourcepos = P.newPos "" 2 1
3144 }
3145 , (Format.Ledger.posting ("a":|["b", "c"]))
3146 { Format.Ledger.posting_amounts = Data.Map.fromList
3147 [ ("$", Amount.nil
3148 { Amount.quantity = -1
3149 , Amount.style = Amount.Style.nil
3150 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3151 , Amount.Style.unit_spaced = Just False
3152 }
3153 , Amount.unit = "$"
3154 })
3155 ]
3156 , Format.Ledger.posting_sourcepos = P.newPos "" 3 1
3157 }
3158 ]
3159 , Format.Ledger.transaction_sourcepos = P.newPos "" 1 1
3160 }
3161 ]
3162 , "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" ~:
3163 (Data.Either.rights $
3164 [P.runParser_with_Error
3165 (Format.Ledger.Read.transaction <* P.eof)
3166 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)])
3167 ~?=
3168 [ Format.Ledger.transaction
3169 { Format.Ledger.transaction_comments_after =
3170 [ " some comment"
3171 , " some other;comment"
3172 , " some Tag:"
3173 , " some last comment"
3174 ]
3175 , Format.Ledger.transaction_dates=
3176 ( Time.zonedTimeToUTC $
3177 Time.ZonedTime
3178 (Time.LocalTime
3179 (Time.fromGregorian 2000 01 01)
3180 (Time.TimeOfDay 0 0 0))
3181 (Time.utc)
3182 , [] )
3183 , Format.Ledger.transaction_description="some description"
3184 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3185 [ (Format.Ledger.posting ("A":|["B", "C"]))
3186 { Format.Ledger.posting_amounts = Data.Map.fromList
3187 [ ("$", Amount.nil
3188 { Amount.quantity = 1
3189 , Amount.style = Amount.Style.nil
3190 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3191 , Amount.Style.unit_spaced = Just False
3192 }
3193 , Amount.unit = "$"
3194 })
3195 ]
3196 , Format.Ledger.posting_sourcepos = P.newPos "" 5 1
3197 }
3198 , (Format.Ledger.posting ("a":|["b", "c"]))
3199 { Format.Ledger.posting_amounts = Data.Map.fromList
3200 [ ("$", Amount.nil
3201 { Amount.quantity = -1
3202 , Amount.style = Amount.Style.nil
3203 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3204 , Amount.Style.unit_spaced = Just False
3205 }
3206 , Amount.unit = "$"
3207 })
3208 ]
3209 , Format.Ledger.posting_sourcepos = P.newPos "" 6 1
3210 }
3211 ]
3212 , Format.Ledger.transaction_tags = Data.Map.fromList
3213 [ ("Tag", [""])
3214 ]
3215 , Format.Ledger.transaction_sourcepos = P.newPos "" 1 1
3216 }
3217 ]
3218 ]
3219 , "journal" ~: TestList
3220 [ "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
3221 jnl <- liftIO $
3222 P.runParserT_with_Error
3223 (Format.Ledger.Read.journal "" {-<* P.eof-})
3224 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)
3225 (Data.List.map
3226 (\j -> j{Format.Ledger.journal_last_read_time=
3227 Format.Ledger.journal_last_read_time Format.Ledger.journal}) $
3228 Data.Either.rights [jnl])
3229 @?=
3230 [ Format.Ledger.journal
3231 { Format.Ledger.journal_transactions =
3232 Format.Ledger.transaction_by_Date
3233 [ Format.Ledger.transaction
3234 { Format.Ledger.transaction_dates=
3235 ( Time.zonedTimeToUTC $
3236 Time.ZonedTime
3237 (Time.LocalTime
3238 (Time.fromGregorian 2000 01 01)
3239 (Time.TimeOfDay 0 0 0))
3240 (Time.utc)
3241 , [] )
3242 , Format.Ledger.transaction_description="1° description"
3243 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3244 [ (Format.Ledger.posting ("A":|["B", "C"]))
3245 { Format.Ledger.posting_amounts = Data.Map.fromList
3246 [ ("$", Amount.nil
3247 { Amount.quantity = 1
3248 , Amount.style = Amount.Style.nil
3249 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3250 , Amount.Style.unit_spaced = Just False
3251 }
3252 , Amount.unit = "$"
3253 })
3254 ]
3255 , Format.Ledger.posting_sourcepos = P.newPos "" 2 1
3256 }
3257 , (Format.Ledger.posting ("a":|["b", "c"]))
3258 { Format.Ledger.posting_amounts = Data.Map.fromList
3259 [ ("$", Amount.nil
3260 { Amount.quantity = -1
3261 , Amount.style = Amount.Style.nil
3262 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3263 , Amount.Style.unit_spaced = Just False
3264 }
3265 , Amount.unit = "$"
3266 })
3267 ]
3268 , Format.Ledger.posting_sourcepos = P.newPos "" 3 1
3269 }
3270 ]
3271 , Format.Ledger.transaction_sourcepos = P.newPos "" 1 1
3272 }
3273 , Format.Ledger.transaction
3274 { Format.Ledger.transaction_dates=
3275 ( Time.zonedTimeToUTC $
3276 Time.ZonedTime
3277 (Time.LocalTime
3278 (Time.fromGregorian 2000 01 02)
3279 (Time.TimeOfDay 0 0 0))
3280 (Time.utc)
3281 , [] )
3282 , Format.Ledger.transaction_description="2° description"
3283 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3284 [ (Format.Ledger.posting ("A":|["B", "C"]))
3285 { Format.Ledger.posting_amounts = Data.Map.fromList
3286 [ ("$", Amount.nil
3287 { Amount.quantity = 1
3288 , Amount.style = Amount.Style.nil
3289 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3290 , Amount.Style.unit_spaced = Just False
3291 }
3292 , Amount.unit = "$"
3293 })
3294 ]
3295 , Format.Ledger.posting_sourcepos = P.newPos "" 5 1
3296 }
3297 , (Format.Ledger.posting ("x":|["y", "z"]))
3298 { Format.Ledger.posting_amounts = Data.Map.fromList
3299 [ ("$", Amount.nil
3300 { Amount.quantity = -1
3301 , Amount.style = Amount.Style.nil
3302 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3303 , Amount.Style.unit_spaced = Just False
3304 }
3305 , Amount.unit = "$"
3306 })
3307 ]
3308 , Format.Ledger.posting_sourcepos = P.newPos "" 6 1
3309 }
3310 ]
3311 , Format.Ledger.transaction_sourcepos = P.newPos "" 4 1
3312 }
3313 ]
3314 }
3315 ]
3316 ]
3317 ]
3318 , "Write" ~: TestList
3319 [ "account" ~: TestList
3320 [ "A" ~:
3321 ((Format.Ledger.Write.show
3322 Format.Ledger.Write.Style
3323 { Format.Ledger.Write.style_color=False
3324 , Format.Ledger.Write.style_align=True
3325 } $
3326 Format.Ledger.Write.account Format.Ledger.Posting_Type_Regular $
3327 "A":|[])
3328 ~?=
3329 "A")
3330 , "A:B:C" ~:
3331 ((Format.Ledger.Write.show
3332 Format.Ledger.Write.Style
3333 { Format.Ledger.Write.style_color=False
3334 , Format.Ledger.Write.style_align=True
3335 } $
3336 Format.Ledger.Write.account Format.Ledger.Posting_Type_Regular $
3337 "A":|["B", "C"])
3338 ~?=
3339 "A:B:C")
3340 , "(A:B:C)" ~:
3341 ((Format.Ledger.Write.show
3342 Format.Ledger.Write.Style
3343 { Format.Ledger.Write.style_color=False
3344 , Format.Ledger.Write.style_align=True
3345 } $
3346 Format.Ledger.Write.account Format.Ledger.Posting_Type_Virtual $
3347 "A":|["B", "C"])
3348 ~?=
3349 "(A:B:C)")
3350 , "[A:B:C]" ~:
3351 ((Format.Ledger.Write.show
3352 Format.Ledger.Write.Style
3353 { Format.Ledger.Write.style_color=False
3354 , Format.Ledger.Write.style_align=True
3355 } $
3356 Format.Ledger.Write.account Format.Ledger.Posting_Type_Virtual_Balanced $
3357 "A":|["B", "C"])
3358 ~?=
3359 "[A:B:C]")
3360 ]
3361 , "amount" ~: TestList
3362 [ "nil" ~:
3363 ((Format.Ledger.Write.show
3364 Format.Ledger.Write.Style
3365 { Format.Ledger.Write.style_color=False
3366 , Format.Ledger.Write.style_align=True
3367 } $
3368 Format.Ledger.Write.amount
3369 Amount.nil)
3370 ~?=
3371 "0")
3372 , "nil @ prec=2" ~:
3373 ((Format.Ledger.Write.show
3374 Format.Ledger.Write.Style
3375 { Format.Ledger.Write.style_color=False
3376 , Format.Ledger.Write.style_align=True
3377 } $
3378 Format.Ledger.Write.amount
3379 Amount.nil
3380 { Amount.style = Amount.Style.nil
3381 { Amount.Style.precision = 2 }
3382 })
3383 ~?=
3384 "0.00")
3385 , "123" ~:
3386 ((Format.Ledger.Write.show
3387 Format.Ledger.Write.Style
3388 { Format.Ledger.Write.style_color=False
3389 , Format.Ledger.Write.style_align=True
3390 } $
3391 Format.Ledger.Write.amount
3392 Amount.nil
3393 { Amount.quantity = Decimal 0 123
3394 })
3395 ~?=
3396 "123")
3397 , "-123" ~:
3398 ((Format.Ledger.Write.show
3399 Format.Ledger.Write.Style
3400 { Format.Ledger.Write.style_color=False
3401 , Format.Ledger.Write.style_align=True
3402 } $
3403 Format.Ledger.Write.amount
3404 Amount.nil
3405 { Amount.quantity = Decimal 0 (- 123)
3406 })
3407 ~?=
3408 "-123")
3409 , "12.3 @ prec=0" ~:
3410 ((Format.Ledger.Write.show
3411 Format.Ledger.Write.Style
3412 { Format.Ledger.Write.style_color=False
3413 , Format.Ledger.Write.style_align=True
3414 } $
3415 Format.Ledger.Write.amount
3416 Amount.nil
3417 { Amount.quantity = Decimal 1 123
3418 , Amount.style = Amount.Style.nil
3419 { Amount.Style.fractioning = Just '.'
3420 }
3421 })
3422 ~?=
3423 "12")
3424 , "12.5 @ prec=0" ~:
3425 ((Format.Ledger.Write.show
3426 Format.Ledger.Write.Style
3427 { Format.Ledger.Write.style_color=False
3428 , Format.Ledger.Write.style_align=True
3429 } $
3430 Format.Ledger.Write.amount
3431 Amount.nil
3432 { Amount.quantity = Decimal 1 125
3433 , Amount.style = Amount.Style.nil
3434 { Amount.Style.fractioning = Just '.'
3435 }
3436 })
3437 ~?=
3438 "13")
3439 , "12.3 @ prec=1" ~:
3440 ((Format.Ledger.Write.show
3441 Format.Ledger.Write.Style
3442 { Format.Ledger.Write.style_color=False
3443 , Format.Ledger.Write.style_align=True
3444 } $
3445 Format.Ledger.Write.amount
3446 Amount.nil
3447 { Amount.quantity = Decimal 1 123
3448 , Amount.style = Amount.Style.nil
3449 { Amount.Style.fractioning = Just '.'
3450 , Amount.Style.precision = 1
3451 }
3452 })
3453 ~?=
3454 "12.3")
3455 , "1,234.56 @ prec=2" ~:
3456 ((Format.Ledger.Write.show
3457 Format.Ledger.Write.Style
3458 { Format.Ledger.Write.style_color=False
3459 , Format.Ledger.Write.style_align=True
3460 } $
3461 Format.Ledger.Write.amount
3462 Amount.nil
3463 { Amount.quantity = Decimal 2 123456
3464 , Amount.style = Amount.Style.nil
3465 { Amount.Style.fractioning = Just '.'
3466 , Amount.Style.precision = 2
3467 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
3468 }
3469 })
3470 ~?=
3471 "1,234.56")
3472 , "123,456,789,01,2.3456789 @ prec=7" ~:
3473 ((Format.Ledger.Write.show
3474 Format.Ledger.Write.Style
3475 { Format.Ledger.Write.style_color=False
3476 , Format.Ledger.Write.style_align=True
3477 } $
3478 Format.Ledger.Write.amount
3479 Amount.nil
3480 { Amount.quantity = Decimal 7 1234567890123456789
3481 , Amount.style = Amount.Style.nil
3482 { Amount.Style.fractioning = Just '.'
3483 , Amount.Style.precision = 7
3484 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3485 }
3486 })
3487 ~?=
3488 "123,456,789,01,2.3456789")
3489 , "1234567.8,90,123,456,789 @ prec=12" ~:
3490 ((Format.Ledger.Write.show
3491 Format.Ledger.Write.Style
3492 { Format.Ledger.Write.style_color=False
3493 , Format.Ledger.Write.style_align=True
3494 } $
3495 Format.Ledger.Write.amount
3496 Amount.nil
3497 { Amount.quantity = Decimal 12 1234567890123456789
3498 , Amount.style = Amount.Style.nil
3499 { Amount.Style.fractioning = Just '.'
3500 , Amount.Style.precision = 12
3501 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3502 }
3503 })
3504 ~?=
3505 "1234567.8,90,123,456,789")
3506 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
3507 ((Format.Ledger.Write.show
3508 Format.Ledger.Write.Style
3509 { Format.Ledger.Write.style_color=False
3510 , Format.Ledger.Write.style_align=True
3511 } $
3512 Format.Ledger.Write.amount
3513 Amount.nil
3514 { Amount.quantity = Decimal 7 1234567890123456789
3515 , Amount.style = Amount.Style.nil
3516 { Amount.Style.fractioning = Just '.'
3517 , Amount.Style.precision = 7
3518 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3519 }
3520 })
3521 ~?=
3522 "1,2,3,4,5,6,7,89,012.3456789")
3523 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
3524 ((Format.Ledger.Write.show
3525 Format.Ledger.Write.Style
3526 { Format.Ledger.Write.style_color=False
3527 , Format.Ledger.Write.style_align=True
3528 } $
3529 Format.Ledger.Write.amount
3530 Amount.nil
3531 { Amount.quantity = Decimal 12 1234567890123456789
3532 , Amount.style = Amount.Style.nil
3533 { Amount.Style.fractioning = Just '.'
3534 , Amount.Style.precision = 12
3535 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3536 }
3537 })
3538 ~?=
3539 "1234567.890,12,3,4,5,6,7,8,9")
3540 ]
3541 , "amount_length" ~: TestList
3542 [ "nil" ~:
3543 ((Format.Ledger.Write.amount_length
3544 Amount.nil)
3545 ~?=
3546 1)
3547 , "nil @ prec=2" ~:
3548 ((Format.Ledger.Write.amount_length
3549 Amount.nil
3550 { Amount.style = Amount.Style.nil
3551 { Amount.Style.precision = 2 }
3552 })
3553 ~?=
3554 4)
3555 , "123" ~:
3556 ((Format.Ledger.Write.amount_length
3557 Amount.nil
3558 { Amount.quantity = Decimal 0 123
3559 })
3560 ~?=
3561 3)
3562 , "-123" ~:
3563 ((Format.Ledger.Write.amount_length
3564 Amount.nil
3565 { Amount.quantity = Decimal 0 (- 123)
3566 })
3567 ~?=
3568 4)
3569 , "12.3 @ prec=0" ~:
3570 ((Format.Ledger.Write.amount_length
3571 Amount.nil
3572 { Amount.quantity = Decimal 1 123
3573 , Amount.style = Amount.Style.nil
3574 { Amount.Style.fractioning = Just '.'
3575 }
3576 })
3577 ~?=
3578 2)
3579 , "12.5 @ prec=0" ~:
3580 ((Format.Ledger.Write.amount_length
3581 Amount.nil
3582 { Amount.quantity = Decimal 1 125
3583 , Amount.style = Amount.Style.nil
3584 { Amount.Style.fractioning = Just '.'
3585 }
3586 })
3587 ~?=
3588 2)
3589 , "12.3 @ prec=1" ~:
3590 ((Format.Ledger.Write.amount_length
3591 Amount.nil
3592 { Amount.quantity = Decimal 1 123
3593 , Amount.style = Amount.Style.nil
3594 { Amount.Style.fractioning = Just '.'
3595 , Amount.Style.precision = 1
3596 }
3597 })
3598 ~?=
3599 4)
3600 , "1,234.56 @ prec=2" ~:
3601 ((Format.Ledger.Write.amount_length
3602 Amount.nil
3603 { Amount.quantity = Decimal 2 123456
3604 , Amount.style = Amount.Style.nil
3605 { Amount.Style.fractioning = Just '.'
3606 , Amount.Style.precision = 2
3607 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
3608 }
3609 })
3610 ~?=
3611 8)
3612 , "123,456,789,01,2.3456789 @ prec=7" ~:
3613 ((Format.Ledger.Write.amount_length
3614 Amount.nil
3615 { Amount.quantity = Decimal 7 1234567890123456789
3616 , Amount.style = Amount.Style.nil
3617 { Amount.Style.fractioning = Just '.'
3618 , Amount.Style.precision = 7
3619 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3620 }
3621 })
3622 ~?=
3623 24)
3624 , "1234567.8,90,123,456,789 @ prec=12" ~:
3625 ((Format.Ledger.Write.amount_length
3626 Amount.nil
3627 { Amount.quantity = Decimal 12 1234567890123456789
3628 , Amount.style = Amount.Style.nil
3629 { Amount.Style.fractioning = Just '.'
3630 , Amount.Style.precision = 12
3631 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3632 }
3633 })
3634 ~?=
3635 24)
3636 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
3637 ((Format.Ledger.Write.amount_length
3638 Amount.nil
3639 { Amount.quantity = Decimal 7 1234567890123456789
3640 , Amount.style = Amount.Style.nil
3641 { Amount.Style.fractioning = Just '.'
3642 , Amount.Style.precision = 7
3643 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3644 }
3645 })
3646 ~?=
3647 28)
3648 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
3649 ((Format.Ledger.Write.amount_length
3650 Amount.nil
3651 { Amount.quantity = Decimal 12 1234567890123456789
3652 , Amount.style = Amount.Style.nil
3653 { Amount.Style.fractioning = Just '.'
3654 , Amount.Style.precision = 12
3655 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3656 }
3657 })
3658 ~?=
3659 28)
3660 , "1000000.000,00,0,0,0,0,0,0,0 @ prec=12" ~:
3661 ((Format.Ledger.Write.amount_length
3662 Amount.nil
3663 { Amount.quantity = Decimal 12 1000000000000000000
3664 , Amount.style = Amount.Style.nil
3665 { Amount.Style.fractioning = Just '.'
3666 , Amount.Style.precision = 12
3667 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3668 }
3669 })
3670 ~?=
3671 28)
3672 , "999 @ prec=0" ~:
3673 ((Format.Ledger.Write.amount_length $
3674 Amount.nil
3675 { Amount.quantity = Decimal 0 999
3676 , Amount.style = Amount.Style.nil
3677 { Amount.Style.precision = 0
3678 }
3679 })
3680 ~?=
3681 3)
3682 , "1000 @ prec=0" ~:
3683 ((Format.Ledger.Write.amount_length $
3684 Amount.nil
3685 { Amount.quantity = Decimal 0 1000
3686 , Amount.style = Amount.Style.nil
3687 { Amount.Style.precision = 0
3688 }
3689 })
3690 ~?=
3691 4)
3692 , "10,00€ @ prec=2" ~:
3693 ((Format.Ledger.Write.amount_length $ Amount.eur 10)
3694 ~?=
3695 6)
3696 ]
3697 , "date" ~: TestList
3698 [ "nil" ~:
3699 ((Format.Ledger.Write.show
3700 Format.Ledger.Write.Style
3701 { Format.Ledger.Write.style_color=False
3702 , Format.Ledger.Write.style_align=True
3703 } $
3704 Format.Ledger.Write.date
3705 Date.nil)
3706 ~?=
3707 "1970/01/01")
3708 , "2000/01/01 12:34:51 CET" ~:
3709 (Format.Ledger.Write.show
3710 Format.Ledger.Write.Style
3711 { Format.Ledger.Write.style_color=False
3712 , Format.Ledger.Write.style_align=True
3713 } $
3714 Format.Ledger.Write.date $
3715 Time.zonedTimeToUTC $
3716 Time.ZonedTime
3717 (Time.LocalTime
3718 (Time.fromGregorian 2000 01 01)
3719 (Time.TimeOfDay 12 34 51))
3720 (Time.TimeZone 60 False "CET"))
3721 ~?=
3722 "2000/01/01 11:34:51"
3723 , "2000/01/01 12:34:51 +0100" ~:
3724 (Format.Ledger.Write.show
3725 Format.Ledger.Write.Style
3726 { Format.Ledger.Write.style_color=False
3727 , Format.Ledger.Write.style_align=True
3728 } $
3729 Format.Ledger.Write.date $
3730 Time.zonedTimeToUTC $
3731 Time.ZonedTime
3732 (Time.LocalTime
3733 (Time.fromGregorian 2000 01 01)
3734 (Time.TimeOfDay 12 34 51))
3735 (Time.TimeZone 60 False ""))
3736 ~?=
3737 "2000/01/01 11:34:51"
3738 , "2000/01/01 01:02:03" ~:
3739 (Format.Ledger.Write.show
3740 Format.Ledger.Write.Style
3741 { Format.Ledger.Write.style_color=False
3742 , Format.Ledger.Write.style_align=True
3743 } $
3744 Format.Ledger.Write.date $
3745 Time.zonedTimeToUTC $
3746 Time.ZonedTime
3747 (Time.LocalTime
3748 (Time.fromGregorian 2000 01 01)
3749 (Time.TimeOfDay 1 2 3))
3750 (Time.utc))
3751 ~?=
3752 "2000/01/01 01:02:03"
3753 , "01/01 01:02" ~:
3754 (Format.Ledger.Write.show
3755 Format.Ledger.Write.Style
3756 { Format.Ledger.Write.style_color=False
3757 , Format.Ledger.Write.style_align=True
3758 } $
3759 Format.Ledger.Write.date $
3760 Time.zonedTimeToUTC $
3761 Time.ZonedTime
3762 (Time.LocalTime
3763 (Time.fromGregorian 0 01 01)
3764 (Time.TimeOfDay 1 2 0))
3765 (Time.utc))
3766 ~?=
3767 "01/01 01:02"
3768 , "01/01 01:00" ~:
3769 (Format.Ledger.Write.show
3770 Format.Ledger.Write.Style
3771 { Format.Ledger.Write.style_color=False
3772 , Format.Ledger.Write.style_align=True
3773 } $
3774 Format.Ledger.Write.date $
3775 Time.zonedTimeToUTC $
3776 Time.ZonedTime
3777 (Time.LocalTime
3778 (Time.fromGregorian 0 01 01)
3779 (Time.TimeOfDay 1 0 0))
3780 (Time.utc))
3781 ~?=
3782 "01/01 01:00"
3783 , "01/01 00:01" ~:
3784 (Format.Ledger.Write.show
3785 Format.Ledger.Write.Style
3786 { Format.Ledger.Write.style_color=False
3787 , Format.Ledger.Write.style_align=True
3788 } $
3789 Format.Ledger.Write.date $
3790 Time.zonedTimeToUTC $
3791 Time.ZonedTime
3792 (Time.LocalTime
3793 (Time.fromGregorian 0 01 01)
3794 (Time.TimeOfDay 0 1 0))
3795 (Time.utc))
3796 ~?=
3797 "01/01 00:01"
3798 , "01/01" ~:
3799 (Format.Ledger.Write.show
3800 Format.Ledger.Write.Style
3801 { Format.Ledger.Write.style_color=False
3802 , Format.Ledger.Write.style_align=True
3803 } $
3804 Format.Ledger.Write.date $
3805 Time.zonedTimeToUTC $
3806 Time.ZonedTime
3807 (Time.LocalTime
3808 (Time.fromGregorian 0 01 01)
3809 (Time.TimeOfDay 0 0 0))
3810 (Time.utc))
3811 ~?=
3812 "01/01"
3813 ]
3814 , "transaction" ~: TestList
3815 [ "nil" ~:
3816 ((Format.Ledger.Write.show
3817 Format.Ledger.Write.Style
3818 { Format.Ledger.Write.style_color=False
3819 , Format.Ledger.Write.style_align=True
3820 } $
3821 Format.Ledger.Write.transaction
3822 Format.Ledger.transaction)
3823 ~?=
3824 "1970/01/01\n")
3825 , "2000/01/01 some description\\n\\ta:b:c\\n\\t ; first comment\\n\\t ; second comment\\n\\t ; third comment\\n\\tA:B:C $1" ~:
3826 ((Format.Ledger.Write.show
3827 Format.Ledger.Write.Style
3828 { Format.Ledger.Write.style_color=False
3829 , Format.Ledger.Write.style_align=True
3830 } $
3831 Format.Ledger.Write.transaction $
3832 Format.Ledger.transaction
3833 { Format.Ledger.transaction_dates=
3834 ( Time.zonedTimeToUTC $
3835 Time.ZonedTime
3836 (Time.LocalTime
3837 (Time.fromGregorian 2000 01 01)
3838 (Time.TimeOfDay 0 0 0))
3839 (Time.utc)
3840 , [] )
3841 , Format.Ledger.transaction_description="some description"
3842 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3843 [ (Format.Ledger.posting ("A":|["B", "C"]))
3844 { Format.Ledger.posting_amounts = Data.Map.fromList
3845 [ ("$", Amount.nil
3846 { Amount.quantity = 1
3847 , Amount.style = Amount.Style.nil
3848 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3849 , Amount.Style.unit_spaced = Just False
3850 }
3851 , Amount.unit = "$"
3852 })
3853 ]
3854 }
3855 , (Format.Ledger.posting ("a":|["b", "c"]))
3856 { Format.Ledger.posting_comments = ["first comment","second comment","third comment"]
3857 }
3858 ]
3859 })
3860 ~?=
3861 "2000/01/01 some description\n\ta:b:c\n\t ; first comment\n\t ; second comment\n\t ; third comment\n\tA:B:C $1")
3862 , "2000/01/01 some description\\n\\tA:B:C $1\\n\\tAA:BB:CC $123" ~:
3863 ((Format.Ledger.Write.show
3864 Format.Ledger.Write.Style
3865 { Format.Ledger.Write.style_color=False
3866 , Format.Ledger.Write.style_align=True
3867 } $
3868 Format.Ledger.Write.transaction $
3869 Format.Ledger.transaction
3870 { Format.Ledger.transaction_dates=
3871 ( Time.zonedTimeToUTC $
3872 Time.ZonedTime
3873 (Time.LocalTime
3874 (Time.fromGregorian 2000 01 01)
3875 (Time.TimeOfDay 0 0 0))
3876 (Time.utc)
3877 , [] )
3878 , Format.Ledger.transaction_description="some description"
3879 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3880 [ (Format.Ledger.posting ("A":|["B", "C"]))
3881 { Format.Ledger.posting_amounts = Data.Map.fromList
3882 [ ("$", Amount.nil
3883 { Amount.quantity = 1
3884 , Amount.style = Amount.Style.nil
3885 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3886 , Amount.Style.unit_spaced = Just False
3887 }
3888 , Amount.unit = "$"
3889 })
3890 ]
3891 }
3892 , (Format.Ledger.posting ("AA":|["BB", "CC"]))
3893 { Format.Ledger.posting_amounts = Data.Map.fromList
3894 [ ("$", Amount.nil
3895 { Amount.quantity = 123
3896 , Amount.style = Amount.Style.nil
3897 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3898 , Amount.Style.unit_spaced = Just False
3899 }
3900 , Amount.unit = "$"
3901 })
3902 ]
3903 }
3904 ]
3905 })
3906 ~?=
3907 "2000/01/01 some description\n\tA:B:C $1\n\tAA:BB:CC $123")
3908 ]
3909 ]
3910 ]
3911 ]
3912 ]