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