module Hledger.Data.Types
where
import GHC.Generics (Generic)
import Control.DeepSeq (NFData)
import Control.Monad.Except (ExceptT)
import Data.Data
#ifndef DOUBLE
import Data.Decimal
import Text.Blaze (ToMarkup(..))
#endif
import qualified Data.Map as M
import Data.Time.Calendar
import Data.Time.LocalTime
import System.Time (ClockTime(..))
import Hledger.Utils.Regex
type SmartDate = (String,String,String)
data WhichDate = PrimaryDate | SecondaryDate deriving (Eq,Show)
data DateSpan = DateSpan (Maybe Day) (Maybe Day) deriving (Eq,Ord,Data,Generic,Typeable)
instance NFData DateSpan
data Interval = NoInterval
| Days Int | Weeks Int | Months Int | Quarters Int | Years Int
| DayOfMonth Int | DayOfWeek Int
deriving (Eq,Show,Ord,Data,Generic,Typeable)
instance NFData Interval
type AccountName = String
data AccountAlias = BasicAlias AccountName AccountName
| RegexAlias Regexp Replacement
deriving (Eq, Read, Show, Ord, Data, Generic, Typeable)
instance NFData AccountAlias
data Side = L | R deriving (Eq,Show,Read,Ord,Typeable,Data,Generic)
instance NFData Side
type Commodity = String
numberRepresentation :: String
#ifdef DOUBLE
type Quantity = Double
numberRepresentation = "Double"
#else
type Quantity = Decimal
deriving instance Data (Quantity)
instance ToMarkup (Quantity)
where
toMarkup = toMarkup . show
numberRepresentation = "Decimal"
#endif
data Price = NoPrice | UnitPrice Amount | TotalPrice Amount deriving (Eq,Ord,Typeable,Data,Generic)
instance NFData Price
data AmountStyle = AmountStyle {
ascommodityside :: Side,
ascommodityspaced :: Bool,
asprecision :: Int,
asdecimalpoint :: Maybe Char,
asdigitgroups :: Maybe DigitGroupStyle
} deriving (Eq,Ord,Read,Show,Typeable,Data,Generic)
instance NFData AmountStyle
data DigitGroupStyle = DigitGroups Char [Int]
deriving (Eq,Ord,Read,Show,Typeable,Data,Generic)
instance NFData DigitGroupStyle
data Amount = Amount {
acommodity :: Commodity,
aquantity :: Quantity,
aprice :: Price,
astyle :: AmountStyle
} deriving (Eq,Ord,Typeable,Data,Generic)
instance NFData Amount
newtype MixedAmount = Mixed [Amount] deriving (Eq,Ord,Typeable,Data,Generic)
instance NFData MixedAmount
data PostingType = RegularPosting | VirtualPosting | BalancedVirtualPosting
deriving (Eq,Show,Typeable,Data,Generic)
instance NFData PostingType
type Tag = (String, String)
data ClearedStatus = Uncleared | Pending | Cleared
deriving (Eq,Ord,Typeable,Data,Generic)
instance NFData ClearedStatus
instance Show ClearedStatus where
show Uncleared = ""
show Pending = "!"
show Cleared = "*"
data Posting = Posting {
pdate :: Maybe Day,
pdate2 :: Maybe Day,
pstatus :: ClearedStatus,
paccount :: AccountName,
pamount :: MixedAmount,
pcomment :: String,
ptype :: PostingType,
ptags :: [Tag],
pbalanceassertion :: Maybe MixedAmount,
ptransaction :: Maybe Transaction
} deriving (Typeable,Data,Generic)
instance NFData Posting
instance Eq Posting where
(==) (Posting a1 b1 c1 d1 e1 f1 g1 h1 i1 _) (Posting a2 b2 c2 d2 e2 f2 g2 h2 i2 _) = a1==a2 && b1==b2 && c1==c2 && d1==d2 && e1==e2 && f1==f2 && g1==g2 && h1==h2 && i1==i2
data GenericSourcePos = GenericSourcePos FilePath Int Int
deriving (Eq, Read, Show, Ord, Data, Generic, Typeable)
instance NFData GenericSourcePos
data Transaction = Transaction {
tindex :: Integer,
tsourcepos :: GenericSourcePos,
tdate :: Day,
tdate2 :: Maybe Day,
tstatus :: ClearedStatus,
tcode :: String,
tdescription :: String,
tcomment :: String,
ttags :: [Tag],
tpostings :: [Posting],
tpreceding_comment_lines :: String
} deriving (Eq,Typeable,Data,Generic)
instance NFData Transaction
data ModifierTransaction = ModifierTransaction {
mtvalueexpr :: String,
mtpostings :: [Posting]
} deriving (Eq,Typeable,Data,Generic)
instance NFData ModifierTransaction
data PeriodicTransaction = PeriodicTransaction {
ptperiodicexpr :: String,
ptpostings :: [Posting]
} deriving (Eq,Typeable,Data,Generic)
instance NFData PeriodicTransaction
data TimeLogCode = SetBalance | SetRequiredHours | In | Out | FinalOut deriving (Eq,Ord,Typeable,Data,Generic)
instance NFData TimeLogCode
data TimeLogEntry = TimeLogEntry {
tlsourcepos :: GenericSourcePos,
tlcode :: TimeLogCode,
tldatetime :: LocalTime,
tlaccount :: String,
tldescription :: String
} deriving (Eq,Ord,Typeable,Data,Generic)
instance NFData TimeLogEntry
data MarketPrice = MarketPrice {
mpdate :: Day,
mpcommodity :: Commodity,
mpamount :: Amount
} deriving (Eq,Ord,Typeable,Data,Generic)
instance NFData MarketPrice
type Year = Integer
data JournalContext = Ctx {
ctxYear :: !(Maybe Year)
, ctxDefaultCommodityAndStyle :: !(Maybe (Commodity,AmountStyle))
, ctxAccount :: ![AccountName]
, ctxAliases :: ![AccountAlias]
, ctxTransactionIndex :: !Integer
} deriving (Read, Show, Eq, Data, Typeable, Generic)
instance NFData JournalContext
deriving instance Data (ClockTime)
deriving instance Typeable (ClockTime)
deriving instance Generic (ClockTime)
instance NFData ClockTime
data Journal = Journal {
jmodifiertxns :: [ModifierTransaction],
jperiodictxns :: [PeriodicTransaction],
jtxns :: [Transaction],
open_timelog_entries :: [TimeLogEntry],
jmarketprices :: [MarketPrice],
final_comment_lines :: String,
jContext :: JournalContext,
files :: [(FilePath, String)],
filereadtime :: ClockTime,
jcommoditystyles :: M.Map Commodity AmountStyle
} deriving (Eq, Typeable, Data, Generic)
instance NFData Journal
type JournalUpdate = ExceptT String IO (Journal -> Journal)
type StorageFormat = String
data Reader = Reader {
rFormat :: StorageFormat
,rDetector :: FilePath -> String -> Bool
,rParser :: Maybe FilePath -> Bool -> FilePath -> String -> ExceptT String IO Journal
}
instance Show Reader where show r = rFormat r ++ " reader"
data Account = Account {
aname :: AccountName,
aebalance :: MixedAmount,
asubs :: [Account],
anumpostings :: Int,
aibalance :: MixedAmount,
aparent :: Maybe Account,
aboring :: Bool
}
data Ledger = Ledger {
ljournal :: Journal,
laccounts :: [Account]
}