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