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