{-# LANGUAGE DataKinds #-}
module Haspara.Accounting.TrialBalance where
import qualified Data.Aeson as Aeson
import GHC.Generics (Generic)
import GHC.TypeLits (KnownNat, Nat)
import Haspara.Accounting.Amount (Amount)
import Haspara.Accounting.Balance (Balance(Balance, balanceSide), amountFromBalance, updateBalance)
import Haspara.Accounting.Ledger (GeneralLedger(generalLedgerLedgers), Ledger, ledgerClosing)
import Haspara.Accounting.Side (Side(..))
import Haspara.Internal.Aeson (commonAesonOptions)
newtype TrialBalance (precision :: Nat) account event = TrialBalance
{ TrialBalance precision account event
-> [TrialBalanceItem precision account event]
trialBalanceItems :: [TrialBalanceItem precision account event]
}
deriving (TrialBalance precision account event
-> TrialBalance precision account event -> Bool
(TrialBalance precision account event
-> TrialBalance precision account event -> Bool)
-> (TrialBalance precision account event
-> TrialBalance precision account event -> Bool)
-> Eq (TrialBalance precision account event)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (precision :: Nat) account event.
(Eq account, Eq event) =>
TrialBalance precision account event
-> TrialBalance precision account event -> Bool
/= :: TrialBalance precision account event
-> TrialBalance precision account event -> Bool
$c/= :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
TrialBalance precision account event
-> TrialBalance precision account event -> Bool
== :: TrialBalance precision account event
-> TrialBalance precision account event -> Bool
$c== :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
TrialBalance precision account event
-> TrialBalance precision account event -> Bool
Eq, (forall x.
TrialBalance precision account event
-> Rep (TrialBalance precision account event) x)
-> (forall x.
Rep (TrialBalance precision account event) x
-> TrialBalance precision account event)
-> Generic (TrialBalance precision account event)
forall x.
Rep (TrialBalance precision account event) x
-> TrialBalance precision account event
forall x.
TrialBalance precision account event
-> Rep (TrialBalance 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 (TrialBalance precision account event) x
-> TrialBalance precision account event
forall (precision :: Nat) account event x.
TrialBalance precision account event
-> Rep (TrialBalance precision account event) x
$cto :: forall (precision :: Nat) account event x.
Rep (TrialBalance precision account event) x
-> TrialBalance precision account event
$cfrom :: forall (precision :: Nat) account event x.
TrialBalance precision account event
-> Rep (TrialBalance precision account event) x
Generic, Int -> TrialBalance precision account event -> ShowS
[TrialBalance precision account event] -> ShowS
TrialBalance precision account event -> String
(Int -> TrialBalance precision account event -> ShowS)
-> (TrialBalance precision account event -> String)
-> ([TrialBalance precision account event] -> ShowS)
-> Show (TrialBalance 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 -> TrialBalance precision account event -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[TrialBalance precision account event] -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
TrialBalance precision account event -> String
showList :: [TrialBalance precision account event] -> ShowS
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[TrialBalance precision account event] -> ShowS
show :: TrialBalance precision account event -> String
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
TrialBalance precision account event -> String
showsPrec :: Int -> TrialBalance precision account event -> ShowS
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> TrialBalance precision account event -> ShowS
Show)
instance (KnownNat precision, Aeson.FromJSON account, Aeson.FromJSON event) => Aeson.FromJSON (TrialBalance precision account event) where
parseJSON :: Value -> Parser (TrialBalance precision account event)
parseJSON = Options -> Value -> Parser (TrialBalance precision account event)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
Aeson.genericParseJSON (Options -> Value -> Parser (TrialBalance precision account event))
-> Options
-> Value
-> Parser (TrialBalance precision account event)
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"trialBalance"
instance (KnownNat precision, Aeson.ToJSON account, Aeson.ToJSON event) => Aeson.ToJSON (TrialBalance precision account event) where
toJSON :: TrialBalance precision account event -> Value
toJSON = Options -> TrialBalance precision account event -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
Aeson.genericToJSON (Options -> TrialBalance precision account event -> Value)
-> Options -> TrialBalance precision account event -> Value
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"trialBalance"
data TrialBalanceItem (precision :: Nat) account event = TrialBalanceItem
{ TrialBalanceItem precision account event
-> Ledger precision account event
trialBalanceItemLedger :: !(Ledger precision account event)
, TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance :: !(Balance precision)
}
deriving (TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool
(TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool)
-> (TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool)
-> Eq (TrialBalanceItem precision account event)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (precision :: Nat) account event.
(Eq account, Eq event) =>
TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool
/= :: TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool
$c/= :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool
== :: TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool
$c== :: forall (precision :: Nat) account event.
(Eq account, Eq event) =>
TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool
Eq, (forall x.
TrialBalanceItem precision account event
-> Rep (TrialBalanceItem precision account event) x)
-> (forall x.
Rep (TrialBalanceItem precision account event) x
-> TrialBalanceItem precision account event)
-> Generic (TrialBalanceItem precision account event)
forall x.
Rep (TrialBalanceItem precision account event) x
-> TrialBalanceItem precision account event
forall x.
TrialBalanceItem precision account event
-> Rep (TrialBalanceItem 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 (TrialBalanceItem precision account event) x
-> TrialBalanceItem precision account event
forall (precision :: Nat) account event x.
TrialBalanceItem precision account event
-> Rep (TrialBalanceItem precision account event) x
$cto :: forall (precision :: Nat) account event x.
Rep (TrialBalanceItem precision account event) x
-> TrialBalanceItem precision account event
$cfrom :: forall (precision :: Nat) account event x.
TrialBalanceItem precision account event
-> Rep (TrialBalanceItem precision account event) x
Generic, Int -> TrialBalanceItem precision account event -> ShowS
[TrialBalanceItem precision account event] -> ShowS
TrialBalanceItem precision account event -> String
(Int -> TrialBalanceItem precision account event -> ShowS)
-> (TrialBalanceItem precision account event -> String)
-> ([TrialBalanceItem precision account event] -> ShowS)
-> Show (TrialBalanceItem 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 -> TrialBalanceItem precision account event -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[TrialBalanceItem precision account event] -> ShowS
forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
TrialBalanceItem precision account event -> String
showList :: [TrialBalanceItem precision account event] -> ShowS
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[TrialBalanceItem precision account event] -> ShowS
show :: TrialBalanceItem precision account event -> String
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
TrialBalanceItem precision account event -> String
showsPrec :: Int -> TrialBalanceItem precision account event -> ShowS
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> TrialBalanceItem precision account event -> ShowS
Show)
instance (KnownNat precision, Aeson.FromJSON account, Aeson.FromJSON event) => Aeson.FromJSON (TrialBalanceItem precision account event) where
parseJSON :: Value -> Parser (TrialBalanceItem precision account event)
parseJSON = Options
-> Value -> Parser (TrialBalanceItem precision account event)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
Aeson.genericParseJSON (Options
-> Value -> Parser (TrialBalanceItem precision account event))
-> Options
-> Value
-> Parser (TrialBalanceItem precision account event)
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"trialBalanceItem"
instance (KnownNat precision, Aeson.ToJSON account, Aeson.ToJSON event) => Aeson.ToJSON (TrialBalanceItem precision account event) where
toJSON :: TrialBalanceItem precision account event -> Value
toJSON = Options -> TrialBalanceItem precision account event -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
Aeson.genericToJSON (Options -> TrialBalanceItem precision account event -> Value)
-> Options -> TrialBalanceItem precision account event -> Value
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"trialBalanceItem"
trialBalanceItemAmount
:: KnownNat precision
=> TrialBalanceItem precision account event
-> Amount precision
trialBalanceItemAmount :: TrialBalanceItem precision account event -> Amount precision
trialBalanceItemAmount = Balance precision -> Amount precision
forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision
amountFromBalance (Balance precision -> Amount precision)
-> (TrialBalanceItem precision account event -> Balance precision)
-> TrialBalanceItem precision account event
-> Amount precision
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TrialBalanceItem precision account event -> Balance precision
forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance
prepareTrialBalance
:: KnownNat precision
=> GeneralLedger precision account event
-> TrialBalance precision account event
prepareTrialBalance :: GeneralLedger precision account event
-> TrialBalance precision account event
prepareTrialBalance = [TrialBalanceItem precision account event]
-> TrialBalance precision account event
forall (precision :: Nat) account event.
[TrialBalanceItem precision account event]
-> TrialBalance precision account event
TrialBalance ([TrialBalanceItem precision account event]
-> TrialBalance precision account event)
-> (GeneralLedger precision account event
-> [TrialBalanceItem precision account event])
-> GeneralLedger precision account event
-> TrialBalance precision account event
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Ledger precision account event
-> TrialBalanceItem precision account event)
-> [Ledger precision account event]
-> [TrialBalanceItem precision account event]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Ledger precision account event
-> TrialBalanceItem precision account event
forall (precision :: Nat) account event.
KnownNat precision =>
Ledger precision account event
-> TrialBalanceItem precision account event
mkTrialBalanceItem ([Ledger precision account event]
-> [TrialBalanceItem precision account event])
-> (GeneralLedger precision account event
-> [Ledger precision account event])
-> GeneralLedger precision account event
-> [TrialBalanceItem precision account event]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GeneralLedger precision account event
-> [Ledger precision account event]
forall (precision :: Nat) account event.
GeneralLedger precision account event
-> [Ledger precision account event]
generalLedgerLedgers
mkTrialBalanceItem
:: KnownNat precision
=> Ledger precision account event
-> TrialBalanceItem precision account event
mkTrialBalanceItem :: Ledger precision account event
-> TrialBalanceItem precision account event
mkTrialBalanceItem Ledger precision account event
ledger =
Ledger precision account event
-> Balance precision -> TrialBalanceItem precision account event
forall (precision :: Nat) account event.
Ledger precision account event
-> Balance precision -> TrialBalanceItem precision account event
TrialBalanceItem Ledger precision account event
ledger (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)
trialBalanceTotals
:: KnownNat precision
=> TrialBalance precision account event
-> (Balance precision, Balance precision)
trialBalanceTotals :: TrialBalance precision account event
-> (Balance precision, Balance precision)
trialBalanceTotals (TrialBalance [TrialBalanceItem precision account event]
items) =
let
itemsFromDb :: [Amount precision]
itemsFromDb = Balance precision -> Amount precision
forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision
amountFromBalance (Balance precision -> Amount precision)
-> (TrialBalanceItem precision account event -> Balance precision)
-> TrialBalanceItem precision account event
-> Amount precision
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TrialBalanceItem precision account event -> Balance precision
forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance (TrialBalanceItem precision account event -> Amount precision)
-> [TrialBalanceItem precision account event] -> [Amount precision]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TrialBalanceItem precision account event -> Bool)
-> [TrialBalanceItem precision account event]
-> [TrialBalanceItem precision account event]
forall a. (a -> Bool) -> [a] -> [a]
filter (Side -> Side -> Bool
forall a. Eq a => a -> a -> Bool
(==) Side
SideDebit (Side -> Bool)
-> (TrialBalanceItem precision account event -> Side)
-> TrialBalanceItem precision account event
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Balance precision -> Side
forall (precision :: Nat). Balance precision -> Side
balanceSide (Balance precision -> Side)
-> (TrialBalanceItem precision account event -> Balance precision)
-> TrialBalanceItem precision account event
-> Side
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TrialBalanceItem precision account event -> Balance precision
forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance) [TrialBalanceItem precision account event]
items
itemsFromCr :: [Amount precision]
itemsFromCr = Balance precision -> Amount precision
forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision
amountFromBalance (Balance precision -> Amount precision)
-> (TrialBalanceItem precision account event -> Balance precision)
-> TrialBalanceItem precision account event
-> Amount precision
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TrialBalanceItem precision account event -> Balance precision
forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance (TrialBalanceItem precision account event -> Amount precision)
-> [TrialBalanceItem precision account event] -> [Amount precision]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (TrialBalanceItem precision account event -> Bool)
-> [TrialBalanceItem precision account event]
-> [TrialBalanceItem precision account event]
forall a. (a -> Bool) -> [a] -> [a]
filter (Side -> Side -> Bool
forall a. Eq a => a -> a -> Bool
(==) Side
SideCredit (Side -> Bool)
-> (TrialBalanceItem precision account event -> Side)
-> TrialBalanceItem precision account event
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Balance precision -> Side
forall (precision :: Nat). Balance precision -> Side
balanceSide (Balance precision -> Side)
-> (TrialBalanceItem precision account event -> Balance precision)
-> TrialBalanceItem precision account event
-> Side
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TrialBalanceItem precision account event -> Balance precision
forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance) [TrialBalanceItem precision account event]
items
totalDb :: Balance precision
totalDb = (Balance precision -> Amount precision -> Balance precision)
-> Balance precision -> [Amount precision] -> Balance precision
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Balance precision -> Amount precision -> Balance precision
forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision -> Balance precision
updateBalance (Side -> Quantity precision -> Balance precision
forall (precision :: Nat).
Side -> Quantity precision -> Balance precision
Balance Side
SideDebit Quantity precision
0) [Amount precision]
itemsFromDb
totalCr :: Balance precision
totalCr = (Balance precision -> Amount precision -> Balance precision)
-> Balance precision -> [Amount precision] -> Balance precision
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl Balance precision -> Amount precision -> Balance precision
forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision -> Balance precision
updateBalance (Side -> Quantity precision -> Balance precision
forall (precision :: Nat).
Side -> Quantity precision -> Balance precision
Balance Side
SideCredit Quantity precision
0) [Amount precision]
itemsFromCr
in
(Balance precision
totalDb, Balance precision
totalCr)