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 ->
605 Filter_Path _o [Filter_Path_Section_Many] ->
606 Simplified $ Right True
608 Filter_Path o <$> go fa
610 go :: [Filter_Path_Section] -> Simplified [Filter_Path_Section]
613 [] -> Simplified $ Left []
614 Filter_Path_Section_Many:l@(Filter_Path_Section_Many:_) -> go l
616 case simplified $ simplify_section ff of
617 Left fff -> ((fff :) <$> go l)
618 Right True -> ((Filter_Path_Section_Any :) <$> go l)
619 Right False -> Simplified $ Right False
622 Filter_Path_Section_Any -> Simplified $ Left $ Filter_Path_Section_Any
623 Filter_Path_Section_Many -> Simplified $ Left $ Filter_Path_Section_Many
624 Filter_Path_Section_Text ff -> Filter_Path_Section_Text <$> simplify ff
626 -- ** Type 'Filter_Account'
628 type Filter_Account a
630 (Filter_Account_Component a)
632 data Filter_Account_Component a
633 = Filter_Account_Path (Filter_Path Account.Account_Section)
634 | Filter_Account_Tag Filter_Tags
635 deriving instance Account a => Eq (Filter_Account_Component a)
636 deriving instance Account a => Show (Filter_Account_Component a)
639 => Filter (Filter_Account_Component a) where
640 type Filter_Key (Filter_Account_Component a) = a
641 test (Filter_Account_Path f) a = test f $ account_path a
642 test (Filter_Account_Tag f) a = test f $ account_tags a
645 Filter_Account_Path ff -> Filter_Account_Path <$> simplify ff
646 Filter_Account_Tag ff -> Filter_Account_Tag <$> simplify ff
648 -- ** Type 'Filter_Amount'
650 type Filter_Quantity q
654 = Filter_Bool (Filter_Amount_Section a)
657 => Filter_Amount_Section a
658 = Filter_Amount_Section_Quantity (Filter_Quantity (Amount_Quantity a))
659 | Filter_Amount_Section_Unit (Filter_Unit (Amount_Unit a))
661 deriving instance Amount a => Eq (Filter_Amount_Section a)
662 deriving instance Amount a => Show (Filter_Amount_Section a)
665 => Filter (Filter_Amount_Section a) where
666 type Filter_Key (Filter_Amount_Section a) = a
669 Filter_Amount_Section_Quantity ff -> test ff $ amount_quantity a
670 Filter_Amount_Section_Unit ff -> test ff $ amount_unit a
673 Filter_Amount_Section_Quantity ff -> Filter_Amount_Section_Quantity <$> simplify ff
674 Filter_Amount_Section_Unit ff -> Filter_Amount_Section_Unit <$> simplify ff
676 -- ** Type 'Filter_Posting_Type'
678 data Filter_Posting_Type
679 = Filter_Posting_Type_Any
680 | Filter_Posting_Type_Exact Posting_Type
681 deriving (Data, Eq, Show, Typeable)
683 instance Filter Filter_Posting_Type where
684 type Filter_Key Filter_Posting_Type = Posting_Type
687 Filter_Posting_Type_Any -> True
688 Filter_Posting_Type_Exact ff -> ff == p
692 Filter_Posting_Type_Any -> Right True
693 Filter_Posting_Type_Exact _ -> Left f
695 -- ** Type 'Filter_Date'
698 = Filter_Date_UTC (Filter_Ord Date)
699 | Filter_Date_Year (Filter_Interval Integer)
700 | Filter_Date_Month (Filter_Interval Int)
701 | Filter_Date_DoM (Filter_Interval Int)
702 | Filter_Date_Hour (Filter_Interval Int)
703 | Filter_Date_Minute (Filter_Interval Int)
704 | Filter_Date_Second (Filter_Interval Data.Fixed.Pico)
705 deriving (Eq, Show, Typeable)
707 instance Filter Filter_Date where
708 type Filter_Key Filter_Date = Date
709 test (Filter_Date_UTC f) d = test f $ d
710 test (Filter_Date_Year f) d = test f $ Interval.Limited $ Date.year d
711 test (Filter_Date_Month f) d = test f $ Interval.Limited $ Date.month d
712 test (Filter_Date_DoM f) d = test f $ Interval.Limited $ Date.dom d
713 test (Filter_Date_Hour f) d = test f $ Interval.Limited $ Date.hour d
714 test (Filter_Date_Minute f) d = test f $ Interval.Limited $ Date.minute d
715 test (Filter_Date_Second f) d = test f $ Interval.Limited $ Date.second d
718 Filter_Date_UTC ff -> Filter_Date_UTC <$> simplify ff
719 Filter_Date_Year ff -> Filter_Date_Year <$> simplify ff
720 Filter_Date_Month ff -> Filter_Date_Month <$> simplify ff
721 Filter_Date_DoM ff -> Filter_Date_DoM <$> simplify ff
722 Filter_Date_Hour ff -> Filter_Date_Hour <$> simplify ff
723 Filter_Date_Minute ff -> Filter_Date_Minute <$> simplify ff
724 Filter_Date_Second ff -> Filter_Date_Second <$> simplify ff
726 instance Filter (With_Interval Filter_Date) where
727 type Filter_Key (With_Interval Filter_Date) = Interval (Interval.Unlimitable Date)
728 test (With_Interval (Filter_Date_UTC f)) d = test (With_Interval (Interval.Limited <$> f)) d
729 test (With_Interval (Filter_Date_Year f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.year) d
730 test (With_Interval (Filter_Date_Month f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.month) d
731 test (With_Interval (Filter_Date_DoM f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.dom) d
732 test (With_Interval (Filter_Date_Hour f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.hour) d
733 test (With_Interval (Filter_Date_Minute f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.minute) d
734 test (With_Interval (Filter_Date_Second f)) d = maybe False (test $ With_Interval f) $ Interval.fmap (fmap Date.second) d
735 simplify (With_Interval f) =
737 Filter_Date_UTC ff -> With_Interval . Filter_Date_UTC <$> simplify ff
738 Filter_Date_Year ff -> With_Interval . Filter_Date_Year <$> simplify ff
739 Filter_Date_Month ff -> With_Interval . Filter_Date_Month <$> simplify ff
740 Filter_Date_DoM ff -> With_Interval . Filter_Date_DoM <$> simplify ff
741 Filter_Date_Hour ff -> With_Interval . Filter_Date_Hour <$> simplify ff
742 Filter_Date_Minute ff -> With_Interval . Filter_Date_Minute <$> simplify ff
743 Filter_Date_Second ff -> With_Interval . Filter_Date_Second <$> simplify ff
745 -- ** Type 'Filter_Tags'
752 = Filter_Tag_Path (Filter_Path Tag.Section)
753 | Filter_Tag_Value Filter_Tag_Value
754 deriving ({-Data, -}Eq, Show, Typeable)
756 data Filter_Tag_Value
757 = Filter_Tag_Value_None
758 | Filter_Tag_Value_Any Filter_Text
759 | Filter_Tag_Value_First Filter_Text
760 | Filter_Tag_Value_Last Filter_Text
761 deriving ({-Data, -}Eq, Show, Typeable)
763 instance Filter Filter_Tag where
764 type Filter_Key Filter_Tag = Tag.Tags
765 test f (Tag.Tags ts) =
768 Filter_Tag_Path ff -> test ff . fst
769 Filter_Tag_Value ff -> test ff . snd in
771 Data.Map.foldrWithKey
772 (\p -> mappend . Data.Monoid.Any . tst . (p,))
773 (Data.Monoid.Any False) $
777 Filter_Tag_Path ff -> Filter_Tag_Path <$> simplify ff
778 Filter_Tag_Value ff -> Filter_Tag_Value <$> simplify ff
780 instance Filter Filter_Tag_Value where
781 type Filter_Key Filter_Tag_Value = [Tag.Value]
782 test (Filter_Tag_Value_None ) vs = null vs
783 test (Filter_Tag_Value_Any f) vs = Data.Foldable.any (test f) vs
784 test (Filter_Tag_Value_First f) vs =
788 test (Filter_Tag_Value_Last f) vs =
794 Filter_Tag_Value_None -> Simplified $ Right False
795 Filter_Tag_Value_Any ff -> Filter_Tag_Value_Any <$> simplify ff
796 Filter_Tag_Value_First ff -> Filter_Tag_Value_First <$> simplify ff
797 Filter_Tag_Value_Last ff -> Filter_Tag_Value_Last <$> simplify ff
799 -- ** Type 'Filter_Posting'
802 => Filter_Posting posting
803 = Filter_Posting_Account (Filter_Account (Posting_Account posting))
804 | Filter_Posting_Amount (Filter_Amount (Posting_Amount posting))
805 | Filter_Posting_Positive (Filter_Amount (Posting_Amount posting))
806 | Filter_Posting_Negative (Filter_Amount (Posting_Amount posting))
807 | Filter_Posting_Unit (Filter_Unit (Amount_Unit (Posting_Amount posting)))
808 | Filter_Posting_Type Filter_Posting_Type
811 -- Description Comp_String String
813 -- Account_Tag Comp_String String (Maybe (Comp_String, String))
814 -- Account_Balance Comp_Num Comp_Num_Absolute Amount
815 -- Depth Comp_Num Int
819 -- Tag Comp_String Tag.Name (Maybe (Comp_String, Tag.Value))
820 deriving instance Posting p => Eq (Filter_Posting p)
821 deriving instance Posting p => Show (Filter_Posting p)
824 => Filter (Filter_Posting p) where
825 type Filter_Key (Filter_Posting p) = p
826 test (Filter_Posting_Account f) p =
827 test f $ posting_account p
828 test (Filter_Posting_Amount f) p =
829 Data.Foldable.any (test f) $ posting_amounts p
830 test (Filter_Posting_Positive f) p =
832 (\a -> amount_sign a /= LT && test f a)
834 test (Filter_Posting_Negative f) p =
836 (\a -> amount_sign a /= GT && test f a)
838 test (Filter_Posting_Type f) p =
839 test f $ posting_type p
840 test (Filter_Posting_Unit f) p =
841 Data.Foldable.any (test f . amount_unit) $ posting_amounts p
844 Filter_Posting_Account ff -> Filter_Posting_Account <$> simplify ff
845 Filter_Posting_Amount ff -> Filter_Posting_Amount <$> simplify ff
846 Filter_Posting_Positive ff -> Filter_Posting_Positive <$> simplify ff
847 Filter_Posting_Negative ff -> Filter_Posting_Negative <$> simplify ff
848 Filter_Posting_Type ff -> Filter_Posting_Type <$> simplify ff
849 Filter_Posting_Unit ff -> Filter_Posting_Unit <$> simplify ff
851 -- ** Type 'Filter_Transaction'
854 => Filter_Transaction t
855 = Filter_Transaction_Description Filter_Description
856 | Filter_Transaction_Posting (Filter_Bool (Filter_Posting (Posting_Type, Transaction_Posting t)))
857 | Filter_Transaction_Date (Filter_Bool Filter_Date)
858 | Filter_Transaction_Tag Filter_Tags
860 deriving instance Transaction t => Eq (Filter_Transaction t)
861 deriving instance Transaction t => Show (Filter_Transaction t)
863 instance Transaction t
864 => Filter (Filter_Transaction t) where
865 type Filter_Key (Filter_Transaction t) = t
866 test (Filter_Transaction_Description f) t =
867 test f $ transaction_description t
868 test (Filter_Transaction_Posting f) t =
870 (test f . (Posting_Type_Regular,))
871 (transaction_postings t) ||
873 (test f . (Posting_Type_Virtual,))
874 (transaction_postings_virtual t)
875 test (Filter_Transaction_Date f) t =
876 test f $ transaction_date t
877 test (Filter_Transaction_Tag f) t =
878 test f (transaction_tags t)
881 Filter_Transaction_Date ff -> Filter_Transaction_Date <$> simplify ff
882 Filter_Transaction_Description ff -> Filter_Transaction_Description <$> simplify ff
883 Filter_Transaction_Posting ff -> Filter_Transaction_Posting <$> simplify ff
884 Filter_Transaction_Tag ff -> Filter_Transaction_Tag <$> simplify ff
888 , Journal.Transaction t
892 (Simplified (Filter_Bool (Filter_Transaction t)))
893 Journal.Journal t where
896 then Journal.cons t j
901 , Stats.Transaction t
904 (Simplified (Filter_Bool (Filter_Transaction t)))
911 -- ** Type 'Filter_Balance'
915 = Filter_Balance_Account (Filter_Account (Balance_Account b))
916 | Filter_Balance_Amount (Filter_Amount (Balance_Amount b))
917 | Filter_Balance_Positive (Filter_Amount (Balance_Amount b))
918 | Filter_Balance_Negative (Filter_Amount (Balance_Amount b))
920 deriving instance Balance b => Eq (Filter_Balance b)
921 deriving instance Balance b => Show (Filter_Balance b)
924 => Filter (Filter_Balance b) where
925 type Filter_Key (Filter_Balance b) = b
926 test (Filter_Balance_Account f) b =
927 test f $ balance_account b
928 test (Filter_Balance_Amount f) b =
929 test f $ balance_amount b
930 test (Filter_Balance_Positive f) b =
931 Data.Foldable.any (test f) $
933 test (Filter_Balance_Negative f) b =
934 Data.Foldable.any (test f) $
938 Filter_Balance_Account ff -> Filter_Balance_Account <$> simplify ff
939 Filter_Balance_Amount ff -> Filter_Balance_Amount <$> simplify ff
940 Filter_Balance_Positive ff -> Filter_Balance_Positive <$> simplify ff
941 Filter_Balance_Negative ff -> Filter_Balance_Negative <$> simplify ff
946 , amount ~ Balance.Posting_Amount p
948 => Consable (Simplified (Filter_Bool (Filter_Posting p)))
949 (Const (Balance.Balance_by_Account amount))
951 mcons fp p (Const !bal) =
953 case simplified fp of
955 Right True -> Balance.cons_by_account p bal
958 then Balance.cons_by_account p bal
961 ( Transaction transaction
962 , posting ~ Transaction_Posting transaction
963 , amount ~ Balance.Posting_Amount posting
964 , Balance.Posting posting
966 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
967 , (Simplified (Filter_Bool (Filter_Posting posting))) )
968 (Const (Balance.Balance_by_Account amount))
970 mcons (ft, fp) t (Const !bal) =
972 case simplified ft of
974 Right True -> fold_postings bal $ Compose [transaction_postings t, transaction_postings_virtual t]
977 then fold_postings bal $ Compose [transaction_postings t, transaction_postings_virtual t]
982 => Balance.Balance_by_Account amount
984 -> Balance.Balance_by_Account amount
986 case simplified fp of
990 (flip Balance.cons_by_account)
993 (\b p -> if test ff p then Balance.cons_by_account p b else b)
996 , Balance.Posting posting
998 , amount ~ Balance.Posting_Amount posting
1000 => Consable (Simplified (Filter_Bool (Filter_Posting posting)))
1001 (Const (Balance.Balance_by_Account amount))
1002 (foldable posting) where
1003 mcons fp ps (Const !bal) =
1005 case simplified fp of
1008 Data.Foldable.foldl'
1009 (flip Balance.cons_by_account) bal ps
1011 Data.Foldable.foldl' (\b p ->
1013 then Balance.cons_by_account p b
1016 -- ** Type 'Filter_GL'
1020 = Filter_GL_Account (Filter_Account (GL_Account g))
1021 | Filter_GL_Amount_Positive (Filter_Amount (GL_Amount g))
1022 | Filter_GL_Amount_Negative (Filter_Amount (GL_Amount g))
1023 | Filter_GL_Amount_Balance (Filter_Amount (GL_Amount g))
1024 | Filter_GL_Sum_Positive (Filter_Amount (GL_Amount g))
1025 | Filter_GL_Sum_Negative (Filter_Amount (GL_Amount g))
1026 | Filter_GL_Sum_Balance (Filter_Amount (GL_Amount g))
1028 deriving instance GL g => Eq (Filter_GL g)
1029 deriving instance GL g => Show (Filter_GL g)
1032 => Filter (Filter_GL g) where
1033 type Filter_Key (Filter_GL g) = g
1034 test (Filter_GL_Account f) g =
1035 test f $ gl_account g
1036 test (Filter_GL_Amount_Positive f) g =
1037 Data.Foldable.any (test f) $
1038 gl_amount_positive g
1039 test (Filter_GL_Amount_Negative f) g =
1040 Data.Foldable.any (test f) $
1041 gl_amount_negative g
1042 test (Filter_GL_Amount_Balance f) g =
1043 test f $ gl_amount_balance g
1044 test (Filter_GL_Sum_Positive f) g =
1045 Data.Foldable.any (test f) $
1047 test (Filter_GL_Sum_Negative f) g =
1048 Data.Foldable.any (test f) $
1050 test (Filter_GL_Sum_Balance f) g =
1051 test f $ gl_sum_balance g
1054 Filter_GL_Account ff -> Filter_GL_Account <$> simplify ff
1055 Filter_GL_Amount_Positive ff -> Filter_GL_Amount_Positive <$> simplify ff
1056 Filter_GL_Amount_Negative ff -> Filter_GL_Amount_Negative <$> simplify ff
1057 Filter_GL_Amount_Balance ff -> Filter_GL_Amount_Balance <$> simplify ff
1058 Filter_GL_Sum_Positive ff -> Filter_GL_Sum_Positive <$> simplify ff
1059 Filter_GL_Sum_Negative ff -> Filter_GL_Sum_Negative <$> simplify ff
1060 Filter_GL_Sum_Balance ff -> Filter_GL_Sum_Balance <$> simplify ff
1063 ( Transaction transaction
1065 , GL.Transaction transaction
1066 , posting ~ GL.Transaction_Posting transaction
1068 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
1069 , (Simplified (Filter_Bool (Filter_Posting posting ))) )
1072 mcons (ft, fp) t !gl =
1073 case simplified ft of
1076 case simplified fp of
1078 Right True -> GL.cons t gl
1081 (GL.transaction_postings_filter (test f) t)
1086 case simplified fp of
1088 Right True -> GL.cons t gl
1091 (GL.transaction_postings_filter (test ff) t)
1096 , Transaction transaction
1098 , GL.Transaction transaction
1099 , posting ~ GL.Transaction_Posting transaction
1101 => Consable ( (Simplified (Filter_Bool (Filter_Transaction transaction)))
1102 , (Simplified (Filter_Bool (Filter_Posting posting ))) )
1103 (Const (GL.GL transaction))
1104 (foldable transaction) where
1105 mcons (ft, fp) ts (Const !gl) =
1107 case simplified ft of
1110 case simplified fp of
1119 . GL.transaction_postings_filter (test f) )
1126 case simplified fp of
1128 Right True -> GL.cons t
1129 Left ff -> GL.cons $
1130 GL.transaction_postings_filter (test ff) t