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)
18 import Data.Either (Either(..))
19 import Data.Eq (Eq(..))
20 import qualified Data.Fixed
21 import qualified Data.Foldable
22 import Data.Foldable (Foldable(..))
23 import Data.Foldable (all)
24 import Data.Functor (Functor(..), (<$>))
25 import Data.Functor.Compose (Compose(..))
26 -- import qualified Data.List
27 import Data.List (reverse)
28 import Data.List.NonEmpty (NonEmpty(..))
29 import qualified Data.List.NonEmpty as NonEmpty
30 import Data.Map.Strict (Map)
31 import qualified Data.Map.Strict as Data.Map
32 import Data.Maybe (Maybe(..))
33 import Data.Maybe (maybe)
34 import qualified Data.Monoid
35 import Data.Monoid (Monoid(..))
36 import Data.Ord (Ord(..), Ordering(..))
37 import Data.Text (Text)
38 -- import qualified Data.Text as Text
39 -- import qualified Data.Time.Calendar as Time
40 import Data.Traversable (Traversable(..))
41 import Data.Tuple (fst, snd)
42 import Data.Typeable ()
43 import Prelude (($), (.), Int, Integer, Num(..), Show(..), const, flip, id)
44 import Text.Regex.Base ()
45 import Text.Regex.TDFA ()
46 import Text.Regex.TDFA.Text ()
48 import qualified Hcompta.Account as Account
49 import qualified Hcompta.Amount as Amount
50 import qualified Hcompta.Amount.Unit as Amount.Unit
51 import qualified Hcompta.Balance as Balance
52 import Hcompta.Date (Date)
53 import qualified Hcompta.Date as Date
54 -- import qualified Hcompta.Date as Date
55 import qualified Hcompta.GL as GL
56 import qualified Hcompta.Journal as Journal
57 import Hcompta.Lib.Applicative ()
58 import Hcompta.Lib.Consable (Consable(..))
59 import Hcompta.Lib.Interval (Interval)
60 import qualified Hcompta.Lib.Interval as Interval
61 import Hcompta.Lib.Regex (Regex)
62 import qualified Hcompta.Lib.Regex as Regex
63 -- import Hcompta.Lib.TreeMap (TreeMap)
64 -- import qualified Hcompta.Lib.TreeMap as TreeMap
65 -- import qualified Hcompta.Posting as Posting
66 import qualified Hcompta.Stats as Stats
67 import qualified Hcompta.Tag as Tag
69 -- * Requirements' interface
76 class Path_Section a where
77 path_section_text :: a -> Text
79 instance Path_Section Text where
80 path_section_text = id
85 account_path :: a -> Account.Account
86 account_tags :: a -> Tag.Tags
88 instance Account (Account.Account, Tag.Tags) where
92 instance Account Account.Account where
100 unit_text :: a -> Text
102 instance Unit Amount.Unit where
103 unit_text = Amount.Unit.text
105 instance Unit Text where
111 ( Ord (Amount_Quantity a)
112 , Show (Amount_Quantity a)
113 , Show (Amount_Unit a)
114 , Unit (Amount_Unit a)
118 type Amount_Quantity a
119 amount_unit :: a -> Amount_Unit a
120 amount_quantity :: a -> Amount_Quantity a
121 amount_sign :: a -> Ordering
123 instance Amount Amount.Amount where
124 type Amount_Unit Amount.Amount = Amount.Unit
125 type Amount_Quantity Amount.Amount = Amount.Quantity
126 amount_quantity = Amount.quantity
127 amount_unit = Amount.unit
128 amount_sign = Amount.sign
130 instance (Amount a, GL.Amount a)
131 => Amount (Amount.Sum a) where
132 type Amount_Unit (Amount.Sum a) = Amount_Unit a
133 type Amount_Quantity (Amount.Sum a) = Amount_Quantity a
134 amount_quantity = amount_quantity . Amount.sum_balance
135 amount_unit = amount_unit . Amount.sum_balance
136 amount_sign = amount_sign . Amount.sum_balance
138 -- ** Class 'Posting'
141 ( Amount (Posting_Amount p)
142 , Account (Posting_Account p)
144 type Posting_Account p
145 type Posting_Amount p
146 posting_account :: p -> Posting_Account p
147 posting_amounts :: p -> Map (Amount_Unit (Posting_Amount p)) (Posting_Amount p)
148 posting_type :: p -> Posting_Type
151 = Posting_Type_Regular
152 | Posting_Type_Virtual
153 deriving (Data, Eq, Show, Typeable)
156 => Posting (Posting_Type, p) where
157 type Posting_Account (Posting_Type, p) = Posting_Account p
158 type Posting_Amount (Posting_Type, p) = Posting_Amount p
160 posting_account = posting_account . snd
161 posting_amounts = posting_amounts . snd
165 => Posting (Posting_Type, (c, p)) where
166 type Posting_Account (Posting_Type, (c, p)) = Posting_Account p
167 type Posting_Amount (Posting_Type, (c, p)) = Posting_Amount p
169 posting_account = posting_account . snd . snd
170 posting_amounts = posting_amounts . snd . snd
173 instance Balance.Posting p
174 => Balance.Posting (Posting_Type, p) where
175 type Posting_Amount (Posting_Type, p) = Balance.Posting_Amount p
176 posting_account = Balance.posting_account . snd
177 posting_amounts = Balance.posting_amounts . snd
178 posting_set_amounts = second . Balance.posting_set_amounts
180 -- ** Class 'Transaction'
183 ( Posting (Transaction_Posting t)
184 , Foldable (Transaction_Postings t)
186 => Transaction t where
187 type Transaction_Posting t
188 type Transaction_Postings t :: * -> *
189 transaction_date :: t -> Date
190 transaction_description :: t -> Text
191 transaction_postings :: t -> Transaction_Postings t (Transaction_Posting t)
192 transaction_postings_virtual :: t -> Transaction_Postings t (Transaction_Posting t)
193 transaction_tags :: t -> Tag.Tags
196 instance Transaction t
197 => Transaction (c, t) where
198 type Transaction_Context (c, t) = c
199 type Transaction_Posting (c, t) = Transaction_Posting t
200 type Transaction_Postings (c, t) = Transaction_Postings t
201 transaction_context = fst
202 transaction_date = transaction_date . snd
203 transaction_description = transaction_description . snd
204 transaction_postings = transaction_postings . snd
205 transaction_postings_virtual = transaction_postings_virtual . snd
206 transaction_tags = transaction_tags . snd
209 -- ** Class 'Balance'
212 ( Account (Balance_Account b)
213 , Amount (Balance_Amount b)
215 type Balance_Account b
216 type Balance_Amount b
217 balance_account :: b -> Balance_Account b
218 balance_amount :: b -> Balance_Amount b
219 balance_positive :: b -> Maybe (Balance_Amount b)
220 balance_negative :: b -> Maybe (Balance_Amount b)
226 ) => Balance (acct, Amount.Sum amt) where
227 type Balance_Account (acct, Amount.Sum amt) = acct
228 type Balance_Amount (acct, Amount.Sum amt) = amt
229 balance_account = fst
230 balance_amount (_, amt) =
232 Amount.Sum_Negative n -> n
233 Amount.Sum_Positive p -> p
234 Amount.Sum_Both n p -> Balance.amount_add n p
235 balance_positive = Amount.sum_positive . snd
236 balance_negative = Amount.sum_negative . snd
241 ( Account (GL_Account g)
242 , Amount (GL_Amount g)
246 gl_account :: g -> GL_Account g
248 gl_amount_positive :: g -> Maybe (GL_Amount g)
249 gl_amount_negative :: g -> Maybe (GL_Amount g)
250 gl_amount_balance :: g -> GL_Amount g
251 gl_sum_positive :: g -> Maybe (GL_Amount g)
252 gl_sum_negative :: g -> Maybe (GL_Amount g)
253 gl_sum_balance :: g -> GL_Amount g
259 ) => GL (acct, Date, Amount.Sum amt, Amount.Sum amt) where
260 type GL_Account (acct, Date, Amount.Sum amt, Amount.Sum amt) = acct
261 type GL_Amount (acct, Date, Amount.Sum amt, Amount.Sum amt) = amt
262 gl_account (x, _, _, _) = x
263 gl_date (_, x, _, _) = x
264 gl_amount_positive (_, _, x, _) = Amount.sum_positive x
265 gl_amount_negative (_, _, x, _) = Amount.sum_negative x
266 gl_amount_balance (_, _, x, _) = Amount.sum_balance x
267 gl_sum_positive (_, _, _, x) = Amount.sum_positive x
268 gl_sum_negative (_, _, _, x) = Amount.sum_negative x
269 gl_sum_balance (_, _, _, x) = Amount.sum_balance x
275 test :: f -> Filter_Key f -> Bool
276 simplify :: f -> Simplified f
277 -- simplify f = Simplified $ Left f
278 -- | Type to pass an 'Interval' to 'test'.
279 newtype With_Interval f
283 :: (Foldable t, Filter f, Monoid (Filter_Key f))
284 => f -> t (Filter_Key f) -> Filter_Key f
286 Data.Foldable.foldMap
287 (\x -> if test f x then x else mempty)
289 -- ** Type 'Simplified'
291 newtype Simplified filter
292 = Simplified (Either filter Bool)
294 simplified :: Simplified f -> Either f Bool
295 simplified (Simplified e) = e
297 instance Functor Simplified where
298 fmap _f (Simplified (Right b)) = Simplified (Right b)
299 fmap f (Simplified (Left x)) = Simplified (Left $ f x)
300 instance Filter f => Filter (Simplified f) where
301 type Filter_Key (Simplified f) = Filter_Key f
302 test (Simplified (Right b)) _x = b
303 test (Simplified (Left f)) x = test f x
304 simplify (Simplified (Right b)) = Simplified $ Right b
305 simplify (Simplified (Left f)) =
307 case simplified $ simplify f of
309 Left sf -> Left (Simplified $ Left sf)
310 -- | Conjonctive ('&&') 'Monoid'.
311 instance Monoid f => Monoid (Simplified f) where
312 mempty = Simplified (Right True)
313 mappend (Simplified x) (Simplified y) =
316 (Right bx , Right by ) -> Right (bx && by)
317 (Right True , Left _fy ) -> y
318 (Right False, Left _fy ) -> x
319 (Left _fx , Right True ) -> x
320 (Left _fx , Right False) -> y
321 (Left fx , Left fy ) -> Left $ fx `mappend` fy
323 -- ** Type 'Filter_Text'
327 | Filter_Text_Exact Text
328 | Filter_Text_Regex Regex
329 deriving ({-Data, -}Eq, Show, Typeable)
331 instance Filter Filter_Text where
332 type Filter_Key Filter_Text = Text
335 Filter_Text_Any -> True
336 Filter_Text_Exact m -> (==) m x
337 Filter_Text_Regex m -> Regex.match m x
341 Filter_Text_Any -> Right True
344 -- ** Type 'Filter_Ord'
347 = Lt -- ^ Lower than.
348 | Le -- ^ Lower or equal.
350 | Ge -- ^ Greater or equal.
351 | Gt -- ^ Greater than.
352 deriving (Data, Eq, Show, Typeable)
357 deriving (Data, Eq, Show, Typeable)
358 instance Functor Filter_Ord where
361 Filter_Ord Lt o -> Filter_Ord Lt (f o)
362 Filter_Ord Le o -> Filter_Ord Le (f o)
363 Filter_Ord Eq o -> Filter_Ord Eq (f o)
364 Filter_Ord Ge o -> Filter_Ord Ge (f o)
365 Filter_Ord Gt o -> Filter_Ord Gt (f o)
366 Filter_Ord_Any -> Filter_Ord_Any
368 => Filter (Filter_Ord o) where
369 type Filter_Key (Filter_Ord o) = o
372 Filter_Ord Lt o -> (<) x o
373 Filter_Ord Le o -> (<=) x o
374 Filter_Ord Eq o -> (==) x o
375 Filter_Ord Ge o -> (>=) x o
376 Filter_Ord Gt o -> (>) x o
377 Filter_Ord_Any -> True
381 Filter_Ord_Any -> Right True
384 => Filter (With_Interval (Filter_Ord o)) where
385 type Filter_Key (With_Interval (Filter_Ord o)) = Interval o
386 test (With_Interval f) i =
387 let l = Interval.low i in
388 let h = Interval.high i in
390 Filter_Ord Lt o -> case compare (Interval.limit h) o of
392 EQ -> Interval.adherence h == Interval.Out
394 Filter_Ord Le o -> Interval.limit h <= o
395 Filter_Ord Eq o -> Interval.limit l == o && Interval.limit h == o
396 Filter_Ord Ge o -> Interval.limit l >= o
397 Filter_Ord Gt o -> case compare (Interval.limit l) o of
399 EQ -> Interval.adherence l == Interval.Out
401 Filter_Ord_Any -> True
405 With_Interval Filter_Ord_Any -> Right True
408 -- ** Type 'Filter_Interval'
410 data Filter_Interval x
411 = Filter_Interval_In (Interval (Interval.Unlimitable x))
412 deriving (Eq, Ord, Show)
413 --instance Functor Filter_Interval where
414 -- fmap f (Filter_Interval_In i) = Filter_Interval_In (fmap (fmap f) i)
416 => Filter (Filter_Interval o) where
417 type Filter_Key (Filter_Interval o) = Interval.Unlimitable o
418 test (Filter_Interval_In i) x =
419 Interval.locate x i == EQ
420 simplify = Simplified . Left
422 => Filter (With_Interval (Filter_Interval o)) where
423 type Filter_Key (With_Interval (Filter_Interval o)) = Interval (Interval.Unlimitable o)
424 test (With_Interval (Filter_Interval_In i)) x = Interval.into x i
425 simplify = Simplified . Left
427 -- ** Type 'Filter_Num_Abs'
431 = Filter_Num_Abs (Filter_Ord n)
432 deriving (Data, Eq, Show, Typeable)
434 instance (Num x, Ord x)
435 => Filter (Filter_Num_Abs x) where
436 type Filter_Key (Filter_Num_Abs x) = x
437 test (Filter_Num_Abs f) x = test f (abs x)
440 Filter_Num_Abs ff -> Filter_Num_Abs <$> simplify ff
442 -- ** Type 'Filter_Bool'
447 | Not (Filter_Bool f)
448 | And (Filter_Bool f) (Filter_Bool f)
449 | Or (Filter_Bool f) (Filter_Bool f)
450 deriving (Data, Eq, Show, Typeable)
451 instance Functor Filter_Bool where
453 fmap f (Bool x) = Bool (f x)
454 fmap f (Not t) = Not (fmap f t)
455 fmap f (And t0 t1) = And (fmap f t0) (fmap f t1)
456 fmap f (Or t0 t1) = Or (fmap f t0) (fmap f t1)
457 -- | Conjonctive ('And') 'Monoid'.
458 instance Monoid (Filter_Bool f) where
461 instance Foldable Filter_Bool where
462 foldr _ acc Any = acc
463 foldr m acc (Bool f) = m f acc
464 foldr m acc (Not f) = Data.Foldable.foldr m acc f
465 foldr m acc (And f0 f1) = Data.Foldable.foldr m (Data.Foldable.foldr m acc f0) f1
466 foldr m acc (Or f0 f1) = Data.Foldable.foldr m (Data.Foldable.foldr m acc f0) f1
467 instance Traversable Filter_Bool where
468 traverse _ Any = pure Any
469 traverse m (Bool f) = Bool <$> m f
470 traverse m (Not f) = Not <$> traverse m f
471 traverse m (And f0 f1) = And <$> traverse m f0 <*> traverse m f1
472 traverse m (Or f0 f1) = Or <$> traverse m f0 <*> traverse m f1
474 => Filter (Filter_Bool f) where
475 type Filter_Key (Filter_Bool f) = Filter_Key f
477 test (Bool f) x = test f x
478 test (Not f) x = not $ test f x
479 test (And f0 f1) x = test f0 x && test f1 x
480 test (Or f0 f1) x = test f0 x || test f1 x
482 simplify Any = Simplified $ Right True
483 simplify (Bool f) = Bool <$> simplify f
486 case simplified (simplify f) of
487 Left ff -> Left $ Not ff
488 Right b -> Right $ not b
489 simplify (And f0 f1) =
492 ( simplified $ simplify f0
493 , simplified $ simplify f1 ) of
494 (Right b0, Right b1) -> Right $ b0 && b1
495 (Right b0, Left s1) -> if b0 then Left s1 else Right False
496 (Left s0, Right b1) -> if b1 then Left s0 else Right False
497 (Left s0, Left s1) -> Left $ And s0 s1
498 simplify (Or f0 f1) =
501 ( simplified $ simplify f0
502 , simplified $ simplify f1 ) of
503 (Right b0, Right b1) -> Right $ b0 || b1
504 (Right b0, Left s1) -> if b0 then Right True else Left s1
505 (Left s0, Right b1) -> if b1 then Right True else Left s0
506 (Left s0, Left s1) -> Left $ Or s0 s1
508 -- ** Type 'Filter_Unit'
510 newtype Filter_Unit u
511 = Filter_Unit Filter_Text
512 deriving (Eq, Show, Typeable)
515 => Filter (Filter_Unit u) where
516 type Filter_Key (Filter_Unit u) = u
517 test (Filter_Unit f) = test f . unit_text
520 Filter_Unit ff -> Filter_Unit <$> simplify ff
522 -- ** Type 'Filter_Description'
524 type Filter_Description
527 -- ** Type 'Filter_Path'
529 data Filter_Path section
530 = Filter_Path Order [Filter_Path_Section]
531 deriving ({-Data, -}Eq, Show, Typeable)
533 data Filter_Path_Section
534 = Filter_Path_Section_Any
535 | Filter_Path_Section_Many
536 | Filter_Path_Section_Text Filter_Text
537 deriving ({-Data, -}Eq, Show, Typeable)
539 instance Path_Section s
540 => Filter (Filter_Path s) where
541 type Filter_Key (Filter_Path s) = Path s
542 test (Filter_Path ord flt) path =
543 go ord (NonEmpty.toList path) flt
545 go :: Order -> [s] -> [Filter_Path_Section] -> Bool
553 go o _ [Filter_Path_Section_Many] =
570 Filter_Path_Section_Any -> True
571 Filter_Path_Section_Many -> True
572 Filter_Path_Section_Text m -> test m n
574 go o no@(n:ns) fo@(f:fs) =
576 Filter_Path_Section_Any -> go o ns fs
577 Filter_Path_Section_Many -> go o no fs || go o ns fo
578 Filter_Path_Section_Text m -> test m (path_section_text n) &&
589 Filter_Path o l | all (Filter_Path_Section_Many ==) l ->
606 Filter_Path o <$> go fa
608 go :: [Filter_Path_Section] -> Simplified [Filter_Path_Section]
611 [] -> Simplified $ Left []
612 [Filter_Path_Section_Many] -> Simplified $ Right True -- FIXME: useful?
613 Filter_Path_Section_Many:l@(Filter_Path_Section_Many:_) -> go l
615 case simplified $ simplify_section ff of
616 Left fff -> ((fff :) <$> go l)
617 Right True -> ((Filter_Path_Section_Any :) <$> go l)
618 Right False -> Simplified $ Right False
621 Filter_Path_Section_Any -> Simplified $ Left $ Filter_Path_Section_Any
622 Filter_Path_Section_Many -> Simplified $ Left $ Filter_Path_Section_Many
623 Filter_Path_Section_Text ff -> Filter_Path_Section_Text <$> simplify ff
625 -- ** Type 'Filter_Account'
627 type Filter_Account a
629 (Filter_Account_Component a)
631 data Filter_Account_Component a
632 = Filter_Account_Path (Filter_Path Account.Account_Section)
633 | Filter_Account_Tag Filter_Tags
634 deriving instance Account a => Eq (Filter_Account_Component a)
635 deriving instance Account a => Show (Filter_Account_Component a)
638 => Filter (Filter_Account_Component a) where
639 type Filter_Key (Filter_Account_Component a) = a
640 test (Filter_Account_Path f) a = test f $ account_path a
641 test (Filter_Account_Tag f) a = test f $ account_tags a
644 Filter_Account_Path ff -> Filter_Account_Path <$> simplify ff
645 Filter_Account_Tag ff -> Filter_Account_Tag <$> simplify ff
647 -- ** Type 'Filter_Amount'
649 type Filter_Quantity q
653 = Filter_Bool (Filter_Amount_Section a)
656 => Filter_Amount_Section a
657 = Filter_Amount_Section_Quantity (Filter_Quantity (Amount_Quantity a))
658 | Filter_Amount_Section_Unit (Filter_Unit (Amount_Unit a))
660 deriving instance Amount a => Eq (Filter_Amount_Section a)
661 deriving instance Amount a => Show (Filter_Amount_Section a)
664 => Filter (Filter_Amount_Section a) where
665 type Filter_Key (Filter_Amount_Section a) = a
668 Filter_Amount_Section_Quantity ff -> test ff $ amount_quantity a
669 Filter_Amount_Section_Unit ff -> test ff $ amount_unit a
672 Filter_Amount_Section_Quantity ff -> Filter_Amount_Section_Quantity <$> simplify ff
673 Filter_Amount_Section_Unit ff -> Filter_Amount_Section_Unit <$> simplify ff
675 -- ** Type 'Filter_Posting_Type'
677 data Filter_Posting_Type
678 = Filter_Posting_Type_Any
679 | Filter_Posting_Type_Exact Posting_Type
680 deriving (Data, Eq, Show, Typeable)
682 instance Filter Filter_Posting_Type where
683 type Filter_Key Filter_Posting_Type = Posting_Type
686 Filter_Posting_Type_Any -> True
687 Filter_Posting_Type_Exact ff -> ff == p
691 Filter_Posting_Type_Any -> Right True
692 Filter_Posting_Type_Exact _ -> Left f
694 -- ** Type 'Filter_Date'
697 = Filter_Date_UTC (Filter_Ord Date)
698 | Filter_Date_Year (Filter_Interval Integer)
699 | Filter_Date_Month (Filter_Interval Int)
700 | Filter_Date_DoM (Filter_Interval Int)
701 | Filter_Date_Hour (Filter_Interval Int)
702 | Filter_Date_Minute (Filter_Interval Int)
703 | Filter_Date_Second (Filter_Interval Data.Fixed.Pico)
704 deriving (Eq, Show, Typeable)
706 instance Filter Filter_Date where
707 type Filter_Key Filter_Date = Date
708 test (Filter_Date_UTC f) d = test f $ d
709 test (Filter_Date_Year f) d = test f $ Interval.Limited $ Date.year d
710 test (Filter_Date_Month f) d = test f $ Interval.Limited $ Date.month d
711 test (Filter_Date_DoM f) d = test f $ Interval.Limited $ Date.dom d
712 test (Filter_Date_Hour f) d = test f $ Interval.Limited $ Date.hour d
713 test (Filter_Date_Minute f) d = test f $ Interval.Limited $ Date.minute d
714 test (Filter_Date_Second f) d = test f $ Interval.Limited $ Date.second d
717 Filter_Date_UTC ff -> Filter_Date_UTC <$> simplify ff
718 Filter_Date_Year ff -> Filter_Date_Year <$> simplify ff
719 Filter_Date_Month ff -> Filter_Date_Month <$> simplify ff
720 Filter_Date_DoM ff -> Filter_Date_DoM <$> simplify ff
721 Filter_Date_Hour ff -> Filter_Date_Hour <$> simplify ff
722 Filter_Date_Minute ff -> Filter_Date_Minute <$> simplify ff
723 Filter_Date_Second ff -> Filter_Date_Second <$> simplify ff
725 instance Filter (With_Interval Filter_Date) where
726 type Filter_Key (With_Interval Filter_Date) = Interval (Interval.Unlimitable Date)
727 test (With_Interval (Filter_Date_UTC f)) d = test (With_Interval (Interval.Limited <$> f)) d
728 test (With_Interval (Filter_Date_Year f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.year) d
729 test (With_Interval (Filter_Date_Month f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.month) d
730 test (With_Interval (Filter_Date_DoM f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.dom) d
731 test (With_Interval (Filter_Date_Hour f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.hour) d
732 test (With_Interval (Filter_Date_Minute f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.minute) d
733 test (With_Interval (Filter_Date_Second f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.second) d
734 simplify (With_Interval f) =
736 Filter_Date_UTC ff -> With_Interval . Filter_Date_UTC <$> simplify ff
737 Filter_Date_Year ff -> With_Interval . Filter_Date_Year <$> simplify ff
738 Filter_Date_Month ff -> With_Interval . Filter_Date_Month <$> simplify ff
739 Filter_Date_DoM ff -> With_Interval . Filter_Date_DoM <$> simplify ff
740 Filter_Date_Hour ff -> With_Interval . Filter_Date_Hour <$> simplify ff
741 Filter_Date_Minute ff -> With_Interval . Filter_Date_Minute <$> simplify ff
742 Filter_Date_Second ff -> With_Interval . Filter_Date_Second <$> simplify ff
744 -- ** Type 'Filter_Tags'
751 = Filter_Tag_Path (Filter_Path Tag.Section)
752 | Filter_Tag_Value Filter_Tag_Value
753 deriving ({-Data, -}Eq, Show, Typeable)
755 data Filter_Tag_Value
756 = Filter_Tag_Value_None
757 | Filter_Tag_Value_Any Filter_Text
758 | Filter_Tag_Value_First Filter_Text
759 | Filter_Tag_Value_Last Filter_Text
760 deriving ({-Data, -}Eq, Show, Typeable)
762 instance Filter Filter_Tag where
763 type Filter_Key Filter_Tag = Tag.Tags
764 test f (Tag.Tags ts) =
767 Filter_Tag_Path ff -> test ff . fst
768 Filter_Tag_Value ff -> test ff . snd in
770 Data.Map.foldrWithKey
771 (\p -> mappend . Data.Monoid.Any . tst . (p,))
772 (Data.Monoid.Any False) $
776 Filter_Tag_Path ff -> Filter_Tag_Path <$> simplify ff
777 Filter_Tag_Value ff -> Filter_Tag_Value <$> simplify ff
779 instance Filter Filter_Tag_Value where
780 type Filter_Key Filter_Tag_Value = [Tag.Value]
781 test (Filter_Tag_Value_None ) vs = null vs
782 test (Filter_Tag_Value_Any f) vs = Data.Foldable.any (test f) vs
783 test (Filter_Tag_Value_First f) vs =
787 test (Filter_Tag_Value_Last f) vs =
793 Filter_Tag_Value_None -> Simplified $ Right False
794 Filter_Tag_Value_Any ff -> Filter_Tag_Value_Any <$> simplify ff
795 Filter_Tag_Value_First ff -> Filter_Tag_Value_First <$> simplify ff
796 Filter_Tag_Value_Last ff -> Filter_Tag_Value_Last <$> simplify ff
798 -- ** Type 'Filter_Posting'
801 => Filter_Posting posting
802 = Filter_Posting_Account (Filter_Account (Posting_Account posting))
803 | Filter_Posting_Amount (Filter_Amount (Posting_Amount posting))
804 | Filter_Posting_Positive (Filter_Amount (Posting_Amount posting))
805 | Filter_Posting_Negative (Filter_Amount (Posting_Amount posting))
806 | Filter_Posting_Unit (Filter_Unit (Amount_Unit (Posting_Amount posting)))
807 | Filter_Posting_Type Filter_Posting_Type
810 -- Description Comp_String String
812 -- Account_Tag Comp_String String (Maybe (Comp_String, String))
813 -- Account_Balance Comp_Num Comp_Num_Absolute Amount
814 -- Depth Comp_Num Int
818 -- Tag Comp_String Tag.Name (Maybe (Comp_String, Tag.Value))
819 deriving instance Posting p => Eq (Filter_Posting p)
820 deriving instance Posting p => Show (Filter_Posting p)
823 => Filter (Filter_Posting p) where
824 type Filter_Key (Filter_Posting p) = p
825 test (Filter_Posting_Account f) p =
826 test f $ posting_account p
827 test (Filter_Posting_Amount f) p =
828 Data.Foldable.any (test f) $ posting_amounts p
829 test (Filter_Posting_Positive f) p =
831 (\a -> amount_sign a /= LT && test f a)
833 test (Filter_Posting_Negative f) p =
835 (\a -> amount_sign a /= GT && test f a)
837 test (Filter_Posting_Type f) p =
838 test f $ posting_type p
839 test (Filter_Posting_Unit f) p =
840 Data.Foldable.any (test f . amount_unit) $ posting_amounts p
843 Filter_Posting_Account ff -> Filter_Posting_Account <$> simplify ff
844 Filter_Posting_Amount ff -> Filter_Posting_Amount <$> simplify ff
845 Filter_Posting_Positive ff -> Filter_Posting_Positive <$> simplify ff
846 Filter_Posting_Negative ff -> Filter_Posting_Negative <$> simplify ff
847 Filter_Posting_Type ff -> Filter_Posting_Type <$> simplify ff
848 Filter_Posting_Unit ff -> Filter_Posting_Unit <$> simplify ff
850 -- ** Type 'Filter_Transaction'
853 => Filter_Transaction t
854 = Filter_Transaction_Description Filter_Description
855 | Filter_Transaction_Posting (Filter_Bool (Filter_Posting (Posting_Type, Transaction_Posting t)))
856 | Filter_Transaction_Date (Filter_Bool Filter_Date)
857 | Filter_Transaction_Tag Filter_Tags
859 deriving instance Transaction t => Eq (Filter_Transaction t)
860 deriving instance Transaction t => Show (Filter_Transaction t)
862 instance Transaction t
863 => Filter (Filter_Transaction t) where
864 type Filter_Key (Filter_Transaction t) = t
865 test (Filter_Transaction_Description f) t =
866 test f $ transaction_description t
867 test (Filter_Transaction_Posting f) t =
869 (test f . (Posting_Type_Regular,))
870 (transaction_postings t) ||
872 (test f . (Posting_Type_Virtual,))
873 (transaction_postings_virtual t)
874 test (Filter_Transaction_Date f) t =
875 test f $ transaction_date t
876 test (Filter_Transaction_Tag f) t =
877 test f (transaction_tags t)
880 Filter_Transaction_Date ff -> Filter_Transaction_Date <$> simplify ff
881 Filter_Transaction_Description ff -> Filter_Transaction_Description <$> simplify ff
882 Filter_Transaction_Posting ff -> Filter_Transaction_Posting <$> simplify ff
883 Filter_Transaction_Tag ff -> Filter_Transaction_Tag <$> simplify ff
887 , Journal.Transaction t
891 (Simplified (Filter_Bool (Filter_Transaction t)))
892 Journal.Journal t where
895 then Journal.cons t j
900 , Stats.Transaction t
903 (Simplified (Filter_Bool (Filter_Transaction t)))
910 -- ** Type 'Filter_Balance'
914 = Filter_Balance_Account (Filter_Account (Balance_Account b))
915 | Filter_Balance_Amount (Filter_Amount (Balance_Amount b))
916 | Filter_Balance_Positive (Filter_Amount (Balance_Amount b))
917 | Filter_Balance_Negative (Filter_Amount (Balance_Amount b))
919 deriving instance Balance b => Eq (Filter_Balance b)
920 deriving instance Balance b => Show (Filter_Balance b)
923 => Filter (Filter_Balance b) where
924 type Filter_Key (Filter_Balance b) = b
925 test (Filter_Balance_Account f) b =
926 test f $ balance_account b
927 test (Filter_Balance_Amount f) b =
928 test f $ balance_amount b
929 test (Filter_Balance_Positive f) b =
930 Data.Foldable.any (test f) $
932 test (Filter_Balance_Negative f) b =
933 Data.Foldable.any (test f) $
937 Filter_Balance_Account ff -> Filter_Balance_Account <$> simplify ff
938 Filter_Balance_Amount ff -> Filter_Balance_Amount <$> simplify ff
939 Filter_Balance_Positive ff -> Filter_Balance_Positive <$> simplify ff
940 Filter_Balance_Negative ff -> Filter_Balance_Negative <$> simplify ff
945 , amount ~ Balance.Posting_Amount p
947 => Consable (Simplified (Filter_Bool (Filter_Posting p)))
948 (Const (Balance.Balance_by_Account amount))
950 mcons fp p (Const !bal) =
952 case simplified fp of
954 Right True -> Balance.cons_by_account p bal
957 then Balance.cons_by_account p bal
960 ( Transaction transaction
961 , posting ~ Transaction_Posting transaction
962 , amount ~ Balance.Posting_Amount posting
963 , Balance.Posting posting
965 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
966 , (Simplified (Filter_Bool (Filter_Posting posting))) )
967 (Const (Balance.Balance_by_Account amount))
969 mcons (ft, fp) t (Const !bal) =
971 case simplified ft of
973 Right True -> fold_postings bal $ Compose [transaction_postings t, transaction_postings_virtual t]
976 then fold_postings bal $ Compose [transaction_postings t, transaction_postings_virtual t]
981 => Balance.Balance_by_Account amount
983 -> Balance.Balance_by_Account amount
985 case simplified fp of
989 (flip Balance.cons_by_account)
992 (\b p -> if test ff p then Balance.cons_by_account p b else b)
995 , Balance.Posting posting
997 , amount ~ Balance.Posting_Amount posting
999 => Consable (Simplified (Filter_Bool (Filter_Posting posting)))
1000 (Const (Balance.Balance_by_Account amount))
1001 (foldable posting) where
1002 mcons fp ps (Const !bal) =
1004 case simplified fp of
1007 Data.Foldable.foldl'
1008 (flip Balance.cons_by_account) bal ps
1010 Data.Foldable.foldl' (\b p ->
1012 then Balance.cons_by_account p b
1015 -- ** Type 'Filter_GL'
1019 = Filter_GL_Account (Filter_Account (GL_Account g))
1020 | Filter_GL_Amount_Positive (Filter_Amount (GL_Amount g))
1021 | Filter_GL_Amount_Negative (Filter_Amount (GL_Amount g))
1022 | Filter_GL_Amount_Balance (Filter_Amount (GL_Amount g))
1023 | Filter_GL_Sum_Positive (Filter_Amount (GL_Amount g))
1024 | Filter_GL_Sum_Negative (Filter_Amount (GL_Amount g))
1025 | Filter_GL_Sum_Balance (Filter_Amount (GL_Amount g))
1027 deriving instance GL g => Eq (Filter_GL g)
1028 deriving instance GL g => Show (Filter_GL g)
1031 => Filter (Filter_GL g) where
1032 type Filter_Key (Filter_GL g) = g
1033 test (Filter_GL_Account f) g =
1034 test f $ gl_account g
1035 test (Filter_GL_Amount_Positive f) g =
1036 Data.Foldable.any (test f) $
1037 gl_amount_positive g
1038 test (Filter_GL_Amount_Negative f) g =
1039 Data.Foldable.any (test f) $
1040 gl_amount_negative g
1041 test (Filter_GL_Amount_Balance f) g =
1042 test f $ gl_amount_balance g
1043 test (Filter_GL_Sum_Positive f) g =
1044 Data.Foldable.any (test f) $
1046 test (Filter_GL_Sum_Negative f) g =
1047 Data.Foldable.any (test f) $
1049 test (Filter_GL_Sum_Balance f) g =
1050 test f $ gl_sum_balance g
1053 Filter_GL_Account ff -> Filter_GL_Account <$> simplify ff
1054 Filter_GL_Amount_Positive ff -> Filter_GL_Amount_Positive <$> simplify ff
1055 Filter_GL_Amount_Negative ff -> Filter_GL_Amount_Negative <$> simplify ff
1056 Filter_GL_Amount_Balance ff -> Filter_GL_Amount_Balance <$> simplify ff
1057 Filter_GL_Sum_Positive ff -> Filter_GL_Sum_Positive <$> simplify ff
1058 Filter_GL_Sum_Negative ff -> Filter_GL_Sum_Negative <$> simplify ff
1059 Filter_GL_Sum_Balance ff -> Filter_GL_Sum_Balance <$> simplify ff
1062 ( Transaction transaction
1064 , GL.Transaction transaction
1065 , posting ~ GL.Transaction_Posting transaction
1067 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
1068 , (Simplified (Filter_Bool (Filter_Posting posting ))) )
1071 mcons (ft, fp) t !gl =
1072 case simplified ft of
1075 case simplified fp of
1077 Right True -> GL.cons t gl
1080 (GL.transaction_postings_filter (test f) t)
1085 case simplified fp of
1087 Right True -> GL.cons t gl
1090 (GL.transaction_postings_filter (test ff) t)
1095 , Transaction transaction
1097 , GL.Transaction transaction
1098 , posting ~ GL.Transaction_Posting transaction
1100 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
1101 , (Simplified (Filter_Bool (Filter_Posting posting ))) )
1102 (Const (GL.GL transaction))
1103 (foldable transaction) where
1104 mcons (ft, fp) ts (Const !gl) =
1106 case simplified ft of
1109 case simplified fp of
1118 . GL.transaction_postings_filter (test f) )
1125 case simplified fp of
1127 Right True -> GL.cons t
1128 Left ff -> GL.cons $
1129 GL.transaction_postings_filter (test ff) t