From 95d50b25c990e8c945ce2507b16ff3c8b039d286 Mon Sep 17 00:00:00 2001 From: Rutger Broekhoff Date: Mon, 25 Aug 2025 19:48:19 +0200 Subject: OCaml --- lib/ledger.ml | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 lib/ledger.ml (limited to 'lib/ledger.ml') diff --git a/lib/ledger.ml b/lib/ledger.ml new file mode 100644 index 0000000..fd1b2a9 --- /dev/null +++ b/lib/ledger.ml @@ -0,0 +1,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 -- cgit v1.2.3