diff options
Diffstat (limited to 'lib/balanced_batch.ml')
| -rw-r--r-- | lib/balanced_batch.ml | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/lib/balanced_batch.ml b/lib/balanced_batch.ml new file mode 100644 index 0000000..5a64546 --- /dev/null +++ b/lib/balanced_batch.ml | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | open Prelude | ||
| 2 | |||
| 3 | (* Degenerate transactions, which can be applied directly to account | ||
| 4 | hierarchies (because we ideally want no unsafe operations on | ||
| 5 | accounts) *) | ||
| 6 | module Make (K : Map_intf.Key) : sig | ||
| 7 | type entry = { | ||
| 8 | dc : Money.Debit_credit.t; | ||
| 9 | commodity : Money.Commodity_id.t; | ||
| 10 | amount : Money.Amount.t; | ||
| 11 | } | ||
| 12 | |||
| 13 | type t | ||
| 14 | type error = Unbalanced | ||
| 15 | |||
| 16 | val make : entry Map.Make(K).t -> (t, error) result | ||
| 17 | val entries : t -> entry Map.Make(K).t | ||
| 18 | end = struct | ||
| 19 | type entry = { | ||
| 20 | dc : Money.Debit_credit.t; | ||
| 21 | commodity : Money.Commodity_id.t; | ||
| 22 | amount : Money.Amount.t; | ||
| 23 | } | ||
| 24 | |||
| 25 | type t = entry Map.Make(K).t | ||
| 26 | type error = Unbalanced | ||
| 27 | |||
| 28 | let is_balanced entries = | ||
| 29 | Map.fold entries ~init:Money.Commodity_id.Map.empty | ||
| 30 | ~f:(fun ~key:_ ~data comm_balances -> | ||
| 31 | Map.update comm_balances data.commodity ~f:(fun ocomm_bal -> | ||
| 32 | let comm_bal = Option.value ocomm_bal ~default:Money.Diff.(~$0) in | ||
| 33 | match data.dc with | ||
| 34 | | Money.Debit_credit.Debit -> Money.Diff.(comm_bal +% data.amount) | ||
| 35 | | Money.Debit_credit.Credit -> Money.Diff.(comm_bal -% data.amount))) | ||
| 36 | |> Map.for_all ~f:(fun comm_bal -> Money.Diff.(comm_bal = ~$0)) | ||
| 37 | |||
| 38 | let make entries = | ||
| 39 | if not (is_balanced entries) then Error Unbalanced else Ok entries | ||
| 40 | |||
| 41 | let entries entries = entries (* ambiguous? I disagree *) | ||
| 42 | end | ||