re-enabling the ability to import invoices.
This commit is contained in:
1
resources/sample-excel-small.tsv
Normal file
1
resources/sample-excel-small.tsv
Normal file
@@ -0,0 +1 @@
|
||||
6/16/17 Acme Bread DEMO-CB 3/26/56 12:00 AM $54.00 Naschmarkt X 7/31/17 8:26 AM 8/1/17 3:57 PM 116
|
||||
|
@@ -2,6 +2,7 @@
|
||||
(:require [auto-ap.datomic.clients :as d-clients]
|
||||
[auto-ap.datomic.vendors :as d-vendors]
|
||||
[auto-ap.datomic.invoices :as d-invoices]
|
||||
[auto-ap.datomic.accounts :as d-accounts]
|
||||
[auto-ap.yodlee.import :refer [manual-import]]
|
||||
[auto-ap.utils :refer [by]]
|
||||
[auto-ap.datomic :refer [remove-nils uri]]
|
||||
@@ -69,12 +70,13 @@
|
||||
(catch Exception e
|
||||
(throw (Exception. (str "Could not parse total from value '" (:amount i) "'") e)))))
|
||||
|
||||
(defn parse-default-expense-account [i]
|
||||
(defn parse-account-numeric-code [i]
|
||||
(try
|
||||
(when-let [default-expense-account (:default-expense-account i)]
|
||||
(Integer/parseInt default-expense-account))
|
||||
(when-let [account-numeric-code (:account-numeric-code i)]
|
||||
(d-accounts/get-account-by-numeric-code-and-sets (Integer/parseInt account-numeric-code)
|
||||
["default"]))
|
||||
(catch Exception e
|
||||
(throw (Exception. (str "Could not parse expense account from value '" (:default-expense-account i) "'") e)))))
|
||||
(throw (Exception. (str "Could not parse expense account from value '" (:account-numeric-code i) "'") e)))))
|
||||
|
||||
(defn parse-account-id [i]
|
||||
(try
|
||||
@@ -100,7 +102,7 @@
|
||||
:details (str e)})))))
|
||||
|
||||
(defn parse-invoice-rows [excel-rows]
|
||||
(let [columns [:raw-date :vendor-name :check :location :invoice-number :amount :client-name :bill-entered :bill-rejected :added-on :exported-on :default-expense-account]
|
||||
(let [columns [:raw-date :vendor-name :check :location :invoice-number :amount :client-name :bill-entered :bill-rejected :added-on :exported-on :account-numeric-code]
|
||||
all-vendors (by :vendor/name (d-vendors/get-graphql {}))
|
||||
all-clients (d-clients/get-all)
|
||||
all-clients (merge (by :client/code all-clients) (by :client/name all-clients))
|
||||
@@ -112,7 +114,7 @@
|
||||
(map (parse-or-error :client-id #(parse-client % all-clients)))
|
||||
(map (parse-or-error :vendor #(parse-vendor % all-vendors)))
|
||||
(map (parse-or-error :vendor-id #(parse-vendor-id %)))
|
||||
(map (parse-or-error :default-expense-account parse-default-expense-account))
|
||||
(map (parse-or-error :account-id parse-account-numeric-code))
|
||||
(map (parse-or-error :invoice-number parse-invoice-number))
|
||||
(map (parse-or-error :total parse-amount))
|
||||
(map (parse-or-error :date parse-date)))]
|
||||
@@ -122,13 +124,13 @@
|
||||
|
||||
(defn invoice-rows->transaction [rows]
|
||||
(->> rows
|
||||
(mapcat (fn [{:keys [vendor-id total client-id amount date invoice-number default-location default-expense-account check vendor]}]
|
||||
(mapcat (fn [{:keys [vendor-id total client-id amount date invoice-number default-location account-id check vendor]}]
|
||||
(let [invoice #:invoice {:db/id (.toString (java.util.UUID/randomUUID))
|
||||
:vendor vendor-id
|
||||
:client client-id
|
||||
:default-location default-location
|
||||
:import-status :import-status/imported
|
||||
:default-expense-account default-expense-account
|
||||
#_#_:default-expense-account default-expense-account
|
||||
:total total
|
||||
:outstanding-balance (if (= "Cash" check)
|
||||
0.0
|
||||
@@ -138,7 +140,8 @@
|
||||
:invoice-status/unpaid)
|
||||
:invoice-number invoice-number
|
||||
:date (to-date date)
|
||||
:expense-accounts [#:invoice-expense-account {:expense-account-id (or default-expense-account (:vendor/default-expense-account vendor))
|
||||
:expense-accounts [#:invoice-expense-account {:account (or account-id
|
||||
(-> vendor :vendor/account :db/id))
|
||||
:location default-location
|
||||
:amount total}]}
|
||||
payment (if (= :invoice-status/paid (:invoice/status invoice))
|
||||
@@ -160,18 +163,18 @@
|
||||
|
||||
(defn import-uploaded-invoice [imports]
|
||||
(let [clients (d-clients/get-all)
|
||||
_ (println imports)
|
||||
_ (clojure.pprint/pprint imports)
|
||||
|
||||
transactions (reduce (fn [result {:keys [invoice-number customer-identifier total date vendor-code text] :as info}]
|
||||
(let [[matching-vendor default-expense-account] (->> (d/query
|
||||
(cond-> {:query {:find ['?vendor '?default-expense-account]
|
||||
:in ['$ '?vendor-name]
|
||||
:where ['[?vendor :vendor/name ?vendor-name]
|
||||
'[?vendor :vendor/default-expense-account ?default-expense-account]]}
|
||||
:args [(d/db (d/connect uri)) vendor-code]}))
|
||||
first)
|
||||
(let [[matching-vendor default-account] (->> (d/query
|
||||
(cond-> {:query {:find ['?vendor '?default-account]
|
||||
:in ['$ '?vendor-name]
|
||||
:where ['[?vendor :vendor/name ?vendor-name]
|
||||
'[?vendor :vendor/default-account ?default-account]]}
|
||||
:args [(d/db (d/connect uri)) vendor-code]}))
|
||||
first)
|
||||
matching-client (parse/best-match clients customer-identifier)
|
||||
_ (println "New invoice matches client" matching-client)
|
||||
_ (println "New invoice matches client '" matching-client "', vendor '" matching-vendor "', account '" default-account "'")
|
||||
matching-location (parse/best-location-match matching-client text )
|
||||
[existing-id existing-outstanding-balance existing-status import-status] (->> (d/query
|
||||
(cond-> {:query {:find ['?e '?outstanding-balance '?status '?import-status2]
|
||||
@@ -196,7 +199,7 @@
|
||||
:invoice/import-status :import-status/pending
|
||||
:invoice/outstanding-balance (or existing-outstanding-balance (Double/parseDouble total))
|
||||
:invoice/status (or existing-status :invoice-status/unpaid)
|
||||
:invoice/expense-accounts (when-not existing-id [#:invoice-expense-account {:expense-account-id default-expense-account
|
||||
:invoice/expense-accounts (when-not existing-id [#:invoice-expense-account {:account default-account
|
||||
:location matching-location
|
||||
:amount (Double/parseDouble total)}])
|
||||
:db/id existing-id
|
||||
@@ -205,8 +208,7 @@
|
||||
[]
|
||||
imports)]
|
||||
|
||||
@(d/transact (d/connect uri) transactions)
|
||||
))
|
||||
@(d/transact (d/connect uri) transactions)))
|
||||
|
||||
(defroutes routes
|
||||
(wrap-routes
|
||||
@@ -224,12 +226,10 @@
|
||||
(drop 1)
|
||||
(map #(str/split % #"\t"))
|
||||
(map #(into {} (filter identity (map (fn [c k] [k c] ) % columns))))
|
||||
|
||||
(map (parse-or-error :amount parse-amount))
|
||||
(map (parse-or-error :date parse-date)))
|
||||
error-rows (filter :errors rows)
|
||||
_ (println "importing raw transactions" rows)
|
||||
|
||||
raw-transactions (vec (->> rows
|
||||
(filter #(not (seq (:errors %))) )
|
||||
(map (fn [{:keys [description-original client-code status high-level-category amount bank-account-code date]}]
|
||||
@@ -242,8 +242,6 @@
|
||||
:bank-account-id (:db/id (all-bank-accounts bank-account-code))}))))]
|
||||
|
||||
(manual-import raw-transactions)
|
||||
|
||||
|
||||
{:status 200
|
||||
:body (pr-str {:imported (count raw-transactions)
|
||||
:errors (map #(dissoc % :date) error-rows)})
|
||||
@@ -251,8 +249,9 @@
|
||||
|
||||
(context "/invoices" []
|
||||
(POST "/upload"
|
||||
{{ files "file"} :params :as params}
|
||||
(let [{:keys [filename tempfile]} files]
|
||||
{{ file :file } :params :as params}
|
||||
#_(clojure.pprint/pprint params)
|
||||
(let [{:keys [filename tempfile]} file]
|
||||
(import-uploaded-invoice (parse/parse-file (.getPath tempfile) filename))
|
||||
{:status 200
|
||||
:body (pr-str {})
|
||||
|
||||
Reference in New Issue
Block a user