summaryrefslogtreecommitdiffstats
path: root/app/Data/Ledger.hs
blob: 4aa51374f628465273833c610077520d24fce844 (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}

module Data.Ledger where

import Data.Constraint.Extras.TH (deriveArgDict)
import Data.Dependent.Map (DMap, fromList, singleton, union, unionWithKey)
import Data.Dependent.Sum ((==>))
import Data.Functor.Identity
import Data.Functor.Identity (Identity (..))
import Data.GADT.Compare.TH (deriveGCompare, deriveGEq)
import Data.GADT.Show.TH (deriveGShow)
import Data.Iban
import Data.Map qualified as M
import Data.Text qualified as T
import Data.Time.Calendar
import Data.Time.Clock
import Data.UUID
import GHC.Generics

data AccountType = Asset | Equity | Liability | Expense | Income

data TxAction = Inc | Dec

txaOpp :: TxAction -> TxAction
txaOpp Inc = Dec
txaOpp Dec = Inc

onDebit :: AccountType -> TxAction
onDebit Asset = Inc
onDebit Equity = Dec
onDebit Liability = Dec
onDebit Expense = Inc
onDebit Income = Dec

onCredit :: AccountType -> TxAction
onCredit = txaOpp . onDebit

data TxType
  = InterestCtx
  | OnlineBankingTx
  | RecurrentDirectTx
  | PaymentTerminalTx
  | CashPaymentTx
  | AtmTx
  | AutoSaveRoundingTx
  | BatchTx
  | DirectDebitTx
  | PeriodicTx

data IbanTag = AccountTag | CounterpartyIbanTag deriving (Eq, Enum, Ord, Show)

data UnitTag = FiledTag | GooglePayTag | AutoRoundSavingsTag deriving (Eq, Enum, Ord, Show)

data TextTag = DescTag | UserTag | CounterpartyNameTag | ReferenceTag | MandateIdTag | CreditorIdTag | OtherPartyTag | TransactionTag | TerminalTag | CardSeqNoTag | SavingsAccountTag deriving (Eq, Enum, Ord, Show)

data Label a where
  TextLabel :: TextTag -> Label T.Text
  IbanLabel :: IbanTag -> Label Iban
  UnitLabel :: UnitTag -> Label ()
  TimestampLabel :: Label UTCTime

deriveGEq ''Label
deriveGCompare ''Label
deriveGShow ''Label
deriveArgDict ''Label

type Labels = DMap Label Identity

data Money = Money Integer deriving (Show)

infixl 6 +, -(+) :: Money -> Money -> Money
Money x +€ Money y = Money (x + y)

(-) :: Money -> Money -> Money
Money x -€ Money y = Money (x - y)

data Scalar = Amount Money | Rate Integer deriving (Show)

data AccountId = AccountId [T.Text] deriving (Show)

data CommodityId = CommodityId UUID deriving (Show)

data Account = Account
  { id :: AccountId,
    description :: [T.Text],
    commodityId :: CommodityId,
    balance :: Money
  }

-- A balance assertion is only valid when all transactions before it have been
-- cleared and the balance of the account agrees with the amount in the
-- assertion.
data BalAssert = BalAssert
  { account :: AccountId,
    amount :: Money,
    labels :: Labels
  }

data Tx = Tx
  { cleared :: Maybe Day,
    commodityId :: CommodityId, -- the commodity w.r.t. which rates are calculated
    debit :: M.Map AccountId Scalar,
    credit :: M.Map AccountId Scalar,
    labels :: Labels
  }
  deriving (Show, Generic)

-- data SeqTx = SeqTx [Integer] Tx

data Entry = TxEntry Tx | BalAssertEntry BalAssert

data Ledger = Ledger [Entry]