module Business.Bookkeeping
(
ppr
, year
, month
, activity
, dateTrans
, runTransactions
, Transactions
, YearTransactions
, MonthTransactions
, DateTransactions
, Transaction(..)
, Year(..)
, Month(..)
, Date(..)
, Description(..)
, SubDescription(..)
, Amount(..)
, Category(..)
, CategoryName(..)
, CategoryType(..)
, DebitCategory(..)
, CreditCategory(..)
) where
import Control.Monad.State (State, execState, modify)
import qualified Data.DList as DList
import Data.DList (DList)
import Data.Monoid ((<>))
import Data.String (IsString(..))
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.Time.Calendar (Day, fromGregorian)
year :: Year -> YearTransactions -> Transactions
year y =
modify . flip mappend . fmap ($ y) . toDList
month :: Month -> MonthTransactions -> YearTransactions
month m =
modify . flip mappend . fmap ($ m) . toDList
activity :: Date -> Description -> DateTransactions -> MonthTransactions
activity d desc =
modify . flip mappend . fmap (($ desc) . ($ d)) . toDList
dateTrans :: DebitCategory
-> CreditCategory
-> SubDescription
-> Amount
-> DateTransactions
dateTrans debit credit subdesc amount =
modify . flip mappend . DList.singleton $ \d desc m y ->
Transaction
{ tDay = fromGregorian (unYear y) (unMonth m) (unDate d)
, tDescription = desc
, tSubDescription = subdesc
, tDebit = debit
, tCredit = credit
, tAmount = amount
}
runTransactions :: Transactions -> [Transaction]
runTransactions = DList.toList . toDList
toDList :: Trans a -> DList a
toDList ts = execState ts mempty
ppr :: Transactions -> IO ()
ppr = T.putStr . T.unlines . map format . runTransactions
where
format :: Transaction -> T.Text
format Transaction {..} =
T.unlines
[ "tDay: " <> (T.pack . show) tDay
, "tDescription: " <> unDescription tDescription
, "tSubDescription: " <> unSubDescription tSubDescription
, "tDebit: " <> (unCategoryName . cName . unDebitCategory) tDebit <>
" (" <>
(T.pack . show . cType . unDebitCategory) tDebit <>
")"
, "tCredit: " <> (unCategoryName . cName . unCreditCategory) tCredit <>
" (" <>
(T.pack . show . cType . unCreditCategory) tCredit <>
")"
, "tAmount: " <> (T.pack . show . unAmount) tAmount
]
type Trans a = State (DList a) ()
type Transactions = Trans Transaction
type YearTransactions = Trans (Year -> Transaction)
type MonthTransactions = Trans (Month -> Year -> Transaction)
type DateTransactions = Trans (Date -> Description -> Month -> Year -> Transaction)
data Transaction = Transaction
{ tDay :: Day
, tDescription :: Description
, tSubDescription :: SubDescription
, tDebit :: DebitCategory
, tCredit :: CreditCategory
, tAmount :: Amount
} deriving (Show, Read, Ord, Eq)
newtype Year = Year
{ unYear :: Integer
} deriving (Show, Read, Ord, Eq, Num, Enum)
newtype Month = Month
{ unMonth :: Int
} deriving (Show, Read, Ord, Eq, Num, Enum)
newtype Date = Date
{ unDate :: Int
} deriving (Show, Read, Ord, Eq, Num, Enum)
newtype Description = Description
{ unDescription :: Text
} deriving (Show, Read, Ord, Eq)
instance IsString Description where
fromString = Description . fromString
instance Monoid Description where
mempty = Description mempty
mappend (Description a) (Description b) = Description $ mappend a b
newtype SubDescription = SubDescription
{ unSubDescription :: Text
} deriving (Show, Read, Ord, Eq)
instance IsString SubDescription where
fromString = SubDescription . fromString
instance Monoid SubDescription where
mempty = SubDescription mempty
mappend (SubDescription a) (SubDescription b) = SubDescription $ mappend a b
newtype Amount = Amount
{ unAmount :: Int
} deriving (Show, Read, Ord, Eq, Num)
newtype DebitCategory = DebitCategory
{ unDebitCategory :: Category
} deriving (Show, Read, Ord, Eq)
newtype CreditCategory = CreditCategory
{ unCreditCategory :: Category
} deriving (Show, Read, Ord, Eq)
data Category = Category
{ cName :: CategoryName
, cType :: CategoryType
} deriving (Show, Read, Ord, Eq)
newtype CategoryName = CategoryName
{ unCategoryName :: Text
} deriving (Show, Read, Ord, Eq)
instance IsString CategoryName where
fromString = CategoryName . fromString
data CategoryType
= Assets
| Liabilities
| Stock
| Revenue
| Expenses
deriving (Show, Read, Ord, Eq, Enum)