{-# LANGUAGE DataKinds #-}
module Haspara.Accounting.Journal where
import qualified Data.Text as T
import Data.Time (Day)
import GHC.Generics (Generic)
import GHC.TypeLits (KnownNat, Nat)
import Haspara.Accounting.Account (Account(accountKind))
import Haspara.Accounting.Amount (Amount(..), amountFromQuantity, amountFromValue)
import Haspara.Accounting.Side (Side(..))
import Haspara.Quantity (Quantity, UnsignedQuantity, sumUnsignedQuantity)
newtype Journal (precision :: Nat) account event = Journal
{ Journal precision account event
-> [JournalEntry precision account event]
journalEntries :: [JournalEntry precision account event]
}
deriving (Int -> Journal precision account event -> ShowS
[Journal precision account event] -> ShowS
Journal precision account event -> String
(Int -> Journal precision account event -> ShowS)
-> (Journal precision account event -> String)
-> ([Journal precision account event] -> ShowS)
-> Show (Journal precision account event)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> Journal precision account event -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[Journal precision account event] -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Journal precision account event -> String
showList :: [Journal precision account event] -> ShowS
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[Journal precision account event] -> ShowS
show :: Journal precision account event -> String
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Journal precision account event -> String
showsPrec :: Int -> Journal precision account event -> ShowS
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> Journal precision account event -> ShowS
Show)
data JournalEntry (precision :: Nat) account event = JournalEntry
{ JournalEntry precision account event -> Text
journalEntryId :: !T.Text
, JournalEntry precision account event -> Day
journalEntryDate :: !Day
, JournalEntry precision account event
-> [JournalEntryItem precision account event]
journalEntryItems :: ![JournalEntryItem precision account event]
, JournalEntry precision account event -> Text
journalEntryDescription :: !T.Text
}
deriving (Int -> JournalEntry precision account event -> ShowS
[JournalEntry precision account event] -> ShowS
JournalEntry precision account event -> String
(Int -> JournalEntry precision account event -> ShowS)
-> (JournalEntry precision account event -> String)
-> ([JournalEntry precision account event] -> ShowS)
-> Show (JournalEntry precision account event)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> JournalEntry precision account event -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[JournalEntry precision account event] -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
JournalEntry precision account event -> String
showList :: [JournalEntry precision account event] -> ShowS
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[JournalEntry precision account event] -> ShowS
show :: JournalEntry precision account event -> String
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
JournalEntry precision account event -> String
showsPrec :: Int -> JournalEntry precision account event -> ShowS
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> JournalEntry precision account event -> ShowS
Show)
journalEntryTotalDebit
:: KnownNat precision
=> JournalEntry precision account event
-> UnsignedQuantity precision
journalEntryTotalDebit :: JournalEntry precision account event -> UnsignedQuantity precision
journalEntryTotalDebit =
[UnsignedQuantity precision] -> UnsignedQuantity precision
forall (s :: Nat).
KnownNat s =>
[UnsignedQuantity s] -> UnsignedQuantity s
sumUnsignedQuantity
([UnsignedQuantity precision] -> UnsignedQuantity precision)
-> (JournalEntry precision account event
-> [UnsignedQuantity precision])
-> JournalEntry precision account event
-> UnsignedQuantity precision
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (JournalEntryItem precision account event
-> UnsignedQuantity precision)
-> [JournalEntryItem precision account event]
-> [UnsignedQuantity precision]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Amount precision -> UnsignedQuantity precision
forall (precision :: Nat).
Amount precision -> UnsignedQuantity precision
amountValue (Amount precision -> UnsignedQuantity precision)
-> (JournalEntryItem precision account event -> Amount precision)
-> JournalEntryItem precision account event
-> UnsignedQuantity precision
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JournalEntryItem precision account event -> Amount precision
forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount)
([JournalEntryItem precision account event]
-> [UnsignedQuantity precision])
-> (JournalEntry precision account event
-> [JournalEntryItem precision account event])
-> JournalEntry precision account event
-> [UnsignedQuantity precision]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (JournalEntryItem precision account event -> Bool)
-> [JournalEntryItem precision account event]
-> [JournalEntryItem precision account event]
forall a. (a -> Bool) -> [a] -> [a]
filter (Side -> Side -> Bool
forall a. Eq a => a -> a -> Bool
(==) Side
SideDebit (Side -> Bool)
-> (JournalEntryItem precision account event -> Side)
-> JournalEntryItem precision account event
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount precision -> Side
forall (precision :: Nat). Amount precision -> Side
amountSide (Amount precision -> Side)
-> (JournalEntryItem precision account event -> Amount precision)
-> JournalEntryItem precision account event
-> Side
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JournalEntryItem precision account event -> Amount precision
forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount)
([JournalEntryItem precision account event]
-> [JournalEntryItem precision account event])
-> (JournalEntry precision account event
-> [JournalEntryItem precision account event])
-> JournalEntry precision account event
-> [JournalEntryItem precision account event]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JournalEntry precision account event
-> [JournalEntryItem precision account event]
forall (precision :: Nat) account event.
JournalEntry precision account event
-> [JournalEntryItem precision account event]
journalEntryItems
journalEntryTotalCredit
:: KnownNat precision
=> JournalEntry precision account event
-> UnsignedQuantity precision
journalEntryTotalCredit :: JournalEntry precision account event -> UnsignedQuantity precision
journalEntryTotalCredit =
[UnsignedQuantity precision] -> UnsignedQuantity precision
forall (s :: Nat).
KnownNat s =>
[UnsignedQuantity s] -> UnsignedQuantity s
sumUnsignedQuantity
([UnsignedQuantity precision] -> UnsignedQuantity precision)
-> (JournalEntry precision account event
-> [UnsignedQuantity precision])
-> JournalEntry precision account event
-> UnsignedQuantity precision
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (JournalEntryItem precision account event
-> UnsignedQuantity precision)
-> [JournalEntryItem precision account event]
-> [UnsignedQuantity precision]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Amount precision -> UnsignedQuantity precision
forall (precision :: Nat).
Amount precision -> UnsignedQuantity precision
amountValue (Amount precision -> UnsignedQuantity precision)
-> (JournalEntryItem precision account event -> Amount precision)
-> JournalEntryItem precision account event
-> UnsignedQuantity precision
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JournalEntryItem precision account event -> Amount precision
forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount)
([JournalEntryItem precision account event]
-> [UnsignedQuantity precision])
-> (JournalEntry precision account event
-> [JournalEntryItem precision account event])
-> JournalEntry precision account event
-> [UnsignedQuantity precision]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (JournalEntryItem precision account event -> Bool)
-> [JournalEntryItem precision account event]
-> [JournalEntryItem precision account event]
forall a. (a -> Bool) -> [a] -> [a]
filter (Side -> Side -> Bool
forall a. Eq a => a -> a -> Bool
(==) Side
SideCredit (Side -> Bool)
-> (JournalEntryItem precision account event -> Side)
-> JournalEntryItem precision account event
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Amount precision -> Side
forall (precision :: Nat). Amount precision -> Side
amountSide (Amount precision -> Side)
-> (JournalEntryItem precision account event -> Amount precision)
-> JournalEntryItem precision account event
-> Side
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JournalEntryItem precision account event -> Amount precision
forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount)
([JournalEntryItem precision account event]
-> [JournalEntryItem precision account event])
-> (JournalEntry precision account event
-> [JournalEntryItem precision account event])
-> JournalEntry precision account event
-> [JournalEntryItem precision account event]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. JournalEntry precision account event
-> [JournalEntryItem precision account event]
forall (precision :: Nat) account event.
JournalEntry precision account event
-> [JournalEntryItem precision account event]
journalEntryItems
isJournalEntryBalanced
:: KnownNat precision
=> JournalEntry precision account event
-> Bool
isJournalEntryBalanced :: JournalEntry precision account event -> Bool
isJournalEntryBalanced = UnsignedQuantity precision -> UnsignedQuantity precision -> Bool
forall a. Eq a => a -> a -> Bool
(==)
(UnsignedQuantity precision -> UnsignedQuantity precision -> Bool)
-> (JournalEntry precision account event
-> UnsignedQuantity precision)
-> JournalEntry precision account event
-> UnsignedQuantity precision
-> Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> JournalEntry precision account event -> UnsignedQuantity precision
forall (precision :: Nat) account event.
KnownNat precision =>
JournalEntry precision account event -> UnsignedQuantity precision
journalEntryTotalDebit
(JournalEntry precision account event
-> UnsignedQuantity precision -> Bool)
-> (JournalEntry precision account event
-> UnsignedQuantity precision)
-> JournalEntry precision account event
-> Bool
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> JournalEntry precision account event -> UnsignedQuantity precision
forall (precision :: Nat) account event.
KnownNat precision =>
JournalEntry precision account event -> UnsignedQuantity precision
journalEntryTotalCredit
data JournalEntryItem (precision :: Nat) account event = JournalEntryItem
{ JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount :: !(Amount precision)
, JournalEntryItem precision account event -> Account account
journalEntryItemAccount :: !(Account account)
, JournalEntryItem precision account event -> event
journalEntryItemEvent :: !event
}
deriving (JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool
(JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool)
-> (JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool)
-> Eq (JournalEntryItem precision account event)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (precision :: Nat) account event.
(Eq account, Eq event) =>
JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool
/= :: JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool
$c/= :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool
== :: JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool
$c== :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool
Eq, (forall x.
JournalEntryItem precision account event
-> Rep (JournalEntryItem precision account event) x)
-> (forall x.
Rep (JournalEntryItem precision account event) x
-> JournalEntryItem precision account event)
-> Generic (JournalEntryItem precision account event)
forall x.
Rep (JournalEntryItem precision account event) x
-> JournalEntryItem precision account event
forall x.
JournalEntryItem precision account event
-> Rep (JournalEntryItem precision account event) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (precision :: Nat) account event x.
Rep (JournalEntryItem precision account event) x
-> JournalEntryItem precision account event
forall (precision :: Nat) account event x.
JournalEntryItem precision account event
-> Rep (JournalEntryItem precision account event) x
$cto :: forall (precision :: Nat) account event x.
Rep (JournalEntryItem precision account event) x
-> JournalEntryItem precision account event
$cfrom :: forall (precision :: Nat) account event x.
JournalEntryItem precision account event
-> Rep (JournalEntryItem precision account event) x
Generic, Int -> JournalEntryItem precision account event -> ShowS
[JournalEntryItem precision account event] -> ShowS
JournalEntryItem precision account event -> String
(Int -> JournalEntryItem precision account event -> ShowS)
-> (JournalEntryItem precision account event -> String)
-> ([JournalEntryItem precision account event] -> ShowS)
-> Show (JournalEntryItem precision account event)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> JournalEntryItem precision account event -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[JournalEntryItem precision account event] -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
JournalEntryItem precision account event -> String
showList :: [JournalEntryItem precision account event] -> ShowS
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[JournalEntryItem precision account event] -> ShowS
show :: JournalEntryItem precision account event -> String
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
JournalEntryItem precision account event -> String
showsPrec :: Int -> JournalEntryItem precision account event -> ShowS
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> JournalEntryItem precision account event -> ShowS
Show)
mkJournalEntryItemFromQuantity
:: KnownNat precision
=> Quantity precision
-> Account account
-> event
-> JournalEntryItem precision account event
mkJournalEntryItemFromQuantity :: Quantity precision
-> Account account
-> event
-> JournalEntryItem precision account event
mkJournalEntryItemFromQuantity Quantity precision
qty Account account
acc event
evt =
JournalEntryItem :: forall (precision :: Nat) account event.
Amount precision
-> Account account
-> event
-> JournalEntryItem precision account event
JournalEntryItem
{ journalEntryItemAmount :: Amount precision
journalEntryItemAmount = AccountKind -> Quantity precision -> Amount precision
forall (precision :: Nat).
KnownNat precision =>
AccountKind -> Quantity precision -> Amount precision
amountFromQuantity (Account account -> AccountKind
forall o. Account o -> AccountKind
accountKind Account account
acc) Quantity precision
qty
, journalEntryItemAccount :: Account account
journalEntryItemAccount = Account account
acc
, journalEntryItemEvent :: event
journalEntryItemEvent = event
evt
}
mkJournalEntryItemFromValue
:: KnownNat precision
=> Quantity precision
-> Account account
-> event
-> JournalEntryItem precision account event
mkJournalEntryItemFromValue :: Quantity precision
-> Account account
-> event
-> JournalEntryItem precision account event
mkJournalEntryItemFromValue Quantity precision
val Account account
acc event
evt =
JournalEntryItem :: forall (precision :: Nat) account event.
Amount precision
-> Account account
-> event
-> JournalEntryItem precision account event
JournalEntryItem
{ journalEntryItemAmount :: Amount precision
journalEntryItemAmount = AccountKind -> Quantity precision -> Amount precision
forall (precision :: Nat).
KnownNat precision =>
AccountKind -> Quantity precision -> Amount precision
amountFromValue (Account account -> AccountKind
forall o. Account o -> AccountKind
accountKind Account account
acc) Quantity precision
val
, journalEntryItemAccount :: Account account
journalEntryItemAccount = Account account
acc
, journalEntryItemEvent :: event
journalEntryItemEvent = event
evt
}