commit 2c3337cb894ad93341b26047e5409adf040b8005 Author: Matthieu Dubuget Date: Tue Dec 31 15:18:43 2019 +0100 commit initial diff --git a/.ocamlformat b/.ocamlformat new file mode 100644 index 0000000..e69de29 diff --git a/compta.ml b/compta.ml new file mode 100644 index 0000000..a76d6c1 --- /dev/null +++ b/compta.ml @@ -0,0 +1,110 @@ +let optstring = function Some s -> s | None -> "" + +type mvt = { + year : int; + month : int; + day : int; + category : string; + subcategory : string; + amount : float; + account : string; + payee : string; + notes : string; +} + +let mvt year month day category subcategory amount account payee notes = + { + year = truncate year; + month = truncate month; + day = truncate day; + category; + subcategory = optstring subcategory; + amount; + account; + payee; + notes = optstring notes; + } + +let after y m d l = + Printf.sprintf "%04d-%02d-%02d" l.year l.month l.day + > Printf.sprintf "%04d-%02d-%02d" y m d + +let until y m d l = + Printf.sprintf "%04d-%02d-%02d" l.year l.month l.day + <= Printf.sprintf "%04d-%02d-%02d" y m d + +let is_account_caisse m = m.account = "CAISSE" + +let is_account_courant m = m.account = "COURANT" + +let any_account _ = true + +let mvts fn = + Sqlite3_utils.( + with_db fn (fun db -> + exec db + "select Year, Month, Day, Category, Subcategory, Amount, \ + AccountName, Payee, Notes from alldata" + ~ty: + Ty. + ( nil, + p3 float float float + @>> p2 text (nullable text) + @>> p1 float + @>> p3 text text (nullable text), + mvt ) + ~f:Cursor.to_list)) + |> Rresult.R.get_ok + +let solde ~cpt_filter ~at:(y, m, d) mvts = + mvts + |> List.filter (until y m d) + |> List.filter cpt_filter + |> List.map (fun m -> m.amount) + |> List.fold_left ( +. ) 0. + +let balance ~cpt_filter ~from ~until mvts = + solde ~cpt_filter ~at:until mvts -. solde ~cpt_filter ~at:from mvts + +let bilan ~cpt_filter ~from:(fy, fm, fd) ~until:(uy, um, ud) mvts () = + let t = Hashtbl.create 164 in + mvts + |> List.filter (after fy fm fd) + |> List.filter (until uy um ud) + |> List.filter cpt_filter + |> List.iter (fun mvt -> + let i = mvt.category ^ ":" ^ mvt.subcategory in + match Hashtbl.find_opt t i with + | None -> Hashtbl.add t i mvt.amount + | Some a -> Hashtbl.replace t i (mvt.amount +. a)); + + Hashtbl.iter + (fun cat mont -> if mont < 0. then Printf.printf "%50s\t%04.02f\n" cat mont) + t; + + Hashtbl.iter + (fun cat mont -> + if mont >= 0. then Printf.printf "%50s\t%04.02f\n" cat mont) + t + +let main ~from:((yf, mf, df) as from) ~until:((yu, mu, du) as until) () = + let ops = + mvts "/home/matt/Téléchargements/NOVEMBRE2.mmb_update_2019-11-12.mmb" + in + + let caisse_dbt = solde ~cpt_filter:is_account_caisse ~at:from ops + and caisse_fin = solde ~cpt_filter:is_account_caisse ~at:until ops + and courant_dbt = solde ~cpt_filter:is_account_courant ~at:from ops + and courant_fin = solde ~cpt_filter:is_account_courant ~at:until ops in + + Printf.printf "%04d-%02d-%02d\n" yf mf df; + Printf.printf "CAISSE : %.2f\n" caisse_dbt; + Printf.printf "COURANT : %.2f\n" courant_dbt; + + bilan ~cpt_filter:any_account ~from ~until ops (); + + Printf.printf "%04d-%02d-%02d\n" yu mu du; + Printf.printf "CAISSE : %.2f\n" caisse_fin; + Printf.printf "COURANT : %.2f\n" courant_fin + +let () = main ~from:(2018, 11, 25) ~until:(2019, 10, 31) () diff --git a/dune b/dune new file mode 100644 index 0000000..cb6ddec --- /dev/null +++ b/dune @@ -0,0 +1,3 @@ +(executable + (name compta) + (libraries rresult sqlite3_utils)) diff --git a/dune-project b/dune-project new file mode 100644 index 0000000..25680a8 --- /dev/null +++ b/dune-project @@ -0,0 +1,8 @@ + +(lang dune 2.0) +(generate_opam_files true) + +(package + (name compta) + (synopsis "Comptabilite from one MMB file") + (depends rresult sqlite3_utils))