{-# LANGUAGE OverloadedStrings #-}
module Haspara.Accounting.Side where
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Encoding as Aeson.Encoding
import qualified Data.Text as T
import GHC.TypeLits (KnownNat)
import Haspara.Accounting.Account (AccountKind (..))
import Haspara.Quantity (Quantity)
data Side = SideDebit | SideCredit
deriving (Side -> Side -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Side -> Side -> Bool
$c/= :: Side -> Side -> Bool
== :: Side -> Side -> Bool
$c== :: Side -> Side -> Bool
Eq, Eq Side
Side -> Side -> Bool
Side -> Side -> Ordering
Side -> Side -> Side
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Side -> Side -> Side
$cmin :: Side -> Side -> Side
max :: Side -> Side -> Side
$cmax :: Side -> Side -> Side
>= :: Side -> Side -> Bool
$c>= :: Side -> Side -> Bool
> :: Side -> Side -> Bool
$c> :: Side -> Side -> Bool
<= :: Side -> Side -> Bool
$c<= :: Side -> Side -> Bool
< :: Side -> Side -> Bool
$c< :: Side -> Side -> Bool
compare :: Side -> Side -> Ordering
$ccompare :: Side -> Side -> Ordering
Ord, Int -> Side -> ShowS
[Side] -> ShowS
Side -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Side] -> ShowS
$cshowList :: [Side] -> ShowS
show :: Side -> String
$cshow :: Side -> String
showsPrec :: Int -> Side -> ShowS
$cshowsPrec :: Int -> Side -> ShowS
Show)
instance Aeson.FromJSON Side where
parseJSON :: Value -> Parser Side
parseJSON = forall a. String -> (Text -> Parser a) -> Value -> Parser a
Aeson.withText String
"Side" forall a b. (a -> b) -> a -> b
$ \Text
t -> case Text
t of
Text
"db" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Side
SideDebit
Text
"cr" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure Side
SideCredit
Text
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Unkown side indicator: \"" forall a. Semigroup a => a -> a -> a
<> Text -> String
T.unpack Text
t forall a. Semigroup a => a -> a -> a
<> String
"\". Expecting one of \"db\" or \"cr\""
instance Aeson.ToJSON Side where
toJSON :: Side -> Value
toJSON Side
SideDebit = Text -> Value
Aeson.String Text
"db"
toJSON Side
SideCredit = Text -> Value
Aeson.String Text
"cr"
toEncoding :: Side -> Encoding
toEncoding Side
SideDebit = forall a. Text -> Encoding' a
Aeson.Encoding.text Text
"db"
toEncoding Side
SideCredit = forall a. Text -> Encoding' a
Aeson.Encoding.text Text
"cr"
otherSide :: Side -> Side
otherSide :: Side -> Side
otherSide Side
SideDebit = Side
SideCredit
otherSide Side
SideCredit = Side
SideDebit
sideByAccountKind
:: KnownNat precision
=> AccountKind
-> Quantity precision
-> Side
sideByAccountKind :: forall (precision :: Nat).
KnownNat precision =>
AccountKind -> Quantity precision -> Side
sideByAccountKind AccountKind
k Quantity precision
q = case (AccountKind
k, forall a. Num a => a -> a
signum Quantity precision
q forall a. Ord a => a -> a -> Bool
>= Quantity precision
0) of
(AccountKind
AccountKindAsset, Bool
False) -> Side
SideCredit
(AccountKind
AccountKindAsset, Bool
True) -> Side
SideDebit
(AccountKind
AccountKindLiability, Bool
False) -> Side
SideDebit
(AccountKind
AccountKindLiability, Bool
True) -> Side
SideCredit
(AccountKind
AccountKindEquity, Bool
False) -> Side
SideDebit
(AccountKind
AccountKindEquity, Bool
True) -> Side
SideCredit
(AccountKind
AccountKindRevenue, Bool
False) -> Side
SideDebit
(AccountKind
AccountKindRevenue, Bool
True) -> Side
SideCredit
(AccountKind
AccountKindExpense, Bool
False) -> Side
SideCredit
(AccountKind
AccountKindExpense, Bool
True) -> Side
SideDebit
normalSideByAccountKind :: AccountKind -> Side
normalSideByAccountKind :: AccountKind -> Side
normalSideByAccountKind AccountKind
AccountKindAsset = Side
SideDebit
normalSideByAccountKind AccountKind
AccountKindLiability = Side
SideCredit
normalSideByAccountKind AccountKind
AccountKindEquity = Side
SideCredit
normalSideByAccountKind AccountKind
AccountKindRevenue = Side
SideCredit
normalSideByAccountKind AccountKind
AccountKindExpense = Side
SideDebit