{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE KindSignatures #-}
module Haspara.Accounting.Journal where
import qualified Data.Aeson as Aeson
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 (..), amountFromValue)
import Haspara.Accounting.Side (Side (..))
import Haspara.Internal.Aeson (commonAesonOptions)
import Haspara.Quantity (Quantity, UnsignedQuantity, sumUnsignedQuantity)
newtype Journal (precision :: Nat) account event = Journal
{ forall (precision :: Nat) account event.
Journal precision account event
-> [JournalEntry precision account event]
journalEntries :: [JournalEntry precision account event]
}
deriving (forall (precision :: Nat) account event x.
Rep (Journal precision account event) x
-> Journal precision account event
forall (precision :: Nat) account event x.
Journal precision account event
-> Rep (Journal 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 (Journal precision account event) x
-> Journal precision account event
$cfrom :: forall (precision :: Nat) account event x.
Journal precision account event
-> Rep (Journal precision account event) x
Generic, Int -> Journal precision account event -> ShowS
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
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
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)
instance (KnownNat precision, Aeson.FromJSON account, Aeson.FromJSON event) => Aeson.FromJSON (Journal precision account event) where
parseJSON :: Value -> Parser (Journal 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
"journal"
instance (KnownNat precision, Aeson.ToJSON account, Aeson.ToJSON event) => Aeson.ToJSON (Journal precision account event) where
toJSON :: Journal 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
"journal"
toEncoding :: Journal 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
"journal"
data JournalEntry (precision :: Nat) account event = JournalEntry
{ forall (precision :: Nat) account event.
JournalEntry precision account event -> Text
journalEntryId :: !T.Text
, forall (precision :: Nat) account event.
JournalEntry precision account event -> Day
journalEntryDate :: !Day
, forall (precision :: Nat) account event.
JournalEntry precision account event
-> [JournalEntryItem precision account event]
journalEntryItems :: ![JournalEntryItem precision account event]
, forall (precision :: Nat) account event.
JournalEntry precision account event -> Text
journalEntryDescription :: !T.Text
}
deriving (forall (precision :: Nat) account event x.
Rep (JournalEntry precision account event) x
-> JournalEntry precision account event
forall (precision :: Nat) account event x.
JournalEntry precision account event
-> Rep (JournalEntry 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 (JournalEntry precision account event) x
-> JournalEntry precision account event
$cfrom :: forall (precision :: Nat) account event x.
JournalEntry precision account event
-> Rep (JournalEntry precision account event) x
Generic, Int -> JournalEntry precision account event -> ShowS
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
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
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)
instance (KnownNat precision, Aeson.FromJSON account, Aeson.FromJSON event) => Aeson.FromJSON (JournalEntry precision account event) where
parseJSON :: Value -> Parser (JournalEntry 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
"journalEntry"
instance (KnownNat precision, Aeson.ToJSON account, Aeson.ToJSON event) => Aeson.ToJSON (JournalEntry precision account event) where
toJSON :: JournalEntry 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
"journalEntry"
toEncoding :: JournalEntry 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
"journalEntry"
journalEntryTotalDebit
:: KnownNat precision
=> JournalEntry precision account event
-> UnsignedQuantity precision
journalEntryTotalDebit :: forall (precision :: Nat) account event.
KnownNat precision =>
JournalEntry precision account event -> UnsignedQuantity precision
journalEntryTotalDebit =
forall (s :: Nat).
KnownNat s =>
[UnsignedQuantity s] -> UnsignedQuantity s
sumUnsignedQuantity
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).
Amount precision -> UnsignedQuantity precision
amountValue forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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). Amount precision -> Side
amountSide forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
JournalEntry precision account event
-> [JournalEntryItem precision account event]
journalEntryItems
journalEntryTotalCredit
:: KnownNat precision
=> JournalEntry precision account event
-> UnsignedQuantity precision
journalEntryTotalCredit :: forall (precision :: Nat) account event.
KnownNat precision =>
JournalEntry precision account event -> UnsignedQuantity precision
journalEntryTotalCredit =
forall (s :: Nat).
KnownNat s =>
[UnsignedQuantity s] -> UnsignedQuantity s
sumUnsignedQuantity
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).
Amount precision -> UnsignedQuantity precision
amountValue forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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). Amount precision -> Side
amountSide forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (precision :: Nat) account event.
JournalEntry precision account event
-> [JournalEntryItem precision account event]
journalEntryItems
isJournalEntryBalanced
:: KnownNat precision
=> JournalEntry precision account event
-> Bool
isJournalEntryBalanced :: forall (precision :: Nat) account event.
KnownNat precision =>
JournalEntry precision account event -> Bool
isJournalEntryBalanced =
forall a. Eq a => a -> a -> Bool
(==)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (precision :: Nat) account event.
KnownNat precision =>
JournalEntry precision account event -> UnsignedQuantity precision
journalEntryTotalDebit
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (precision :: Nat) account event.
KnownNat precision =>
JournalEntry precision account event -> UnsignedQuantity precision
journalEntryTotalCredit
data JournalEntryItem (precision :: Nat) account event = JournalEntryItem
{ forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Amount precision
journalEntryItemAmount :: !(Amount precision)
, forall (precision :: Nat) account event.
JournalEntryItem precision account event -> Account account
journalEntryItemAccount :: !(Account account)
, forall (precision :: Nat) account event.
JournalEntryItem precision account event -> event
journalEntryItemEvent :: !event
, forall (precision :: Nat) account event.
JournalEntryItem precision account event
-> Maybe (JournalEntryItemInventoryEvent account event)
journalEntryItemInventoryEvent :: !(Maybe (JournalEntryItemInventoryEvent account event))
}
deriving (JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool
forall (precision :: Nat) account event.
(Eq account, Eq event) =>
JournalEntryItem precision account event
-> JournalEntryItem precision account event -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: 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 (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
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$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
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
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
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)
instance (KnownNat precision, Aeson.FromJSON account, Aeson.FromJSON event) => Aeson.FromJSON (JournalEntryItem precision account event) where
parseJSON :: Value -> Parser (JournalEntryItem 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
"journalEntryItem"
instance (KnownNat precision, Aeson.ToJSON account, Aeson.ToJSON event) => Aeson.ToJSON (JournalEntryItem precision account event) where
toJSON :: JournalEntryItem 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
"journalEntryItem"
toEncoding :: JournalEntryItem 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
"journalEntryItem"
data JournalEntryItemInventoryEvent account event = JournalEntryItemInventoryEvent
{ forall account event.
JournalEntryItemInventoryEvent account event -> Account account
journalEntryItemInventoryEventPnlAccount :: !(Account account)
, forall account event.
JournalEntryItemInventoryEvent account event -> event
journalEntryItemInventoryEventEvent :: !event
, forall account event.
JournalEntryItemInventoryEvent account event -> Quantity 12
journalEntryItemInventoryEventQuantity :: !(Quantity 12)
}
deriving (JournalEntryItemInventoryEvent account event
-> JournalEntryItemInventoryEvent account event -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall account event.
(Eq account, Eq event) =>
JournalEntryItemInventoryEvent account event
-> JournalEntryItemInventoryEvent account event -> Bool
/= :: JournalEntryItemInventoryEvent account event
-> JournalEntryItemInventoryEvent account event -> Bool
$c/= :: forall account event.
(Eq account, Eq event) =>
JournalEntryItemInventoryEvent account event
-> JournalEntryItemInventoryEvent account event -> Bool
== :: JournalEntryItemInventoryEvent account event
-> JournalEntryItemInventoryEvent account event -> Bool
$c== :: forall account event.
(Eq account, Eq event) =>
JournalEntryItemInventoryEvent account event
-> JournalEntryItemInventoryEvent account event -> Bool
Eq, forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall account event x.
Rep (JournalEntryItemInventoryEvent account event) x
-> JournalEntryItemInventoryEvent account event
forall account event x.
JournalEntryItemInventoryEvent account event
-> Rep (JournalEntryItemInventoryEvent account event) x
$cto :: forall account event x.
Rep (JournalEntryItemInventoryEvent account event) x
-> JournalEntryItemInventoryEvent account event
$cfrom :: forall account event x.
JournalEntryItemInventoryEvent account event
-> Rep (JournalEntryItemInventoryEvent account event) x
Generic, Int -> JournalEntryItemInventoryEvent account event -> ShowS
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall account event.
(Show account, Show event) =>
Int -> JournalEntryItemInventoryEvent account event -> ShowS
forall account event.
(Show account, Show event) =>
[JournalEntryItemInventoryEvent account event] -> ShowS
forall account event.
(Show account, Show event) =>
JournalEntryItemInventoryEvent account event -> String
showList :: [JournalEntryItemInventoryEvent account event] -> ShowS
$cshowList :: forall account event.
(Show account, Show event) =>
[JournalEntryItemInventoryEvent account event] -> ShowS
show :: JournalEntryItemInventoryEvent account event -> String
$cshow :: forall account event.
(Show account, Show event) =>
JournalEntryItemInventoryEvent account event -> String
showsPrec :: Int -> JournalEntryItemInventoryEvent account event -> ShowS
$cshowsPrec :: forall account event.
(Show account, Show event) =>
Int -> JournalEntryItemInventoryEvent account event -> ShowS
Show)
instance (Aeson.FromJSON account, Aeson.FromJSON event) => Aeson.FromJSON (JournalEntryItemInventoryEvent account event) where
parseJSON :: Value -> Parser (JournalEntryItemInventoryEvent 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
"journalEntryItemInventoryEvent"
instance (Aeson.ToJSON account, Aeson.ToJSON event) => Aeson.ToJSON (JournalEntryItemInventoryEvent account event) where
toJSON :: JournalEntryItemInventoryEvent 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
"journalEntryItemInventoryEvent"
toEncoding :: JournalEntryItemInventoryEvent 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
"journalEntryItemInventoryEvent"
mkJournalEntryItemFromValue
:: KnownNat precision
=> Quantity precision
-> Account account
-> event
-> JournalEntryItem precision account event
mkJournalEntryItemFromValue :: forall (precision :: Nat) account event.
KnownNat precision =>
Quantity precision
-> Account account
-> event
-> JournalEntryItem precision account event
mkJournalEntryItemFromValue Quantity precision
val Account account
acc event
evt =
JournalEntryItem
{ journalEntryItemAmount :: Amount precision
journalEntryItemAmount = forall (precision :: Nat).
KnownNat precision =>
AccountKind -> Quantity precision -> Amount precision
amountFromValue (forall o. Account o -> AccountKind
accountKind Account account
acc) Quantity precision
val
, journalEntryItemAccount :: Account account
journalEntryItemAccount = Account account
acc
, journalEntryItemEvent :: event
journalEntryItemEvent = event
evt
, journalEntryItemInventoryEvent :: Maybe (JournalEntryItemInventoryEvent account event)
journalEntryItemInventoryEvent = forall a. Maybe a
Nothing
}
mkInventoryJournalEntryItemFromValue
:: KnownNat precision
=> Quantity precision
-> Account account
-> event
-> Account account
-> event
-> Quantity 12
-> JournalEntryItem precision account event
mkInventoryJournalEntryItemFromValue :: forall (precision :: Nat) account event.
KnownNat precision =>
Quantity precision
-> Account account
-> event
-> Account account
-> event
-> Quantity 12
-> JournalEntryItem precision account event
mkInventoryJournalEntryItemFromValue Quantity precision
val Account account
acc event
evt Account account
pnlacc event
pnlevt Quantity 12
evtqty =
JournalEntryItem
{ journalEntryItemAmount :: Amount precision
journalEntryItemAmount = forall (precision :: Nat).
KnownNat precision =>
AccountKind -> Quantity precision -> Amount precision
amountFromValue (forall o. Account o -> AccountKind
accountKind Account account
acc) Quantity precision
val
, journalEntryItemAccount :: Account account
journalEntryItemAccount = Account account
acc
, journalEntryItemEvent :: event
journalEntryItemEvent = event
evt
, journalEntryItemInventoryEvent :: Maybe (JournalEntryItemInventoryEvent account event)
journalEntryItemInventoryEvent =
forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$
JournalEntryItemInventoryEvent
{ journalEntryItemInventoryEventPnlAccount :: Account account
journalEntryItemInventoryEventPnlAccount = Account account
pnlacc
, journalEntryItemInventoryEventQuantity :: Quantity 12
journalEntryItemInventoryEventQuantity = Quantity 12
evtqty
, journalEntryItemInventoryEventEvent :: event
journalEntryItemInventoryEventEvent = event
pnlevt
}
}