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