]> Git — Sourcephile - comptalang.git/blob - lib/Test/Main.hs
Modif : Balance : inutile de mettre amount_sum_balance dans Amount_Sum.
[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_Both
1209 (Amount.usd $ -1)
1210 (Amount.usd $ 1)
1211 ]
1212 ) ]
1213 , Balance.balance_by_unit =
1214 Data.Map.fromList $
1215 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1216 [ Balance.Unit_Sum
1217 { Balance.unit_sum_amount = Balance.Amount_Sum_Both
1218 (Amount.usd $ -1)
1219 (Amount.usd $ 1)
1220 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1221 ["A":|[]]
1222 }
1223 ]
1224 }
1225 , "[A+$1, A-€1] = {A+$1-€1, $+1 €-1}" ~:
1226 (Data.List.foldl
1227 (flip Balance.balance)
1228 Balance.nil
1229 [ (Format.Ledger.posting ("A":|[]))
1230 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1231 }
1232 , (Format.Ledger.posting ("A":|[]))
1233 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.eur $ -1 ]
1234 }
1235 ])
1236 ~?=
1237 Balance.Balance
1238 { Balance.balance_by_account =
1239 Lib.TreeMap.from_List const $
1240 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1241 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ -1 ]) ]
1242 , Balance.balance_by_unit =
1243 Data.Map.fromList $
1244 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1245 [ Balance.Unit_Sum
1246 { Balance.unit_sum_amount = Balance.Amount_Sum_Positive (Amount.usd $ 1)
1247 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1248 ["A":|[]]
1249 }
1250 , Balance.Unit_Sum
1251 { Balance.unit_sum_amount = Balance.Amount_Sum_Negative (Amount.eur $ -1)
1252 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1253 ["A":|[]]
1254 }
1255 ]
1256 }
1257 , "[A+$1, B-$1] = {A+$1 B-$1, $+0}" ~:
1258 (Data.List.foldl
1259 (flip Balance.balance)
1260 Balance.nil
1261 [ (Format.Ledger.posting ("A":|[]))
1262 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1263 }
1264 , (Format.Ledger.posting ("B":|[]))
1265 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1 ]
1266 }
1267 ])
1268 ~?=
1269 Balance.Balance
1270 { Balance.balance_by_account =
1271 Lib.TreeMap.from_List const $
1272 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1273 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1274 , ("B":|[], Amount.from_List [ Amount.usd $ -1 ])
1275 ]
1276 , Balance.balance_by_unit =
1277 Data.Map.fromList $
1278 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1279 [ Balance.Unit_Sum
1280 { Balance.unit_sum_amount = Balance.Amount_Sum_Both
1281 (Amount.usd $ -1)
1282 (Amount.usd $ 1)
1283 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1284 ["A":|[], "B":|[]]
1285 }
1286 ]
1287 }
1288 , "[A+$1, B+$1]" ~:
1289 (Data.List.foldl
1290 (flip Balance.balance)
1291 Balance.nil
1292 [ (Format.Ledger.posting ("A":|[]))
1293 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1294 }
1295 , (Format.Ledger.posting ("B":|[]))
1296 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ]
1297 }
1298 ])
1299 ~?=
1300 Balance.Balance
1301 { Balance.balance_by_account =
1302 Lib.TreeMap.from_List const $
1303 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1304 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1305 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ])
1306 ]
1307 , Balance.balance_by_unit =
1308 Data.Map.fromList $
1309 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1310 [ Balance.Unit_Sum
1311 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1312 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1313 ["A":|[], "B":|[]]
1314 }
1315 ]
1316 }
1317 , "[A+$1+€2, A-$1-€2] = {A+$0+€0, $+0 €+0}" ~:
1318 (Data.List.foldl
1319 (flip Balance.balance)
1320 Balance.nil
1321 [ (Format.Ledger.posting ("A":|[]))
1322 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2 ]
1323 }
1324 , (Format.Ledger.posting ("A":|[]))
1325 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2 ]
1326 }
1327 ])
1328 ~?=
1329 Balance.Balance
1330 { Balance.balance_by_account =
1331 Lib.TreeMap.from_List const $
1332 [ ("A":|[]
1333 , Data.Map.fromListWith const $
1334 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance s, s))
1335 [ Balance.Amount_Sum_Both (Amount.usd $ -1) (Amount.usd $ 1)
1336 , Balance.Amount_Sum_Both (Amount.eur $ -2) (Amount.eur $ 2)
1337 ]
1338 )
1339 ]
1340 , Balance.balance_by_unit =
1341 Data.Map.fromList $
1342 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1343 [ Balance.Unit_Sum
1344 { Balance.unit_sum_amount = Balance.Amount_Sum_Both (Amount.usd $ -1) (Amount.usd $ 1)
1345 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1346 ["A":|[]]
1347 }
1348 , Balance.Unit_Sum
1349 { Balance.unit_sum_amount = Balance.Amount_Sum_Both (Amount.eur $ -2) (Amount.eur $ 2)
1350 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1351 ["A":|[]]
1352 }
1353 ]
1354 }
1355 , "[A+$1+€2+£3, B-$1-2€-£3] = {A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~:
1356 (Data.List.foldl
1357 (flip Balance.balance)
1358 Balance.nil
1359 [ (Format.Ledger.posting ("A":|[]))
1360 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ]
1361 }
1362 , (Format.Ledger.posting ("B":|[]))
1363 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ]
1364 }
1365 ])
1366 ~?=
1367 Balance.Balance
1368 { Balance.balance_by_account =
1369 Lib.TreeMap.from_List const $
1370 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1371 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
1372 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
1373 ]
1374 , Balance.balance_by_unit =
1375 Data.Map.fromList $
1376 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1377 [ Balance.Unit_Sum
1378 { Balance.unit_sum_amount = Balance.Amount_Sum_Both (Amount.usd $ -1) (Amount.usd $ 1)
1379 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1380 ["A":|[], "B":|[]]
1381 }
1382 , Balance.Unit_Sum
1383 { Balance.unit_sum_amount = Balance.Amount_Sum_Both (Amount.eur $ -2) (Amount.eur $ 2)
1384 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1385 ["A":|[], "B":|[]]
1386 }
1387 , Balance.Unit_Sum
1388 { Balance.unit_sum_amount = Balance.Amount_Sum_Both (Amount.gbp $ -3) (Amount.gbp $ 3)
1389 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1390 ["A":|[], "B":|[]]
1391 }
1392 ]
1393 }
1394 ]
1395 , "union" ~: TestList
1396 [ "nil nil = nil" ~:
1397 Balance.union Balance.nil Balance.nil
1398 ~?=
1399 (Balance.nil::Balance.Balance Amount)
1400 , "{A+$1, $+1} {A+$1, $+1} = {A+$2, $+2}" ~:
1401 Balance.union
1402 (Balance.Balance
1403 { Balance.balance_by_account =
1404 Lib.TreeMap.from_List const $
1405 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1406 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1407 , Balance.balance_by_unit =
1408 Data.Map.fromList $
1409 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1410 [ Balance.Unit_Sum
1411 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1412 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1413 ["A":|[]]
1414 }
1415 ]
1416 })
1417 (Balance.Balance
1418 { Balance.balance_by_account =
1419 Lib.TreeMap.from_List const $
1420 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1421 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1422 , Balance.balance_by_unit =
1423 Data.Map.fromList $
1424 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1425 [ Balance.Unit_Sum
1426 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1427 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1428 ["A":|[]]
1429 }
1430 ]
1431 })
1432 ~?=
1433 Balance.Balance
1434 { Balance.balance_by_account =
1435 Lib.TreeMap.from_List const $
1436 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1437 [ ("A":|[], Amount.from_List [ Amount.usd $ 2 ]) ]
1438 , Balance.balance_by_unit =
1439 Data.Map.fromList $
1440 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1441 [ Balance.Unit_Sum
1442 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1443 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1444 ["A":|[]]
1445 }
1446 ]
1447 }
1448 , "{A+$1, $+1} {B+$1, $+1} = {A+$1 B+$1, $+2}" ~:
1449 Balance.union
1450 (Balance.Balance
1451 { Balance.balance_by_account =
1452 Lib.TreeMap.from_List const $
1453 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1454 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1455 , Balance.balance_by_unit =
1456 Data.Map.fromList $
1457 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1458 [ Balance.Unit_Sum
1459 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1460 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1461 ["A":|[]]
1462 }
1463 ]
1464 })
1465 (Balance.Balance
1466 { Balance.balance_by_account =
1467 Lib.TreeMap.from_List const $
1468 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1469 [ ("B":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1470 , Balance.balance_by_unit =
1471 Data.Map.fromList $
1472 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1473 [ Balance.Unit_Sum
1474 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1475 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1476 ["B":|[]]
1477 }
1478 ]
1479 })
1480 ~?=
1481 Balance.Balance
1482 { Balance.balance_by_account =
1483 Lib.TreeMap.from_List const $
1484 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1485 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1486 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1487 , Balance.balance_by_unit =
1488 Data.Map.fromList $
1489 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1490 [ Balance.Unit_Sum
1491 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1492 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1493 ["A":|[], "B":|[]]
1494 }
1495 ]
1496 }
1497 , "{A+$1, $+1} {B+€1, €+1} = {A+$1 B+€1, $+1 €+1}" ~:
1498 Balance.union
1499 (Balance.Balance
1500 { Balance.balance_by_account =
1501 Lib.TreeMap.from_List const $
1502 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1503 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
1504 , Balance.balance_by_unit =
1505 Data.Map.fromList $
1506 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1507 [ Balance.Unit_Sum
1508 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1509 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1510 ["A":|[]]
1511 }
1512 ]
1513 })
1514 (Balance.Balance
1515 { Balance.balance_by_account =
1516 Lib.TreeMap.from_List const $
1517 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1518 [ ("B":|[], Amount.from_List [ Amount.eur $ 1 ]) ]
1519 , Balance.balance_by_unit =
1520 Data.Map.fromList $
1521 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1522 [ Balance.Unit_Sum
1523 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 1
1524 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1525 ["B":|[]]
1526 }
1527 ]
1528 })
1529 ~?=
1530 Balance.Balance
1531 { Balance.balance_by_account =
1532 Lib.TreeMap.from_List const $
1533 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1534 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1535 , ("B":|[], Amount.from_List [ Amount.eur $ 1 ]) ]
1536 , Balance.balance_by_unit =
1537 Data.Map.fromList $
1538 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1539 [ Balance.Unit_Sum
1540 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1541 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1542 ["A":|[]]
1543 }
1544 , Balance.Unit_Sum
1545 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 1
1546 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1547 ["B":|[]]
1548 }
1549 ]
1550 }
1551 ]
1552 , "expanded" ~: TestList
1553 [ "nil_By_Account" ~:
1554 Balance.expanded
1555 Lib.TreeMap.empty
1556 ~?=
1557 (Lib.TreeMap.empty::Balance.Expanded Amount)
1558 , "A+$1 = A+$1" ~:
1559 Balance.expanded
1560 (Lib.TreeMap.from_List const $
1561 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1562 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ])
1563 ~?=
1564 (Lib.TreeMap.from_List const $
1565 [ ("A":|[], Balance.Account_Sum_Expanded
1566 { Balance.inclusive =
1567 Data.Map.map Balance.amount_sum $
1568 Amount.from_List [ Amount.usd $ 1 ]
1569 , Balance.exclusive =
1570 Data.Map.map Balance.amount_sum $
1571 Amount.from_List [ Amount.usd $ 1 ]
1572 })
1573 ])
1574 , "A/A+$1 = A+$1 A/A+$1" ~:
1575 Balance.expanded
1576 (Lib.TreeMap.from_List const $
1577 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1578 [ ("A":|["A"], Amount.from_List [ Amount.usd $ 1 ]) ])
1579 ~?=
1580 (Lib.TreeMap.from_List const
1581 [ ("A":|[], Balance.Account_Sum_Expanded
1582 { Balance.inclusive =
1583 Data.Map.map Balance.amount_sum $
1584 Amount.from_List [ Amount.usd $ 1 ]
1585 , Balance.exclusive =
1586 Data.Map.map Balance.amount_sum $
1587 Amount.from_List []
1588 })
1589 , ("A":|["A"], Balance.Account_Sum_Expanded
1590 { Balance.inclusive =
1591 Data.Map.map Balance.amount_sum $
1592 Amount.from_List [ Amount.usd $ 1 ]
1593 , Balance.exclusive =
1594 Data.Map.map Balance.amount_sum $
1595 Amount.from_List [ Amount.usd $ 1 ]
1596 })
1597 ])
1598 , "A/B+$1 = A+$1 A/B+$1" ~:
1599 Balance.expanded
1600 (Lib.TreeMap.from_List const $
1601 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1602 [ ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ]) ])
1603 ~?=
1604 (Lib.TreeMap.from_List const
1605 [ ("A":|[], Balance.Account_Sum_Expanded
1606 { Balance.inclusive =
1607 Data.Map.map Balance.amount_sum $
1608 Amount.from_List [ Amount.usd $ 1 ]
1609 , Balance.exclusive =
1610 Data.Map.map Balance.amount_sum $
1611 Amount.from_List []
1612 })
1613 , ("A":|["B"], Balance.Account_Sum_Expanded
1614 { Balance.inclusive =
1615 Data.Map.map Balance.amount_sum $
1616 Amount.from_List [ Amount.usd $ 1 ]
1617 , Balance.exclusive =
1618 Data.Map.map Balance.amount_sum $
1619 Amount.from_List [ Amount.usd $ 1 ]
1620 })
1621 ])
1622 , "A/B/C+$1 = A+$1 A/B+$1 A/B/C+$1" ~:
1623 Balance.expanded
1624 (Lib.TreeMap.from_List const $
1625 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1626 [ ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ]) ])
1627 ~?=
1628 (Lib.TreeMap.from_List const $
1629 [ ("A":|[], Balance.Account_Sum_Expanded
1630 { Balance.inclusive =
1631 Data.Map.map Balance.amount_sum $
1632 Amount.from_List [ Amount.usd $ 1 ]
1633 , Balance.exclusive =
1634 Data.Map.map Balance.amount_sum $
1635 Amount.from_List []
1636 })
1637 , ("A":|["B"], Balance.Account_Sum_Expanded
1638 { Balance.inclusive =
1639 Data.Map.map Balance.amount_sum $
1640 Amount.from_List [ Amount.usd $ 1 ]
1641 , Balance.exclusive =
1642 Data.Map.map Balance.amount_sum $
1643 Amount.from_List []
1644 })
1645 , ("A":|["B", "C"], Balance.Account_Sum_Expanded
1646 { Balance.inclusive =
1647 Data.Map.map Balance.amount_sum $
1648 Amount.from_List [ Amount.usd $ 1 ]
1649 , Balance.exclusive =
1650 Data.Map.map Balance.amount_sum $
1651 Amount.from_List [ Amount.usd $ 1 ]
1652 })
1653 ])
1654 , "A+$1 A/B+$1 = A+$2 A/B+$1" ~:
1655 Balance.expanded
1656 (Lib.TreeMap.from_List const $
1657 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1658 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1659 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1660 ])
1661 ~?=
1662 (Lib.TreeMap.from_List const
1663 [ ("A":|[], Balance.Account_Sum_Expanded
1664 { Balance.inclusive =
1665 Data.Map.map Balance.amount_sum $
1666 Amount.from_List [ Amount.usd $ 2 ]
1667 , Balance.exclusive =
1668 Data.Map.map Balance.amount_sum $
1669 Amount.from_List [ Amount.usd $ 1 ]
1670 })
1671 , ("A":|["B"], 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 [ Amount.usd $ 1 ]
1678 })
1679 ])
1680 , "A+$1 A/B+$1 A/B/C+$1 = A+$3 A/B+$2 A/B/C+$1" ~:
1681 Balance.expanded
1682 (Lib.TreeMap.from_List const $
1683 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1684 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1685 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1686 , ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ])
1687 ])
1688 ~?=
1689 (Lib.TreeMap.from_List const
1690 [ ("A":|[], Balance.Account_Sum_Expanded
1691 { Balance.inclusive =
1692 Data.Map.map Balance.amount_sum $
1693 Amount.from_List [ Amount.usd $ 3 ]
1694 , Balance.exclusive =
1695 Data.Map.map Balance.amount_sum $
1696 Amount.from_List [ Amount.usd $ 1 ]
1697 })
1698 , ("A":|["B"], Balance.Account_Sum_Expanded
1699 { Balance.inclusive =
1700 Data.Map.map Balance.amount_sum $
1701 Amount.from_List [ Amount.usd $ 2 ]
1702 , Balance.exclusive =
1703 Data.Map.map Balance.amount_sum $
1704 Amount.from_List [ Amount.usd $ 1 ]
1705 })
1706 , ("A":|["B", "C"], Balance.Account_Sum_Expanded
1707 { Balance.inclusive =
1708 Data.Map.map Balance.amount_sum $
1709 Amount.from_List [ Amount.usd $ 1 ]
1710 , Balance.exclusive =
1711 Data.Map.map Balance.amount_sum $
1712 Amount.from_List [ Amount.usd $ 1 ]
1713 })
1714 ])
1715 , "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" ~:
1716 Balance.expanded
1717 (Lib.TreeMap.from_List const $
1718 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1719 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1720 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1721 , ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ])
1722 , ("A":|["B", "C", "D"], Amount.from_List [ Amount.usd $ 1 ])
1723 ])
1724 ~?=
1725 (Lib.TreeMap.from_List const
1726 [ ("A":|[], Balance.Account_Sum_Expanded
1727 { Balance.inclusive =
1728 Data.Map.map Balance.amount_sum $
1729 Amount.from_List [ Amount.usd $ 4 ]
1730 , Balance.exclusive =
1731 Data.Map.map Balance.amount_sum $
1732 Amount.from_List [ Amount.usd $ 1 ]
1733 })
1734 , ("A":|["B"], Balance.Account_Sum_Expanded
1735 { Balance.inclusive =
1736 Data.Map.map Balance.amount_sum $
1737 Amount.from_List [ Amount.usd $ 3 ]
1738 , Balance.exclusive =
1739 Data.Map.map Balance.amount_sum $
1740 Amount.from_List [ Amount.usd $ 1 ]
1741 })
1742 , ("A":|["B", "C"], Balance.Account_Sum_Expanded
1743 { Balance.inclusive =
1744 Data.Map.map Balance.amount_sum $
1745 Amount.from_List [ Amount.usd $ 2 ]
1746 , Balance.exclusive =
1747 Data.Map.map Balance.amount_sum $
1748 Amount.from_List [ Amount.usd $ 1 ]
1749 })
1750 , ("A":|["B", "C", "D"], Balance.Account_Sum_Expanded
1751 { Balance.inclusive =
1752 Data.Map.map Balance.amount_sum $
1753 Amount.from_List [ Amount.usd $ 1 ]
1754 , Balance.exclusive =
1755 Data.Map.map Balance.amount_sum $
1756 Amount.from_List [ Amount.usd $ 1 ]
1757 })
1758 ])
1759 , "A+$1 A/B+$1 A/BB+$1 AA/B+$1 = A+$3 A/B+$1 A/BB+$1 AA+$1 AA/B+$1" ~:
1760 Balance.expanded
1761 (Lib.TreeMap.from_List const $
1762 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1763 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1764 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1765 , ("A":|["BB"], Amount.from_List [ Amount.usd $ 1 ])
1766 , ("AA":|["B"], Amount.from_List [ Amount.usd $ 1 ])
1767 ])
1768 ~?=
1769 (Lib.TreeMap.from_List const
1770 [ ("A":|[], Balance.Account_Sum_Expanded
1771 { Balance.inclusive =
1772 Data.Map.map Balance.amount_sum $
1773 Amount.from_List [ Amount.usd $ 3 ]
1774 , Balance.exclusive =
1775 Data.Map.map Balance.amount_sum $
1776 Amount.from_List [ Amount.usd $ 1 ]
1777 })
1778 , ("A":|["B"], Balance.Account_Sum_Expanded
1779 { Balance.inclusive =
1780 Data.Map.map Balance.amount_sum $
1781 Amount.from_List [ Amount.usd $ 1 ]
1782 , Balance.exclusive =
1783 Data.Map.map Balance.amount_sum $
1784 Amount.from_List [ Amount.usd $ 1 ]
1785 })
1786 , ("A":|["BB"], Balance.Account_Sum_Expanded
1787 { Balance.inclusive =
1788 Data.Map.map Balance.amount_sum $
1789 Amount.from_List [ Amount.usd $ 1 ]
1790 , Balance.exclusive =
1791 Data.Map.map Balance.amount_sum $
1792 Amount.from_List [ Amount.usd $ 1 ]
1793 })
1794 , ("AA":|[], Balance.Account_Sum_Expanded
1795 { Balance.inclusive =
1796 Data.Map.map Balance.amount_sum $
1797 Amount.from_List [ Amount.usd $ 1 ]
1798 , Balance.exclusive =
1799 Data.Map.map Balance.amount_sum $
1800 Amount.from_List []
1801 })
1802 , ("AA":|["B"], Balance.Account_Sum_Expanded
1803 { Balance.inclusive =
1804 Data.Map.map Balance.amount_sum $
1805 Amount.from_List [ Amount.usd $ 1 ]
1806 , Balance.exclusive =
1807 Data.Map.map Balance.amount_sum $
1808 Amount.from_List [ Amount.usd $ 1 ]
1809 })
1810 ])
1811 ]
1812 , "deviation" ~: TestList
1813 [ "{A+$1, $1}" ~:
1814 (Balance.deviation $
1815 Balance.Balance
1816 { Balance.balance_by_account =
1817 Lib.TreeMap.from_List const $
1818 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1819 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1820 , ("B":|[], Amount.from_List [])
1821 ]
1822 , Balance.balance_by_unit =
1823 Data.Map.fromList $
1824 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1825 [ Balance.Unit_Sum
1826 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1827 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1828 ["A":|[]]
1829 }
1830 ]
1831 })
1832 ~?=
1833 (Balance.Deviation $
1834 Data.Map.fromList $
1835 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1836 [ Balance.Unit_Sum
1837 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1838 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1839 ["B":|[]]
1840 }
1841 ])
1842 , "{A+$1 B+$1, $2}" ~:
1843 (Balance.deviation $
1844 Balance.Balance
1845 { Balance.balance_by_account =
1846 Lib.TreeMap.from_List const $
1847 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1848 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1849 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ])
1850 ]
1851 , Balance.balance_by_unit =
1852 Data.Map.fromList $
1853 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1854 [ Balance.Unit_Sum
1855 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
1856 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1857 [ "A":|[]
1858 , "B":|[]
1859 ]
1860 }
1861 ]
1862 })
1863 ~?=
1864 (Balance.Deviation $
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 $ 2
1869 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1870 [
1871 ]
1872 }
1873 ])
1874 ]
1875 , "is_equilibrium_inferrable" ~: TestList
1876 [ "nil" ~: TestCase $
1877 (@=?) True $
1878 Balance.is_equilibrium_inferrable $
1879 Balance.deviation $
1880 (Balance.nil::Balance.Balance Amount.Amount)
1881 , "{A+$0, $+0}" ~: TestCase $
1882 (@=?) True $
1883 Balance.is_equilibrium_inferrable $
1884 Balance.deviation $
1885 Balance.Balance
1886 { Balance.balance_by_account =
1887 Lib.TreeMap.from_List const $
1888 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1889 [ ("A":|[], Amount.from_List [ Amount.usd $ 0 ])
1890 ]
1891 , Balance.balance_by_unit =
1892 Data.Map.fromList $
1893 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1894 [ Balance.Unit_Sum
1895 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
1896 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1897 ["A":|[]]
1898 }
1899 ]
1900 }
1901 , "{A+$1, $+1}" ~: TestCase $
1902 (@=?) False $
1903 Balance.is_equilibrium_inferrable $
1904 Balance.deviation $
1905 Balance.Balance
1906 { Balance.balance_by_account =
1907 Lib.TreeMap.from_List const $
1908 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1909 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1910 ]
1911 , Balance.balance_by_unit =
1912 Data.Map.fromList $
1913 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1914 [ Balance.Unit_Sum
1915 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1916 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1917 ["A":|[]]
1918 }
1919 ]
1920 }
1921 , "{A+$0+€0, $0 €+0}" ~: TestCase $
1922 (@=?) True $
1923 Balance.is_equilibrium_inferrable $
1924 Balance.deviation $
1925 Balance.Balance
1926 { Balance.balance_by_account =
1927 Lib.TreeMap.from_List const $
1928 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1929 [ ("A":|[], Amount.from_List [ Amount.usd $ 0, Amount.eur $ 0 ])
1930 ]
1931 , Balance.balance_by_unit =
1932 Data.Map.fromList $
1933 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1934 [ Balance.Unit_Sum
1935 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
1936 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1937 ["A":|[]]
1938 }
1939 , Balance.Unit_Sum
1940 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 0
1941 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1942 ["A":|[]]
1943 }
1944 ]
1945 }
1946 , "{A+$1, B-$1, $+0}" ~: TestCase $
1947 (@=?) True $
1948 Balance.is_equilibrium_inferrable $
1949 Balance.deviation $
1950 Balance.Balance
1951 { Balance.balance_by_account =
1952 Lib.TreeMap.from_List const $
1953 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1954 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1955 , ("B":|[], Amount.from_List [ Amount.usd $ -1 ])
1956 ]
1957 , Balance.balance_by_unit =
1958 Data.Map.fromList $
1959 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1960 [ Balance.Unit_Sum
1961 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
1962 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1963 ["A":|[], "B":|[]]
1964 }
1965 ]
1966 }
1967 , "{A+$1 B, $+1}" ~: TestCase $
1968 (@=?) True $
1969 Balance.is_equilibrium_inferrable $
1970 Balance.deviation $
1971 Balance.Balance
1972 { Balance.balance_by_account =
1973 Lib.TreeMap.from_List const $
1974 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
1975 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
1976 , ("B":|[], Amount.from_List [])
1977 ]
1978 , Balance.balance_by_unit =
1979 Data.Map.fromList $
1980 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
1981 [ Balance.Unit_Sum
1982 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 1
1983 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
1984 ["A":|[]]
1985 }
1986 ]
1987 }
1988 , "{A+$1 B+€1, $+1 €+1}" ~: 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.eur $ 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 $ 1
2004 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2005 ["A":|[]]
2006 }
2007 , Balance.Unit_Sum
2008 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 1
2009 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2010 ["B":|[]]
2011 }
2012 ]
2013 }
2014 , "{A+$1 B-$1+€1, $+0 €+1}" ~: TestCase $
2015 (@=?) True $
2016 Balance.is_equilibrium_inferrable $
2017 Balance.deviation $
2018 Balance.Balance
2019 { Balance.balance_by_account =
2020 Lib.TreeMap.from_List const $
2021 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
2022 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
2023 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ 1 ])
2024 ]
2025 , Balance.balance_by_unit =
2026 Data.Map.fromList $
2027 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
2028 [ Balance.Unit_Sum
2029 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
2030 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2031 ["A":|[], "B":|[]]
2032 }
2033 , Balance.Unit_Sum
2034 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 1
2035 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2036 ["B":|[]]
2037 }
2038 ]
2039 }
2040 , "{A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~: TestCase $
2041 (@=?) True $
2042 Balance.is_equilibrium_inferrable $
2043 Balance.deviation $
2044 Balance.Balance
2045 { Balance.balance_by_account =
2046 Lib.TreeMap.from_List const $
2047 Data.List.map (id *** Data.Map.map Balance.amount_sum) $
2048 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
2049 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
2050 ]
2051 , Balance.balance_by_unit =
2052 Data.Map.fromList $
2053 Data.List.map (\s -> (Amount.unit $ Balance.amount_sum_balance $ Balance.unit_sum_amount s, s))
2054 [ Balance.Unit_Sum
2055 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 0
2056 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2057 ["A":|[], "B":|[]]
2058 }
2059 , Balance.Unit_Sum
2060 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.eur $ 0
2061 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2062 ["A":|[], "B":|[]]
2063 }
2064 , Balance.Unit_Sum
2065 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.gbp $ 0
2066 , Balance.unit_sum_accounts = Data.Map.fromList $ Data.List.map (,())
2067 ["A":|[], "B":|[]]
2068 }
2069 ]
2070 }
2071 ]
2072 , "infer_equilibrium" ~: TestList
2073 [ "{A+$1 B}" ~:
2074 (snd $ Balance.infer_equilibrium $
2075 Format.Ledger.posting_by_Account
2076 [ (Format.Ledger.posting ("A":|[]))
2077 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2078 , (Format.Ledger.posting ("B":|[]))
2079 { Format.Ledger.posting_amounts=Amount.from_List [] }
2080 ])
2081 ~?=
2082 (Right $
2083 Format.Ledger.posting_by_Account
2084 [ (Format.Ledger.posting ("A":|[]))
2085 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2086 , (Format.Ledger.posting ("B":|[]))
2087 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1 ] }
2088 ])
2089 , "{A+$1 B-1€}" ~:
2090 (snd $ Balance.infer_equilibrium $
2091 Format.Ledger.posting_by_Account
2092 [ (Format.Ledger.posting ("A":|[]))
2093 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2094 , (Format.Ledger.posting ("B":|[]))
2095 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.eur $ -1 ] }
2096 ])
2097 ~?=
2098 (Right $
2099 Format.Ledger.posting_by_Account
2100 [ (Format.Ledger.posting ("A":|[]))
2101 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 1] }
2102 , (Format.Ledger.posting ("B":|[]))
2103 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.eur $ -1, Amount.usd $ -1 ] }
2104 ])
2105 , "{A+$1 B+$1}" ~:
2106 (snd $ Balance.infer_equilibrium $
2107 Format.Ledger.posting_by_Account
2108 [ (Format.Ledger.posting ("A":|[]))
2109 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2110 , (Format.Ledger.posting ("B":|[]))
2111 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2112 ])
2113 ~?=
2114 (Left
2115 [ Balance.Unit_Sum
2116 { Balance.unit_sum_amount = Balance.amount_sum $ Amount.usd $ 2
2117 , Balance.unit_sum_accounts = Data.Map.fromList []}
2118 ])
2119 , "{A+$1 B-$1 B-1€}" ~:
2120 (snd $ Balance.infer_equilibrium $
2121 Format.Ledger.posting_by_Account
2122 [ (Format.Ledger.posting ("A":|[]))
2123 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1 ] }
2124 , (Format.Ledger.posting ("B":|[]))
2125 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -1 ] }
2126 ])
2127 ~?=
2128 (Right $
2129 Format.Ledger.posting_by_Account
2130 [ (Format.Ledger.posting ("A":|[]))
2131 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 1 ] }
2132 , (Format.Ledger.posting ("B":|[]))
2133 { Format.Ledger.posting_amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -1 ] }
2134 ])
2135 ]
2136 ]
2137 , "Format" ~: TestList
2138 [ "Ledger" ~: TestList
2139 [ "Read" ~: TestList
2140 [ "account_name" ~: TestList
2141 [ "\"\"" ~:
2142 (Data.Either.rights $
2143 [P.runParser
2144 (Format.Ledger.Read.account_name <* P.eof)
2145 () "" (""::Text)])
2146 ~?=
2147 []
2148 , "\"A\"" ~:
2149 (Data.Either.rights $
2150 [P.runParser
2151 (Format.Ledger.Read.account_name <* P.eof)
2152 () "" ("A"::Text)])
2153 ~?=
2154 ["A"]
2155 , "\"AA\"" ~:
2156 (Data.Either.rights $
2157 [P.runParser
2158 (Format.Ledger.Read.account_name <* P.eof)
2159 () "" ("AA"::Text)])
2160 ~?=
2161 ["AA"]
2162 , "\" \"" ~:
2163 (Data.Either.rights $
2164 [P.runParser
2165 (Format.Ledger.Read.account_name <* P.eof)
2166 () "" (" "::Text)])
2167 ~?=
2168 []
2169 , "\":\"" ~:
2170 (Data.Either.rights $
2171 [P.runParser
2172 (Format.Ledger.Read.account_name <* P.eof)
2173 () "" (":"::Text)])
2174 ~?=
2175 []
2176 , "\"A:\"" ~:
2177 (Data.Either.rights $
2178 [P.runParser
2179 (Format.Ledger.Read.account_name <* P.eof)
2180 () "" ("A:"::Text)])
2181 ~?=
2182 []
2183 , "\":A\"" ~:
2184 (Data.Either.rights $
2185 [P.runParser
2186 (Format.Ledger.Read.account_name <* P.eof)
2187 () "" (":A"::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 []
2197 , "\"A \"" ~:
2198 (Data.Either.rights $
2199 [P.runParser
2200 (Format.Ledger.Read.account_name)
2201 () "" ("A "::Text)])
2202 ~?=
2203 ["A"]
2204 , "\"A A\"" ~:
2205 (Data.Either.rights $
2206 [P.runParser
2207 (Format.Ledger.Read.account_name <* P.eof)
2208 () "" ("A A"::Text)])
2209 ~?=
2210 ["A A"]
2211 , "\"A \"" ~:
2212 (Data.Either.rights $
2213 [P.runParser
2214 (Format.Ledger.Read.account_name <* P.eof)
2215 () "" ("A "::Text)])
2216 ~?=
2217 []
2218 , "\"A \\n\"" ~:
2219 (Data.Either.rights $
2220 [P.runParser
2221 (Format.Ledger.Read.account_name <* P.eof)
2222 () "" ("A \n"::Text)])
2223 ~?=
2224 []
2225 , "\"(A)A\"" ~:
2226 (Data.Either.rights $
2227 [P.runParser
2228 (Format.Ledger.Read.account_name <* P.eof)
2229 () "" ("(A)A"::Text)])
2230 ~?=
2231 ["(A)A"]
2232 , "\"( )A\"" ~:
2233 (Data.Either.rights $
2234 [P.runParser
2235 (Format.Ledger.Read.account_name <* P.eof)
2236 () "" ("( )A"::Text)])
2237 ~?=
2238 ["( )A"]
2239 , "\"(A) A\"" ~:
2240 (Data.Either.rights $
2241 [P.runParser
2242 (Format.Ledger.Read.account_name <* P.eof)
2243 () "" ("(A) A"::Text)])
2244 ~?=
2245 ["(A) A"]
2246 , "\"[ ]A\"" ~:
2247 (Data.Either.rights $
2248 [P.runParser
2249 (Format.Ledger.Read.account_name <* P.eof)
2250 () "" ("[ ]A"::Text)])
2251 ~?=
2252 ["[ ]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)\"" ~:
2261 (Data.Either.rights $
2262 [P.runParser
2263 (Format.Ledger.Read.account_name <* P.eof)
2264 () "" ("(A)"::Text)])
2265 ~?=
2266 ["(A)"]
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)"::Text)]
2274 , "\"[A]A\"" ~:
2275 (Data.Either.rights $
2276 [P.runParser
2277 (Format.Ledger.Read.account_name <* P.eof)
2278 () "" ("[A]A"::Text)])
2279 ~?=
2280 ["[A]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 []
2295 , "\"[A]\"" ~:
2296 (Data.Either.rights $
2297 [P.runParser
2298 (Format.Ledger.Read.account_name <* P.eof)
2299 () "" ("[A]"::Text)])
2300 ~?=
2301 ["[A]"]
2302 ]
2303 , "account" ~: TestList
2304 [ "\"\"" ~:
2305 (Data.Either.rights $
2306 [P.runParser
2307 (Format.Ledger.Read.account <* P.eof)
2308 () "" (""::Text)])
2309 ~?=
2310 []
2311 , "\"A\"" ~:
2312 (Data.Either.rights $
2313 [P.runParser
2314 (Format.Ledger.Read.account <* P.eof)
2315 () "" ("A"::Text)])
2316 ~?=
2317 ["A":|[]]
2318 , "\"A:\"" ~:
2319 (Data.Either.rights $
2320 [P.runParser
2321 (Format.Ledger.Read.account <* P.eof)
2322 () "" ("A:"::Text)])
2323 ~?=
2324 []
2325 , "\":A\"" ~:
2326 (Data.Either.rights $
2327 [P.runParser
2328 (Format.Ledger.Read.account <* P.eof)
2329 () "" (":A"::Text)])
2330 ~?=
2331 []
2332 , "\"A \"" ~:
2333 (Data.Either.rights $
2334 [P.runParser
2335 (Format.Ledger.Read.account <* P.eof)
2336 () "" ("A "::Text)])
2337 ~?=
2338 []
2339 , "\" A\"" ~:
2340 (Data.Either.rights $
2341 [P.runParser
2342 (Format.Ledger.Read.account <* P.eof)
2343 () "" (" A"::Text)])
2344 ~?=
2345 []
2346 , "\"A:B\"" ~:
2347 (Data.Either.rights $
2348 [P.runParser
2349 (Format.Ledger.Read.account <* P.eof)
2350 () "" ("A:B"::Text)])
2351 ~?=
2352 ["A":|["B"]]
2353 , "\"A:B:C\"" ~:
2354 (Data.Either.rights $
2355 [P.runParser
2356 (Format.Ledger.Read.account <* P.eof)
2357 () "" ("A:B:C"::Text)])
2358 ~?=
2359 ["A":|["B", "C"]]
2360 , "\"Aa:Bbb:Cccc\"" ~:
2361 (Data.Either.rights $
2362 [P.runParser
2363 (Format.Ledger.Read.account <* P.eof)
2364 () "" ("Aa:Bbb:Cccc"::Text)])
2365 ~?=
2366 ["Aa":|["Bbb", "Cccc"]]
2367 , "\"A a : B b b : C c c c\"" ~:
2368 (Data.Either.rights $
2369 [P.runParser
2370 (Format.Ledger.Read.account <* P.eof)
2371 () "" ("A a : B b b : C c c c"::Text)])
2372 ~?=
2373 ["A a ":|[" B b b ", " C c c c"]]
2374 , "\"A: :C\"" ~:
2375 (Data.Either.rights $
2376 [P.runParser
2377 (Format.Ledger.Read.account <* P.eof)
2378 () "" ("A: :C"::Text)])
2379 ~?=
2380 ["A":|[" ", "C"]]
2381 , "\"A::C\"" ~:
2382 (Data.Either.rights $
2383 [P.runParser
2384 (Format.Ledger.Read.account <* P.eof)
2385 () "" ("A::C"::Text)])
2386 ~?=
2387 []
2388 , "\"A:B:(C)\"" ~:
2389 (Data.Either.rights $
2390 [P.runParser
2391 (Format.Ledger.Read.account <* P.eof)
2392 () "" ("A:B:(C)"::Text)])
2393 ~?=
2394 ["A":|["B", "(C)"]]
2395 ]
2396 , "posting_type" ~: TestList
2397 [ "A" ~:
2398 Format.Ledger.Read.posting_type
2399 ("A":|[])
2400 ~?=
2401 (Format.Ledger.Posting_Type_Regular, "A":|[])
2402 , "(" ~:
2403 Format.Ledger.Read.posting_type
2404 ("(":|[])
2405 ~?=
2406 (Format.Ledger.Posting_Type_Regular, "(":|[])
2407 , ")" ~:
2408 Format.Ledger.Read.posting_type
2409 (")":|[])
2410 ~?=
2411 (Format.Ledger.Posting_Type_Regular, ")":|[])
2412 , "()" ~:
2413 Format.Ledger.Read.posting_type
2414 ("()":|[])
2415 ~?=
2416 (Format.Ledger.Posting_Type_Regular, "()":|[])
2417 , "( )" ~:
2418 Format.Ledger.Read.posting_type
2419 ("( )":|[])
2420 ~?=
2421 (Format.Ledger.Posting_Type_Regular, "( )":|[])
2422 , "(A)" ~:
2423 Format.Ledger.Read.posting_type
2424 ("(A)":|[])
2425 ~?=
2426 (Format.Ledger.Posting_Type_Virtual, "A":|[])
2427 , "(A:B:C)" ~:
2428 Format.Ledger.Read.posting_type
2429 ("(A":|["B", "C)"])
2430 ~?=
2431 (Format.Ledger.Posting_Type_Virtual, "A":|["B", "C"])
2432 , "A:B:C" ~:
2433 Format.Ledger.Read.posting_type
2434 ("A":|["B", "C"])
2435 ~?=
2436 (Format.Ledger.Posting_Type_Regular, "A":|["B", "C"])
2437 , "(A):B:C" ~:
2438 Format.Ledger.Read.posting_type
2439 ("(A)":|["B", "C"])
2440 ~?=
2441 (Format.Ledger.Posting_Type_Regular, "(A)":|["B", "C"])
2442 , "A:(B):C" ~:
2443 Format.Ledger.Read.posting_type
2444 ("A":|["(B)", "C"])
2445 ~?=
2446 (Format.Ledger.Posting_Type_Regular, "A":|["(B)", "C"])
2447 , "A:B:(C)" ~:
2448 Format.Ledger.Read.posting_type
2449 ("A":|["B", "(C)"])
2450 ~?=
2451 (Format.Ledger.Posting_Type_Regular, "A":|["B", "(C)"])
2452 , "[" ~:
2453 Format.Ledger.Read.posting_type
2454 ("[":|[])
2455 ~?=
2456 (Format.Ledger.Posting_Type_Regular, "[":|[])
2457 , "]" ~:
2458 Format.Ledger.Read.posting_type
2459 ("]":|[])
2460 ~?=
2461 (Format.Ledger.Posting_Type_Regular, "]":|[])
2462 , "[]" ~:
2463 Format.Ledger.Read.posting_type
2464 ("[]":|[])
2465 ~?=
2466 (Format.Ledger.Posting_Type_Regular, "[]":|[])
2467 , "[ ]" ~:
2468 Format.Ledger.Read.posting_type
2469 ("[ ]":|[])
2470 ~?=
2471 (Format.Ledger.Posting_Type_Regular, "[ ]":|[])
2472 , "[A]" ~:
2473 Format.Ledger.Read.posting_type
2474 ("[A]":|[])
2475 ~?=
2476 (Format.Ledger.Posting_Type_Virtual_Balanced, "A":|[])
2477 , "[A:B:C]" ~:
2478 Format.Ledger.Read.posting_type
2479 ("[A":|["B", "C]"])
2480 ~?=
2481 (Format.Ledger.Posting_Type_Virtual_Balanced, "A":|["B", "C"])
2482 , "A:B:C" ~:
2483 Format.Ledger.Read.posting_type
2484 ("A":|["B", "C"])
2485 ~?=
2486 (Format.Ledger.Posting_Type_Regular, "A":|["B", "C"])
2487 , "[A]:B:C" ~:
2488 Format.Ledger.Read.posting_type
2489 ("[A]":|["B", "C"])
2490 ~?=
2491 (Format.Ledger.Posting_Type_Regular, "[A]":|["B", "C"])
2492 , "A:[B]:C" ~:
2493 Format.Ledger.Read.posting_type
2494 ("A":|["[B]", "C"])
2495 ~?=
2496 (Format.Ledger.Posting_Type_Regular, "A":|["[B]", "C"])
2497 , "A:B:[C]" ~:
2498 Format.Ledger.Read.posting_type
2499 ("A":|["B", "[C]"])
2500 ~?=
2501 (Format.Ledger.Posting_Type_Regular, "A":|["B", "[C]"])
2502 ]
2503 , "comment" ~: TestList
2504 [ "; some comment = Right \" some comment\"" ~:
2505 (Data.Either.rights $
2506 [P.runParser
2507 (Format.Ledger.Read.comment <* P.eof)
2508 () "" ("; some comment"::Text)])
2509 ~?=
2510 [ " some comment" ]
2511 , "; some comment \\n = Right \" some comment \"" ~:
2512 (Data.Either.rights $
2513 [P.runParser
2514 (Format.Ledger.Read.comment <* P.newline <* P.eof)
2515 () "" ("; some comment \n"::Text)])
2516 ~?=
2517 [ " some comment " ]
2518 , "; some comment \\r\\n = Right \" some comment \"" ~:
2519 (Data.Either.rights $
2520 [P.runParser
2521 (Format.Ledger.Read.comment <* P.string "\r\n" <* P.eof)
2522 () "" ("; some comment \r\n"::Text)])
2523 ~?=
2524 [ " some comment " ]
2525 ]
2526 , "comments" ~: TestList
2527 [ "; some comment\\n ; some other comment = Right [\" some comment\", \" some other comment\"]" ~:
2528 (Data.Either.rights $
2529 [P.runParser
2530 (Format.Ledger.Read.comments <* P.eof)
2531 () "" ("; some comment\n ; some other comment"::Text)])
2532 ~?=
2533 [ [" some comment", " some other comment"] ]
2534 , "; some comment \\n = Right \" some comment \"" ~:
2535 (Data.Either.rights $
2536 [P.runParser
2537 (Format.Ledger.Read.comments <* P.string "\n" <* P.eof)
2538 () "" ("; some comment \n"::Text)])
2539 ~?=
2540 [ [" some comment "] ]
2541 ]
2542 , "tag_value" ~: TestList
2543 [ "," ~:
2544 (Data.Either.rights $
2545 [P.runParser
2546 (Format.Ledger.Read.tag_value <* P.eof)
2547 () "" (","::Text)])
2548 ~?=
2549 [","]
2550 , ",\\n" ~:
2551 (Data.Either.rights $
2552 [P.runParser
2553 (Format.Ledger.Read.tag_value <* P.char '\n' <* P.eof)
2554 () "" (",\n"::Text)])
2555 ~?=
2556 [","]
2557 , ",x" ~:
2558 (Data.Either.rights $
2559 [P.runParser
2560 (Format.Ledger.Read.tag_value <* P.eof)
2561 () "" (",x"::Text)])
2562 ~?=
2563 [",x"]
2564 , ",x:" ~:
2565 (Data.Either.rights $
2566 [P.runParser
2567 (Format.Ledger.Read.tag_value <* P.string ",x:" <* P.eof)
2568 () "" (",x:"::Text)])
2569 ~?=
2570 [""]
2571 , "v, v, n:" ~:
2572 (Data.Either.rights $
2573 [P.runParser
2574 (Format.Ledger.Read.tag_value <* P.string ", n:" <* P.eof)
2575 () "" ("v, v, n:"::Text)])
2576 ~?=
2577 ["v, v"]
2578 ]
2579 , "tag" ~: TestList
2580 [ "Name:" ~:
2581 (Data.Either.rights $
2582 [P.runParser
2583 (Format.Ledger.Read.tag <* P.eof)
2584 () "" ("Name:"::Text)])
2585 ~?=
2586 [("Name", "")]
2587 , "Name:Value" ~:
2588 (Data.Either.rights $
2589 [P.runParser
2590 (Format.Ledger.Read.tag <* P.eof)
2591 () "" ("Name:Value"::Text)])
2592 ~?=
2593 [("Name", "Value")]
2594 , "Name:Value\\n" ~:
2595 (Data.Either.rights $
2596 [P.runParser
2597 (Format.Ledger.Read.tag <* P.string "\n" <* P.eof)
2598 () "" ("Name:Value\n"::Text)])
2599 ~?=
2600 [("Name", "Value")]
2601 , "Name:Val ue" ~:
2602 (Data.Either.rights $
2603 [P.runParser
2604 (Format.Ledger.Read.tag <* P.eof)
2605 () "" ("Name:Val ue"::Text)])
2606 ~?=
2607 [("Name", "Val ue")]
2608 , "Name:," ~:
2609 (Data.Either.rights $
2610 [P.runParser
2611 (Format.Ledger.Read.tag <* P.eof)
2612 () "" ("Name:,"::Text)])
2613 ~?=
2614 [("Name", ",")]
2615 , "Name:Val,ue" ~:
2616 (Data.Either.rights $
2617 [P.runParser
2618 (Format.Ledger.Read.tag <* P.eof)
2619 () "" ("Name:Val,ue"::Text)])
2620 ~?=
2621 [("Name", "Val,ue")]
2622 , "Name:Val,ue:" ~:
2623 (Data.Either.rights $
2624 [P.runParser
2625 (Format.Ledger.Read.tag <* P.string ",ue:" <* P.eof)
2626 () "" ("Name:Val,ue:"::Text)])
2627 ~?=
2628 [("Name", "Val")]
2629 ]
2630 , "tags" ~: TestList
2631 [ "Name:" ~:
2632 (Data.Either.rights $
2633 [P.runParser
2634 (Format.Ledger.Read.tags <* P.eof)
2635 () "" ("Name:"::Text)])
2636 ~?=
2637 [Data.Map.fromList
2638 [ ("Name", [""])
2639 ]
2640 ]
2641 , "Name:," ~:
2642 (Data.Either.rights $
2643 [P.runParser
2644 (Format.Ledger.Read.tags <* P.eof)
2645 () "" ("Name:,"::Text)])
2646 ~?=
2647 [Data.Map.fromList
2648 [ ("Name", [","])
2649 ]
2650 ]
2651 , "Name:,Name:" ~:
2652 (Data.Either.rights $
2653 [P.runParser
2654 (Format.Ledger.Read.tags <* P.eof)
2655 () "" ("Name:,Name:"::Text)])
2656 ~?=
2657 [Data.Map.fromList
2658 [ ("Name", ["", ""])
2659 ]
2660 ]
2661 , "Name:,Name2:" ~:
2662 (Data.Either.rights $
2663 [P.runParser
2664 (Format.Ledger.Read.tags <* P.eof)
2665 () "" ("Name:,Name2:"::Text)])
2666 ~?=
2667 [Data.Map.fromList
2668 [ ("Name", [""])
2669 , ("Name2", [""])
2670 ]
2671 ]
2672 , "Name: , Name2:" ~:
2673 (Data.Either.rights $
2674 [P.runParser
2675 (Format.Ledger.Read.tags <* P.eof)
2676 () "" ("Name: , Name2:"::Text)])
2677 ~?=
2678 [Data.Map.fromList
2679 [ ("Name", [" "])
2680 , ("Name2", [""])
2681 ]
2682 ]
2683 , "Name:,Name2:,Name3:" ~:
2684 (Data.Either.rights $
2685 [P.runParser
2686 (Format.Ledger.Read.tags <* P.eof)
2687 () "" ("Name:,Name2:,Name3:"::Text)])
2688 ~?=
2689 [Data.Map.fromList
2690 [ ("Name", [""])
2691 , ("Name2", [""])
2692 , ("Name3", [""])
2693 ]
2694 ]
2695 , "Name:Val ue,Name2:V a l u e,Name3:V al ue" ~:
2696 (Data.Either.rights $
2697 [P.runParser
2698 (Format.Ledger.Read.tags <* P.eof)
2699 () "" ("Name:Val ue,Name2:V a l u e,Name3:V al ue"::Text)])
2700 ~?=
2701 [Data.Map.fromList
2702 [ ("Name", ["Val ue"])
2703 , ("Name2", ["V a l u e"])
2704 , ("Name3", ["V al ue"])
2705 ]
2706 ]
2707 ]
2708 , "posting" ~: TestList
2709 [ " A:B:C = Right A:B:C" ~:
2710 (Data.Either.rights $
2711 [P.runParser_with_Error
2712 (Format.Ledger.Read.posting <* P.eof)
2713 Format.Ledger.Read.nil_Context "" (" A:B:C"::Text)])
2714 ~?=
2715 [ ( (Format.Ledger.posting ("A":|["B", "C"]))
2716 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2717 }
2718 , Format.Ledger.Posting_Type_Regular
2719 )
2720 ]
2721 , " !A:B:C = Right !A:B:C" ~:
2722 (Data.List.map fst $
2723 Data.Either.rights $
2724 [P.runParser_with_Error
2725 (Format.Ledger.Read.posting <* P.eof)
2726 Format.Ledger.Read.nil_Context "" (" !A:B:C"::Text)])
2727 ~?=
2728 [ (Format.Ledger.posting ("A":|["B", "C"]))
2729 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2730 , Format.Ledger.posting_status = True
2731 }
2732 ]
2733 , " *A:B:C = Right *A:B:C" ~:
2734 (Data.List.map fst $
2735 Data.Either.rights $
2736 [P.runParser_with_Error
2737 (Format.Ledger.Read.posting <* P.eof)
2738 Format.Ledger.Read.nil_Context "" (" *A:B:C"::Text)])
2739 ~?=
2740 [ (Format.Ledger.posting ("A":|["B", "C"]))
2741 { Format.Ledger.posting_amounts = Data.Map.fromList []
2742 , Format.Ledger.posting_comments = []
2743 , Format.Ledger.posting_dates = []
2744 , Format.Ledger.posting_status = True
2745 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2746 , Format.Ledger.posting_tags = Data.Map.fromList []
2747 }
2748 ]
2749 , " A:B:C $1 = Right A:B:C $1" ~:
2750 (Data.List.map fst $
2751 Data.Either.rights $
2752 [P.runParser_with_Error
2753 (Format.Ledger.Read.posting <* P.eof)
2754 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
2755 ~?=
2756 [ (Format.Ledger.posting ("A":|["B","C $1"]))
2757 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2758 }
2759 ]
2760 , " A:B:C $1 = Right A:B:C $1" ~:
2761 (Data.List.map fst $
2762 Data.Either.rights $
2763 [P.runParser_with_Error
2764 (Format.Ledger.Read.posting <* P.eof)
2765 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
2766 ~?=
2767 [ (Format.Ledger.posting ("A":|["B", "C"]))
2768 { Format.Ledger.posting_amounts = Data.Map.fromList
2769 [ ("$", Amount.nil
2770 { Amount.quantity = 1
2771 , Amount.style = Amount.Style.nil
2772 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2773 , Amount.Style.unit_spaced = Just False
2774 }
2775 , Amount.unit = "$"
2776 })
2777 ]
2778 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2779 }
2780 ]
2781 , " A:B:C $1 + 1€ = Right A:B:C $1 + 1€" ~:
2782 (Data.List.map fst $
2783 Data.Either.rights $
2784 [P.runParser_with_Error
2785 (Format.Ledger.Read.posting <* P.eof)
2786 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1€"::Text)])
2787 ~?=
2788 [ (Format.Ledger.posting ("A":|["B", "C"]))
2789 { Format.Ledger.posting_amounts = Data.Map.fromList
2790 [ ("$", Amount.nil
2791 { Amount.quantity = 1
2792 , Amount.style = Amount.Style.nil
2793 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2794 , Amount.Style.unit_spaced = Just False
2795 }
2796 , Amount.unit = "$"
2797 })
2798 , ("€", Amount.nil
2799 { Amount.quantity = 1
2800 , Amount.style = Amount.Style.nil
2801 { Amount.Style.unit_side = Just Amount.Style.Side_Right
2802 , Amount.Style.unit_spaced = Just False
2803 }
2804 , Amount.unit = "€"
2805 })
2806 ]
2807 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2808 }
2809 ]
2810 , " A:B:C $1 + 1$ = Right A:B:C $2" ~:
2811 (Data.List.map fst $
2812 Data.Either.rights $
2813 [P.runParser_with_Error
2814 (Format.Ledger.Read.posting <* P.eof)
2815 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$"::Text)])
2816 ~?=
2817 [ (Format.Ledger.posting ("A":|["B", "C"]))
2818 { Format.Ledger.posting_amounts = Data.Map.fromList
2819 [ ("$", Amount.nil
2820 { Amount.quantity = 2
2821 , Amount.style = Amount.Style.nil
2822 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2823 , Amount.Style.unit_spaced = Just False
2824 }
2825 , Amount.unit = "$"
2826 })
2827 ]
2828 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2829 }
2830 ]
2831 , " A:B:C $1 + 1$ + 1$ = Right A:B:C $3" ~:
2832 (Data.List.map fst $
2833 Data.Either.rights $
2834 [P.runParser_with_Error
2835 (Format.Ledger.Read.posting <* P.eof)
2836 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$ + 1$"::Text)])
2837 ~?=
2838 [ (Format.Ledger.posting ("A":|["B", "C"]))
2839 { Format.Ledger.posting_amounts = Data.Map.fromList
2840 [ ("$", Amount.nil
2841 { Amount.quantity = 3
2842 , Amount.style = Amount.Style.nil
2843 { Amount.Style.unit_side = Just Amount.Style.Side_Left
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 ; some comment = Right A:B:C ; some comment" ~:
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 ; some comment"::Text)])
2858 ~?=
2859 [ (Format.Ledger.posting ("A":|["B", "C"]))
2860 { Format.Ledger.posting_amounts = Data.Map.fromList []
2861 , Format.Ledger.posting_comments = [" some comment"]
2862 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2863 }
2864 ]
2865 , " A:B:C ; some comment\\n ; some other comment = Right A:B:C ; some comment\\n ; some other comment" ~:
2866 (Data.List.map fst $
2867 Data.Either.rights $
2868 [P.runParser_with_Error
2869 (Format.Ledger.Read.posting <* P.eof)
2870 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment\n ; some other comment"::Text)])
2871 ~?=
2872 [ (Format.Ledger.posting ("A":|["B", "C"]))
2873 { Format.Ledger.posting_amounts = Data.Map.fromList []
2874 , Format.Ledger.posting_comments = [" some comment", " some other comment"]
2875 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2876 }
2877 ]
2878 , " A:B:C $1 ; some comment = Right A:B:C $1 ; some comment" ~:
2879 (Data.List.map fst $
2880 Data.Either.rights $
2881 [P.runParser_with_Error
2882 (Format.Ledger.Read.posting)
2883 Format.Ledger.Read.nil_Context "" (" A:B:C $1 ; some comment"::Text)])
2884 ~?=
2885 [ (Format.Ledger.posting ("A":|["B", "C"]))
2886 { Format.Ledger.posting_amounts = Data.Map.fromList
2887 [ ("$", Amount.nil
2888 { Amount.quantity = 1
2889 , Amount.style = Amount.Style.nil
2890 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2891 , Amount.Style.unit_spaced = Just False
2892 }
2893 , Amount.unit = "$"
2894 })
2895 ]
2896 , Format.Ledger.posting_comments = [" some comment"]
2897 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2898 }
2899 ]
2900 , " A:B:C ; N:V = Right A:B:C ; N:V" ~:
2901 (Data.List.map fst $
2902 Data.Either.rights $
2903 [P.runParser_with_Error
2904 (Format.Ledger.Read.posting <* P.eof)
2905 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V"::Text)])
2906 ~?=
2907 [ (Format.Ledger.posting ("A":|["B", "C"]))
2908 { Format.Ledger.posting_comments = [" N:V"]
2909 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2910 , Format.Ledger.posting_tags = Data.Map.fromList
2911 [ ("N", ["V"])
2912 ]
2913 }
2914 ]
2915 , " A:B:C ; some comment N:V = Right A:B:C ; some comment N:V" ~:
2916 (Data.List.map fst $
2917 Data.Either.rights $
2918 [P.runParser_with_Error
2919 (Format.Ledger.Read.posting <* P.eof)
2920 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V"::Text)])
2921 ~?=
2922 [ (Format.Ledger.posting ("A":|["B", "C"]))
2923 { Format.Ledger.posting_comments = [" some comment N:V"]
2924 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2925 , Format.Ledger.posting_tags = Data.Map.fromList
2926 [ ("N", ["V"])
2927 ]
2928 }
2929 ]
2930 , " A:B:C ; some comment N:V v, N2:V2 v2 = Right A:B:C ; some comment N:V v, N2:V2 v2" ~:
2931 (Data.List.map fst $
2932 Data.Either.rights $
2933 [P.runParser_with_Error
2934 (Format.Ledger.Read.posting )
2935 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V v, N2:V2 v2"::Text)])
2936 ~?=
2937 [ (Format.Ledger.posting ("A":|["B", "C"]))
2938 { Format.Ledger.posting_comments = [" some comment N:V v, N2:V2 v2"]
2939 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2940 , Format.Ledger.posting_tags = Data.Map.fromList
2941 [ ("N", ["V v"])
2942 , ("N2", ["V2 v2"])
2943 ]
2944 }
2945 ]
2946 , " A:B:C ; N:V\\n ; N:V2 = Right A:B:C ; N:V\\n ; N:V2" ~:
2947 (Data.List.map fst $
2948 Data.Either.rights $
2949 [P.runParser_with_Error
2950 (Format.Ledger.Read.posting <* P.eof)
2951 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N:V2"::Text)])
2952 ~?=
2953 [ (Format.Ledger.posting ("A":|["B", "C"]))
2954 { Format.Ledger.posting_comments = [" N:V", " N:V2"]
2955 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2956 , Format.Ledger.posting_tags = Data.Map.fromList
2957 [ ("N", ["V", "V2"])
2958 ]
2959 }
2960 ]
2961 , " A:B:C ; N:V\\n ; N2:V = Right A:B:C ; N:V\\n ; N2:V" ~:
2962 (Data.List.map fst $
2963 Data.Either.rights $
2964 [P.runParser_with_Error
2965 (Format.Ledger.Read.posting <* P.eof)
2966 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N2:V"::Text)])
2967 ~?=
2968 [ (Format.Ledger.posting ("A":|["B", "C"]))
2969 { Format.Ledger.posting_comments = [" N:V", " N2:V"]
2970 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2971 , Format.Ledger.posting_tags = Data.Map.fromList
2972 [ ("N", ["V"])
2973 , ("N2", ["V"])
2974 ]
2975 }
2976 ]
2977 , " A:B:C ; date:2001/01/01 = Right A:B:C ; date:2001/01/01" ~:
2978 (Data.List.map fst $
2979 Data.Either.rights $
2980 [P.runParser_with_Error
2981 (Format.Ledger.Read.posting <* P.eof)
2982 Format.Ledger.Read.nil_Context "" (" A:B:C ; date:2001/01/01"::Text)])
2983 ~?=
2984 [ (Format.Ledger.posting ("A":|["B", "C"]))
2985 { Format.Ledger.posting_comments = [" date:2001/01/01"]
2986 , Format.Ledger.posting_dates =
2987 [ Time.zonedTimeToUTC $
2988 Time.ZonedTime
2989 (Time.LocalTime
2990 (Time.fromGregorian 2001 01 01)
2991 (Time.TimeOfDay 0 0 0))
2992 Time.utc
2993 ]
2994 , Format.Ledger.posting_sourcepos = P.newPos "" 1 1
2995 , Format.Ledger.posting_tags = Data.Map.fromList
2996 [ ("date", ["2001/01/01"])
2997 ]
2998 }
2999 ]
3000 , " (A:B:C) = Right (A:B:C)" ~:
3001 (Data.Either.rights $
3002 [P.runParser_with_Error
3003 (Format.Ledger.Read.posting <* P.eof)
3004 Format.Ledger.Read.nil_Context "" (" (A:B:C)"::Text)])
3005 ~?=
3006 [ ( (Format.Ledger.posting ("A":|["B", "C"]))
3007 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
3008 }
3009 , Format.Ledger.Posting_Type_Virtual
3010 )
3011 ]
3012 , " [A:B:C] = Right [A:B:C]" ~:
3013 (Data.Either.rights $
3014 [P.runParser_with_Error
3015 (Format.Ledger.Read.posting <* P.eof)
3016 Format.Ledger.Read.nil_Context "" (" [A:B:C]"::Text)])
3017 ~?=
3018 [ ( (Format.Ledger.posting ("A":|["B", "C"]))
3019 { Format.Ledger.posting_sourcepos = P.newPos "" 1 1
3020 }
3021 , Format.Ledger.Posting_Type_Virtual_Balanced
3022 )
3023 ]
3024 ]
3025 , "transaction" ~: TestList
3026 [ "2000/01/01 some description\\n A:B:C $1\\n a:b:c" ~:
3027 (Data.Either.rights $
3028 [P.runParser_with_Error
3029 (Format.Ledger.Read.transaction <* P.eof)
3030 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c"::Text)])
3031 ~?=
3032 [ Format.Ledger.transaction
3033 { Format.Ledger.transaction_dates=
3034 ( Time.zonedTimeToUTC $
3035 Time.ZonedTime
3036 (Time.LocalTime
3037 (Time.fromGregorian 2000 01 01)
3038 (Time.TimeOfDay 0 0 0))
3039 (Time.utc)
3040 , [] )
3041 , Format.Ledger.transaction_description="some description"
3042 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3043 [ (Format.Ledger.posting ("A":|["B", "C"]))
3044 { Format.Ledger.posting_amounts = Data.Map.fromList
3045 [ ("$", Amount.nil
3046 { Amount.quantity = 1
3047 , Amount.style = Amount.Style.nil
3048 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3049 , Amount.Style.unit_spaced = Just False
3050 }
3051 , Amount.unit = "$"
3052 })
3053 ]
3054 , Format.Ledger.posting_sourcepos = P.newPos "" 2 1
3055 }
3056 , (Format.Ledger.posting ("a":|["b", "c"]))
3057 { Format.Ledger.posting_amounts = Data.Map.fromList
3058 [ ("$", Amount.nil
3059 { Amount.quantity = -1
3060 , Amount.style = Amount.Style.nil
3061 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3062 , Amount.Style.unit_spaced = Just False
3063 }
3064 , Amount.unit = "$"
3065 })
3066 ]
3067 , Format.Ledger.posting_sourcepos = P.newPos "" 3 1
3068 }
3069 ]
3070 , Format.Ledger.transaction_sourcepos = P.newPos "" 1 1
3071 }
3072 ]
3073 , "2000/01/01 some description\\n A:B:C $1\\n a:b:c\\n" ~:
3074 (Data.Either.rights $
3075 [P.runParser_with_Error
3076 (Format.Ledger.Read.transaction <* P.newline <* P.eof)
3077 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c\n"::Text)])
3078 ~?=
3079 [ Format.Ledger.transaction
3080 { Format.Ledger.transaction_dates=
3081 ( Time.zonedTimeToUTC $
3082 Time.ZonedTime
3083 (Time.LocalTime
3084 (Time.fromGregorian 2000 01 01)
3085 (Time.TimeOfDay 0 0 0))
3086 (Time.utc)
3087 , [] )
3088 , Format.Ledger.transaction_description="some description"
3089 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3090 [ (Format.Ledger.posting ("A":|["B", "C"]))
3091 { Format.Ledger.posting_amounts = Data.Map.fromList
3092 [ ("$", Amount.nil
3093 { Amount.quantity = 1
3094 , Amount.style = Amount.Style.nil
3095 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3096 , Amount.Style.unit_spaced = Just False
3097 }
3098 , Amount.unit = "$"
3099 })
3100 ]
3101 , Format.Ledger.posting_sourcepos = P.newPos "" 2 1
3102 }
3103 , (Format.Ledger.posting ("a":|["b", "c"]))
3104 { Format.Ledger.posting_amounts = Data.Map.fromList
3105 [ ("$", Amount.nil
3106 { Amount.quantity = -1
3107 , Amount.style = Amount.Style.nil
3108 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3109 , Amount.Style.unit_spaced = Just False
3110 }
3111 , Amount.unit = "$"
3112 })
3113 ]
3114 , Format.Ledger.posting_sourcepos = P.newPos "" 3 1
3115 }
3116 ]
3117 , Format.Ledger.transaction_sourcepos = P.newPos "" 1 1
3118 }
3119 ]
3120 , "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" ~:
3121 (Data.Either.rights $
3122 [P.runParser_with_Error
3123 (Format.Ledger.Read.transaction <* P.eof)
3124 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)])
3125 ~?=
3126 [ Format.Ledger.transaction
3127 { Format.Ledger.transaction_comments_after =
3128 [ " some comment"
3129 , " some other;comment"
3130 , " some Tag:"
3131 , " some last comment"
3132 ]
3133 , Format.Ledger.transaction_dates=
3134 ( Time.zonedTimeToUTC $
3135 Time.ZonedTime
3136 (Time.LocalTime
3137 (Time.fromGregorian 2000 01 01)
3138 (Time.TimeOfDay 0 0 0))
3139 (Time.utc)
3140 , [] )
3141 , Format.Ledger.transaction_description="some description"
3142 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3143 [ (Format.Ledger.posting ("A":|["B", "C"]))
3144 { Format.Ledger.posting_amounts = Data.Map.fromList
3145 [ ("$", Amount.nil
3146 { Amount.quantity = 1
3147 , Amount.style = Amount.Style.nil
3148 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3149 , Amount.Style.unit_spaced = Just False
3150 }
3151 , Amount.unit = "$"
3152 })
3153 ]
3154 , Format.Ledger.posting_sourcepos = P.newPos "" 5 1
3155 }
3156 , (Format.Ledger.posting ("a":|["b", "c"]))
3157 { Format.Ledger.posting_amounts = Data.Map.fromList
3158 [ ("$", Amount.nil
3159 { Amount.quantity = -1
3160 , Amount.style = Amount.Style.nil
3161 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3162 , Amount.Style.unit_spaced = Just False
3163 }
3164 , Amount.unit = "$"
3165 })
3166 ]
3167 , Format.Ledger.posting_sourcepos = P.newPos "" 6 1
3168 }
3169 ]
3170 , Format.Ledger.transaction_tags = Data.Map.fromList
3171 [ ("Tag", [""])
3172 ]
3173 , Format.Ledger.transaction_sourcepos = P.newPos "" 1 1
3174 }
3175 ]
3176 ]
3177 , "journal" ~: TestList
3178 [ "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
3179 jnl <- liftIO $
3180 P.runParserT_with_Error
3181 (Format.Ledger.Read.journal "" {-<* P.eof-})
3182 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)
3183 (Data.List.map
3184 (\j -> j{Format.Ledger.journal_last_read_time=
3185 Format.Ledger.journal_last_read_time Format.Ledger.journal}) $
3186 Data.Either.rights [jnl])
3187 @?=
3188 [ Format.Ledger.journal
3189 { Format.Ledger.journal_transactions =
3190 Format.Ledger.transaction_by_Date
3191 [ Format.Ledger.transaction
3192 { Format.Ledger.transaction_dates=
3193 ( Time.zonedTimeToUTC $
3194 Time.ZonedTime
3195 (Time.LocalTime
3196 (Time.fromGregorian 2000 01 01)
3197 (Time.TimeOfDay 0 0 0))
3198 (Time.utc)
3199 , [] )
3200 , Format.Ledger.transaction_description="1° description"
3201 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3202 [ (Format.Ledger.posting ("A":|["B", "C"]))
3203 { Format.Ledger.posting_amounts = Data.Map.fromList
3204 [ ("$", Amount.nil
3205 { Amount.quantity = 1
3206 , Amount.style = Amount.Style.nil
3207 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3208 , Amount.Style.unit_spaced = Just False
3209 }
3210 , Amount.unit = "$"
3211 })
3212 ]
3213 , Format.Ledger.posting_sourcepos = P.newPos "" 2 1
3214 }
3215 , (Format.Ledger.posting ("a":|["b", "c"]))
3216 { Format.Ledger.posting_amounts = Data.Map.fromList
3217 [ ("$", Amount.nil
3218 { Amount.quantity = -1
3219 , Amount.style = Amount.Style.nil
3220 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3221 , Amount.Style.unit_spaced = Just False
3222 }
3223 , Amount.unit = "$"
3224 })
3225 ]
3226 , Format.Ledger.posting_sourcepos = P.newPos "" 3 1
3227 }
3228 ]
3229 , Format.Ledger.transaction_sourcepos = P.newPos "" 1 1
3230 }
3231 , Format.Ledger.transaction
3232 { Format.Ledger.transaction_dates=
3233 ( Time.zonedTimeToUTC $
3234 Time.ZonedTime
3235 (Time.LocalTime
3236 (Time.fromGregorian 2000 01 02)
3237 (Time.TimeOfDay 0 0 0))
3238 (Time.utc)
3239 , [] )
3240 , Format.Ledger.transaction_description="2° description"
3241 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3242 [ (Format.Ledger.posting ("A":|["B", "C"]))
3243 { Format.Ledger.posting_amounts = Data.Map.fromList
3244 [ ("$", Amount.nil
3245 { Amount.quantity = 1
3246 , Amount.style = Amount.Style.nil
3247 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3248 , Amount.Style.unit_spaced = Just False
3249 }
3250 , Amount.unit = "$"
3251 })
3252 ]
3253 , Format.Ledger.posting_sourcepos = P.newPos "" 5 1
3254 }
3255 , (Format.Ledger.posting ("x":|["y", "z"]))
3256 { Format.Ledger.posting_amounts = Data.Map.fromList
3257 [ ("$", Amount.nil
3258 { Amount.quantity = -1
3259 , Amount.style = Amount.Style.nil
3260 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3261 , Amount.Style.unit_spaced = Just False
3262 }
3263 , Amount.unit = "$"
3264 })
3265 ]
3266 , Format.Ledger.posting_sourcepos = P.newPos "" 6 1
3267 }
3268 ]
3269 , Format.Ledger.transaction_sourcepos = P.newPos "" 4 1
3270 }
3271 ]
3272 }
3273 ]
3274 ]
3275 ]
3276 , "Write" ~: TestList
3277 [ "account" ~: TestList
3278 [ "A" ~:
3279 ((Format.Ledger.Write.show
3280 Format.Ledger.Write.Style
3281 { Format.Ledger.Write.style_color=False
3282 , Format.Ledger.Write.style_align=True
3283 } $
3284 Format.Ledger.Write.account Format.Ledger.Posting_Type_Regular $
3285 "A":|[])
3286 ~?=
3287 "A")
3288 , "A:B:C" ~:
3289 ((Format.Ledger.Write.show
3290 Format.Ledger.Write.Style
3291 { Format.Ledger.Write.style_color=False
3292 , Format.Ledger.Write.style_align=True
3293 } $
3294 Format.Ledger.Write.account Format.Ledger.Posting_Type_Regular $
3295 "A":|["B", "C"])
3296 ~?=
3297 "A:B:C")
3298 , "(A:B:C)" ~:
3299 ((Format.Ledger.Write.show
3300 Format.Ledger.Write.Style
3301 { Format.Ledger.Write.style_color=False
3302 , Format.Ledger.Write.style_align=True
3303 } $
3304 Format.Ledger.Write.account Format.Ledger.Posting_Type_Virtual $
3305 "A":|["B", "C"])
3306 ~?=
3307 "(A:B:C)")
3308 , "[A:B:C]" ~:
3309 ((Format.Ledger.Write.show
3310 Format.Ledger.Write.Style
3311 { Format.Ledger.Write.style_color=False
3312 , Format.Ledger.Write.style_align=True
3313 } $
3314 Format.Ledger.Write.account Format.Ledger.Posting_Type_Virtual_Balanced $
3315 "A":|["B", "C"])
3316 ~?=
3317 "[A:B:C]")
3318 ]
3319 , "amount" ~: TestList
3320 [ "nil" ~:
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.amount
3327 Amount.nil)
3328 ~?=
3329 "0")
3330 , "nil @ prec=2" ~:
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.amount
3337 Amount.nil
3338 { Amount.style = Amount.Style.nil
3339 { Amount.Style.precision = 2 }
3340 })
3341 ~?=
3342 "0.00")
3343 , "123" ~:
3344 ((Format.Ledger.Write.show
3345 Format.Ledger.Write.Style
3346 { Format.Ledger.Write.style_color=False
3347 , Format.Ledger.Write.style_align=True
3348 } $
3349 Format.Ledger.Write.amount
3350 Amount.nil
3351 { Amount.quantity = Decimal 0 123
3352 })
3353 ~?=
3354 "123")
3355 , "-123" ~:
3356 ((Format.Ledger.Write.show
3357 Format.Ledger.Write.Style
3358 { Format.Ledger.Write.style_color=False
3359 , Format.Ledger.Write.style_align=True
3360 } $
3361 Format.Ledger.Write.amount
3362 Amount.nil
3363 { Amount.quantity = Decimal 0 (- 123)
3364 })
3365 ~?=
3366 "-123")
3367 , "12.3 @ prec=0" ~:
3368 ((Format.Ledger.Write.show
3369 Format.Ledger.Write.Style
3370 { Format.Ledger.Write.style_color=False
3371 , Format.Ledger.Write.style_align=True
3372 } $
3373 Format.Ledger.Write.amount
3374 Amount.nil
3375 { Amount.quantity = Decimal 1 123
3376 , Amount.style = Amount.Style.nil
3377 { Amount.Style.fractioning = Just '.'
3378 }
3379 })
3380 ~?=
3381 "12")
3382 , "12.5 @ prec=0" ~:
3383 ((Format.Ledger.Write.show
3384 Format.Ledger.Write.Style
3385 { Format.Ledger.Write.style_color=False
3386 , Format.Ledger.Write.style_align=True
3387 } $
3388 Format.Ledger.Write.amount
3389 Amount.nil
3390 { Amount.quantity = Decimal 1 125
3391 , Amount.style = Amount.Style.nil
3392 { Amount.Style.fractioning = Just '.'
3393 }
3394 })
3395 ~?=
3396 "13")
3397 , "12.3 @ prec=1" ~:
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 1 123
3406 , Amount.style = Amount.Style.nil
3407 { Amount.Style.fractioning = Just '.'
3408 , Amount.Style.precision = 1
3409 }
3410 })
3411 ~?=
3412 "12.3")
3413 , "1,234.56 @ prec=2" ~:
3414 ((Format.Ledger.Write.show
3415 Format.Ledger.Write.Style
3416 { Format.Ledger.Write.style_color=False
3417 , Format.Ledger.Write.style_align=True
3418 } $
3419 Format.Ledger.Write.amount
3420 Amount.nil
3421 { Amount.quantity = Decimal 2 123456
3422 , Amount.style = Amount.Style.nil
3423 { Amount.Style.fractioning = Just '.'
3424 , Amount.Style.precision = 2
3425 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
3426 }
3427 })
3428 ~?=
3429 "1,234.56")
3430 , "123,456,789,01,2.3456789 @ prec=7" ~:
3431 ((Format.Ledger.Write.show
3432 Format.Ledger.Write.Style
3433 { Format.Ledger.Write.style_color=False
3434 , Format.Ledger.Write.style_align=True
3435 } $
3436 Format.Ledger.Write.amount
3437 Amount.nil
3438 { Amount.quantity = Decimal 7 1234567890123456789
3439 , Amount.style = Amount.Style.nil
3440 { Amount.Style.fractioning = Just '.'
3441 , Amount.Style.precision = 7
3442 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3443 }
3444 })
3445 ~?=
3446 "123,456,789,01,2.3456789")
3447 , "1234567.8,90,123,456,789 @ prec=12" ~:
3448 ((Format.Ledger.Write.show
3449 Format.Ledger.Write.Style
3450 { Format.Ledger.Write.style_color=False
3451 , Format.Ledger.Write.style_align=True
3452 } $
3453 Format.Ledger.Write.amount
3454 Amount.nil
3455 { Amount.quantity = Decimal 12 1234567890123456789
3456 , Amount.style = Amount.Style.nil
3457 { Amount.Style.fractioning = Just '.'
3458 , Amount.Style.precision = 12
3459 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3460 }
3461 })
3462 ~?=
3463 "1234567.8,90,123,456,789")
3464 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
3465 ((Format.Ledger.Write.show
3466 Format.Ledger.Write.Style
3467 { Format.Ledger.Write.style_color=False
3468 , Format.Ledger.Write.style_align=True
3469 } $
3470 Format.Ledger.Write.amount
3471 Amount.nil
3472 { Amount.quantity = Decimal 7 1234567890123456789
3473 , Amount.style = Amount.Style.nil
3474 { Amount.Style.fractioning = Just '.'
3475 , Amount.Style.precision = 7
3476 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3477 }
3478 })
3479 ~?=
3480 "1,2,3,4,5,6,7,89,012.3456789")
3481 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
3482 ((Format.Ledger.Write.show
3483 Format.Ledger.Write.Style
3484 { Format.Ledger.Write.style_color=False
3485 , Format.Ledger.Write.style_align=True
3486 } $
3487 Format.Ledger.Write.amount
3488 Amount.nil
3489 { Amount.quantity = Decimal 12 1234567890123456789
3490 , Amount.style = Amount.Style.nil
3491 { Amount.Style.fractioning = Just '.'
3492 , Amount.Style.precision = 12
3493 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3494 }
3495 })
3496 ~?=
3497 "1234567.890,12,3,4,5,6,7,8,9")
3498 ]
3499 , "amount_length" ~: TestList
3500 [ "nil" ~:
3501 ((Format.Ledger.Write.amount_length
3502 Amount.nil)
3503 ~?=
3504 1)
3505 , "nil @ prec=2" ~:
3506 ((Format.Ledger.Write.amount_length
3507 Amount.nil
3508 { Amount.style = Amount.Style.nil
3509 { Amount.Style.precision = 2 }
3510 })
3511 ~?=
3512 4)
3513 , "123" ~:
3514 ((Format.Ledger.Write.amount_length
3515 Amount.nil
3516 { Amount.quantity = Decimal 0 123
3517 })
3518 ~?=
3519 3)
3520 , "-123" ~:
3521 ((Format.Ledger.Write.amount_length
3522 Amount.nil
3523 { Amount.quantity = Decimal 0 (- 123)
3524 })
3525 ~?=
3526 4)
3527 , "12.3 @ prec=0" ~:
3528 ((Format.Ledger.Write.amount_length
3529 Amount.nil
3530 { Amount.quantity = Decimal 1 123
3531 , Amount.style = Amount.Style.nil
3532 { Amount.Style.fractioning = Just '.'
3533 }
3534 })
3535 ~?=
3536 2)
3537 , "12.5 @ prec=0" ~:
3538 ((Format.Ledger.Write.amount_length
3539 Amount.nil
3540 { Amount.quantity = Decimal 1 125
3541 , Amount.style = Amount.Style.nil
3542 { Amount.Style.fractioning = Just '.'
3543 }
3544 })
3545 ~?=
3546 2)
3547 , "12.3 @ prec=1" ~:
3548 ((Format.Ledger.Write.amount_length
3549 Amount.nil
3550 { Amount.quantity = Decimal 1 123
3551 , Amount.style = Amount.Style.nil
3552 { Amount.Style.fractioning = Just '.'
3553 , Amount.Style.precision = 1
3554 }
3555 })
3556 ~?=
3557 4)
3558 , "1,234.56 @ prec=2" ~:
3559 ((Format.Ledger.Write.amount_length
3560 Amount.nil
3561 { Amount.quantity = Decimal 2 123456
3562 , Amount.style = Amount.Style.nil
3563 { Amount.Style.fractioning = Just '.'
3564 , Amount.Style.precision = 2
3565 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
3566 }
3567 })
3568 ~?=
3569 8)
3570 , "123,456,789,01,2.3456789 @ prec=7" ~:
3571 ((Format.Ledger.Write.amount_length
3572 Amount.nil
3573 { Amount.quantity = Decimal 7 1234567890123456789
3574 , Amount.style = Amount.Style.nil
3575 { Amount.Style.fractioning = Just '.'
3576 , Amount.Style.precision = 7
3577 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3578 }
3579 })
3580 ~?=
3581 24)
3582 , "1234567.8,90,123,456,789 @ prec=12" ~:
3583 ((Format.Ledger.Write.amount_length
3584 Amount.nil
3585 { Amount.quantity = Decimal 12 1234567890123456789
3586 , Amount.style = Amount.Style.nil
3587 { Amount.Style.fractioning = Just '.'
3588 , Amount.Style.precision = 12
3589 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3590 }
3591 })
3592 ~?=
3593 24)
3594 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
3595 ((Format.Ledger.Write.amount_length
3596 Amount.nil
3597 { Amount.quantity = Decimal 7 1234567890123456789
3598 , Amount.style = Amount.Style.nil
3599 { Amount.Style.fractioning = Just '.'
3600 , Amount.Style.precision = 7
3601 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3602 }
3603 })
3604 ~?=
3605 28)
3606 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
3607 ((Format.Ledger.Write.amount_length
3608 Amount.nil
3609 { Amount.quantity = Decimal 12 1234567890123456789
3610 , Amount.style = Amount.Style.nil
3611 { Amount.Style.fractioning = Just '.'
3612 , Amount.Style.precision = 12
3613 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3614 }
3615 })
3616 ~?=
3617 28)
3618 , "1000000.000,00,0,0,0,0,0,0,0 @ prec=12" ~:
3619 ((Format.Ledger.Write.amount_length
3620 Amount.nil
3621 { Amount.quantity = Decimal 12 1000000000000000000
3622 , Amount.style = Amount.Style.nil
3623 { Amount.Style.fractioning = Just '.'
3624 , Amount.Style.precision = 12
3625 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3626 }
3627 })
3628 ~?=
3629 28)
3630 , "999 @ prec=0" ~:
3631 ((Format.Ledger.Write.amount_length $
3632 Amount.nil
3633 { Amount.quantity = Decimal 0 999
3634 , Amount.style = Amount.Style.nil
3635 { Amount.Style.precision = 0
3636 }
3637 })
3638 ~?=
3639 3)
3640 , "1000 @ prec=0" ~:
3641 ((Format.Ledger.Write.amount_length $
3642 Amount.nil
3643 { Amount.quantity = Decimal 0 1000
3644 , Amount.style = Amount.Style.nil
3645 { Amount.Style.precision = 0
3646 }
3647 })
3648 ~?=
3649 4)
3650 , "10,00€ @ prec=2" ~:
3651 ((Format.Ledger.Write.amount_length $ Amount.eur 10)
3652 ~?=
3653 6)
3654 ]
3655 , "date" ~: TestList
3656 [ "nil" ~:
3657 ((Format.Ledger.Write.show
3658 Format.Ledger.Write.Style
3659 { Format.Ledger.Write.style_color=False
3660 , Format.Ledger.Write.style_align=True
3661 } $
3662 Format.Ledger.Write.date
3663 Date.nil)
3664 ~?=
3665 "1970/01/01")
3666 , "2000/01/01 12:34:51 CET" ~:
3667 (Format.Ledger.Write.show
3668 Format.Ledger.Write.Style
3669 { Format.Ledger.Write.style_color=False
3670 , Format.Ledger.Write.style_align=True
3671 } $
3672 Format.Ledger.Write.date $
3673 Time.zonedTimeToUTC $
3674 Time.ZonedTime
3675 (Time.LocalTime
3676 (Time.fromGregorian 2000 01 01)
3677 (Time.TimeOfDay 12 34 51))
3678 (Time.TimeZone 60 False "CET"))
3679 ~?=
3680 "2000/01/01 11:34:51"
3681 , "2000/01/01 12:34:51 +0100" ~:
3682 (Format.Ledger.Write.show
3683 Format.Ledger.Write.Style
3684 { Format.Ledger.Write.style_color=False
3685 , Format.Ledger.Write.style_align=True
3686 } $
3687 Format.Ledger.Write.date $
3688 Time.zonedTimeToUTC $
3689 Time.ZonedTime
3690 (Time.LocalTime
3691 (Time.fromGregorian 2000 01 01)
3692 (Time.TimeOfDay 12 34 51))
3693 (Time.TimeZone 60 False ""))
3694 ~?=
3695 "2000/01/01 11:34:51"
3696 , "2000/01/01 01:02:03" ~:
3697 (Format.Ledger.Write.show
3698 Format.Ledger.Write.Style
3699 { Format.Ledger.Write.style_color=False
3700 , Format.Ledger.Write.style_align=True
3701 } $
3702 Format.Ledger.Write.date $
3703 Time.zonedTimeToUTC $
3704 Time.ZonedTime
3705 (Time.LocalTime
3706 (Time.fromGregorian 2000 01 01)
3707 (Time.TimeOfDay 1 2 3))
3708 (Time.utc))
3709 ~?=
3710 "2000/01/01 01:02:03"
3711 , "01/01 01:02" ~:
3712 (Format.Ledger.Write.show
3713 Format.Ledger.Write.Style
3714 { Format.Ledger.Write.style_color=False
3715 , Format.Ledger.Write.style_align=True
3716 } $
3717 Format.Ledger.Write.date $
3718 Time.zonedTimeToUTC $
3719 Time.ZonedTime
3720 (Time.LocalTime
3721 (Time.fromGregorian 0 01 01)
3722 (Time.TimeOfDay 1 2 0))
3723 (Time.utc))
3724 ~?=
3725 "01/01 01:02"
3726 , "01/01 01:00" ~:
3727 (Format.Ledger.Write.show
3728 Format.Ledger.Write.Style
3729 { Format.Ledger.Write.style_color=False
3730 , Format.Ledger.Write.style_align=True
3731 } $
3732 Format.Ledger.Write.date $
3733 Time.zonedTimeToUTC $
3734 Time.ZonedTime
3735 (Time.LocalTime
3736 (Time.fromGregorian 0 01 01)
3737 (Time.TimeOfDay 1 0 0))
3738 (Time.utc))
3739 ~?=
3740 "01/01 01:00"
3741 , "01/01 00:01" ~:
3742 (Format.Ledger.Write.show
3743 Format.Ledger.Write.Style
3744 { Format.Ledger.Write.style_color=False
3745 , Format.Ledger.Write.style_align=True
3746 } $
3747 Format.Ledger.Write.date $
3748 Time.zonedTimeToUTC $
3749 Time.ZonedTime
3750 (Time.LocalTime
3751 (Time.fromGregorian 0 01 01)
3752 (Time.TimeOfDay 0 1 0))
3753 (Time.utc))
3754 ~?=
3755 "01/01 00:01"
3756 , "01/01" ~:
3757 (Format.Ledger.Write.show
3758 Format.Ledger.Write.Style
3759 { Format.Ledger.Write.style_color=False
3760 , Format.Ledger.Write.style_align=True
3761 } $
3762 Format.Ledger.Write.date $
3763 Time.zonedTimeToUTC $
3764 Time.ZonedTime
3765 (Time.LocalTime
3766 (Time.fromGregorian 0 01 01)
3767 (Time.TimeOfDay 0 0 0))
3768 (Time.utc))
3769 ~?=
3770 "01/01"
3771 ]
3772 , "transaction" ~: TestList
3773 [ "nil" ~:
3774 ((Format.Ledger.Write.show
3775 Format.Ledger.Write.Style
3776 { Format.Ledger.Write.style_color=False
3777 , Format.Ledger.Write.style_align=True
3778 } $
3779 Format.Ledger.Write.transaction
3780 Format.Ledger.transaction)
3781 ~?=
3782 "1970/01/01\n")
3783 , "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" ~:
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.transaction $
3790 Format.Ledger.transaction
3791 { Format.Ledger.transaction_dates=
3792 ( Time.zonedTimeToUTC $
3793 Time.ZonedTime
3794 (Time.LocalTime
3795 (Time.fromGregorian 2000 01 01)
3796 (Time.TimeOfDay 0 0 0))
3797 (Time.utc)
3798 , [] )
3799 , Format.Ledger.transaction_description="some description"
3800 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3801 [ (Format.Ledger.posting ("A":|["B", "C"]))
3802 { Format.Ledger.posting_amounts = Data.Map.fromList
3803 [ ("$", Amount.nil
3804 { Amount.quantity = 1
3805 , Amount.style = Amount.Style.nil
3806 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3807 , Amount.Style.unit_spaced = Just False
3808 }
3809 , Amount.unit = "$"
3810 })
3811 ]
3812 }
3813 , (Format.Ledger.posting ("a":|["b", "c"]))
3814 { Format.Ledger.posting_comments = ["first comment","second comment","third comment"]
3815 }
3816 ]
3817 })
3818 ~?=
3819 "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")
3820 , "2000/01/01 some description\\n\\tA:B:C $1\\n\\tAA:BB:CC $123" ~:
3821 ((Format.Ledger.Write.show
3822 Format.Ledger.Write.Style
3823 { Format.Ledger.Write.style_color=False
3824 , Format.Ledger.Write.style_align=True
3825 } $
3826 Format.Ledger.Write.transaction $
3827 Format.Ledger.transaction
3828 { Format.Ledger.transaction_dates=
3829 ( Time.zonedTimeToUTC $
3830 Time.ZonedTime
3831 (Time.LocalTime
3832 (Time.fromGregorian 2000 01 01)
3833 (Time.TimeOfDay 0 0 0))
3834 (Time.utc)
3835 , [] )
3836 , Format.Ledger.transaction_description="some description"
3837 , Format.Ledger.transaction_postings = Format.Ledger.posting_by_Account
3838 [ (Format.Ledger.posting ("A":|["B", "C"]))
3839 { Format.Ledger.posting_amounts = Data.Map.fromList
3840 [ ("$", Amount.nil
3841 { Amount.quantity = 1
3842 , Amount.style = Amount.Style.nil
3843 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3844 , Amount.Style.unit_spaced = Just False
3845 }
3846 , Amount.unit = "$"
3847 })
3848 ]
3849 }
3850 , (Format.Ledger.posting ("AA":|["BB", "CC"]))
3851 { Format.Ledger.posting_amounts = Data.Map.fromList
3852 [ ("$", Amount.nil
3853 { Amount.quantity = 123
3854 , Amount.style = Amount.Style.nil
3855 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3856 , Amount.Style.unit_spaced = Just False
3857 }
3858 , Amount.unit = "$"
3859 })
3860 ]
3861 }
3862 ]
3863 })
3864 ~?=
3865 "2000/01/01 some description\n\tA:B:C $1\n\tAA:BB:CC $123")
3866 ]
3867 ]
3868 ]
3869 ]
3870 ]