1 {-# LANGUAGE DeriveDataTypeable #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
4 {-# LANGUAGE MultiParamTypeClasses #-}
5 {-# LANGUAGE NamedFieldPuns #-}
6 {-# LANGUAGE OverloadedStrings #-}
7 {-# LANGUAGE RecordWildCards #-}
8 {-# LANGUAGE TypeFamilies #-}
9 {-# LANGUAGE TypeOperators #-}
10 {-# LANGUAGE StandaloneDeriving #-}
11 {-# OPTIONS_GHC -fno-warn-orphans #-}
12 module Hcompta.LCC.Posting where
14 import Control.DeepSeq (NFData(..))
15 import Data.Data (Data(..))
16 import Data.Eq (Eq(..))
17 import Data.Function (($), (.), flip, id)
18 import Data.Functor ((<$>))
19 import Data.Functor.Compose (Compose(..))
20 import Data.Map.Strict (Map)
21 import Data.Monoid (Monoid(..))
22 import Data.Ord (Ord(..))
23 import Data.Semigroup (Semigroup(..))
24 import Data.Text (Text)
25 import Data.Typeable (Typeable)
26 import Data.Word (Word)
28 import System.IO (FilePath)
29 import Text.Show (Show)
30 import qualified Data.List as List
31 import qualified Data.Map.Strict as Map
32 import qualified Data.MonoTraversable as MT
33 import qualified Data.Strict as S
34 import qualified Data.Time.Clock as Time
35 import qualified Data.TreeMap.Strict as TreeMap
37 import qualified Hcompta as H
39 import Hcompta.LCC.Account
40 import Hcompta.LCC.Amount
41 import Hcompta.LCC.Tag
43 deriving instance (Data a, Data b) => Data (S.Pair a b)
44 instance (NFData a, NFData b) => NFData (S.Pair a b) where
45 rnf (a S.:!: b) = rnf a `seq` rnf b
48 type Date = Time.UTCTime
52 = SourcePos FilePath {-# UNPACK #-} !PosFile {-# UNPACK #-} !PosFile
53 deriving (Data, Eq, Ord, Show, Typeable)
55 initialPos :: FilePath -> SourcePos
56 initialPos p = SourcePos p (PosFile 0) (PosFile 0)
59 newtype PosFile = PosFile (Word)
60 deriving (Data, Eq, Ord, Show, Typeable)
62 -- ** Type 'SourceRange'
64 = SourceRange SourcePos SourcePos
65 deriving (Data, Eq, Ord, Show, Typeable)
70 { posting_account :: !Account
71 , posting_account_ref :: !(S.Maybe (S.Pair Tag_Path (S.Maybe Account)))
72 , posting_amounts :: !Amounts
73 , posting_comments :: ![Comment]
74 , posting_dates :: ![Date]
75 , posting_sourcepos :: !SourcePos
76 , posting_tags :: !Posting_Tags
77 } deriving (Data, Eq, Ord, Show, Typeable)
78 instance NFData Posting where
80 rnf posting_account `seq`
81 rnf posting_account_ref `seq`
82 rnf posting_amounts `seq`
83 rnf posting_comments `seq`
84 rnf posting_dates `seq`
85 -- rnf posting_sourcepos `seq`
87 instance H.Get (TreeMap.Path Account_Section) Posting where
88 get = H.get . posting_account
89 instance H.Get (Map Unit (H.Polarized Quantity)) Posting where
90 get Posting{posting_amounts = Amounts amts} = H.polarize <$> amts
91 instance H.Set (Map Unit (H.Polarized Quantity)) Posting where
92 set amts p = p{posting_amounts = Amounts $ H.depolarize <$> amts}
93 instance H.Get (H.Balance_Amounts Unit Quantity) Posting where
94 get = H.get . posting_amounts
96 posting :: Account -> Posting
99 { posting_account = acct
100 , posting_account_ref = S.Nothing
101 , posting_amounts = H.quantity_zero
102 , posting_comments = mempty
103 , posting_dates = mempty
104 , posting_sourcepos = initialPos ""
105 , posting_tags = mempty
108 postings_by_account :: [Posting] -> Map Account [Posting]
109 postings_by_account =
110 Map.fromListWith (flip mappend) .
111 List.map (\p -> (posting_account p, [p]))
113 instance H.Posting Posting
115 type instance H.Account H.:@ Posting = Account
116 instance H.GetI H.Account Posting where
117 getI_ _ = posting_account
118 instance H.SetI H.Account Posting where
119 setI_ _ posting_account p = p{posting_account}
121 type instance H.Amounts H.:@ Posting = Amounts
122 instance H.GetI H.Amounts Posting where
123 getI_ _ = posting_amounts
124 instance H.SetI H.Amounts Posting where
125 setI_ _ posting_amounts p = p{posting_amounts}
128 -- * Type 'Posting_Anchor'
129 newtype Posting_Anchor = Posting_Anchor Anchor
130 deriving (Data, Eq, NFData, Ord, Show, Typeable)
131 -- * Type 'Posting_Anchors'
132 newtype Posting_Anchors = Posting_Anchors Anchors
133 deriving (Data, Eq, Monoid, NFData, Ord, Semigroup, Show, Typeable)
134 type instance MT.Element Posting_Anchors = Posting_Anchor
137 -- * Type 'Posting_Tag'
138 newtype Posting_Tag = Posting_Tag Tag
139 deriving (Data, Eq, NFData, Ord, Show, Typeable)
140 -- * Type 'Posting_Tags'
141 newtype Posting_Tags = Posting_Tags Tags
142 deriving (Data, Eq, Monoid, NFData, Ord, Semigroup, Show, Typeable)
143 type instance MT.Element Posting_Tags = Posting_Tag
146 newtype Comment = Comment Text
147 deriving (Data, Eq, NFData, Ord, Show, Typeable)
150 newtype Postings = Postings (Map Account [Posting])
151 deriving (Data, Eq, NFData, Ord, Show, Typeable)
152 unPostings :: Postings -> Map Account [Posting]
153 unPostings (Postings ps) = ps
154 type instance H.Postings H.:@ Postings = Postings
155 instance H.Get Postings Postings where
157 instance H.Postings Postings
158 instance Semigroup Postings where
159 Postings x <> Postings y =
160 Postings $ Map.unionWith (flip (<>)) x y
161 instance Monoid Postings where
162 mempty = Postings mempty
164 type instance MT.Element Postings = Posting
165 instance MT.MonoFunctor Postings where
166 omap f (Postings m) = Postings (MT.omap f `MT.omap` m)
167 instance MT.MonoFoldable Postings where
168 ofoldMap f (Postings m) = MT.ofoldMap f (Compose m)
169 ofoldr f a (Postings m) = MT.ofoldr f a (Compose m)
170 ofoldr1Ex f (Postings m) = MT.ofoldr1Ex f (Compose m)
171 ofoldl1Ex' f (Postings m) = MT.ofoldl1Ex' f (Compose m)
172 ofoldl' f a (Postings m) = MT.ofoldl' f a (Compose m)
177 instance H.Posting Posting where
178 type Posting_Account Posting = Account
179 type Posting_Amount Posting = Amount
180 type Amounts Posting = [Amount]
181 posting_account = posting_account
182 posting_amounts = (uncurry Amount <$>) . Map.toList . posting_amounts
183 instance H.Posting (Charted Posting) where
184 type Posting_Account (Charted Posting) = Charted Account
185 type Posting_Amount (Charted Posting) = H.Posting_Amount Posting
186 type Amounts (Charted Posting) = H.Amounts Posting
187 posting_account = (H.posting_account <$>)
188 posting_amounts = H.posting_amounts . charted
191 instance H.Balance_Posting Posting where
192 type Balance_Posting_Quantity Posting = H.Polarized Quantity
193 balance_posting_amounts = (H.polarize <$>) . posting_amounts
194 balance_posting_amounts_set amounts p =
195 p { posting_amounts = H.depolarize <$> amounts }
196 instance H.Balance_Posting (Charted Posting) where
197 type Balance_Posting_Quantity (Charted Posting) = H.Balance_Posting_Quantity Posting
198 balance_posting_amounts = H.balance_posting_amounts . charted
199 balance_posting_amounts_set amounts (Charted c p) =
200 Charted c p{ posting_amounts = H.depolarize <$> amounts }
203 instance H.GL_Posting Posting where
204 type GL_Posting_Quantity Posting = Map Unit (H.Polarized Quantity)
205 gl_posting_quantity = (H.polarize <$>) . posting_amounts
206 instance H.GL_Posting (Charted Posting) where
207 type GL_Posting_Quantity (Charted Posting) = H.GL_Posting_Quantity Posting
208 gl_posting_quantity = H.gl_posting_quantity . charted