{-# 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
(Side -> Side -> Bool) -> (Side -> Side -> Bool) -> Eq Side
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Side -> Side -> Bool
== :: Side -> Side -> Bool
$c/= :: Side -> Side -> Bool
/= :: Side -> Side -> Bool
Eq, Eq Side
Eq Side =>
(Side -> Side -> Ordering)
-> (Side -> Side -> Bool)
-> (Side -> Side -> Bool)
-> (Side -> Side -> Bool)
-> (Side -> Side -> Bool)
-> (Side -> Side -> Side)
-> (Side -> Side -> Side)
-> Ord 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
$ccompare :: Side -> Side -> Ordering
compare :: Side -> Side -> Ordering
$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
>= :: Side -> Side -> Bool
$cmax :: Side -> Side -> Side
max :: Side -> Side -> Side
$cmin :: Side -> Side -> Side
min :: Side -> Side -> Side
Ord, Int -> Side -> ShowS
[Side] -> ShowS
Side -> String
(Int -> Side -> ShowS)
-> (Side -> String) -> ([Side] -> ShowS) -> Show Side
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Side -> ShowS
showsPrec :: Int -> Side -> ShowS
$cshow :: Side -> String
show :: Side -> String
$cshowList :: [Side] -> ShowS
showList :: [Side] -> ShowS
Show)
instance Aeson.FromJSON Side where
parseJSON :: Value -> Parser Side
parseJSON = String -> (Text -> Parser Side) -> Value -> Parser Side
forall a. String -> (Text -> Parser a) -> Value -> Parser a
Aeson.withText String
"Side" ((Text -> Parser Side) -> Value -> Parser Side)
-> (Text -> Parser Side) -> Value -> Parser Side
forall a b. (a -> b) -> a -> b
$ \Text
t -> case Text
t of
Text
"db" -> Side -> Parser Side
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Side
SideDebit
Text
"cr" -> Side -> Parser Side
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Side
SideCredit
Text
_ -> String -> Parser Side
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser Side) -> String -> Parser Side
forall a b. (a -> b) -> a -> b
$ String
"Unkown side indicator: \"" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
T.unpack Text
t String -> ShowS
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 = Text -> Encoding
forall a. Text -> Encoding' a
Aeson.Encoding.text Text
"db"
toEncoding Side
SideCredit = Text -> Encoding
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, Quantity precision -> Quantity precision
forall a. Num a => a -> a
signum Quantity precision
q Quantity precision -> Quantity precision -> Bool
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