{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
module Haspara.Accounting.Ledger where
import qualified Data.Aeson as Aeson
import qualified Data.Map.Strict as HM
import Data.Maybe (fromMaybe, listToMaybe)
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.Balance (Balance(Balance), updateBalance)
import Haspara.Accounting.Journal (JournalEntry(..), JournalEntryItem(JournalEntryItem))
import Haspara.Accounting.Side (normalSideByAccountKind)
import Haspara.Internal.Aeson (commonAesonOptions)
import Haspara.Quantity (Quantity)
newtype GeneralLedger (precision :: Nat) account event = GeneralLedger
{ GeneralLedger precision account event
-> [Ledger precision account event]
generalLedgerLedgers :: [Ledger precision account event]
}
deriving (GeneralLedger precision account event
-> GeneralLedger precision account event -> Bool
(GeneralLedger precision account event
-> GeneralLedger precision account event -> Bool)
-> (GeneralLedger precision account event
-> GeneralLedger precision account event -> Bool)
-> Eq (GeneralLedger precision account event)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (precision :: Nat) account event.
(Eq account, Eq event) =>
GeneralLedger precision account event
-> GeneralLedger precision account event -> Bool
/= :: GeneralLedger precision account event
-> GeneralLedger precision account event -> Bool
$c/= :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
GeneralLedger precision account event
-> GeneralLedger precision account event -> Bool
== :: GeneralLedger precision account event
-> GeneralLedger precision account event -> Bool
$c== :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
GeneralLedger precision account event
-> GeneralLedger precision account event -> Bool
Eq, (forall x.
GeneralLedger precision account event
-> Rep (GeneralLedger precision account event) x)
-> (forall x.
Rep (GeneralLedger precision account event) x
-> GeneralLedger precision account event)
-> Generic (GeneralLedger precision account event)
forall x.
Rep (GeneralLedger precision account event) x
-> GeneralLedger precision account event
forall x.
GeneralLedger precision account event
-> Rep (GeneralLedger 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 (GeneralLedger precision account event) x
-> GeneralLedger precision account event
forall (precision :: Nat) account event x.
GeneralLedger precision account event
-> Rep (GeneralLedger precision account event) x
$cto :: forall (precision :: Nat) account event x.
Rep (GeneralLedger precision account event) x
-> GeneralLedger precision account event
$cfrom :: forall (precision :: Nat) account event x.
GeneralLedger precision account event
-> Rep (GeneralLedger precision account event) x
Generic, Int -> GeneralLedger precision account event -> ShowS
[GeneralLedger precision account event] -> ShowS
GeneralLedger precision account event -> String
(Int -> GeneralLedger precision account event -> ShowS)
-> (GeneralLedger precision account event -> String)
-> ([GeneralLedger precision account event] -> ShowS)
-> Show (GeneralLedger 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 -> GeneralLedger precision account event -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[GeneralLedger precision account event] -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
GeneralLedger precision account event -> String
showList :: [GeneralLedger precision account event] -> ShowS
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[GeneralLedger precision account event] -> ShowS
show :: GeneralLedger precision account event -> String
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
GeneralLedger precision account event -> String
showsPrec :: Int -> GeneralLedger precision account event -> ShowS
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> GeneralLedger precision account event -> ShowS
Show)
instance (KnownNat precision, Aeson.FromJSON account, Aeson.FromJSON event) => Aeson.FromJSON (GeneralLedger precision account event) where
parseJSON :: Value -> Parser (GeneralLedger precision account event)
parseJSON = Options -> Value -> Parser (GeneralLedger precision account event)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
Aeson.genericParseJSON (Options
-> Value -> Parser (GeneralLedger precision account event))
-> Options
-> Value
-> Parser (GeneralLedger precision account event)
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"generalLedger"
instance (KnownNat precision, Aeson.ToJSON account, Aeson.ToJSON event) => Aeson.ToJSON (GeneralLedger precision account event) where
toJSON :: GeneralLedger precision account event -> Value
toJSON = Options -> GeneralLedger precision account event -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
Aeson.genericToJSON (Options -> GeneralLedger precision account event -> Value)
-> Options -> GeneralLedger precision account event -> Value
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"generalLedger"
data Ledger (precision :: Nat) account event = Ledger
{ Ledger precision account event -> Account account
ledgerAccount :: !(Account account)
, Ledger precision account event -> Balance precision
ledgerOpening :: !(Balance precision)
, Ledger precision account event -> [LedgerEntry precision event]
ledgerRunning :: ![LedgerEntry precision event]
}
deriving (Ledger precision account event
-> Ledger precision account event -> Bool
(Ledger precision account event
-> Ledger precision account event -> Bool)
-> (Ledger precision account event
-> Ledger precision account event -> Bool)
-> Eq (Ledger precision account event)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (precision :: Nat) account event.
(Eq account, Eq event) =>
Ledger precision account event
-> Ledger precision account event -> Bool
/= :: Ledger precision account event
-> Ledger precision account event -> Bool
$c/= :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
Ledger precision account event
-> Ledger precision account event -> Bool
== :: Ledger precision account event
-> Ledger precision account event -> Bool
$c== :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
Ledger precision account event
-> Ledger precision account event -> Bool
Eq, (forall x.
Ledger precision account event
-> Rep (Ledger precision account event) x)
-> (forall x.
Rep (Ledger precision account event) x
-> Ledger precision account event)
-> Generic (Ledger precision account event)
forall x.
Rep (Ledger precision account event) x
-> Ledger precision account event
forall x.
Ledger precision account event
-> Rep (Ledger 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 (Ledger precision account event) x
-> Ledger precision account event
forall (precision :: Nat) account event x.
Ledger precision account event
-> Rep (Ledger precision account event) x
$cto :: forall (precision :: Nat) account event x.
Rep (Ledger precision account event) x
-> Ledger precision account event
$cfrom :: forall (precision :: Nat) account event x.
Ledger precision account event
-> Rep (Ledger precision account event) x
Generic, Int -> Ledger precision account event -> ShowS
[Ledger precision account event] -> ShowS
Ledger precision account event -> String
(Int -> Ledger precision account event -> ShowS)
-> (Ledger precision account event -> String)
-> ([Ledger precision account event] -> ShowS)
-> Show (Ledger 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 -> Ledger precision account event -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[Ledger precision account event] -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Ledger precision account event -> String
showList :: [Ledger precision account event] -> ShowS
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[Ledger precision account event] -> ShowS
show :: Ledger precision account event -> String
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Ledger precision account event -> String
showsPrec :: Int -> Ledger precision account event -> ShowS
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> Ledger precision account event -> ShowS
Show)
instance (KnownNat precision, Aeson.FromJSON account, Aeson.FromJSON event) => Aeson.FromJSON (Ledger precision account event) where
parseJSON :: Value -> Parser (Ledger precision account event)
parseJSON = Options -> Value -> Parser (Ledger precision account event)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
Aeson.genericParseJSON (Options -> Value -> Parser (Ledger precision account event))
-> Options -> Value -> Parser (Ledger precision account event)
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"ledger"
instance (KnownNat precision, Aeson.ToJSON account, Aeson.ToJSON event) => Aeson.ToJSON (Ledger precision account event) where
toJSON :: Ledger precision account event -> Value
toJSON = Options -> Ledger precision account event -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
Aeson.genericToJSON (Options -> Ledger precision account event -> Value)
-> Options -> Ledger precision account event -> Value
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"ledger"
ledgerClosing
:: KnownNat precision
=> Ledger precision account event
-> Balance precision
ledgerClosing :: Ledger precision account event -> Balance precision
ledgerClosing Ledger precision account event
ledger = Balance precision
-> (LedgerEntry precision event -> Balance precision)
-> Maybe (LedgerEntry precision event)
-> Balance precision
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Ledger precision account event -> Balance precision
forall (precision :: Nat) account event.
Ledger precision account event -> Balance precision
ledgerOpening Ledger precision account event
ledger) LedgerEntry precision event -> Balance precision
forall (precision :: Nat) event.
LedgerEntry precision event -> Balance precision
ledgerEntryBalance ([LedgerEntry precision event]
-> Maybe (LedgerEntry precision event)
forall a. [a] -> Maybe a
listToMaybe (Ledger precision account event -> [LedgerEntry precision event]
forall (precision :: Nat) account event.
Ledger precision account event -> [LedgerEntry precision event]
ledgerRunning Ledger precision account event
ledger))
data LedgerEntry (precision :: Nat) event = LedgerEntry
{ LedgerEntry precision event -> Day
ledgerEntryDate :: !Day
, LedgerEntry precision event -> Amount precision
ledgerEntryAmount :: !(Amount precision)
, LedgerEntry precision event -> Text
ledgerEntryDescription :: !T.Text
, LedgerEntry precision event -> event
ledgerEntryEvent :: !event
, LedgerEntry precision event -> Text
ledgerEntryPostingId :: !T.Text
, LedgerEntry precision event -> Balance precision
ledgerEntryBalance :: !(Balance precision)
}
deriving (LedgerEntry precision event -> LedgerEntry precision event -> Bool
(LedgerEntry precision event
-> LedgerEntry precision event -> Bool)
-> (LedgerEntry precision event
-> LedgerEntry precision event -> Bool)
-> Eq (LedgerEntry precision event)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (precision :: Nat) event.
Eq event =>
LedgerEntry precision event -> LedgerEntry precision event -> Bool
/= :: LedgerEntry precision event -> LedgerEntry precision event -> Bool
$c/= :: forall (precision :: Nat) event.
Eq event =>
LedgerEntry precision event -> LedgerEntry precision event -> Bool
== :: LedgerEntry precision event -> LedgerEntry precision event -> Bool
$c== :: forall (precision :: Nat) event.
Eq event =>
LedgerEntry precision event -> LedgerEntry precision event -> Bool
Eq, (forall x.
LedgerEntry precision event -> Rep (LedgerEntry precision event) x)
-> (forall x.
Rep (LedgerEntry precision event) x -> LedgerEntry precision event)
-> Generic (LedgerEntry precision event)
forall x.
Rep (LedgerEntry precision event) x -> LedgerEntry precision event
forall x.
LedgerEntry precision event -> Rep (LedgerEntry precision event) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (precision :: Nat) event x.
Rep (LedgerEntry precision event) x -> LedgerEntry precision event
forall (precision :: Nat) event x.
LedgerEntry precision event -> Rep (LedgerEntry precision event) x
$cto :: forall (precision :: Nat) event x.
Rep (LedgerEntry precision event) x -> LedgerEntry precision event
$cfrom :: forall (precision :: Nat) event x.
LedgerEntry precision event -> Rep (LedgerEntry precision event) x
Generic, Int -> LedgerEntry precision event -> ShowS
[LedgerEntry precision event] -> ShowS
LedgerEntry precision event -> String
(Int -> LedgerEntry precision event -> ShowS)
-> (LedgerEntry precision event -> String)
-> ([LedgerEntry precision event] -> ShowS)
-> Show (LedgerEntry precision event)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (precision :: Nat) event.
(KnownNat precision, Show event) =>
Int -> LedgerEntry precision event -> ShowS
forall (precision :: Nat) event.
(KnownNat precision, Show event) =>
[LedgerEntry precision event] -> ShowS
forall (precision :: Nat) event.
(KnownNat precision, Show event) =>
LedgerEntry precision event -> String
showList :: [LedgerEntry precision event] -> ShowS
$cshowList :: forall (precision :: Nat) event.
(KnownNat precision, Show event) =>
[LedgerEntry precision event] -> ShowS
show :: LedgerEntry precision event -> String
$cshow :: forall (precision :: Nat) event.
(KnownNat precision, Show event) =>
LedgerEntry precision event -> String
showsPrec :: Int -> LedgerEntry precision event -> ShowS
$cshowsPrec :: forall (precision :: Nat) event.
(KnownNat precision, Show event) =>
Int -> LedgerEntry precision event -> ShowS
Show)
instance (KnownNat precision, Aeson.FromJSON event) => Aeson.FromJSON (LedgerEntry precision event) where
parseJSON :: Value -> Parser (LedgerEntry precision event)
parseJSON = Options -> Value -> Parser (LedgerEntry precision event)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
Aeson.genericParseJSON (Options -> Value -> Parser (LedgerEntry precision event))
-> Options -> Value -> Parser (LedgerEntry precision event)
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"ledgerEntry"
instance (KnownNat precision, Aeson.ToJSON event) => Aeson.ToJSON (LedgerEntry precision event) where
toJSON :: LedgerEntry precision event -> Value
toJSON = Options -> LedgerEntry precision event -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
Aeson.genericToJSON (Options -> LedgerEntry precision event -> Value)
-> Options -> LedgerEntry precision event -> Value
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"ledgerEntry"
initLedger
:: KnownNat precision
=> Account account
-> Ledger precision account event
initLedger :: Account account -> Ledger precision account event
initLedger Account account
acc = Account account
-> Balance precision
-> [LedgerEntry precision event]
-> Ledger precision account event
forall (precision :: Nat) account event.
Account account
-> Balance precision
-> [LedgerEntry precision event]
-> Ledger precision account event
Ledger Account account
acc Balance precision
balance []
where
balance :: Balance precision
balance = Side -> Quantity precision -> Balance precision
forall (precision :: Nat).
Side -> Quantity precision -> Balance precision
Balance (AccountKind -> Side
normalSideByAccountKind (Account account -> AccountKind
forall o. Account o -> AccountKind
accountKind Account account
acc)) Quantity precision
0
initLedgerWithOpeningBalance
:: KnownNat precision
=> Account account
-> Balance precision
-> Ledger precision account event
initLedgerWithOpeningBalance :: Account account
-> Balance precision -> Ledger precision account event
initLedgerWithOpeningBalance Account account
acc Balance precision
balance = Account account
-> Balance precision
-> [LedgerEntry precision event]
-> Ledger precision account event
forall (precision :: Nat) account event.
Account account
-> Balance precision
-> [LedgerEntry precision event]
-> Ledger precision account event
Ledger Account account
acc Balance precision
balance []
initLedgerWithOpeningValue
:: KnownNat precision
=> Account account
-> Quantity precision
-> Ledger precision account event
initLedgerWithOpeningValue :: Account account
-> Quantity precision -> Ledger precision account event
initLedgerWithOpeningValue Account account
acc Quantity precision
qty = Account account
-> Balance precision -> Ledger precision account event
forall (precision :: Nat) account event.
KnownNat precision =>
Account account
-> Balance precision -> Ledger precision account event
initLedgerWithOpeningBalance Account account
acc Balance precision
balance
where
amount :: Amount precision
amount = 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
qty
balance0 :: Balance precision
balance0 = Side -> Quantity precision -> Balance precision
forall (precision :: Nat).
Side -> Quantity precision -> Balance precision
Balance (AccountKind -> Side
normalSideByAccountKind (Account account -> AccountKind
forall o. Account o -> AccountKind
accountKind Account account
acc)) Quantity precision
0
balance :: Balance precision
balance = Balance precision -> Amount precision -> Balance precision
forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision -> Balance precision
updateBalance Balance precision
balance0 Amount precision
amount
initLedgerWithOpeningQuantity
:: KnownNat precision
=> Account account
-> Quantity precision
-> Ledger precision account event
initLedgerWithOpeningQuantity :: Account account
-> Quantity precision -> Ledger precision account event
initLedgerWithOpeningQuantity Account account
acc Quantity precision
qty = Account account
-> Balance precision -> Ledger precision account event
forall (precision :: Nat) account event.
KnownNat precision =>
Account account
-> Balance precision -> Ledger precision account event
initLedgerWithOpeningBalance Account account
acc Balance precision
balance
where
amount :: Amount precision
amount = 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
balance0 :: Balance precision
balance0 = Side -> Quantity precision -> Balance precision
forall (precision :: Nat).
Side -> Quantity precision -> Balance precision
Balance (AccountKind -> Side
normalSideByAccountKind (Account account -> AccountKind
forall o. Account o -> AccountKind
accountKind Account account
acc)) Quantity precision
0
balance :: Balance precision
balance = Balance precision -> Amount precision -> Balance precision
forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision -> Balance precision
updateBalance Balance precision
balance0 Amount precision
amount
postEntries
:: KnownNat precision
=> Eq account
=> Ord account
=> GeneralLedger precision account event
-> [JournalEntry precision account event]
-> GeneralLedger precision account event
postEntries :: GeneralLedger precision account event
-> [JournalEntry precision account event]
-> GeneralLedger precision account event
postEntries = (GeneralLedger precision account event
-> JournalEntry precision account event
-> GeneralLedger precision account event)
-> GeneralLedger precision account event
-> [JournalEntry precision account event]
-> GeneralLedger precision account event
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl GeneralLedger precision account event
-> JournalEntry precision account event
-> GeneralLedger precision account event
forall (precision :: Nat) account event.
(KnownNat precision, Eq account, Ord account) =>
GeneralLedger precision account event
-> JournalEntry precision account event
-> GeneralLedger precision account event
postEntry
postEntry
:: KnownNat precision
=> Eq account
=> Ord account
=> GeneralLedger precision account event
-> JournalEntry precision account event
-> GeneralLedger precision account event
postEntry :: GeneralLedger precision account event
-> JournalEntry precision account event
-> GeneralLedger precision account event
postEntry GeneralLedger precision account event
gl JournalEntry precision account event
je = (GeneralLedger precision account event
-> JournalEntryItem precision account event
-> GeneralLedger precision account event)
-> GeneralLedger precision account event
-> [JournalEntryItem precision account event]
-> GeneralLedger precision account event
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (GeneralLedger precision account event
-> JournalEntry precision account event
-> JournalEntryItem precision account event
-> GeneralLedger precision account event
forall (precision :: Nat) account event.
(KnownNat precision, Eq account, Ord account) =>
GeneralLedger precision account event
-> JournalEntry precision account event
-> JournalEntryItem precision account event
-> GeneralLedger precision account event
`postEntryItem` JournalEntry precision account event
je) GeneralLedger precision account event
gl (JournalEntry precision account event
-> [JournalEntryItem precision account event]
forall (precision :: Nat) account event.
JournalEntry precision account event
-> [JournalEntryItem precision account event]
journalEntryItems JournalEntry precision account event
je)
postEntryItem
:: KnownNat precision
=> Eq account
=> Ord account
=> GeneralLedger precision account event
-> JournalEntry precision account event
-> JournalEntryItem precision account event
-> GeneralLedger precision account event
postEntryItem :: GeneralLedger precision account event
-> JournalEntry precision account event
-> JournalEntryItem precision account event
-> GeneralLedger precision account event
postEntryItem GeneralLedger precision account event
gl JournalEntry precision account event
je (JournalEntryItem Amount precision
amt Account account
acc event
evt) =
let
ledgers :: [Ledger precision account event]
ledgers = GeneralLedger precision account event
-> [Ledger precision account event]
forall (precision :: Nat) account event.
GeneralLedger precision account event
-> [Ledger precision account event]
generalLedgerLedgers GeneralLedger precision account event
gl
ledgersDb :: Map (Account account) (Ledger precision account event)
ledgersDb = [(Account account, Ledger precision account event)]
-> Map (Account account) (Ledger precision account event)
forall k a. Ord k => [(k, a)] -> Map k a
HM.fromList ([(Account account, Ledger precision account event)]
-> Map (Account account) (Ledger precision account event))
-> [(Account account, Ledger precision account event)]
-> Map (Account account) (Ledger precision account event)
forall a b. (a -> b) -> a -> b
$ [Account account]
-> [Ledger precision account event]
-> [(Account account, Ledger precision account event)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((Ledger precision account event -> Account account)
-> [Ledger precision account event] -> [Account account]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Ledger precision account event -> Account account
forall (precision :: Nat) account event.
Ledger precision account event -> Account account
ledgerAccount [Ledger precision account event]
ledgers) [Ledger precision account event]
ledgers
ledgerCurr :: Ledger precision account event
ledgerCurr = Ledger precision account event
-> Maybe (Ledger precision account event)
-> Ledger precision account event
forall a. a -> Maybe a -> a
fromMaybe (Account account -> Ledger precision account event
forall (precision :: Nat) account event.
KnownNat precision =>
Account account -> Ledger precision account event
initLedger Account account
acc) (Maybe (Ledger precision account event)
-> Ledger precision account event)
-> Maybe (Ledger precision account event)
-> Ledger precision account event
forall a b. (a -> b) -> a -> b
$ Account account
-> Map (Account account) (Ledger precision account event)
-> Maybe (Ledger precision account event)
forall k a. Ord k => k -> Map k a -> Maybe a
HM.lookup Account account
acc Map (Account account) (Ledger precision account event)
ledgersDb
ledgerNext :: Ledger precision account event
ledgerNext = Ledger precision account event
-> Day
-> Amount precision
-> Text
-> event
-> Text
-> Ledger precision account event
forall (precision :: Nat) account event.
KnownNat precision =>
Ledger precision account event
-> Day
-> Amount precision
-> Text
-> event
-> Text
-> Ledger precision account event
postItem Ledger precision account event
ledgerCurr (JournalEntry precision account event -> Day
forall (precision :: Nat) account event.
JournalEntry precision account event -> Day
journalEntryDate JournalEntry precision account event
je) Amount precision
amt (JournalEntry precision account event -> Text
forall (precision :: Nat) account event.
JournalEntry precision account event -> Text
journalEntryDescription JournalEntry precision account event
je) event
evt (JournalEntry precision account event -> Text
forall (precision :: Nat) account event.
JournalEntry precision account event -> Text
journalEntryId JournalEntry precision account event
je)
ledgersDbNext :: Map (Account account) (Ledger precision account event)
ledgersDbNext = Account account
-> Ledger precision account event
-> Map (Account account) (Ledger precision account event)
-> Map (Account account) (Ledger precision account event)
forall k a. Ord k => k -> a -> Map k a -> Map k a
HM.insert Account account
acc Ledger precision account event
ledgerNext Map (Account account) (Ledger precision account event)
ledgersDb
in
GeneralLedger :: forall (precision :: Nat) account event.
[Ledger precision account event]
-> GeneralLedger precision account event
GeneralLedger
{ generalLedgerLedgers :: [Ledger precision account event]
generalLedgerLedgers = Map (Account account) (Ledger precision account event)
-> [Ledger precision account event]
forall k a. Map k a -> [a]
HM.elems Map (Account account) (Ledger precision account event)
ledgersDbNext
}
postItem
:: KnownNat precision
=> Ledger precision account event
-> Day
-> Amount precision
-> T.Text
-> event
-> T.Text
-> Ledger precision account event
postItem :: Ledger precision account event
-> Day
-> Amount precision
-> Text
-> event
-> Text
-> Ledger precision account event
postItem Ledger precision account event
ledger Day
date Amount precision
amt Text
dsc event
evt Text
pid =
let
balanceLast :: Balance precision
balanceLast = Ledger precision account event -> Balance precision
forall (precision :: Nat) account event.
KnownNat precision =>
Ledger precision account event -> Balance precision
ledgerClosing Ledger precision account event
ledger
balanceNext :: Balance precision
balanceNext = Balance precision -> Amount precision -> Balance precision
forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision -> Balance precision
updateBalance Balance precision
balanceLast Amount precision
amt
item :: LedgerEntry precision event
item = LedgerEntry :: forall (precision :: Nat) event.
Day
-> Amount precision
-> Text
-> event
-> Text
-> Balance precision
-> LedgerEntry precision event
LedgerEntry
{ ledgerEntryDate :: Day
ledgerEntryDate = Day
date
, ledgerEntryAmount :: Amount precision
ledgerEntryAmount = Amount precision
amt
, ledgerEntryDescription :: Text
ledgerEntryDescription = Text
dsc
, ledgerEntryEvent :: event
ledgerEntryEvent = event
evt
, ledgerEntryPostingId :: Text
ledgerEntryPostingId = Text
pid
, ledgerEntryBalance :: Balance precision
ledgerEntryBalance = Balance precision
balanceNext
}
in
Ledger precision account event
ledger
{ ledgerRunning :: [LedgerEntry precision event]
ledgerRunning = LedgerEntry precision event
item LedgerEntry precision event
-> [LedgerEntry precision event] -> [LedgerEntry precision event]
forall a. a -> [a] -> [a]
: Ledger precision account event -> [LedgerEntry precision event]
forall (precision :: Nat) account event.
Ledger precision account event -> [LedgerEntry precision event]
ledgerRunning Ledger precision account event
ledger
}