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 {-# OPTIONS_GHC -fno-warn-orphans #-}
11 module Hcompta.Filter where
13 import Control.Applicative (Applicative(..), Const(..))
14 -- import Control.Applicative (pure, (<$>), (<*>))
15 import Control.Arrow (second)
16 import Control.DeepSeq (NFData(..))
19 import Data.Decimal ()
20 import Data.Either (Either(..))
21 import Data.Eq (Eq(..))
22 import qualified Data.Fixed
23 import Data.Foldable (Foldable(..), all, any)
24 import Data.Functor (Functor(..), (<$>))
25 import Data.Functor.Compose (Compose(..))
26 import Data.List (reverse)
27 import Data.List.NonEmpty (NonEmpty(..))
28 import qualified Data.List.NonEmpty as NonEmpty
29 import qualified Data.Map.Strict as Data.Map
30 import Data.Maybe (maybe)
31 import qualified Data.Monoid
32 import Data.Monoid (Monoid(..))
33 import Data.Ord (Ord(..), Ordering(..))
34 import Data.Text (Text)
35 import Data.Traversable (Traversable(..))
36 import Data.Tuple (fst, snd)
37 import Data.Typeable ()
38 import Prelude (($), (.), Int, Integer, Num(..), Show(..), const, flip, id)
39 import Text.Regex.Base ()
40 import Text.Regex.TDFA ()
41 import Text.Regex.TDFA.Text ()
43 import qualified Hcompta.Account as Account
44 import qualified Hcompta.Balance as Balance
45 import Hcompta.Date (Date)
46 import qualified Hcompta.Date as Date
47 import qualified Hcompta.GL as GL
48 import qualified Hcompta.Journal as Journal
49 import Hcompta.Lib.Applicative ()
50 import Hcompta.Lib.Consable (Consable(..))
51 import Hcompta.Lib.Interval (Interval)
52 import qualified Hcompta.Lib.Interval as Interval
53 import Hcompta.Lib.Regex (Regex)
54 import qualified Hcompta.Lib.Regex as Regex
55 import Hcompta.Polarize
56 import qualified Hcompta.Posting as Posting
57 import Hcompta.Quantity (Addable(..), Zero(..))
58 import qualified Hcompta.Stats as Stats
59 import qualified Hcompta.Tag as Tag
60 import Hcompta.Unit (Unit(..))
62 -- * Requirements' interface
69 class Path_Section a where
70 path_section_text :: a -> Text
71 instance Path_Section Text where
72 path_section_text = id
76 type Account_Section = Text
77 type Account_Path = Path Account_Section
80 account_path :: a -> Account_Path
81 account_tags :: a -> Tag.Tags
83 instance Account (Tag.Tags, Account_Path) where
90 ( Addable (Amount_Quantity a)
91 , Eq (Amount_Quantity a)
92 , Ord (Amount_Quantity a)
93 , Unit (Amount_Unit a)
95 type Amount_Quantity a
97 amount_quantity :: a -> Polarized (Amount_Quantity a)
98 amount_unit :: a -> Amount_Unit a
106 ) => Amount (unit, Polarized quantity) where
107 type Amount_Quantity (unit, Polarized quantity) = quantity
108 type Amount_Unit (unit, Polarized quantity) = unit
109 amount_quantity = snd
112 -- ** Class 'Posting'
116 , Account (Posting.Posting_Account p)
117 , Amount (Posting.Posting_Amount p)
119 posting_type :: p -> Posting_Type
122 = Posting_Type_Regular
123 | Posting_Type_Virtual
124 deriving (Data, Eq, Show, Typeable)
126 newtype Posting_Typed posting
127 = Posting_Typed (Posting_Type, posting)
131 ) => Posting.Posting (Posting_Typed p) where
132 type Posting_Account (Posting_Typed p) = Posting.Posting_Account p
133 type Posting_Amount (Posting_Typed p) = Posting.Posting_Amount p
134 type Posting_Amounts (Posting_Typed p) = Posting.Posting_Amounts p
135 posting_account (Posting_Typed p) = Posting.posting_account (snd p)
136 posting_amounts (Posting_Typed p) = Posting.posting_amounts (snd p)
138 => Posting (Posting_Typed p) where
139 posting_type (Posting_Typed p) = fst p
141 instance Balance.Posting p
142 => Balance.Posting (Posting_Typed p) where
143 type Posting_Account (Posting_Typed p) = Balance.Posting_Account p
144 type Posting_Quantity (Posting_Typed p) = Balance.Posting_Quantity p
145 type Posting_Unit (Posting_Typed p) = Balance.Posting_Unit p
146 posting_account (Posting_Typed p) = Balance.posting_account (snd p)
147 posting_amounts (Posting_Typed p) = Balance.posting_amounts (snd p)
148 posting_set_amounts m (Posting_Typed p) = Posting_Typed $ second (Balance.posting_set_amounts m) p
150 -- ** Class 'Transaction'
153 ( Posting (Transaction_Posting t)
154 , Foldable (Transaction_Postings t)
156 => Transaction t where
157 type Transaction_Posting t
158 type Transaction_Postings t :: * -> *
159 transaction_date :: t -> Date
160 transaction_description :: t -> Text
161 transaction_postings :: t -> Transaction_Postings t (Transaction_Posting t)
162 transaction_postings_virtual :: t -> Transaction_Postings t (Transaction_Posting t)
163 transaction_tags :: t -> Tag.Tags
165 -- ** Class 'Balance'
168 ( Account (Balance_Account b)
169 , Amount (Balance_Amount b)
171 type Balance_Account b
172 type Balance_Amount b
173 balance_account :: b -> Balance_Account b
174 balance_amount :: b -> Balance_Amount b
179 ) => Balance (acct, amt) where
180 type Balance_Account (acct, amt) = acct
181 type Balance_Amount (acct, amt) = amt
182 balance_account = fst
188 ( Account (GL_Account g)
189 , Amount (GL_Amount g)
193 gl_account :: g -> GL_Account g
195 gl_amount :: g -> GL_Amount g
196 gl_sum :: g -> GL_Amount g
201 ) => GL (acct, Date, amt, amt) where
202 type GL_Account (acct, Date, amt, amt) = acct
203 type GL_Amount (acct, Date, amt, amt) = amt
204 gl_account (x, _, _, _) = x
205 gl_date (_, x, _, _) = x
206 gl_amount (_, _, x, _) = x
207 gl_sum (_, _, _, x) = x
213 test :: f -> Filter_Key f -> Bool
214 simplify :: f -> Simplified f
215 -- simplify f = Simplified $ Left f
216 -- | Type to pass an 'Interval' to 'test'.
217 newtype With_Interval f
223 , Monoid (Filter_Key f)
224 ) => f -> t (Filter_Key f) -> Filter_Key f
227 (\x -> if test f x then x else mempty)
229 -- ** Type 'Simplified'
231 newtype Simplified filter
232 = Simplified (Either filter Bool)
234 simplified :: Simplified f -> Either f Bool
235 simplified (Simplified e) = e
237 instance Functor Simplified where
238 fmap _f (Simplified (Right b)) = Simplified (Right b)
239 fmap f (Simplified (Left x)) = Simplified (Left $ f x)
240 instance Filter f => Filter (Simplified f) where
241 type Filter_Key (Simplified f) = Filter_Key f
242 test (Simplified (Right b)) _x = b
243 test (Simplified (Left f)) x = test f x
244 simplify (Simplified (Right b)) = Simplified $ Right b
245 simplify (Simplified (Left f)) =
247 case simplified $ simplify f of
249 Left sf -> Left (Simplified $ Left sf)
250 -- | Conjonctive ('&&') 'Monoid'.
251 instance Monoid f => Monoid (Simplified f) where
252 mempty = Simplified (Right True)
253 mappend (Simplified x) (Simplified y) =
256 (Right bx , Right by ) -> Right (bx && by)
257 (Right True , Left _fy ) -> y
258 (Right False, Left _fy ) -> x
259 (Left _fx , Right True ) -> x
260 (Left _fx , Right False) -> y
261 (Left fx , Left fy ) -> Left $ fx `mappend` fy
263 -- ** Type 'Filter_Text'
267 | Filter_Text_Exact Text
268 | Filter_Text_Regex Regex
269 deriving ({-Data, -}Eq, Show, Typeable)
271 instance Filter Filter_Text where
272 type Filter_Key Filter_Text = Text
275 Filter_Text_Any -> True
276 Filter_Text_Exact m -> (==) m x
277 Filter_Text_Regex m -> Regex.match m x
281 Filter_Text_Any -> Right True
284 -- ** Type 'Filter_Ord'
287 = Lt -- ^ Lower than.
288 | Le -- ^ Lower or equal.
290 | Ge -- ^ Greater or equal.
291 | Gt -- ^ Greater than.
292 deriving (Data, Eq, Show, Typeable)
297 deriving (Data, Eq, Show, Typeable)
298 instance Functor Filter_Ord where
301 Filter_Ord Lt o -> Filter_Ord Lt (f o)
302 Filter_Ord Le o -> Filter_Ord Le (f o)
303 Filter_Ord Eq o -> Filter_Ord Eq (f o)
304 Filter_Ord Ge o -> Filter_Ord Ge (f o)
305 Filter_Ord Gt o -> Filter_Ord Gt (f o)
306 Filter_Ord_Any -> Filter_Ord_Any
308 => Filter (Filter_Ord o) where
309 type Filter_Key (Filter_Ord o) = o
312 Filter_Ord Lt o -> (<) x o
313 Filter_Ord Le o -> (<=) x o
314 Filter_Ord Eq o -> (==) x o
315 Filter_Ord Ge o -> (>=) x o
316 Filter_Ord Gt o -> (>) x o
317 Filter_Ord_Any -> True
321 Filter_Ord_Any -> Right True
324 => Filter (With_Interval (Filter_Ord o)) where
325 type Filter_Key (With_Interval (Filter_Ord o)) = Interval o
326 test (With_Interval f) i =
327 let l = Interval.low i in
328 let h = Interval.high i in
330 Filter_Ord Lt o -> case compare (Interval.limit h) o of
332 EQ -> Interval.adherence h == Interval.Out
334 Filter_Ord Le o -> Interval.limit h <= o
335 Filter_Ord Eq o -> Interval.limit l == o && Interval.limit h == o
336 Filter_Ord Ge o -> Interval.limit l >= o
337 Filter_Ord Gt o -> case compare (Interval.limit l) o of
339 EQ -> Interval.adherence l == Interval.Out
341 Filter_Ord_Any -> True
345 With_Interval Filter_Ord_Any -> Right True
348 -- ** Type 'Filter_Interval'
350 data Filter_Interval x
351 = Filter_Interval_In (Interval (Interval.Unlimitable x))
352 deriving (Eq, Ord, Show)
353 --instance Functor Filter_Interval where
354 -- fmap f (Filter_Interval_In i) = Filter_Interval_In (fmap (fmap f) i)
356 => Filter (Filter_Interval o) where
357 type Filter_Key (Filter_Interval o) = Interval.Unlimitable o
358 test (Filter_Interval_In i) x =
359 Interval.locate x i == EQ
360 simplify = Simplified . Left
362 => Filter (With_Interval (Filter_Interval o)) where
363 type Filter_Key (With_Interval (Filter_Interval o)) = Interval (Interval.Unlimitable o)
364 test (With_Interval (Filter_Interval_In i)) x = Interval.into x i
365 simplify = Simplified . Left
367 -- ** Type 'Filter_Num_Abs'
371 = Filter_Num_Abs (Filter_Ord n)
372 deriving (Data, Eq, Show, Typeable)
374 instance (Num x, Ord x)
375 => Filter (Filter_Num_Abs x) where
376 type Filter_Key (Filter_Num_Abs x) = x
377 test (Filter_Num_Abs f) x = test f (abs x)
380 Filter_Num_Abs ff -> Filter_Num_Abs <$> simplify ff
382 -- ** Type 'Filter_Bool'
387 | Not (Filter_Bool f)
388 | And (Filter_Bool f) (Filter_Bool f)
389 | Or (Filter_Bool f) (Filter_Bool f)
390 deriving (Data, Eq, Show, Typeable)
391 instance Functor Filter_Bool where
393 fmap f (Bool x) = Bool (f x)
394 fmap f (Not t) = Not (fmap f t)
395 fmap f (And t0 t1) = And (fmap f t0) (fmap f t1)
396 fmap f (Or t0 t1) = Or (fmap f t0) (fmap f t1)
397 -- | Conjonctive ('And') 'Monoid'.
398 instance Monoid (Filter_Bool f) where
401 instance Foldable Filter_Bool where
402 foldr _ acc Any = acc
403 foldr m acc (Bool f) = m f acc
404 foldr m acc (Not f) = foldr m acc f
405 foldr m acc (And f0 f1) = foldr m (foldr m acc f0) f1
406 foldr m acc (Or f0 f1) = foldr m (foldr m acc f0) f1
407 instance Traversable Filter_Bool where
408 traverse _ Any = pure Any
409 traverse m (Bool f) = Bool <$> m f
410 traverse m (Not f) = Not <$> traverse m f
411 traverse m (And f0 f1) = And <$> traverse m f0 <*> traverse m f1
412 traverse m (Or f0 f1) = Or <$> traverse m f0 <*> traverse m f1
414 => Filter (Filter_Bool f) where
415 type Filter_Key (Filter_Bool f) = Filter_Key f
417 test (Bool f) x = test f x
418 test (Not f) x = not $ test f x
419 test (And f0 f1) x = test f0 x && test f1 x
420 test (Or f0 f1) x = test f0 x || test f1 x
422 simplify Any = Simplified $ Right True
423 simplify (Bool f) = Bool <$> simplify f
426 case simplified (simplify f) of
427 Left ff -> Left $ Not ff
428 Right b -> Right $ not b
429 simplify (And f0 f1) =
432 ( simplified $ simplify f0
433 , simplified $ simplify f1 ) of
434 (Right b0, Right b1) -> Right $ b0 && b1
435 (Right b0, Left s1) -> if b0 then Left s1 else Right False
436 (Left s0, Right b1) -> if b1 then Left s0 else Right False
437 (Left s0, Left s1) -> Left $ And s0 s1
438 simplify (Or f0 f1) =
441 ( simplified $ simplify f0
442 , simplified $ simplify f1 ) of
443 (Right b0, Right b1) -> Right $ b0 || b1
444 (Right b0, Left s1) -> if b0 then Right True else Left s1
445 (Left s0, Right b1) -> if b1 then Right True else Left s0
446 (Left s0, Left s1) -> Left $ Or s0 s1
448 -- ** Type 'Filter_Unit'
450 newtype Filter_Unit u
451 = Filter_Unit Filter_Text
452 deriving (Eq, Show, Typeable)
455 => Filter (Filter_Unit u) where
456 type Filter_Key (Filter_Unit u) = u
457 test (Filter_Unit f) = test f . unit_text
460 Filter_Unit ff -> Filter_Unit <$> simplify ff
462 -- ** Type 'Filter_Description'
464 type Filter_Description
467 -- ** Type 'Filter_Path'
469 data Filter_Path section
470 = Filter_Path Order [Filter_Path_Section]
471 deriving ({-Data, -}Eq, Show, Typeable)
473 data Filter_Path_Section
474 = Filter_Path_Section_Any
475 | Filter_Path_Section_Many
476 | Filter_Path_Section_Text Filter_Text
477 deriving ({-Data, -}Eq, Show, Typeable)
479 instance Path_Section s
480 => Filter (Filter_Path s) where
481 type Filter_Key (Filter_Path s) = Path s
482 test (Filter_Path ord flt) path =
483 go ord (NonEmpty.toList path) flt
485 go :: Order -> [s] -> [Filter_Path_Section] -> Bool
493 go o _ [Filter_Path_Section_Many] =
510 Filter_Path_Section_Any -> True
511 Filter_Path_Section_Many -> True
512 Filter_Path_Section_Text m -> test m n
514 go o no@(n:ns) fo@(f:fs) =
516 Filter_Path_Section_Any -> go o ns fs
517 Filter_Path_Section_Many -> go o no fs || go o ns fo
518 Filter_Path_Section_Text m -> test m (path_section_text n) &&
529 Filter_Path o l | all (Filter_Path_Section_Many ==) l ->
545 Filter_Path _o [Filter_Path_Section_Many] ->
546 Simplified $ Right True
548 Filter_Path o <$> go fa
550 go :: [Filter_Path_Section] -> Simplified [Filter_Path_Section]
553 [] -> Simplified $ Left []
554 Filter_Path_Section_Many:l@(Filter_Path_Section_Many:_) -> go l
556 case simplified $ simplify_section ff of
557 Left fff -> ((fff :) <$> go l)
558 Right True -> ((Filter_Path_Section_Any :) <$> go l)
559 Right False -> Simplified $ Right False
562 Filter_Path_Section_Any -> Simplified $ Left $ Filter_Path_Section_Any
563 Filter_Path_Section_Many -> Simplified $ Left $ Filter_Path_Section_Many
564 Filter_Path_Section_Text ff -> Filter_Path_Section_Text <$> simplify ff
566 -- ** Type 'Filter_Account'
568 type Filter_Account a
570 (Filter_Account_Component a)
572 data Filter_Account_Component a
573 = Filter_Account_Path (Filter_Path Account_Section)
574 | Filter_Account_Tag Filter_Tags
575 deriving instance Account a => Eq (Filter_Account_Component a)
576 deriving instance Account a => Show (Filter_Account_Component a)
579 => Filter (Filter_Account_Component a) where
580 type Filter_Key (Filter_Account_Component a) = a
581 test (Filter_Account_Path f) a = test f $ account_path a
582 test (Filter_Account_Tag f) a = test f $ account_tags a
585 Filter_Account_Path ff -> Filter_Account_Path <$> simplify ff
586 Filter_Account_Tag ff -> Filter_Account_Tag <$> simplify ff
588 -- ** Type 'Filter_Quantity'
590 type Filter_Quantity q
593 -- ** Type 'Filter_Polarizable'
595 data Filter_Polarized q
596 = Filter_Polarized_Negative (Filter_Quantity q)
597 | Filter_Polarized_Positive (Filter_Quantity q)
598 | Filter_Polarized_Sum (Filter_Quantity q)
599 deriving (Eq, Show, Typeable)
601 instance (Ord q, Addable q)
602 => Filter (Filter_Polarized q) where
603 type Filter_Key (Filter_Polarized q) = Polarized q
606 Filter_Polarized_Negative ff -> maybe False (test ff) $ polarized_negative q
607 Filter_Polarized_Positive ff -> maybe False (test ff) $ polarized_positive q
608 Filter_Polarized_Sum ff -> test ff $ depolarize q
611 Filter_Polarized_Negative ff -> Filter_Polarized_Negative <$> simplify ff
612 Filter_Polarized_Positive ff -> Filter_Polarized_Positive <$> simplify ff
613 Filter_Polarized_Sum ff -> Filter_Polarized_Sum <$> simplify ff
615 -- ** Type 'Filter_Amount'
618 = Filter_Bool (Filter_Amount_Section a)
621 => Filter_Amount_Section a
622 = Filter_Amount_Section_Quantity (Filter_Polarized (Amount_Quantity a))
623 | Filter_Amount_Section_Unit (Filter_Unit (Amount_Unit a))
625 deriving instance Amount a => Eq (Filter_Amount_Section a)
626 deriving instance Amount a => Show (Filter_Amount_Section a)
629 => Filter (Filter_Amount_Section a) where
630 type Filter_Key (Filter_Amount_Section a) = a
633 Filter_Amount_Section_Quantity ff -> test ff $ amount_quantity a
634 Filter_Amount_Section_Unit ff -> test ff $ amount_unit a
637 Filter_Amount_Section_Quantity ff -> Filter_Amount_Section_Quantity <$> simplify ff
638 Filter_Amount_Section_Unit ff -> Filter_Amount_Section_Unit <$> simplify ff
640 -- ** Type 'Filter_Posting_Type'
642 data Filter_Posting_Type
643 = Filter_Posting_Type_Any
644 | Filter_Posting_Type_Exact Posting_Type
645 deriving (Data, Eq, Show, Typeable)
647 instance Filter Filter_Posting_Type where
648 type Filter_Key Filter_Posting_Type = Posting_Type
651 Filter_Posting_Type_Any -> True
652 Filter_Posting_Type_Exact ff -> ff == p
656 Filter_Posting_Type_Any -> Right True
657 Filter_Posting_Type_Exact _ -> Left f
659 -- ** Type 'Filter_Date'
662 = Filter_Date_UTC (Filter_Ord Date)
663 | Filter_Date_Year (Filter_Interval Integer)
664 | Filter_Date_Month (Filter_Interval Int)
665 | Filter_Date_DoM (Filter_Interval Int)
666 | Filter_Date_Hour (Filter_Interval Int)
667 | Filter_Date_Minute (Filter_Interval Int)
668 | Filter_Date_Second (Filter_Interval Data.Fixed.Pico)
669 deriving (Eq, Show, Typeable)
671 instance Filter Filter_Date where
672 type Filter_Key Filter_Date = Date
673 test (Filter_Date_UTC f) d = test f $ d
674 test (Filter_Date_Year f) d = test f $ Interval.Limited $ Date.year d
675 test (Filter_Date_Month f) d = test f $ Interval.Limited $ Date.month d
676 test (Filter_Date_DoM f) d = test f $ Interval.Limited $ Date.dom d
677 test (Filter_Date_Hour f) d = test f $ Interval.Limited $ Date.hour d
678 test (Filter_Date_Minute f) d = test f $ Interval.Limited $ Date.minute d
679 test (Filter_Date_Second f) d = test f $ Interval.Limited $ Date.second d
682 Filter_Date_UTC ff -> Filter_Date_UTC <$> simplify ff
683 Filter_Date_Year ff -> Filter_Date_Year <$> simplify ff
684 Filter_Date_Month ff -> Filter_Date_Month <$> simplify ff
685 Filter_Date_DoM ff -> Filter_Date_DoM <$> simplify ff
686 Filter_Date_Hour ff -> Filter_Date_Hour <$> simplify ff
687 Filter_Date_Minute ff -> Filter_Date_Minute <$> simplify ff
688 Filter_Date_Second ff -> Filter_Date_Second <$> simplify ff
690 instance Filter (With_Interval Filter_Date) where
691 type Filter_Key (With_Interval Filter_Date) = Interval (Interval.Unlimitable Date)
692 test (With_Interval (Filter_Date_UTC f)) d = test (With_Interval (Interval.Limited <$> f)) d
693 test (With_Interval (Filter_Date_Year f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.year) d
694 test (With_Interval (Filter_Date_Month f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.month) d
695 test (With_Interval (Filter_Date_DoM f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.dom) d
696 test (With_Interval (Filter_Date_Hour f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.hour) d
697 test (With_Interval (Filter_Date_Minute f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.minute) d
698 test (With_Interval (Filter_Date_Second f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.second) d
699 simplify (With_Interval f) =
701 Filter_Date_UTC ff -> With_Interval . Filter_Date_UTC <$> simplify ff
702 Filter_Date_Year ff -> With_Interval . Filter_Date_Year <$> simplify ff
703 Filter_Date_Month ff -> With_Interval . Filter_Date_Month <$> simplify ff
704 Filter_Date_DoM ff -> With_Interval . Filter_Date_DoM <$> simplify ff
705 Filter_Date_Hour ff -> With_Interval . Filter_Date_Hour <$> simplify ff
706 Filter_Date_Minute ff -> With_Interval . Filter_Date_Minute <$> simplify ff
707 Filter_Date_Second ff -> With_Interval . Filter_Date_Second <$> simplify ff
709 -- ** Type 'Filter_Tags'
716 = Filter_Tag_Path (Filter_Path Tag.Section)
717 | Filter_Tag_Value Filter_Tag_Value
718 deriving ({-Data, -}Eq, Show, Typeable)
720 data Filter_Tag_Value
721 = Filter_Tag_Value_None
722 | Filter_Tag_Value_Any Filter_Text
723 | Filter_Tag_Value_First Filter_Text
724 | Filter_Tag_Value_Last Filter_Text
725 deriving ({-Data, -}Eq, Show, Typeable)
727 instance Filter Filter_Tag where
728 type Filter_Key Filter_Tag = Tag.Tags
729 test f (Tag.Tags ts) =
732 Filter_Tag_Path ff -> test ff . fst
733 Filter_Tag_Value ff -> test ff . snd in
735 Data.Map.foldrWithKey
736 (\p -> mappend . Data.Monoid.Any . tst . (p,))
737 (Data.Monoid.Any False) $
741 Filter_Tag_Path ff -> Filter_Tag_Path <$> simplify ff
742 Filter_Tag_Value ff -> Filter_Tag_Value <$> simplify ff
744 instance Filter Filter_Tag_Value where
745 type Filter_Key Filter_Tag_Value = [Tag.Value]
746 test (Filter_Tag_Value_None ) vs = null vs
747 test (Filter_Tag_Value_Any f) vs = any (test f) vs
748 test (Filter_Tag_Value_First f) vs =
752 test (Filter_Tag_Value_Last f) vs =
758 Filter_Tag_Value_None -> Simplified $ Right False
759 Filter_Tag_Value_Any ff -> Filter_Tag_Value_Any <$> simplify ff
760 Filter_Tag_Value_First ff -> Filter_Tag_Value_First <$> simplify ff
761 Filter_Tag_Value_Last ff -> Filter_Tag_Value_Last <$> simplify ff
763 -- ** Type 'Filter_Posting'
767 = Filter_Posting_Account (Filter_Account (Posting.Posting_Account p))
768 | Filter_Posting_Amount (Filter_Amount (Posting.Posting_Amount p))
769 | Filter_Posting_Unit (Filter_Unit (Amount_Unit (Posting.Posting_Amount p))) -- TODO: remove: Filter_Posting_Amount should be enough
770 | Filter_Posting_Type Filter_Posting_Type
773 -- Description Comp_String String
775 -- Account_Tag Comp_String String (Maybe (Comp_String, String))
776 -- Account_Balance Comp_Num Comp_Num_Absolute Amount
777 -- Depth Comp_Num Int
781 -- Tag Comp_String Tag.Name (Maybe (Comp_String, Tag.Value))
782 deriving instance Posting p => Eq (Filter_Posting p)
783 deriving instance Posting p => Show (Filter_Posting p)
786 => Filter (Filter_Posting p) where
787 type Filter_Key (Filter_Posting p) = p
788 test (Filter_Posting_Account f) p =
789 test f $ Posting.posting_account p
790 test (Filter_Posting_Amount f) p =
791 any (test f) $ Posting.posting_amounts p
792 test (Filter_Posting_Type f) p =
793 test f $ posting_type p
794 test (Filter_Posting_Unit f) p =
795 any (test f . amount_unit) $ Posting.posting_amounts p
798 Filter_Posting_Account ff -> Filter_Posting_Account <$> simplify ff
799 Filter_Posting_Amount ff -> Filter_Posting_Amount <$> simplify ff
800 Filter_Posting_Type ff -> Filter_Posting_Type <$> simplify ff
801 Filter_Posting_Unit ff -> Filter_Posting_Unit <$> simplify ff
803 -- ** Type 'Filter_Transaction'
806 => Filter_Transaction t
807 = Filter_Transaction_Description Filter_Description
808 | Filter_Transaction_Posting (Filter_Bool (Filter_Posting (Posting_Typed (Transaction_Posting t))))
809 | Filter_Transaction_Date (Filter_Bool Filter_Date)
810 | Filter_Transaction_Tag Filter_Tags
812 deriving instance Transaction t => Eq (Filter_Transaction t)
813 deriving instance Transaction t => Show (Filter_Transaction t)
815 instance Transaction t
816 => Filter (Filter_Transaction t) where
817 type Filter_Key (Filter_Transaction t) = t
818 test (Filter_Transaction_Description f) t =
819 test f $ transaction_description t
820 test (Filter_Transaction_Posting f) t =
822 (test f . Posting_Typed . (Posting_Type_Regular,))
823 (transaction_postings t) ||
825 (test f . Posting_Typed . (Posting_Type_Virtual,))
826 (transaction_postings_virtual t)
827 test (Filter_Transaction_Date f) t =
828 test f $ transaction_date t
829 test (Filter_Transaction_Tag f) t =
830 test f (transaction_tags t)
833 Filter_Transaction_Date ff -> Filter_Transaction_Date <$> simplify ff
834 Filter_Transaction_Description ff -> Filter_Transaction_Description <$> simplify ff
835 Filter_Transaction_Posting ff -> Filter_Transaction_Posting <$> simplify ff
836 Filter_Transaction_Tag ff -> Filter_Transaction_Tag <$> simplify ff
840 , Journal.Transaction t
844 (Simplified (Filter_Bool (Filter_Transaction t)))
845 Journal.Journal t where
848 then Journal.cons t j
853 , Stats.Transaction t
856 (Simplified (Filter_Bool (Filter_Transaction t)))
863 -- ** Type 'Filter_Balance'
867 = Filter_Balance_Account (Filter_Account (Balance_Account b))
868 | Filter_Balance_Amount (Filter_Amount (Balance_Amount b))
870 deriving instance Balance b => Eq (Filter_Balance b)
871 deriving instance Balance b => Show (Filter_Balance b)
874 => Filter (Filter_Balance b) where
875 type Filter_Key (Filter_Balance b) = b
876 test (Filter_Balance_Account f) b =
877 test f $ balance_account b
878 test (Filter_Balance_Amount f) b =
879 test f $ balance_amount b
882 Filter_Balance_Account ff -> Filter_Balance_Account <$> simplify ff
883 Filter_Balance_Amount ff -> Filter_Balance_Amount <$> simplify ff
888 , account ~ Balance.Posting_Account p
889 , account_section ~ Account.Account_Section account
890 , quantity ~ Balance.Posting_Quantity p
891 , unit ~ Balance.Posting_Unit p
895 => Consable (Simplified (Filter_Bool (Filter_Posting p)))
896 (Const (Balance.Balance_by_Account account_section unit quantity))
898 mcons fp p (Const !bal) =
900 case simplified fp of
902 Right True -> Balance.cons_by_account p bal
905 then Balance.cons_by_account p bal
908 ( Transaction transaction
909 , posting ~ Transaction_Posting transaction
910 , account ~ Balance.Posting_Account posting
911 , account_section ~ Account.Account_Section account
912 , quantity ~ Balance.Posting_Quantity posting
913 , unit ~ Balance.Posting_Unit posting
916 , Balance.Posting posting
917 , NFData account_section
918 , NFData (Balance.Account_Sum unit quantity)
920 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
921 , (Simplified (Filter_Bool (Filter_Posting posting))) )
922 (Const (Balance.Balance_by_Account account_section unit quantity))
924 mcons (ft, fp) t (Const !bal) =
926 case simplified ft of
928 Right True -> fold_postings bal $
930 [ transaction_postings t
931 , transaction_postings_virtual t
935 then fold_postings bal $
937 [ transaction_postings t
938 , transaction_postings_virtual t
944 , account ~ Balance.Posting_Account posting
945 , quantity ~ Balance.Posting_Quantity posting
946 , unit ~ Balance.Posting_Unit posting
948 => Balance.Balance_by_Account account_section unit quantity
950 -> Balance.Balance_by_Account account_section unit quantity
952 case simplified fp of
954 Right True -> foldl' (flip Balance.cons_by_account)
955 Left ff -> foldl' $ \b p ->
957 then Balance.cons_by_account p b
961 , Balance.Posting posting
963 , account ~ Balance.Posting_Account posting
964 , account_section ~ Account.Account_Section account
965 , quantity ~ Balance.Posting_Quantity posting
966 , unit ~ Balance.Posting_Unit posting
970 => Consable (Simplified (Filter_Bool (Filter_Posting posting)))
971 (Const (Balance.Balance_by_Account account_section unit quantity))
972 (foldable posting) where
973 mcons fp ps (Const !bal) =
975 case simplified fp of
977 Right True -> foldl' (flip Balance.cons_by_account) bal ps
981 then Balance.cons_by_account p b
985 -- ** Type 'Filter_GL'
989 = Filter_GL_Account (Filter_Account (GL_Account g))
990 | Filter_GL_Amount (Filter_Amount (GL_Amount g))
991 | Filter_GL_Sum (Filter_Amount (GL_Amount g))
993 deriving instance GL g => Eq (Filter_GL g)
994 deriving instance GL g => Show (Filter_GL g)
997 => Filter (Filter_GL g) where
998 type Filter_Key (Filter_GL g) = g
999 test (Filter_GL_Account f) g =
1000 test f $ gl_account g
1001 test (Filter_GL_Amount f) g =
1002 test f $ gl_amount g
1003 test (Filter_GL_Sum f) g =
1007 Filter_GL_Account ff -> Filter_GL_Account <$> simplify ff
1008 Filter_GL_Amount ff -> Filter_GL_Amount <$> simplify ff
1009 Filter_GL_Sum ff -> Filter_GL_Sum <$> simplify ff
1012 ( Transaction transaction
1014 , GL.Transaction transaction
1015 , posting ~ GL.Transaction_Posting transaction
1017 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
1018 , (Simplified (Filter_Bool (Filter_Posting posting ))) )
1021 mcons (ft, fp) t !gl =
1022 case simplified ft of
1025 case simplified fp of
1027 Right True -> GL.cons t gl
1030 (GL.transaction_postings_filter (test f) t)
1035 case simplified fp of
1037 Right True -> GL.cons t gl
1040 (GL.transaction_postings_filter (test ff) t)
1045 , Transaction transaction
1047 , GL.Transaction transaction
1048 , posting ~ GL.Transaction_Posting transaction
1050 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
1051 , (Simplified (Filter_Bool (Filter_Posting posting ))) )
1052 (Const (GL.GL transaction))
1053 (foldable transaction) where
1054 mcons (ft, fp) ts (Const !gl) =
1056 case simplified ft of
1059 case simplified fp of
1061 Right True -> foldr (GL.cons) gl ts
1065 . GL.transaction_postings_filter (test f) )
1072 case simplified fp of
1074 Right True -> GL.cons t
1075 Left ff -> GL.cons $
1076 GL.transaction_postings_filter (test ff) t