{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE KindSignatures #-}
module Haspara.Accounting.TrialBalance where
import qualified Data.Aeson as Aeson
import Data.Default (def)
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
{ forall (precision :: Nat) account event.
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 (precision :: Nat) account event.
(Eq account, Eq event) =>
TrialBalance precision account event
-> TrialBalance precision account event -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$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
/= :: 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 (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
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
$cfrom :: forall (precision :: Nat) account event x.
TrialBalance precision account event
-> Rep (TrialBalance precision account event) x
from :: forall 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
to :: forall x.
Rep (TrialBalance precision account event) x
-> TrialBalance precision account event
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 (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
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> TrialBalance precision account event -> ShowS
showsPrec :: Int -> TrialBalance precision account event -> ShowS
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
TrialBalance precision account event -> String
show :: TrialBalance precision account event -> String
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[TrialBalance precision account event] -> ShowS
showList :: [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"
toEncoding :: TrialBalance precision account event -> Encoding
toEncoding = Options -> TrialBalance precision account event -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
Aeson.genericToEncoding (Options -> TrialBalance precision account event -> Encoding)
-> Options -> TrialBalance precision account event -> Encoding
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"trialBalance"
data TrialBalanceItem (precision :: Nat) account event = TrialBalanceItem
{ forall (precision :: Nat) account event.
TrialBalanceItem precision account event
-> Ledger precision account event
trialBalanceItemLedger :: !(Ledger precision account event)
, forall (precision :: Nat) 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 (precision :: Nat) account event.
(Eq account, Eq event) =>
TrialBalanceItem precision account event
-> TrialBalanceItem precision account event -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$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
/= :: 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 (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
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
$cfrom :: forall (precision :: Nat) account event x.
TrialBalanceItem precision account event
-> Rep (TrialBalanceItem precision account event) x
from :: forall 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
to :: forall x.
Rep (TrialBalanceItem precision account event) x
-> TrialBalanceItem precision account event
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 (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
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
Int -> TrialBalanceItem precision account event -> ShowS
showsPrec :: Int -> TrialBalanceItem precision account event -> ShowS
$cshow :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
TrialBalanceItem precision account event -> String
show :: TrialBalanceItem precision account event -> String
$cshowList :: forall (precision :: Nat) account event.
(KnownNat precision, Show account, Show event) =>
[TrialBalanceItem precision account event] -> ShowS
showList :: [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"
toEncoding :: TrialBalanceItem precision account event -> Encoding
toEncoding = Options -> TrialBalanceItem precision account event -> Encoding
forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
Aeson.genericToEncoding (Options -> TrialBalanceItem precision account event -> Encoding)
-> Options -> TrialBalanceItem precision account event -> Encoding
forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"trialBalanceItem"
trialBalanceItemAmount
:: KnownNat precision
=> TrialBalanceItem precision account event
-> Amount precision
trialBalanceItemAmount :: forall (precision :: Nat) account event.
KnownNat precision =>
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 :: forall (precision :: Nat) account event.
KnownNat precision =>
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 a b. (a -> b) -> [a] -> [b]
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 :: forall (precision :: Nat) account event.
KnownNat precision =>
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 :: forall (precision :: Nat) account event.
KnownNat precision =>
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 b a. (b -> a -> b) -> b -> [a] -> b
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
-> Inventory 8 12 precision
-> Balance precision
forall (precision :: Nat).
Side
-> Quantity precision
-> Inventory 8 12 precision
-> Balance precision
Balance Side
SideDebit Quantity precision
0 Inventory 8 12 precision
forall a. Default a => a
def) [Amount precision]
itemsFromDb
totalCr :: Balance precision
totalCr = (Balance precision -> Amount precision -> Balance precision)
-> Balance precision -> [Amount precision] -> Balance precision
forall b a. (b -> a -> b) -> b -> [a] -> b
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
-> Inventory 8 12 precision
-> Balance precision
forall (precision :: Nat).
Side
-> Quantity precision
-> Inventory 8 12 precision
-> Balance precision
Balance Side
SideCredit Quantity precision
0 Inventory 8 12 precision
forall a. Default a => a
def) [Amount precision]
itemsFromCr
in (Balance precision
totalDb, Balance precision
totalCr)