Make bank csv parsing generic

This commit is contained in:
Jeremy Dormitzer 2018-05-21 22:42:05 -04:00
parent 08fe745d02
commit 692fa98105

View File

@ -4,28 +4,44 @@
[clojure.java.shell :refer [sh]]) [clojure.java.shell :refer [sh]])
(:gen-class)) (:gen-class))
(defn parse-dcu-csv [filename] (defn nth-or [pred v & xs]
(when xs
(if-let [r (get v (first xs))]
(if (pred r) r (apply nth-or pred v (rest xs)))
(apply nth-or pred v (rest xs)))))
(defn to-seq [x]
(if (coll? x) (seq x) (seq (list x))))
(defn parse-bank-csv [& {:keys [filename
date
description
amount
header-rows]
:or {header-rows 1}}]
(->> (slurp filename) (->> (slurp filename)
(csv/read-csv) (csv/read-csv)
(drop 4) (drop header-rows)
(map (fn [row] (map (fn [row]
(let [date (row 1) (let [row-nth-or (partial nth-or
description (row 3) #(not (string/blank? %))
debit (row 4) row)]
credit (row 5)] {:date (apply row-nth-or (to-seq date))
(if (not (string/blank? debit)) :description (apply row-nth-or (to-seq description))
{:date date :description description :amount debit} :amount (apply row-nth-or (to-seq amount))})))))
{:date date :description description :amount credit}))))))
(defn parse-dcu-csv [filename]
(parse-bank-csv :filename filename
:date 1
:description 3
:amount [4 5]
:header-rows 4))
(defn parse-chase-csv [filename] (defn parse-chase-csv [filename]
(->> (slurp filename) (parse-bank-csv :filename filename
(csv/read-csv) :date 1
(drop 1) :description 3
(map (fn [row] :amount 4))
(let [date (row 1)
description (row 3)
amount (row 4)]
{:date date :description description :amount amount})))))
(defn parse-ledger-row [row] (defn parse-ledger-row [row]
(let [row-vec (string/split row #"\s\s+")] (let [row-vec (string/split row #"\s\s+")]
@ -35,10 +51,10 @@
(defn parse-ledger-output [period account] (defn parse-ledger-output [period account]
(->> (sh "ledger" "-w" "-p" period "reg" account) (->> (sh "ledger" "-w" "-p" period "reg" account)
(:out) (:out)
(#(string/split % #"\n")) (#(string/split % #"\n"))
(map parse-ledger-row) (map parse-ledger-row)
(reverse))) (reverse)))
(defn remove-one [pred coll] (defn remove-one [pred coll]
(let [[f r] (split-with #(not (pred %)) coll)] (let [[f r] (split-with #(not (pred %)) coll)]
@ -71,9 +87,9 @@
bank-record (parse-fn filename) bank-record (parse-fn filename)
ledger-record (parse-ledger-output period account) ledger-record (parse-ledger-output period account)
[bank-unmatched ledger-unmatched] (compare-records [bank-unmatched ledger-unmatched] (compare-records
(reverse bank-record) (reverse bank-record)
(reverse ledger-record) (reverse ledger-record)
'() '())] '() '())]
(if (> (+ (count bank-unmatched) (count ledger-unmatched)) 0) (if (> (+ (count bank-unmatched) (count ledger-unmatched)) 0)
(do (println "Unmatched bank transactions:") (do (println "Unmatched bank transactions:")
(doseq [t bank-unmatched] (println (format-item t))) (doseq [t bank-unmatched] (println (format-item t)))