1 {-# LANGUAGE BangPatterns #-}
2 {-# LANGUAGE DeriveDataTypeable #-}
3 {-# LANGUAGE FlexibleContexts #-}
4 {-# LANGUAGE FlexibleInstances #-}
5 {-# LANGUAGE MultiParamTypeClasses #-}
6 {-# LANGUAGE ScopedTypeVariables #-}
7 {-# LANGUAGE StandaloneDeriving #-}
8 {-# LANGUAGE TupleSections #-}
9 {-# LANGUAGE TypeFamilies #-}
10 module Hcompta.Filter where
12 -- import Control.Applicative (pure, (<$>), (<*>))
13 import Control.Applicative (Const(..))
15 import qualified Data.Fixed
16 import qualified Data.Foldable
17 -- import Data.Foldable (Foldable(..))
18 -- import Data.Functor.Compose (Compose(..))
19 -- import qualified Data.List
20 import Data.Map.Strict (Map)
21 import qualified Data.Map.Strict as Data.Map
22 import qualified Data.Monoid
23 -- import Data.Monoid (Monoid(..))
24 import Data.Text (Text)
25 -- import qualified Data.Text as Text
26 -- import qualified Data.Time.Calendar as Time
27 -- import Data.Traversable (Traversable(..))
28 import Data.Typeable ()
29 import Prelude hiding (filter)
30 import Text.Regex.Base ()
31 import Text.Regex.TDFA ()
32 import Text.Regex.TDFA.Text ()
34 import qualified Data.List.NonEmpty as NonEmpty
35 -- import Data.List.NonEmpty (NonEmpty(..))
36 import Hcompta.Lib.Consable (Consable(..))
37 import Hcompta.Lib.Interval (Interval)
38 import qualified Hcompta.Lib.Interval as Interval
39 import qualified Hcompta.Lib.Regex as Regex
40 import Hcompta.Lib.Regex (Regex)
41 -- import qualified Hcompta.Lib.TreeMap as TreeMap
42 -- import Hcompta.Lib.TreeMap (TreeMap)
43 import qualified Hcompta.Amount as Amount
44 import qualified Hcompta.Amount.Unit as Amount.Unit
45 import qualified Hcompta.Date as Date
46 import Hcompta.Date (Date)
47 import qualified Hcompta.Account as Account
48 import Hcompta.Account (Account)
49 -- import qualified Hcompta.Date as Date
50 import qualified Hcompta.Balance as Balance
51 import qualified Hcompta.GL as GL
52 import qualified Hcompta.Journal as Journal
54 -- * Requirements' interface
59 unit_text :: a -> Text
61 instance Unit Amount.Unit where
62 unit_text = Amount.Unit.text
64 instance Unit Text where
70 ( Ord (Amount_Quantity a)
71 , Show (Amount_Quantity a)
72 , Show (Amount_Unit a)
73 , Unit (Amount_Unit a)
77 type Amount_Quantity a
78 amount_unit :: a -> Amount_Unit a
79 amount_quantity :: a -> Amount_Quantity a
81 instance Amount Amount.Amount where
82 type Amount_Unit Amount.Amount = Amount.Unit
83 type Amount_Quantity Amount.Amount = Amount.Quantity
84 amount_quantity = Amount.quantity
85 amount_unit = Amount.unit
87 instance (Amount a, GL.Amount a)
88 => Amount (Amount.Sum a) where
89 type Amount_Unit (Amount.Sum a) = Amount_Unit a
90 type Amount_Quantity (Amount.Sum a) = Amount_Quantity a
91 amount_quantity = amount_quantity . Amount.sum_balance
92 amount_unit = amount_unit . Amount.sum_balance
96 class Amount (Posting_Amount p)
99 posting_account :: p -> Account
100 posting_amounts :: p -> Map (Amount_Unit (Posting_Amount p)) (Posting_Amount p)
102 -- ** Class 'Transaction'
105 ( Posting (Transaction_Posting t)
106 , Foldable (Transaction_Postings t)
108 => Transaction t where
109 type Transaction_Posting t
110 type Transaction_Postings t :: * -> *
111 transaction_date :: t -> Date
112 transaction_description :: t -> Text
113 transaction_postings :: t -> Transaction_Postings t (Transaction_Posting t)
114 transaction_tags :: t -> Map Text [Text]
116 -- ** Class 'Balance'
118 class Amount (Balance_Amount b)
120 type Balance_Amount b
121 balance_account :: b -> Account
122 balance_amount :: b -> Balance_Amount b
123 balance_positive :: b -> Maybe (Balance_Amount b)
124 balance_negative :: b -> Maybe (Balance_Amount b)
126 instance (Amount a, Balance.Amount a)
127 => Balance (Account, Amount.Sum a) where
128 type Balance_Amount (Account, Amount.Sum a) = a
129 balance_account = fst
130 balance_amount (_, amt) =
132 Amount.Sum_Negative n -> n
133 Amount.Sum_Positive p -> p
134 Amount.Sum_Both n p -> Balance.amount_add n p
135 balance_positive = Amount.sum_positive . snd
136 balance_negative = Amount.sum_negative . snd
140 class Amount (GL_Amount r)
143 gl_account :: r -> Account
145 gl_amount_positive :: r -> Maybe (GL_Amount r)
146 gl_amount_negative :: r -> Maybe (GL_Amount r)
147 gl_amount_balance :: r -> GL_Amount r
148 gl_sum_positive :: r -> Maybe (GL_Amount r)
149 gl_sum_negative :: r -> Maybe (GL_Amount r)
150 gl_sum_balance :: r -> GL_Amount r
152 instance (Amount a, GL.Amount a)
153 => GL (Account, Date, Amount.Sum a, Amount.Sum a) where
154 type GL_Amount (Account, Date, Amount.Sum a, Amount.Sum a) = a
155 gl_account (x, _, _, _) = x
156 gl_date (_, x, _, _) = x
157 gl_amount_positive (_, _, x, _) = Amount.sum_positive x
158 gl_amount_negative (_, _, x, _) = Amount.sum_negative x
159 gl_amount_balance (_, _, x, _) = Amount.sum_balance x
160 gl_sum_positive (_, _, _, x) = Amount.sum_positive x
161 gl_sum_negative (_, _, _, x) = Amount.sum_negative x
162 gl_sum_balance (_, _, _, x) = Amount.sum_balance x
164 -- * Newtypes to avoid overlapping instances
168 instance Functor Scalar where
169 fmap f (Scalar x) = Scalar (f x)
171 -- * Types for folding
173 type Fold_Transaction acc transaction =
178 (Filter_Transaction transaction))
180 type Fold_Posting acc transaction =
185 (Filter_Posting transaction))
187 type Fold_Transaction_and_Posting acc transaction posting =
192 (Filter_Transaction transaction))
195 (Filter_Posting posting))
201 = Simplified (Either p Bool)
203 simplified :: Simplified p -> Either p Bool
204 simplified (Simplified x) = x
206 instance Functor Simplified where
207 fmap _f (Simplified (Right b)) = Simplified (Right b)
208 fmap f (Simplified (Left x)) = Simplified (Left $ f x)
209 instance Filter p x => Filter (Simplified p) x where
210 test (Simplified (Right b)) _x = b
211 test (Simplified (Left f)) x = test f x
212 simplify (Simplified (Right b)) _x = Simplified $ Right b
213 simplify (Simplified (Left f)) x =
215 case simplified $ simplify f x of
217 Left sf -> Left (Simplified $ Left sf)
219 -- | Conjonctive ('&&') 'Monoid'.
220 instance Monoid p => Monoid (Simplified p) where
221 mempty = Simplified (Right True)
222 mappend (Simplified x) (Simplified y) =
225 (Right bx , Right by ) -> Right (bx && by)
226 (Right True , Left _fy ) -> y
227 (Right False, Left _fy ) -> x
228 (Left _fx , Right True ) -> x
229 (Left _fx , Right False) -> y
230 (Left fx , Left fy ) -> Left $ fx `mappend` fy
232 class Filter p x where
233 test :: p -> x -> Bool
234 simplify :: p -> Maybe x -> Simplified p
235 simplify p _x = Simplified $ Left p
238 :: (Foldable t, Filter p x, Monoid x)
241 Data.Foldable.foldMap
242 (\x -> if test p x then x else mempty)
244 -- ** Type 'Filter_Text'
248 | Filter_Text_Exact Text
249 | Filter_Text_Regex Regex
250 deriving (Eq, Show, Typeable)
252 instance Filter Filter_Text Text where
255 Filter_Text_Any -> True
256 Filter_Text_Exact m -> (==) m x
257 Filter_Text_Regex m -> Regex.match m x
259 -- ** Type 'Filter_Ord'
268 deriving (Data, Eq, Show, Typeable)
270 instance Functor Filter_Ord where
273 Filter_Ord_Lt o -> Filter_Ord_Lt (f o)
274 Filter_Ord_Le o -> Filter_Ord_Le (f o)
275 Filter_Ord_Gt o -> Filter_Ord_Gt (f o)
276 Filter_Ord_Ge o -> Filter_Ord_Ge (f o)
277 Filter_Ord_Eq o -> Filter_Ord_Eq (f o)
278 Filter_Ord_Any -> Filter_Ord_Any
279 instance (Ord o, o ~ x)
280 => Filter (Filter_Ord o) (Scalar x) where
283 Filter_Ord_Lt o -> (<) x o
284 Filter_Ord_Le o -> (<=) x o
285 Filter_Ord_Gt o -> (>) x o
286 Filter_Ord_Ge o -> (>=) x o
287 Filter_Ord_Eq o -> (==) x o
288 Filter_Ord_Any -> True
289 instance (Ord o, o ~ x)
290 => Filter (Filter_Ord o) (Interval x) where
292 let l = Interval.low i in
293 let h = Interval.high i in
295 Filter_Ord_Lt o -> case compare (Interval.limit h) o of
297 EQ -> Interval.adherence h == Interval.Out
299 Filter_Ord_Le o -> Interval.limit h <= o
300 Filter_Ord_Gt o -> case compare (Interval.limit l) o of
302 EQ -> Interval.adherence l == Interval.Out
304 Filter_Ord_Ge o -> Interval.limit l >= o
305 Filter_Ord_Eq o -> Interval.limit l == o && Interval.limit h == o
306 Filter_Ord_Any -> True
308 -- ** Type 'Filter_Interval'
310 data Filter_Interval x
311 = Filter_Interval_In (Interval (Interval.Unlimitable x))
312 deriving (Eq, Ord, Show)
313 --instance Functor Filter_Interval where
314 -- fmap f (Filter_Interval_In i) = Filter_Interval_In (fmap (fmap f) i)
315 instance (Ord o, o ~ x)
316 => Filter (Filter_Interval o) (Scalar (Interval.Unlimitable x)) where
317 test (Filter_Interval_In p) (Scalar x) =
318 Interval.locate x p == EQ
319 instance (Ord o, o ~ x)
320 => Filter (Filter_Interval o) (Interval (Interval.Unlimitable x)) where
321 test (Filter_Interval_In p) i = Interval.into i p
323 -- ** Type 'Filter_Num_Abs'
327 = Filter_Num_Abs (Filter_Ord n)
328 deriving (Data, Eq, Show, Typeable)
330 instance (Num n, Ord x, n ~ x)
331 => Filter (Filter_Num_Abs n) x where
332 test (Filter_Num_Abs f) x = test f (Scalar (abs x))
334 -- ** Type 'Filter_Bool'
339 | Not (Filter_Bool p)
340 | And (Filter_Bool p) (Filter_Bool p)
341 | Or (Filter_Bool p) (Filter_Bool p)
343 deriving instance Eq p => Eq (Filter_Bool p)
344 instance Functor Filter_Bool where
346 fmap f (Bool x) = Bool (f x)
347 fmap f (Not t) = Not (fmap f t)
348 fmap f (And t0 t1) = And (fmap f t0) (fmap f t1)
349 fmap f (Or t0 t1) = Or (fmap f t0) (fmap f t1)
350 -- | Conjonctive ('And') 'Monoid'.
351 instance Monoid (Filter_Bool p) where
354 instance Foldable Filter_Bool where
355 foldr _ acc Any = acc
356 foldr f acc (Bool p) = f p acc
357 foldr f acc (Not t) = Data.Foldable.foldr f acc t
358 foldr f acc (And t0 t1) = Data.Foldable.foldr f (Data.Foldable.foldr f acc t0) t1
359 foldr f acc (Or t0 t1) = Data.Foldable.foldr f (Data.Foldable.foldr f acc t0) t1
360 instance Traversable Filter_Bool where
361 traverse _ Any = pure Any
362 traverse f (Bool x) = Bool <$> f x
363 traverse f (Not t) = Not <$> traverse f t
364 traverse f (And t0 t1) = And <$> traverse f t0 <*> traverse f t1
365 traverse f (Or t0 t1) = Or <$> traverse f t0 <*> traverse f t1
366 instance Filter p x => Filter (Filter_Bool p) x where
368 test (Bool p) x = test p x
369 test (Not t) x = not $ test t x
370 test (And t0 t1) x = test t0 x && test t1 x
371 test (Or t0 t1) x = test t0 x || test t1 x
373 simplify Any _ = Simplified $ Right True
374 simplify (Bool p) x =
376 case simplified (simplify p x) of
377 Left p' -> Left (Bool p')
381 case simplified (simplify t x) of
382 Left p' -> Left (Not $ p')
384 simplify (And t0 t1) x =
386 case (simplified $ simplify t0 x, simplified $ simplify t1 x) of
387 (Right b0, Right b1) -> Right (b0 && b1)
388 (Right b0, Left p1) -> if b0 then Left p1 else Right False
389 (Left p0, Right b1) -> if b1 then Left p0 else Right False
390 (Left p0, Left p1) -> Left (And p0 p1)
391 simplify (Or t0 t1) x =
393 case (simplified $ simplify t0 x, simplified $ simplify t1 x) of
394 (Right b0, Right b1) -> Right (b0 || b1)
395 (Right b0, Left p1) -> if b0 then Right True else Left p1
396 (Left p0, Right b1) -> if b1 then Right True else Left p0
397 (Left p0, Left p1) -> Left (Or p0 p1)
399 bool :: Filter p x => Filter_Bool p -> x -> Bool
401 bool (Bool p) x = test p x
402 bool (Not t) x = not $ test t x
403 bool (And t0 t1) x = test t0 x && test t1 x
404 bool (Or t0 t1) x = test t0 x || test t1 x
406 -- ** Type 'Filter_Unit'
409 = Filter_Unit Filter_Text
410 deriving (Eq, Show, Typeable)
412 instance Unit u => Filter Filter_Unit u where
413 test (Filter_Unit f) = test f . unit_text
415 -- ** Type 'Filter_Account'
418 = [Filter_Account_Section]
420 data Filter_Account_Section
421 = Filter_Account_Section_Any
422 | Filter_Account_Section_Many
423 | Filter_Account_Section_Text Filter_Text
424 deriving (Eq, Show, Typeable)
426 instance Filter Filter_Account Account where
428 comp f (NonEmpty.toList acct)
430 comp :: [Filter_Account_Section] -> [Account.Name] -> Bool
432 comp [Filter_Account_Section_Many] _ = True
437 Filter_Account_Section_Any -> True
438 Filter_Account_Section_Many -> True
439 Filter_Account_Section_Text m -> test m n
441 comp so@(s:ss) no@(n:ns) =
443 Filter_Account_Section_Any -> comp ss ns
444 Filter_Account_Section_Many -> comp ss no || comp so ns
445 Filter_Account_Section_Text m -> test m n && comp ss ns
448 -- ** Type 'Filter_Amount'
450 type Filter_Quantity q
456 { filter_amount_quantity :: Filter_Quantity (Amount_Quantity a)
457 , filter_amount_unit :: Filter_Unit
458 } deriving (Typeable)
459 deriving instance Amount a => Eq (Filter_Amount a)
460 deriving instance Amount a => Show (Filter_Amount a)
463 => Filter (Filter_Amount a) a where
464 test (Filter_Amount fq fu) amt =
465 test fu (amount_unit amt) &&
466 test fq (Scalar (amount_quantity amt))
468 -- ** Type 'Filter_Date'
471 = Filter_Date_UTC (Filter_Ord Date)
472 | Filter_Date_Year (Filter_Interval Integer)
473 | Filter_Date_Month (Filter_Interval Int)
474 | Filter_Date_DoM (Filter_Interval Int)
475 | Filter_Date_Hour (Filter_Interval Int)
476 | Filter_Date_Minute (Filter_Interval Int)
477 | Filter_Date_Second (Filter_Interval Data.Fixed.Pico)
479 deriving instance Show (Filter_Date)
481 instance Filter Filter_Date Date where
482 test (Filter_Date_UTC f) d = test f $ Scalar d
483 test (Filter_Date_Year f) d = test f $ Scalar $ Interval.Limited $ Date.year d
484 test (Filter_Date_Month f) d = test f $ Scalar $ Interval.Limited $ Date.month d
485 test (Filter_Date_DoM f) d = test f $ Scalar $ Interval.Limited $ Date.dom d
486 test (Filter_Date_Hour f) d = test f $ Scalar $ Interval.Limited $ Date.hour d
487 test (Filter_Date_Minute f) d = test f $ Scalar $ Interval.Limited $ Date.minute d
488 test (Filter_Date_Second f) d = test f $ Scalar $ Interval.Limited $ Date.second d
490 instance Filter Filter_Date (Interval (Interval.Unlimitable Date)) where
491 test (Filter_Date_UTC f) d = test (Interval.Limited <$> f) d
492 test (Filter_Date_Year f) d = maybe False (test f) $ Interval.fmap (fmap Date.year) d
493 test (Filter_Date_Month f) d = maybe False (test f) $ Interval.fmap (fmap Date.month) d
494 test (Filter_Date_DoM f) d = maybe False (test f) $ Interval.fmap (fmap Date.dom) d
495 test (Filter_Date_Hour f) d = maybe False (test f) $ Interval.fmap (fmap Date.hour) d
496 test (Filter_Date_Minute f) d = maybe False (test f) $ Interval.fmap (fmap Date.minute) d
497 test (Filter_Date_Second f) d = maybe False (test f) $ Interval.fmap (fmap Date.second) d
499 -- ** Type 'Filter_Tag'
502 = Filter_Tag_Name Filter_Text
503 | Filter_Tag_Value Filter_Text
505 deriving instance Show (Filter_Tag)
507 instance Filter Filter_Tag (Text, Text) where
508 test (Filter_Tag_Name f) (x, _) = test f x
509 test (Filter_Tag_Value f) (_, x) = test f x
511 -- ** Type 'Filter_Posting'
514 => Filter_Posting posting
515 = Filter_Posting_Account Filter_Account
516 | Filter_Posting_Amount (Filter_Amount (Posting_Amount posting))
517 | Filter_Posting_Unit Filter_Unit
520 -- Description Comp_String String
522 -- Account_Tag Comp_String String (Maybe (Comp_String, String))
523 -- Account_Balance Comp_Num Comp_Num_Absolute Amount
524 -- Depth Comp_Num Int
528 -- Tag Comp_String Tag.Name (Maybe (Comp_String, Tag.Value))
529 deriving instance Posting p => Eq (Filter_Posting p)
530 deriving instance Posting p => Show (Filter_Posting p)
533 => Filter (Filter_Posting p) p where
534 test (Filter_Posting_Account f) p =
535 test f $ posting_account p
536 test (Filter_Posting_Amount f) p =
537 Data.Foldable.any (test f) $ posting_amounts p
538 test (Filter_Posting_Unit f) p =
539 Data.Foldable.any (test f . amount_unit) $ posting_amounts p
541 newtype Cross t = Cross t
542 instance (Transaction t, Transaction_Posting t ~ p, Posting p)
543 => Filter (Filter_Transaction t) (Cross p) where
546 (Filter_Transaction_Description _) -> True
547 (Filter_Transaction_Posting f) -> test f p
548 (Filter_Transaction_Date _) -> True -- TODO: use posting_date
549 (Filter_Transaction_Tag _) -> False -- TODO: use posting_tags
551 -- ** Type 'Filter_Transaction'
554 => Filter_Transaction t
555 = Filter_Transaction_Description Filter_Text
556 | Filter_Transaction_Posting (Filter_Posting (Transaction_Posting t))
557 | Filter_Transaction_Date (Filter_Bool Filter_Date)
558 | Filter_Transaction_Tag (Filter_Bool Filter_Tag)
560 deriving instance Transaction t => Show (Filter_Transaction t)
562 instance Transaction t
563 => Filter (Filter_Transaction t) t where
564 test (Filter_Transaction_Description f) t =
565 test f $ transaction_description t
566 test (Filter_Transaction_Posting f) t =
567 Data.Foldable.any (test f) $
568 transaction_postings t
569 test (Filter_Transaction_Date f) t =
570 test f $ transaction_date t
571 test (Filter_Transaction_Tag f) t =
573 Data.Map.foldrWithKey
574 (\n -> mappend . Data.Monoid.Any .
575 Data.Foldable.any (test f . (n,)))
576 (Data.Monoid.Any False) $
580 ( Transaction transaction
581 , Journal.Transaction transaction
583 => Consable (Fold_Transaction (Journal.Journal transaction) transaction)
585 mcons t (Const (!j, ft)) =
588 then Journal.cons t j
592 , Transaction transaction
593 , Journal.Transaction transaction
595 => Consable (Fold_Transaction (Journal.Journal transaction) transaction)
596 (foldable transaction) where
597 mcons ts (Const (!j, ft)) =
599 case simplified ft of
613 -- ** Type 'Filter_Balance'
617 = Filter_Balance_Account Filter_Account
618 | Filter_Balance_Amount (Filter_Amount (Balance_Amount b))
619 | Filter_Balance_Positive (Filter_Amount (Balance_Amount b))
620 | Filter_Balance_Negative (Filter_Amount (Balance_Amount b))
622 deriving instance Balance b => Eq (Filter_Balance b)
623 deriving instance Balance b => Show (Filter_Balance b)
626 => Filter (Filter_Balance b) b where
627 test (Filter_Balance_Account f) b =
628 test f $ balance_account b
629 test (Filter_Balance_Amount f) b =
630 test f $ balance_amount b
631 test (Filter_Balance_Positive f) b =
632 Data.Foldable.any (test f) $
634 test (Filter_Balance_Negative f) b =
635 Data.Foldable.any (test f) $
639 ( Balance.Posting posting
641 , amount ~ Balance.Posting_Amount posting
643 => Consable (Fold_Posting (Balance.Balance_by_Account amount) posting)
645 mcons p (Const (!b, fp)) =
647 case simplified fp of
649 Right True -> Balance.cons_by_account p b
652 then Balance.cons_by_account p b
655 ( Transaction transaction
656 , posting ~ Transaction_Posting transaction
657 , amount ~ Balance.Posting_Amount posting
658 , Balance.Amount amount
659 , Balance.Posting posting
661 => Consable (Fold_Transaction_and_Posting
662 (Balance.Balance_by_Account amount)
665 mcons t (Const (!bal, ft, fp)) =
667 case simplified ft of
669 Right True -> filter_postings $ transaction_postings t
672 then filter_postings $ transaction_postings t
674 where filter_postings ps =
675 case simplified fp of
679 (flip Balance.cons_by_account)
683 (\b p -> if test ff p then Balance.cons_by_account p b else b)
687 , Balance.Posting posting
689 , amount ~ Balance.Posting_Amount posting
691 => Consable (Fold_Posting (Balance.Balance_by_Account amount) posting)
692 (foldable posting) where
693 mcons ps (Const (!bal, fp)) =
695 case simplified fp of
699 (flip Balance.cons_by_account) bal ps
701 Data.Foldable.foldl' (\b p ->
703 then Balance.cons_by_account p b
706 -- ** Type 'Filter_GL'
710 = Filter_GL_Account Filter_Account
711 | Filter_GL_Amount_Positive (Filter_Amount (GL_Amount r))
712 | Filter_GL_Amount_Negative (Filter_Amount (GL_Amount r))
713 | Filter_GL_Amount_Balance (Filter_Amount (GL_Amount r))
714 | Filter_GL_Sum_Positive (Filter_Amount (GL_Amount r))
715 | Filter_GL_Sum_Negative (Filter_Amount (GL_Amount r))
716 | Filter_GL_Sum_Balance (Filter_Amount (GL_Amount r))
718 deriving instance GL r => Eq (Filter_GL r)
719 deriving instance GL r => Show (Filter_GL r)
722 => Filter (Filter_GL r) r where
723 test (Filter_GL_Account f) r =
724 test f $ gl_account r
725 test (Filter_GL_Amount_Positive f) r =
726 Data.Foldable.any (test f) $
728 test (Filter_GL_Amount_Negative f) r =
729 Data.Foldable.any (test f) $
731 test (Filter_GL_Amount_Balance f) r =
732 test f $ gl_amount_balance r
733 test (Filter_GL_Sum_Positive f) r =
734 Data.Foldable.any (test f) $
736 test (Filter_GL_Sum_Negative f) r =
737 Data.Foldable.any (test f) $
739 test (Filter_GL_Sum_Balance f) r =
740 test f $ gl_sum_balance r
742 ( GL.Transaction transaction
743 , Transaction transaction
745 , posting ~ GL.Transaction_Posting transaction
747 => Consable (Fold_Transaction_and_Posting
751 mcons t (Const (!gl, ft, fp)) =
753 case simplified ft of
756 case simplified fp of
758 Right True -> GL.cons t gl
761 (GL.transaction_postings_filter (test f) t)
766 case simplified fp of
768 Right True -> GL.cons t gl
771 (GL.transaction_postings_filter (test ff) t)
776 , GL.Transaction transaction
777 , Transaction transaction
779 , posting ~ GL.Transaction_Posting transaction
781 => Consable (Fold_Transaction_and_Posting
784 (foldable transaction) where
785 mcons ts (Const (!gl, ft, fp)) =
787 case simplified ft of
790 case simplified fp of
799 . GL.transaction_postings_filter (test f) )
806 case simplified fp of
808 Right True -> GL.cons t
810 GL.transaction_postings_filter (test ff) t