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