packages feed

bookkeeping (empty) → 0.1.0.1

raw patch · 7 files changed

+360/−0 lines, 7 filesdep +Globdep +basedep +bookkeepingsetup-changed

Dependencies added: Glob, base, bookkeeping, dlist, doctest, mtl, text, time

Files

+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2017 Kadzuya OKAMOTO, http://www.arow.info++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ README.md view
@@ -0,0 +1,13 @@+[![Build Status](https://travis-ci.org/arowM/haskell-bookkeeping.svg?branch=master)](https://travis-ci.org/arowM/heterocephalus)++# Haskell-bookkeeping++A module for bookkeeping by double entry. This module provides a way to do bookkeeping programmatically.++## Example++TODO++## Export as CSV++TODO
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ bookkeeping.cabal view
@@ -0,0 +1,54 @@+name:                bookkeeping+version:             0.1.0.1+synopsis:            A module for bookkeeping by double entry.+description:+    A module for bookkeeping by double entry. This module provides a way to do bookkeeping programmatically.+homepage:            https://github.com/arowM/haskell-bookkeeping#readme+license:             MIT+license-file:        LICENSE+author:              Kadzuya Okamoto+maintainer:          arow.okamoto+github@gmail.com+copyright:           2017 Kadzuya Okamoto+category:            Business+build-type:          Simple+extra-source-files:  README.md+cabal-version:       >=1.10++library+  hs-source-dirs:      src+  exposed-modules:     Business.Bookkeeping+  build-depends:       base >= 4.9 && < 4.10+                     , dlist >= 0.8.0.2 && < 0.9+                     , mtl >= 2.2.1 && < 2.3+                     , text >= 1.2.2.1 && < 1.3+                     , time >= 1.6.0.1 && < 1.7+  default-language:    Haskell2010+  default-extensions:  OverloadedStrings+                     , RecordWildCards+                     , Strict+                     , StrictData+  other-extensions:    GeneralizedNewtypeDeriving++test-suite bookkeeping-test+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Spec.hs+  build-depends:       base+                     , bookkeeping+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  default-language:    Haskell2010++test-suite doctest+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Doctest.hs+  build-depends:       base+                     , Glob+                     , doctest >= 0.10+                     , bookkeeping+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N+  default-language:    Haskell2010++source-repository head+  type:     git+  location: https://github.com/arowM/haskell-bookkeeping
+ src/Business/Bookkeeping.hs view
@@ -0,0 +1,249 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++{- |+Module      :  Business.Bookkeeping++Copyright   :  Kadzuya Okamoto 2017+License     :  MIT++Stability   :  experimental+Portability :  unknown++This module exports core functions and types for bookkeeping.+-}+module Business.Bookkeeping+  (+  -- * Usage examples+  -- $setup++  -- * Pritty printers+    ppr++  -- * Constructors+  , year+  , month+  , activity+  , dateTrans++  -- * Converters+  , runTransactions++  -- * Types+  , Transactions+  , YearTransactions+  , MonthTransactions+  , DateTransactions+  , Transaction(..)+  , Year(..)+  , Month(..)+  , Date(..)+  , Description(..)+  , 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)++{- $setup+>>> :{+let+  advance :: CategoryName -> Description -> Amount -> DateTransactions+  advance name = dateTrans+    (DebitCategory $ Category name Expenses)+    (CreditCategory $ Category "Deposit" Assets)+  sample =+    year 2015 $ do+      month 1 $ do+        activity 1 "Constant expenses --" $+          advance "Communication" "Mobile phone" 3000+        activity 3 "Mail a contract --" $ do+          advance "Communication" "Stamp" 50+          advance "Office supplies" "Envelope" 100+      month 2 $+        activity 1 "Constant expenses --" $+          advance "Communication" "Mobile phone" 3000+:}+-}+{-| Convert from 'YearTransactions' to 'Transactions'.+-}+year :: Year -> YearTransactions -> Transactions+year y =+  modify . flip mappend . fmap ($ y) . toDList++{-| Convert from 'MonthTransactions' to 'YearTransactions'.+-}+month :: Month -> MonthTransactions -> YearTransactions+month m =+  modify . flip mappend . fmap ($ m) . toDList++{-| Convert from 'DateTransactions' to 'MonthTransactions'.+-}+activity :: Date -> Description -> DateTransactions -> MonthTransactions+activity d desc =+  modify . flip mappend . fmap (($ desc) . ($ d)) . toDList++dateTrans :: DebitCategory+          -> CreditCategory+          -> Description+          -> Amount+          -> DateTransactions+dateTrans debit credit desc amount =+  modify . flip mappend . DList.singleton $ \d desc' m y ->+    Transaction+    { tDay = fromGregorian (unYear y) (unMonth m) (unDate d)+    , tDescription = desc' <> " " <> desc+    , tDebit = debit+    , tCredit = credit+    , tAmount = amount+    }++{-| Take list of `Transaction` out from 'Transactions'.+-}+runTransactions :: Transactions -> [Transaction]+runTransactions = DList.toList . toDList++toDList :: Trans a -> DList a+toDList ts = execState ts mempty++{-| A pretty printer for `Transactions`.++>>> ppr sample+tDay: 2015-01-01+tDescription: Constant expenses -- Mobile phone+tDebit: Communication (Expenses)+tCredit: Deposit (Assets)+tAmount: 3000+<BLANKLINE>+tDay: 2015-01-03+tDescription: Mail a contract -- Stamp+tDebit: Communication (Expenses)+tCredit: Deposit (Assets)+tAmount: 50+<BLANKLINE>+tDay: 2015-01-03+tDescription: Mail a contract -- Envelope+tDebit: Office supplies (Expenses)+tCredit: Deposit (Assets)+tAmount: 100+<BLANKLINE>+tDay: 2015-02-01+tDescription: Constant expenses -- Mobile phone+tDebit: Communication (Expenses)+tCredit: Deposit (Assets)+tAmount: 3000+<BLANKLINE>+-}+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+        , "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+        ]+++{- ==============+ -     Types+ - ============== -}++type Trans a = State (DList a) ()++{-| A type for handling `Transaction` values.+ -}+type Transactions = Trans Transaction++type YearTransactions = Trans (Year -> Transaction)++type MonthTransactions = Trans (Month -> Year -> Transaction)++type DateTransactions = Trans (Date -> Description -> Month -> Year -> Transaction)++{-| A type representing a transaction.+ -}+data Transaction = Transaction+  { tDay :: Day+  , tDescription :: Description+  , tDebit :: DebitCategory+  , tCredit :: CreditCategory+  , tAmount :: Amount+  } deriving (Show, Read, Ord, Eq)++newtype Year = Year+  { unYear :: Integer+  } deriving (Show, Read, Ord, Eq, Num)++newtype Month = Month+  { unMonth :: Int+  } deriving (Show, Read, Ord, Eq, Num)++newtype Date = Date+  { unDate :: Int+  } deriving (Show, Read, Ord, Eq, Num)++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 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)++{-| A type representing an accounts title.+ -}+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)
+ test/Doctest.hs view
@@ -0,0 +1,19 @@+module Main where++import Data.Monoid ((<>))+import System.FilePath.Glob (glob)+import Test.DocTest (doctest)++main :: IO ()+main = glob "src/**/*.hs" >>= doDocTest++doDocTest :: [String] -> IO ()+doDocTest options = doctest $ options <> ghcExtensions++ghcExtensions :: [String]+ghcExtensions =+    [ "-XOverloadedStrings"+    , "-XRecordWildCards"+    , "-XStrict"+    , "-XStrictData"+    ]
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"