1 {-# LANGUAGE TupleSections #-}
5 import Test.Framework.Providers.HUnit (hUnitTestToTests)
6 import Test.Framework.Runners.Console (defaultMain)
8 import qualified Data.List
9 import qualified Data.Map
11 import qualified Hcompta.Model as Model
12 import qualified Hcompta.Model.Account as Account
13 import qualified Hcompta.Model.Amount as Amount
14 import qualified Hcompta.Model.Amount.Quantity as Quantity
15 import qualified Hcompta.Model.Transaction as Transaction
16 import qualified Hcompta.Model.Transaction.Posting as Posting
17 import Hcompta.Model.Transaction.Posting (Posting)
18 import qualified Hcompta.Calc as Calc
19 import qualified Hcompta.Calc.Balance as Calc.Balance
22 main = defaultMain $ hUnitTestToTests test_Hcompta
28 [ "Account" ~: TestList
31 (reverse $ Account.fold [] (:) []) ~?= []
33 (reverse $ Account.fold ["A"] (:) []) ~?= [["A"]]
34 , "[A, B] = [[A], [A, B]]" ~:
35 (reverse $ Account.fold ["A", "B"] (:) []) ~?= [["A"], ["A", "B"]]
36 , "[A, B, C] = [[A], [A, B], [A, B, C]]" ~:
37 (reverse $ Account.fold ["A", "B", "C"] (:) []) ~?= [["A"], ["A", "B"], ["A", "B", "C"]]
41 Account.chomp [] ~?= []
43 Account.chomp ["A"] ~?= []
45 Account.chomp ["A", "B"] ~?= ["A"]
46 , "[A, B, C] = [A, B]" ~:
47 Account.chomp ["A", "B", "C"] ~?= ["A", "B"]
52 [ "Balance" ~: TestList
53 [ "posting" ~: TestList
54 [ "[A+$1] = A+$1 & $+1" ~:
57 { Posting.account=["A"]
58 , Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
63 { Calc.Balance.by_account =
65 [ (["A"], Amount.from_List [ Amount.usd $ 1 ]) ]
66 , Calc.Balance.by_unit =
68 Data.List.map Calc.Balance.assoc_by_amount_unit $
69 [ Calc.Balance.Sum_by_Unit
70 { Calc.Balance.amount = Amount.usd $ 1
71 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
76 , "[A+$1, A-$1] = {A+$0, $+0}" ~:
78 (flip Calc.Balance.posting)
81 { Posting.account=["A"]
82 , Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
85 { Posting.account=["A"]
86 , Posting.amounts=Amount.from_List [ Amount.usd $ -1 ]
91 { Calc.Balance.by_account =
93 [ (["A"], Amount.from_List [ Amount.usd $ 0 ]) ]
94 , Calc.Balance.by_unit =
96 Data.List.map Calc.Balance.assoc_by_amount_unit $
97 [ Calc.Balance.Sum_by_Unit
98 { Calc.Balance.amount = Amount.usd $ 0
99 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
104 , "[A+$1, A-€1] = {A+$1-€1, $+1 €-1}" ~:
106 (flip Calc.Balance.posting)
109 { Posting.account=["A"]
110 , Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
113 { Posting.account=["A"]
114 , Posting.amounts=Amount.from_List [ Amount.eur $ -1 ]
119 { Calc.Balance.by_account =
121 [ (["A"], Amount.from_List [ Amount.usd $ 1, Amount.eur $ -1 ]) ]
122 , Calc.Balance.by_unit =
124 Data.List.map Calc.Balance.assoc_by_amount_unit $
125 [ Calc.Balance.Sum_by_Unit
126 { Calc.Balance.amount = Amount.usd $ 1
127 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
130 , Calc.Balance.Sum_by_Unit
131 { Calc.Balance.amount = Amount.eur $ -1
132 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
137 , "[A+$1, B-$1] = {A+$1 B-$1, $+0}" ~:
139 (flip Calc.Balance.posting)
142 { Posting.account=["A"]
143 , Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
146 { Posting.account=["B"]
147 , Posting.amounts=Amount.from_List [ Amount.usd $ -1 ]
152 { Calc.Balance.by_account =
154 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
155 , (["B"], Amount.from_List [ Amount.usd $ -1 ])
157 , Calc.Balance.by_unit =
159 Data.List.map Calc.Balance.assoc_by_amount_unit $
160 [ Calc.Balance.Sum_by_Unit
161 { Calc.Balance.amount = Amount.usd $ 0
162 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
167 , "[A+$1+€2, A-$1-€2] = {A+$0+€0, $+0 €+0}" ~:
169 (flip Calc.Balance.posting)
172 { Posting.account=["A"]
173 , Posting.amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2 ]
176 { Posting.account=["A"]
177 , Posting.amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2 ]
182 { Calc.Balance.by_account =
184 [ (["A"], Amount.from_List [ Amount.usd $ 0, Amount.eur $ 0 ])
186 , Calc.Balance.by_unit =
188 Data.List.map Calc.Balance.assoc_by_amount_unit $
189 [ Calc.Balance.Sum_by_Unit
190 { Calc.Balance.amount = Amount.usd $ 0
191 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
194 , Calc.Balance.Sum_by_Unit
195 { Calc.Balance.amount = Amount.eur $ 0
196 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
201 , "[A+$1+€2+£3, B-$1-2€-£3] = {A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~:
203 (flip Calc.Balance.posting)
206 { Posting.account=["A"]
207 , Posting.amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ]
210 { Posting.account=["B"]
211 , Posting.amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ]
216 { Calc.Balance.by_account =
218 [ (["A"], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
219 , (["B"], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
221 , Calc.Balance.by_unit =
223 Data.List.map Calc.Balance.assoc_by_amount_unit $
224 [ Calc.Balance.Sum_by_Unit
225 { Calc.Balance.amount = Amount.usd $ 0
226 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
229 , Calc.Balance.Sum_by_Unit
230 { Calc.Balance.amount = Amount.eur $ 0
231 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
234 , Calc.Balance.Sum_by_Unit
235 { Calc.Balance.amount = Amount.gbp $ 0
236 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
242 , "union" ~: TestList
243 [ "null null = null" ~:
249 , "{A+$1, $+1} {A+$1, $+1} = {A+$2, $+2}" ~:
251 (Calc.Balance.Balance
252 { Calc.Balance.by_account =
254 [ (["A"], Amount.from_List [ Amount.usd $ 1 ]) ]
255 , Calc.Balance.by_unit =
257 Data.List.map Calc.Balance.assoc_by_amount_unit $
258 [ Calc.Balance.Sum_by_Unit
259 { Calc.Balance.amount = Amount.usd $ 1
260 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
265 (Calc.Balance.Balance
266 { Calc.Balance.by_account =
268 [ (["A"], Amount.from_List [ Amount.usd $ 1 ]) ]
269 , Calc.Balance.by_unit =
271 Data.List.map Calc.Balance.assoc_by_amount_unit $
272 [ Calc.Balance.Sum_by_Unit
273 { Calc.Balance.amount = Amount.usd $ 1
274 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
281 { Calc.Balance.by_account =
283 [ (["A"], Amount.from_List [ Amount.usd $ 2 ]) ]
284 , Calc.Balance.by_unit =
286 Data.List.map Calc.Balance.assoc_by_amount_unit $
287 [ Calc.Balance.Sum_by_Unit
288 { Calc.Balance.amount = Amount.usd $ 2
289 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
294 , "{A+$1, $+1} {B+$1, $+1} = {A+$1 B+$1, $+2}" ~:
296 (Calc.Balance.Balance
297 { Calc.Balance.by_account =
299 [ (["A"], Amount.from_List [ Amount.usd $ 1 ]) ]
300 , Calc.Balance.by_unit =
302 Data.List.map Calc.Balance.assoc_by_amount_unit $
303 [ Calc.Balance.Sum_by_Unit
304 { Calc.Balance.amount = Amount.usd $ 1
305 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
310 (Calc.Balance.Balance
311 { Calc.Balance.by_account =
313 [ (["B"], Amount.from_List [ Amount.usd $ 1 ]) ]
314 , Calc.Balance.by_unit =
316 Data.List.map Calc.Balance.assoc_by_amount_unit $
317 [ Calc.Balance.Sum_by_Unit
318 { Calc.Balance.amount = Amount.usd $ 1
319 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
326 { Calc.Balance.by_account =
328 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
329 , (["B"], Amount.from_List [ Amount.usd $ 1 ]) ]
330 , Calc.Balance.by_unit =
332 Data.List.map Calc.Balance.assoc_by_amount_unit $
333 [ Calc.Balance.Sum_by_Unit
334 { Calc.Balance.amount = Amount.usd $ 2
335 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
340 , "{A+$1, $+1} {B+€1, €+1} = {A+$1 B+€1, $+1 €+1}" ~:
342 (Calc.Balance.Balance
343 { Calc.Balance.by_account =
345 [ (["A"], Amount.from_List [ Amount.usd $ 1 ]) ]
346 , Calc.Balance.by_unit =
348 Data.List.map Calc.Balance.assoc_by_amount_unit $
349 [ Calc.Balance.Sum_by_Unit
350 { Calc.Balance.amount = Amount.usd $ 1
351 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
356 (Calc.Balance.Balance
357 { Calc.Balance.by_account =
359 [ (["B"], Amount.from_List [ Amount.eur $ 1 ]) ]
360 , Calc.Balance.by_unit =
362 Data.List.map Calc.Balance.assoc_by_amount_unit $
363 [ Calc.Balance.Sum_by_Unit
364 { Calc.Balance.amount = Amount.eur $ 1
365 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
372 { Calc.Balance.by_account =
374 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
375 , (["B"], Amount.from_List [ Amount.eur $ 1 ]) ]
376 , Calc.Balance.by_unit =
378 Data.List.map Calc.Balance.assoc_by_amount_unit $
379 [ Calc.Balance.Sum_by_Unit
380 { Calc.Balance.amount = Amount.usd $ 1
381 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
384 , Calc.Balance.Sum_by_Unit
385 { Calc.Balance.amount = Amount.eur $ 1
386 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
392 , "expand" ~: TestList
393 [ "null_By_Account = null_By_Account" ~:
395 Calc.Balance.null_By_Account
397 (Calc.Balance.Expanded $
398 Calc.Balance.null_By_Account)
402 [ (["A"], Amount.from_List [ Amount.usd $ 1 ]) ])
404 (Calc.Balance.Expanded $
406 [ (["A"], Amount.from_List [ Amount.usd $ 1 ]) ])
407 , "A/A+$1 = A+$1 A/A+$1" ~:
410 [ (["A", "A"], Amount.from_List [ Amount.usd $ 1 ]) ])
412 (Calc.Balance.Expanded $
414 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
415 , (["A", "A"], Amount.from_List [ Amount.usd $ 1 ]) ])
416 , "A/B+$1 = A+$1 A/B+$1" ~:
419 [ (["A", "B"], Amount.from_List [ Amount.usd $ 1 ]) ])
421 (Calc.Balance.Expanded $
423 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
424 , (["A", "B"], Amount.from_List [ Amount.usd $ 1 ]) ])
425 , "A/B/C+$1 = A+$1 A/B+$1 A/B/C+$1" ~:
428 [ (["A", "B", "C"], Amount.from_List [ Amount.usd $ 1 ]) ])
430 (Calc.Balance.Expanded $
432 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
433 , (["A", "B"], Amount.from_List [ Amount.usd $ 1 ])
434 , (["A", "B", "C"], Amount.from_List [ Amount.usd $ 1 ]) ])
435 , "A+$1 A/B+$1 = A+$2 A/B+$1" ~:
438 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
439 , (["A", "B"], Amount.from_List [ Amount.usd $ 1 ]) ])
441 (Calc.Balance.Expanded $
443 [ (["A"], Amount.from_List [ Amount.usd $ 2 ])
444 , (["A", "B"], Amount.from_List [ Amount.usd $ 1 ]) ])
445 , "A+$1 A/B+$1 B/A+$1 = A+$2 A/B+$1 B/A+$1" ~:
448 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
449 , (["A", "B"], Amount.from_List [ Amount.usd $ 1 ])
450 , (["B", "A"], Amount.from_List [ Amount.usd $ 1 ]) ])
452 (Calc.Balance.Expanded $
454 [ (["A"], Amount.from_List [ Amount.usd $ 2 ])
455 , (["A", "B"], Amount.from_List [ Amount.usd $ 1 ])
456 , (["B"], Amount.from_List [ Amount.usd $ 1 ])
457 , (["B", "A"], Amount.from_List [ Amount.usd $ 1 ]) ])
458 , "A+$1 A/B+$1 B/A+$1 = A+$2 A/B+$1 B/A+$1" ~:
461 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
462 , (["A", "B"], Amount.from_List [ Amount.usd $ 1 ])
463 , (["B", "A"], Amount.from_List [ Amount.usd $ 1 ]) ])
465 (Calc.Balance.Expanded $
467 [ (["A"], Amount.from_List [ Amount.usd $ 2 ])
468 , (["A", "B"], Amount.from_List [ Amount.usd $ 1 ])
469 , (["B"], Amount.from_List [ Amount.usd $ 1 ])
470 , (["B", "A"], Amount.from_List [ Amount.usd $ 1 ]) ])
472 , "is_equilibrated" ~: TestList
473 [ "null = True" ~: TestCase $
475 Calc.Balance.is_equilibrated $
477 , "{A+$0, $+0} = True" ~: TestCase $
479 Calc.Balance.is_equilibrated $
481 { Calc.Balance.by_account =
483 [ (["A"], Amount.from_List [ Amount.usd $ 0 ])
485 , Calc.Balance.by_unit =
487 Data.List.map Calc.Balance.assoc_by_amount_unit $
488 [ Calc.Balance.Sum_by_Unit
489 { Calc.Balance.amount = Amount.usd $ 0
490 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
495 , "{A+$1, $+1} = False" ~: TestCase $
497 Calc.Balance.is_equilibrated $
499 { Calc.Balance.by_account =
501 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
503 , Calc.Balance.by_unit =
505 Data.List.map Calc.Balance.assoc_by_amount_unit $
506 [ Calc.Balance.Sum_by_Unit
507 { Calc.Balance.amount = Amount.usd $ 1
508 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
513 , "{A+$0+€0, $0 €+0} = True" ~: TestCase $
515 Calc.Balance.is_equilibrated $
517 { Calc.Balance.by_account =
519 [ (["A"], Amount.from_List [ Amount.usd $ 0, Amount.eur $ 0 ])
521 , Calc.Balance.by_unit =
523 Data.List.map Calc.Balance.assoc_by_amount_unit $
524 [ Calc.Balance.Sum_by_Unit
525 { Calc.Balance.amount = Amount.usd $ 0
526 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
529 , Calc.Balance.Sum_by_Unit
530 { Calc.Balance.amount = Amount.eur $ 0
531 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
536 , "{A+$1, B-$1, $+0} = True" ~: TestCase $
538 Calc.Balance.is_equilibrated $
540 { Calc.Balance.by_account =
542 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
543 , (["B"], Amount.from_List [ Amount.usd $ -1 ])
545 , Calc.Balance.by_unit =
547 Data.List.map Calc.Balance.assoc_by_amount_unit $
548 [ Calc.Balance.Sum_by_Unit
549 { Calc.Balance.amount = Amount.usd $ 0
550 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
555 , "{A+$1 B, $+1} = True" ~: TestCase $
557 Calc.Balance.is_equilibrated $
559 { Calc.Balance.by_account =
561 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
562 , (["B"], Amount.from_List [])
564 , Calc.Balance.by_unit =
566 Data.List.map Calc.Balance.assoc_by_amount_unit $
567 [ Calc.Balance.Sum_by_Unit
568 { Calc.Balance.amount = Amount.usd $ 1
569 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
574 , "{A+$1 B+€1, $+1 €+1} = True" ~: TestCase $
576 Calc.Balance.is_equilibrated $
578 { Calc.Balance.by_account =
580 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
581 , (["B"], Amount.from_List [ Amount.eur $ 1 ])
583 , Calc.Balance.by_unit =
585 Data.List.map Calc.Balance.assoc_by_amount_unit $
586 [ Calc.Balance.Sum_by_Unit
587 { Calc.Balance.amount = Amount.usd $ 1
588 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
591 , Calc.Balance.Sum_by_Unit
592 { Calc.Balance.amount = Amount.eur $ 1
593 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
598 , "{A+$1 B-$1+€1, $+0 €+1} = True" ~: TestCase $
600 Calc.Balance.is_equilibrated $
602 { Calc.Balance.by_account =
604 [ (["A"], Amount.from_List [ Amount.usd $ 1 ])
605 , (["B"], Amount.from_List [ Amount.usd $ -1, Amount.eur $ 1 ])
607 , Calc.Balance.by_unit =
609 Data.List.map Calc.Balance.assoc_by_amount_unit $
610 [ Calc.Balance.Sum_by_Unit
611 { Calc.Balance.amount = Amount.usd $ 0
612 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
615 , Calc.Balance.Sum_by_Unit
616 { Calc.Balance.amount = Amount.eur $ 1
617 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
622 , "{A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0} = True" ~: TestCase $
624 Calc.Balance.is_equilibrated $
626 { Calc.Balance.by_account =
628 [ (["A"], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
629 , (["B"], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
631 , Calc.Balance.by_unit =
633 Data.List.map Calc.Balance.assoc_by_amount_unit $
634 [ Calc.Balance.Sum_by_Unit
635 { Calc.Balance.amount = Amount.usd $ 0
636 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
639 , Calc.Balance.Sum_by_Unit
640 { Calc.Balance.amount = Amount.eur $ 0
641 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
644 , Calc.Balance.Sum_by_Unit
645 { Calc.Balance.amount = Amount.gbp $ 0
646 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())