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