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
|
open Core
type account_type = Asset | Equity | Liability | Expense | Income
type tx_type =
| Interest_tx
| Online_banking_tx
| Recurrent_direct_tx
| Payment_terminal_tx
| Cash_payment_tx
| Atm_tx
| Auto_save_rounding_tx
| Batch_tx
| Direct_debit_tx
| Periodic_tx
type iban_tag = Account_tag | Counterparty_iban_tag [@@deriving compare]
type unit_tag = Filed_tag | GooglePay_tag | AutoRoundSavings_tag
[@@deriving compare]
type string_tag =
| Desc_tag
| User_tag
| Counterparty_name_tag
| Reference_tag
| Mandate_id_tag
| Creditor_id_tag
| Other_party_tag
| Transaction_tag
| Terminal_tag
| Card_seq_no_tag
| Savings_account_tag
[@@deriving compare]
module Label = struct
type 'a t =
| Iban_label : iban_tag -> Iban.t t
| String_label : string_tag -> string t
| Timestamp_label : Time_ns.t t
| Unit_label : unit_tag -> unit t
let int_to_cmp x : ('a, 'a) Dmap.cmp =
if x < 0 then Lt else if x > 0 then Gt else Eq
let compare (type a1 a2) (v1 : a1 t) (v2 : a2 t) : (a1, a2) Dmap.cmp =
match (v1, v2) with
| Iban_label t1, Iban_label t2 -> int_to_cmp @@ [%compare: iban_tag] t1 t2
| String_label t1, String_label t2 ->
int_to_cmp @@ [%compare: string_tag] t1 t2
| Timestamp_label, Timestamp_label -> Eq
| Unit_label t1, Unit_label t2 -> int_to_cmp @@ [%compare: unit_tag] t1 t2
| Iban_label _, _ -> Lt
| String_label _, Iban_label _ -> Gt
| String_label _, _ -> Lt
| Timestamp_label, Unit_label _ -> Lt
| Timestamp_label, _ -> Gt
| Unit_label _, _ -> Gt
end
module Labels = Dmap.Make (Label)
module Money : sig
type t
val equal : t -> t -> bool
val compare : t -> t -> int
val of_z : Z.t -> t
val to_z : t -> Z.t
val ( + ) : t -> t -> t
val ( - ) : t -> t -> t
end = struct
type t = Z.t
let equal = Z.equal
let compare = Z.compare
let of_z = Fn.id
let to_z = Fn.id
let ( + ) x y = Z.(x + y)
let ( - ) x y = Z.(x - y)
end
type scalar = Amount of Money.t | Rate of Z.t [@@deriving equal, compare]
type account_id = string list
type commodity_id = string (* TODO: consider making this UUID *)
type account = {
id : account_id;
description : string list;
commodity_id : commodity_id;
balance : Money.t;
}
type bal_assert = { account : account_id; amount : Money.t; labels : Labels.t }
module Account_id_key = struct
type t = account_id
type comparator_witness
end
type tx = {
cleared : Date.t option;
commodity_id : commodity_id;
debit : scalar Map.M(Account_id_key).t;
credit : scalar Map.M(Account_id_key).t;
labels : Labels.t;
}
type item = Tx_item of tx | Bal_assert_item of bal_assert
type ledger = Ledger of item list
|