{-# 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
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
/= :: 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 (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 a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$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
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
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 = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
Aeson.genericParseJSON 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 = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
Aeson.genericToJSON forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"trialBalance"
toEncoding :: TrialBalance precision account event -> Encoding
toEncoding = forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
Aeson.genericToEncoding 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
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
/= :: 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 (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 a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$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
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
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 = forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
Aeson.genericParseJSON 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 = forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
Aeson.genericToJSON forall a b. (a -> b) -> a -> b
$ String -> Options
commonAesonOptions String
"trialBalanceItem"
toEncoding :: TrialBalanceItem precision account event -> Encoding
toEncoding = forall a.
(Generic a, GToJSON' Encoding Zero (Rep a)) =>
Options -> a -> Encoding
Aeson.genericToEncoding 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 = forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision
amountFromBalance forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 = forall (precision :: Nat) account event.
[TrialBalanceItem precision account event]
-> TrialBalance precision account event
TrialBalance forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall (precision :: Nat) account event.
KnownNat precision =>
Ledger precision account event
-> TrialBalanceItem precision account event
mkTrialBalanceItem forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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 =
forall (precision :: Nat) account event.
Ledger precision account event
-> Balance precision -> TrialBalanceItem precision account event
TrialBalanceItem Ledger precision account event
ledger (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 = forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision
amountFromBalance forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Eq a => a -> a -> Bool
(==) Side
SideDebit forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat). Balance precision -> Side
balanceSide forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance) [TrialBalanceItem precision account event]
items
itemsFromCr :: [Amount precision]
itemsFromCr = forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision
amountFromBalance forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. (a -> Bool) -> [a] -> [a]
filter (forall a. Eq a => a -> a -> Bool
(==) Side
SideCredit forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat). Balance precision -> Side
balanceSide forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
TrialBalanceItem precision account event -> Balance precision
trialBalanceItemBalance) [TrialBalanceItem precision account event]
items
totalDb :: Balance precision
totalDb = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision -> Balance precision
updateBalance (forall (precision :: Nat).
Side
-> Quantity precision
-> Inventory 8 12 precision
-> Balance precision
Balance Side
SideDebit Quantity precision
0 forall a. Default a => a
def) [Amount precision]
itemsFromDb
totalCr :: Balance precision
totalCr = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall (precision :: Nat).
KnownNat precision =>
Balance precision -> Amount precision -> Balance precision
updateBalance (forall (precision :: Nat).
Side
-> Quantity precision
-> Inventory 8 12 precision
-> Balance precision
Balance Side
SideCredit Quantity precision
0 forall a. Default a => a
def) [Amount precision]
itemsFromCr
in (Balance precision
totalDb, Balance precision
totalCr)