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